Implement resilient register_app config reload
This commit is contained in:
parent
deb56f0c7b
commit
84ccc2bd84
@ -9,9 +9,10 @@ subparsers = parser.add_subparsers()
|
|||||||
|
|
||||||
parser_register_app = subparsers.add_parser('register-app')
|
parser_register_app = subparsers.add_parser('register-app')
|
||||||
parser_register_app.set_defaults(action='register-app')
|
parser_register_app.set_defaults(action='register-app')
|
||||||
parser_register_app.add_argument('app')
|
parser_register_app.add_argument('app', help='Application name')
|
||||||
parser_register_app.add_argument('login', nargs='?')
|
parser_register_app.add_argument('host', help='Application subdomain')
|
||||||
parser_register_app.add_argument('password', nargs='?')
|
parser_register_app.add_argument('login', nargs='?', help='Admin login')
|
||||||
|
parser_register_app.add_argument('password', nargs='?', help='Admin password')
|
||||||
|
|
||||||
parser_rebuild_issue = subparsers.add_parser('rebuild-issue')
|
parser_rebuild_issue = subparsers.add_parser('rebuild-issue')
|
||||||
parser_rebuild_issue.set_defaults(action='rebuild-issue')
|
parser_rebuild_issue.set_defaults(action='rebuild-issue')
|
||||||
@ -43,7 +44,7 @@ vmmgr = VMMgr(conf)
|
|||||||
lxcmgr = LXCMgr(conf)
|
lxcmgr = LXCMgr(conf)
|
||||||
if args.action == 'register-app':
|
if args.action == 'register-app':
|
||||||
# Used by app install scripts
|
# Used by app install scripts
|
||||||
vmmgr.register_app(args.app, args.login, args.password)
|
vmmgr.register_app(args.app, args.host, args.login, args.password)
|
||||||
elif args.action == 'rebuild-issue':
|
elif args.action == 'rebuild-issue':
|
||||||
# Used on VM startup
|
# Used on VM startup
|
||||||
vmmgr.rebuild_issue()
|
vmmgr.rebuild_issue()
|
||||||
|
@ -70,15 +70,18 @@ class AppMgr:
|
|||||||
with subprocess.Popen(['apk', '--progress-fd', str(pipe_wfd), '--no-cache', 'add', 'vm-{}@vm'.format(item.key)], pass_fds=[pipe_wfd]) as p:
|
with subprocess.Popen(['apk', '--progress-fd', str(pipe_wfd), '--no-cache', 'add', 'vm-{}@vm'.format(item.key)], pass_fds=[pipe_wfd]) as p:
|
||||||
while p.poll() == None:
|
while p.poll() == None:
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
# Read pipe
|
||||||
data = b''
|
data = b''
|
||||||
while True:
|
while True:
|
||||||
chunk = os.read(pipe_rfd, 8192)
|
chunk = os.read(pipe_rfd, 8192)
|
||||||
data += chunk
|
data += chunk
|
||||||
if len(chunk) < 8192:
|
if len(chunk) < 8192:
|
||||||
break
|
break
|
||||||
|
# Parse last apk progress line
|
||||||
progress = data.decode().splitlines()[-1].split('/')
|
progress = data.decode().splitlines()[-1].split('/')
|
||||||
item.data.bytes_downloaded = progress[0]
|
item.data.bytes_downloaded = progress[0]
|
||||||
item.data.bytes_total = progress[1]
|
item.data.bytes_total = progress[1]
|
||||||
|
# Close pipe
|
||||||
os.close(pipe_rfd)
|
os.close(pipe_rfd)
|
||||||
os.close(pipe_wfd)
|
os.close(pipe_wfd)
|
||||||
|
|
||||||
|
@ -17,12 +17,18 @@ class VMMgr:
|
|||||||
self.domain = conf['host']['domain']
|
self.domain = conf['host']['domain']
|
||||||
self.port = conf['host']['port']
|
self.port = conf['host']['port']
|
||||||
|
|
||||||
def register_app(self, app, login, password):
|
def register_app(self, app, host, login, password):
|
||||||
# Register newly installed application and its credentials
|
# Register newly installed application, its subdomain and credentials
|
||||||
self.conf['apps'][app] = {'login': login if login else 'N/A',
|
self.conf['apps'][app] = {'host': host,
|
||||||
|
'login': login if login else 'N/A',
|
||||||
'password': password if password else 'N/A',
|
'password': password if password else 'N/A',
|
||||||
'visible': False}
|
'visible': False}
|
||||||
self.conf.save()
|
self.conf.save()
|
||||||
|
# Attempt to contact running vmmgr WSGI application to reload config
|
||||||
|
try:
|
||||||
|
requests.get('https://127.0.0.1/reload-config', timeout=3)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
def update_host(self, domain, port):
|
def update_host(self, domain, port):
|
||||||
# Update domain and port and rebuild all configuration. Web interface calls restart_nginx() in WSGI close handler
|
# Update domain and port and rebuild all configuration. Web interface calls restart_nginx() in WSGI close handler
|
||||||
|
@ -62,6 +62,9 @@ class WSGIApp:
|
|||||||
Rule('/shutdown-vm', endpoint='shutdown_vm_action'),
|
Rule('/shutdown-vm', endpoint='shutdown_vm_action'),
|
||||||
Rule('/reboot-vm', endpoint='reboot_vm_action')
|
Rule('/reboot-vm', endpoint='reboot_vm_action')
|
||||||
))
|
))
|
||||||
|
self.localhost_url_map = Map((
|
||||||
|
Rule('/reload-config', endpoint='reload_config_action')
|
||||||
|
))
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
return self.wsgi_app(environ, start_response)
|
return self.wsgi_app(environ, start_response)
|
||||||
@ -76,7 +79,12 @@ class WSGIApp:
|
|||||||
return response(environ, start_response)
|
return response(environ, start_response)
|
||||||
|
|
||||||
def dispatch_request(self, request):
|
def dispatch_request(self, request):
|
||||||
url_map = self.admin_url_map if request.session['admin'] else self.url_map
|
if request.session['admin']:
|
||||||
|
url_map = self.admin_url_map
|
||||||
|
elif request.remote_addr in ('127.0.0.1', '::1'):
|
||||||
|
url_map = self.localhost_url_map
|
||||||
|
else:
|
||||||
|
url_map = self.url_map
|
||||||
adapter = url_map.bind_to_environ(request.environ)
|
adapter = url_map.bind_to_environ(request.environ)
|
||||||
try:
|
try:
|
||||||
endpoint, values = adapter.match()
|
endpoint, values = adapter.match()
|
||||||
@ -386,5 +394,10 @@ class WSGIApp:
|
|||||||
response.call_on_close(self.appmgr.shutdown_vm)
|
response.call_on_close(self.appmgr.shutdown_vm)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def reload_config_action(self, request):
|
||||||
|
# Reload configuration (called by vmmgr.register_app())
|
||||||
|
self.config.load()
|
||||||
|
return Response(status=204)
|
||||||
|
|
||||||
def is_app_visible(self, app):
|
def is_app_visible(self, app):
|
||||||
return app in self.conf['apps'] and self.conf['apps'][app]['visible'] and self.appmgr.is_service_started(app)
|
return app in self.conf['apps'] and self.conf['apps'][app]['visible'] and self.appmgr.is_service_started(app)
|
||||||
|
Loading…
Reference in New Issue
Block a user