Add proper status page for datasync
or rather, it's a good start.. plenty more could be added
This commit is contained in:
parent
839c4e0c28
commit
065f845707
|
@ -4,7 +4,7 @@
|
|||
<%def name="context_menu_items()">
|
||||
${parent.context_menu_items()}
|
||||
% if request.has_perm('datasync.list'):
|
||||
<li>${h.link_to("View DataSync Threads", url('datasync'))}</li>
|
||||
<li>${h.link_to("View DataSync Status", url('datasync.status'))}</li>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
|
|
|
@ -53,29 +53,30 @@
|
|||
<p class="block">
|
||||
This tool works by modifying settings in the DB. It
|
||||
does <span class="is-italic">not</span> modify any config
|
||||
files. If you intend to manage datasync config via files
|
||||
only then you should
|
||||
<span class="is-italic">not</span> use this tool!
|
||||
files. If you intend to manage datasync watcher/consumer
|
||||
config via files only then you should be sure to UNCHECK the
|
||||
"Use these Settings.." checkbox near the top of page.
|
||||
</p>
|
||||
<p class="block">
|
||||
If you have managed config via files thus far, and want to use
|
||||
this tool anyway/instead, that's fine - but after saving
|
||||
the settings via this tool you should probably remove all
|
||||
If you have managed config via files thus far, and want to
|
||||
start using this tool to manage via DB settings instead,
|
||||
that's fine - but after saving the settings via this tool
|
||||
you should probably remove all
|
||||
<span class="is-family-code">[rattail.datasync]</span> entries
|
||||
from your config file (and restart apps) so as to avoid
|
||||
confusion.
|
||||
</p>
|
||||
<p class="block">
|
||||
Finally, you should know that this tool will
|
||||
<span class="is-italic">overwrite</span> the entire
|
||||
<span class="is-family-code">rattail.datasync</span> namespace
|
||||
within the DB settings. In other words if you have
|
||||
manually created any ${h.link_to("Raw Settings", url('settings'))}
|
||||
within that namepsace, they will be lost when you save settings
|
||||
with this tool.
|
||||
</p>
|
||||
</b-notification>
|
||||
|
||||
<b-field>
|
||||
<b-checkbox name="use_profile_settings"
|
||||
v-model="useProfileSettings"
|
||||
native-value="true"
|
||||
@input="settingsNeedSaved = true">
|
||||
Use these Settings to configure watchers and consumers
|
||||
</b-checkbox>
|
||||
</b-field>
|
||||
|
||||
<div class="level">
|
||||
<div class="level-left">
|
||||
<div class="level-item">
|
||||
|
@ -83,7 +84,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="level-right">
|
||||
<div class="level-item">
|
||||
<div class="level-item"
|
||||
v-show="useProfileSettings">
|
||||
<b-button type="is-primary"
|
||||
@click="newProfile()"
|
||||
icon-pack="fas"
|
||||
|
@ -130,7 +132,8 @@
|
|||
<b-table-column field="enabled" label="Enabled">
|
||||
{{ props.row.enabled ? "Yes" : "No" }}
|
||||
</b-table-column>
|
||||
<b-table-column label="Actions">
|
||||
<b-table-column label="Actions"
|
||||
v-if="useProfileSettings">
|
||||
<a href="#"
|
||||
class="grid-action"
|
||||
@click.prevent="editProfile(props.row)">
|
||||
|
@ -397,15 +400,22 @@
|
|||
|
||||
<h3 class="is-size-3">Misc.</h3>
|
||||
|
||||
<b-field grouped>
|
||||
<b-field label="Restart Command"
|
||||
message="This will run as '${system_user}' system user - please configure sudoers as needed. Typical command is like: sudo supervisorctl restart poser:poser_datasync"
|
||||
expanded>
|
||||
<b-input name="restart_command"
|
||||
v-model="restartCommand"
|
||||
@input="settingsNeedSaved = true">
|
||||
</b-input>
|
||||
</b-field>
|
||||
<b-field label="Supervisor Process Name"
|
||||
message="This should be the complete name, including group - e.g. poser:poser_datasync"
|
||||
expanded>
|
||||
<b-input name="supervisor_process_name"
|
||||
v-model="supervisorProcessName"
|
||||
@input="settingsNeedSaved = true">
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Restart Command"
|
||||
message="This will run as '${system_user}' system user - please configure sudoers as needed. Typical command is like: sudo supervisorctl restart poser:poser_datasync"
|
||||
expanded>
|
||||
<b-input name="restart_command"
|
||||
v-model="restartCommand"
|
||||
@input="settingsNeedSaved = true">
|
||||
</b-input>
|
||||
</b-field>
|
||||
|
||||
</%def>
|
||||
|
@ -417,6 +427,7 @@
|
|||
ThisPageData.showConfigFilesNote = false
|
||||
ThisPageData.profilesData = ${json.dumps(profiles_data)|n}
|
||||
ThisPageData.showDisabledProfiles = false
|
||||
ThisPageData.useProfileSettings = ${json.dumps(use_profile_settings)|n}
|
||||
|
||||
ThisPageData.editProfileShowDialog = false
|
||||
ThisPageData.editingProfile = null
|
||||
|
@ -441,6 +452,7 @@
|
|||
ThisPageData.editingConsumerRunas = null
|
||||
ThisPageData.editingConsumerEnabled = true
|
||||
|
||||
ThisPageData.supervisorProcessName = ${json.dumps(supervisor_process_name)|n}
|
||||
ThisPageData.restartCommand = ${json.dumps(restart_command)|n}
|
||||
|
||||
ThisPage.computed.filteredProfilesData = function() {
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
## -*- coding: utf-8; -*-
|
||||
<%inherit file="/master/index.mako" />
|
||||
|
||||
<%def name="context_menu_items()">
|
||||
${parent.context_menu_items()}
|
||||
% if request.has_perm('datasync_changes.list'):
|
||||
<li>${h.link_to("View DataSync Changes", url('datasyncchanges'))}</li>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="render_grid_component()">
|
||||
<b-notification :closable="false">
|
||||
TODO: this page coming soon...
|
||||
</b-notification>
|
||||
${parent.render_grid_component()}
|
||||
</%def>
|
||||
|
||||
|
||||
${parent.body()}
|
121
tailbone/templates/datasync/status.mako
Normal file
121
tailbone/templates/datasync/status.mako
Normal file
|
@ -0,0 +1,121 @@
|
|||
## -*- coding: utf-8; -*-
|
||||
<%inherit file="/page.mako" />
|
||||
|
||||
<%def name="content_title()"></%def>
|
||||
|
||||
<%def name="context_menu_items()">
|
||||
${parent.context_menu_items()}
|
||||
% if request.has_perm('datasync_changes.list'):
|
||||
<li>${h.link_to("View DataSync Changes", url('datasyncchanges'))}</li>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
<%def name="page_content()">
|
||||
<b-field label="Supervisor Status">
|
||||
<div style="display: flex;">
|
||||
|
||||
% if process_info:
|
||||
<pre class="has-background-${'success' if process_info['statename'] == 'RUNNING' else 'danger'}">${process_info['group']}:${process_info['name']} ${process_info['statename']} ${process_info['description']}</pre>
|
||||
% else:
|
||||
<pre class="has-background-warning">${supervisor_error}</pre>
|
||||
% endif
|
||||
|
||||
<div style="margin-left: 1rem;">
|
||||
% if request.has_perm('datasync.restart'):
|
||||
${h.form(url('datasync.restart'), **{'@submit': 'restartProcess'})}
|
||||
${h.csrf_token(request)}
|
||||
<b-button type="is-primary"
|
||||
native-type="submit"
|
||||
icon-pack="fas"
|
||||
icon-left="redo"
|
||||
:disabled="restartingProcess">
|
||||
{{ restartingProcess ? "Working, please wait..." : "Restart Process" }}
|
||||
</b-button>
|
||||
${h.end_form()}
|
||||
% endif
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Watcher Status">
|
||||
<b-table :data="watchers">
|
||||
<template slot-scope="props">
|
||||
<b-table-column field="key"
|
||||
label="Watcher">
|
||||
{{ props.row.key }}
|
||||
</b-table-column>
|
||||
<b-table-column field="spec"
|
||||
label="Spec">
|
||||
{{ props.row.spec }}
|
||||
</b-table-column>
|
||||
<b-table-column field="dbkey"
|
||||
label="DB Key">
|
||||
{{ props.row.dbkey }}
|
||||
</b-table-column>
|
||||
<b-table-column field="delay"
|
||||
label="Delay">
|
||||
{{ props.row.delay }} second(s)
|
||||
</b-table-column>
|
||||
<b-table-column field="lastrun"
|
||||
label="Last Watched">
|
||||
<span v-html="props.row.lastrun"></span>
|
||||
</b-table-column>
|
||||
<b-table-column field="status"
|
||||
label="Status"
|
||||
:class="props.row.status == 'okay' ? 'has-background-success' : 'has-background-warning'">
|
||||
{{ props.row.status }}
|
||||
</b-table-column>
|
||||
</template>
|
||||
</b-table>
|
||||
</b-field>
|
||||
|
||||
<b-field label="Consumer Status">
|
||||
<b-table :data="consumers">
|
||||
<template slot-scope="props">
|
||||
<b-table-column field="key"
|
||||
label="Consumer">
|
||||
{{ props.row.key }}
|
||||
</b-table-column>
|
||||
<b-table-column field="spec"
|
||||
label="Spec">
|
||||
{{ props.row.spec }}
|
||||
</b-table-column>
|
||||
<b-table-column field="dbkey"
|
||||
label="DB Key">
|
||||
{{ props.row.dbkey }}
|
||||
</b-table-column>
|
||||
<b-table-column field="delay"
|
||||
label="Delay">
|
||||
{{ props.row.delay }} second(s)
|
||||
</b-table-column>
|
||||
<b-table-column field="changes"
|
||||
label="Pending Changes">
|
||||
{{ props.row.changes }}
|
||||
</b-table-column>
|
||||
<b-table-column field="status"
|
||||
label="Status"
|
||||
:class="props.row.status == 'okay' ? 'has-background-success' : 'has-background-warning'">
|
||||
{{ props.row.status }}
|
||||
</b-table-column>
|
||||
</template>
|
||||
</b-table>
|
||||
</b-field>
|
||||
</%def>
|
||||
|
||||
<%def name="modify_this_page_vars()">
|
||||
<script type="text/javascript">
|
||||
|
||||
ThisPageData.restartingProcess = false
|
||||
ThisPageData.watchers = ${json.dumps(watcher_data)|n}
|
||||
ThisPageData.consumers = ${json.dumps(consumer_data)|n}
|
||||
|
||||
ThisPage.methods.restartProcess = function() {
|
||||
this.restartingProcess = true
|
||||
}
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
|
||||
${parent.body()}
|
|
@ -127,6 +127,8 @@ def raw_datetime(config, value, verbose=False, as_date=False):
|
|||
if not value:
|
||||
return ''
|
||||
|
||||
app = config.get_app()
|
||||
|
||||
# Make sure we're dealing with a tz-aware value. If we're given a naive
|
||||
# value, we assume it to be local to the UTC timezone.
|
||||
if not value.tzinfo:
|
||||
|
@ -150,10 +152,8 @@ def raw_datetime(config, value, verbose=False, as_date=False):
|
|||
else:
|
||||
kwargs['c'] = six.text_type(value)
|
||||
|
||||
# avoid humanize error when calculating huge time diff
|
||||
time_diff = None
|
||||
if abs(time_ago.days) < 100000:
|
||||
time_diff = humanize.naturaltime(time_ago)
|
||||
time_diff = app.render_time_ago(time_ago, fallback=None)
|
||||
if time_diff is not None:
|
||||
|
||||
# by "verbose" we mean the result text to look like "YYYY-MM-DD (X days ago)"
|
||||
if verbose:
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2021 Lance Edgar
|
||||
# Copyright © 2010-2022 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -31,11 +31,15 @@ import json
|
|||
import subprocess
|
||||
import logging
|
||||
|
||||
import six
|
||||
import sqlalchemy as sa
|
||||
|
||||
from rattail.db import model
|
||||
from rattail.datasync.config import load_profiles
|
||||
from rattail.datasync.util import purge_datasync_settings
|
||||
from rattail.util import simple_error
|
||||
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.util import raw_datetime
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -49,11 +53,12 @@ class DataSyncThreadView(MasterView):
|
|||
index view, with status for each, sort of akin to "dashboard".
|
||||
For now it only serves the config view.
|
||||
"""
|
||||
normalized_model_name = 'datasyncthread'
|
||||
model_title = "DataSync Thread"
|
||||
model_title_plural = "DataSync Daemon"
|
||||
model_key = 'key'
|
||||
route_prefix = 'datasync'
|
||||
url_prefix = '/datasync'
|
||||
listable = False
|
||||
viewable = False
|
||||
creatable = False
|
||||
editable = False
|
||||
|
@ -68,26 +73,122 @@ class DataSyncThreadView(MasterView):
|
|||
'key',
|
||||
]
|
||||
|
||||
def __init__(self, request, context=None):
|
||||
super(DataSyncThreadView, self).__init__(request, context=context)
|
||||
app = self.get_rattail_app()
|
||||
self.datasync_handler = app.get_datasync_handler()
|
||||
|
||||
def status(self):
|
||||
"""
|
||||
View to list/filter/sort the model data.
|
||||
|
||||
If this view receives a non-empty 'partial' parameter in the query
|
||||
string, then the view will return the rendered grid only. Otherwise
|
||||
returns the full page.
|
||||
"""
|
||||
app = self.get_rattail_app()
|
||||
model = self.model
|
||||
|
||||
try:
|
||||
process_info = self.datasync_handler.get_supervisor_process_info()
|
||||
supervisor_error = None
|
||||
except Exception as error:
|
||||
process_info = None
|
||||
supervisor_error = simple_error(error)
|
||||
|
||||
profiles = self.datasync_handler.get_configured_profiles()
|
||||
|
||||
sql = """
|
||||
select source, consumer, count(*) as changes
|
||||
from datasync_change
|
||||
group by source, consumer
|
||||
"""
|
||||
result = self.Session.execute(sql)
|
||||
all_changes = {}
|
||||
for row in result:
|
||||
all_changes[(row.source, row.consumer)] = row.changes
|
||||
|
||||
watcher_data = []
|
||||
consumer_data = []
|
||||
now = app.localtime()
|
||||
for key, profile in six.iteritems(profiles):
|
||||
watcher = profile.watcher
|
||||
|
||||
lastrun = self.datasync_handler.get_watcher_lastrun(
|
||||
watcher.key, local=True, session=self.Session())
|
||||
|
||||
status = "okay"
|
||||
if (now - lastrun).total_seconds() >= (watcher.delay * 2):
|
||||
status = "dead watcher"
|
||||
|
||||
watcher_data.append({
|
||||
'key': watcher.key,
|
||||
'spec': profile.watcher_spec,
|
||||
'dbkey': watcher.dbkey,
|
||||
'delay': watcher.delay,
|
||||
'lastrun': raw_datetime(self.rattail_config, lastrun, verbose=True),
|
||||
'status': status,
|
||||
})
|
||||
|
||||
for consumer in profile.consumers:
|
||||
if consumer.watcher is watcher:
|
||||
|
||||
changes = all_changes.get((watcher.key, consumer.key), 0)
|
||||
if changes:
|
||||
oldest = self.Session.query(sa.func.min(model.DataSyncChange.obtained))\
|
||||
.filter(model.DataSyncChange.source == watcher.key)\
|
||||
.filter(model.DataSyncChange.consumer == consumer.key)\
|
||||
.scalar()
|
||||
oldest = app.localtime(oldest, from_utc=True)
|
||||
changes = "{} (oldest from {})".format(
|
||||
changes,
|
||||
app.render_time_ago(now - oldest))
|
||||
|
||||
status = "okay"
|
||||
if changes:
|
||||
status = "processing changes"
|
||||
|
||||
consumer_data.append({
|
||||
'key': '{} -> {}'.format(watcher.key, consumer.key),
|
||||
'spec': consumer.spec,
|
||||
'dbkey': consumer.dbkey,
|
||||
'delay': consumer.delay,
|
||||
'changes': changes,
|
||||
'status': status,
|
||||
})
|
||||
|
||||
watcher_data.sort(key=lambda w: w['key'])
|
||||
consumer_data.sort(key=lambda c: c['key'])
|
||||
|
||||
context = {
|
||||
'index_title': "DataSync Status",
|
||||
'index_url': None,
|
||||
'process_info': process_info,
|
||||
'supervisor_error': supervisor_error,
|
||||
'watcher_data': watcher_data,
|
||||
'consumer_data': consumer_data,
|
||||
}
|
||||
return self.render_to_response('status', context)
|
||||
|
||||
def get_data(self, session=None):
|
||||
data = []
|
||||
return data
|
||||
|
||||
def restart(self):
|
||||
cmd = self.rattail_config.getlist('tailbone', 'datasync.restart',
|
||||
# nb. simulate by default
|
||||
default='/bin/sleep 3')
|
||||
log.debug("attempting datasync restart with command: %s", cmd)
|
||||
result = subprocess.call(cmd)
|
||||
if result == 0:
|
||||
try:
|
||||
self.datasync_handler.restart_supervisor_process()
|
||||
self.request.session.flash("DataSync daemon has been restarted.")
|
||||
else:
|
||||
self.request.session.flash("DataSync daemon could not be restarted; result was: {}".format(result), 'error')
|
||||
return self.redirect(self.request.get_referrer(default=self.request.route_url('datasyncchanges')))
|
||||
|
||||
except Exception as error:
|
||||
self.request.session.flash(simple_error(error), 'error')
|
||||
|
||||
return self.redirect(self.request.get_referrer(
|
||||
default=self.request.route_url('datasyncchanges')))
|
||||
|
||||
def configure_get_context(self):
|
||||
profiles = load_profiles(self.rattail_config,
|
||||
include_disabled=True,
|
||||
ignore_problems=True)
|
||||
profiles = self.datasync_handler.get_configured_profiles(
|
||||
include_disabled=True,
|
||||
ignore_problems=True)
|
||||
|
||||
profiles_data = []
|
||||
for profile in sorted(profiles.values(), key=lambda p: p.key):
|
||||
|
@ -125,7 +226,12 @@ class DataSyncThreadView(MasterView):
|
|||
return {
|
||||
'profiles': profiles,
|
||||
'profiles_data': profiles_data,
|
||||
'restart_command': self.rattail_config.get('tailbone', 'datasync.restart'),
|
||||
'use_profile_settings': self.rattail_config.getbool(
|
||||
'rattail.datasync', 'use_profile_settings'),
|
||||
'supervisor_process_name': self.rattail_config.get(
|
||||
'rattail.datasync', 'supervisor_process_name'),
|
||||
'restart_command': self.rattail_config.get(
|
||||
'tailbone', 'datasync.restart'),
|
||||
'system_user': getpass.getuser(),
|
||||
}
|
||||
|
||||
|
@ -133,58 +239,67 @@ class DataSyncThreadView(MasterView):
|
|||
settings = []
|
||||
watch = []
|
||||
|
||||
for profile in json.loads(data['profiles']):
|
||||
pkey = profile['key']
|
||||
if profile['enabled']:
|
||||
watch.append(pkey)
|
||||
use_profile_settings = data.get('use_profile_settings') == 'true'
|
||||
settings.append({'name': 'rattail.datasync.use_profile_settings',
|
||||
'value': 'true' if use_profile_settings else 'false'})
|
||||
|
||||
settings.extend([
|
||||
{'name': 'rattail.datasync.{}.watcher'.format(pkey),
|
||||
'value': profile['watcher_spec']},
|
||||
{'name': 'rattail.datasync.{}.watcher.db'.format(pkey),
|
||||
'value': profile['watcher_dbkey']},
|
||||
{'name': 'rattail.datasync.{}.watcher.delay'.format(pkey),
|
||||
'value': profile['watcher_delay']},
|
||||
{'name': 'rattail.datasync.{}.watcher.retry_attempts'.format(pkey),
|
||||
'value': profile['watcher_retry_attempts']},
|
||||
{'name': 'rattail.datasync.{}.watcher.retry_delay'.format(pkey),
|
||||
'value': profile['watcher_retry_delay']},
|
||||
{'name': 'rattail.datasync.{}.consumers.runas'.format(pkey),
|
||||
'value': profile['watcher_default_runas']},
|
||||
])
|
||||
if use_profile_settings:
|
||||
|
||||
consumers = []
|
||||
if profile['watcher_consumes_self']:
|
||||
consumers = ['self']
|
||||
else:
|
||||
for profile in json.loads(data['profiles']):
|
||||
pkey = profile['key']
|
||||
if profile['enabled']:
|
||||
watch.append(pkey)
|
||||
|
||||
for consumer in profile['consumers_data']:
|
||||
ckey = consumer['key']
|
||||
if consumer['enabled']:
|
||||
consumers.append(ckey)
|
||||
settings.extend([
|
||||
{'name': 'rattail.datasync.{}.consumer.{}'.format(pkey, ckey),
|
||||
'value': consumer['consumer_spec']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.db'.format(pkey, ckey),
|
||||
'value': consumer['consumer_dbkey']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.delay'.format(pkey, ckey),
|
||||
'value': consumer['consumer_delay']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.retry_attempts'.format(pkey, ckey),
|
||||
'value': consumer['consumer_retry_attempts']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.retry_delay'.format(pkey, ckey),
|
||||
'value': consumer['consumer_retry_delay']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.runas'.format(pkey, ckey),
|
||||
'value': consumer['consumer_runas']},
|
||||
])
|
||||
settings.extend([
|
||||
{'name': 'rattail.datasync.{}.watcher'.format(pkey),
|
||||
'value': profile['watcher_spec']},
|
||||
{'name': 'rattail.datasync.{}.watcher.db'.format(pkey),
|
||||
'value': profile['watcher_dbkey']},
|
||||
{'name': 'rattail.datasync.{}.watcher.delay'.format(pkey),
|
||||
'value': profile['watcher_delay']},
|
||||
{'name': 'rattail.datasync.{}.watcher.retry_attempts'.format(pkey),
|
||||
'value': profile['watcher_retry_attempts']},
|
||||
{'name': 'rattail.datasync.{}.watcher.retry_delay'.format(pkey),
|
||||
'value': profile['watcher_retry_delay']},
|
||||
{'name': 'rattail.datasync.{}.consumers.runas'.format(pkey),
|
||||
'value': profile['watcher_default_runas']},
|
||||
])
|
||||
|
||||
settings.extend([
|
||||
{'name': 'rattail.datasync.{}.consumers'.format(pkey),
|
||||
'value': ', '.join(consumers)},
|
||||
])
|
||||
consumers = []
|
||||
if profile['watcher_consumes_self']:
|
||||
consumers = ['self']
|
||||
else:
|
||||
|
||||
if watch:
|
||||
settings.append({'name': 'rattail.datasync.watch',
|
||||
'value': ', '.join(watch)})
|
||||
for consumer in profile['consumers_data']:
|
||||
ckey = consumer['key']
|
||||
if consumer['enabled']:
|
||||
consumers.append(ckey)
|
||||
settings.extend([
|
||||
{'name': 'rattail.datasync.{}.consumer.{}'.format(pkey, ckey),
|
||||
'value': consumer['consumer_spec']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.db'.format(pkey, ckey),
|
||||
'value': consumer['consumer_dbkey']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.delay'.format(pkey, ckey),
|
||||
'value': consumer['consumer_delay']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.retry_attempts'.format(pkey, ckey),
|
||||
'value': consumer['consumer_retry_attempts']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.retry_delay'.format(pkey, ckey),
|
||||
'value': consumer['consumer_retry_delay']},
|
||||
{'name': 'rattail.datasync.{}.consumer.{}.runas'.format(pkey, ckey),
|
||||
'value': consumer['consumer_runas']},
|
||||
])
|
||||
|
||||
settings.extend([
|
||||
{'name': 'rattail.datasync.{}.consumers'.format(pkey),
|
||||
'value': ', '.join(consumers)},
|
||||
])
|
||||
|
||||
if watch:
|
||||
settings.append({'name': 'rattail.datasync.watch',
|
||||
'value': ', '.join(watch)})
|
||||
|
||||
settings.append({'name': 'rattail.datasync.supervisor_process_name',
|
||||
'value': data['supervisor_process_name']})
|
||||
|
||||
settings.append({'name': 'tailbone.datasync.restart',
|
||||
'value': data['restart_command']})
|
||||
|
@ -204,6 +319,25 @@ class DataSyncThreadView(MasterView):
|
|||
permission_prefix = cls.get_permission_prefix()
|
||||
route_prefix = cls.get_route_prefix()
|
||||
url_prefix = cls.get_url_prefix()
|
||||
index_title = cls.get_index_title()
|
||||
|
||||
# view status
|
||||
config.add_tailbone_permission(permission_prefix,
|
||||
'{}.status'.format(permission_prefix),
|
||||
"View status for DataSync daemon")
|
||||
# nb. simple 'datasync' route points to 'datasync.status' for now..
|
||||
config.add_route(route_prefix,
|
||||
'{}/status/'.format(url_prefix))
|
||||
config.add_route('{}.status'.format(route_prefix),
|
||||
'{}/status/'.format(url_prefix))
|
||||
config.add_view(cls, attr='status',
|
||||
route_name=route_prefix,
|
||||
permission='{}.status'.format(permission_prefix))
|
||||
config.add_view(cls, attr='status',
|
||||
route_name='{}.status'.format(route_prefix),
|
||||
permission='{}.status'.format(permission_prefix))
|
||||
config.add_tailbone_index_page(route_prefix, index_title,
|
||||
'{}.status'.format(permission_prefix))
|
||||
|
||||
# restart
|
||||
config.add_tailbone_permission(permission_prefix,
|
||||
|
|
Loading…
Reference in a new issue