Implement OS update control

This commit is contained in:
Disassembler 2021-01-24 11:27:06 +01:00
parent f3a7e2d832
commit f961f75784
No known key found for this signature in database
GPG Key ID: 524BD33A0EE29499
5 changed files with 55 additions and 4 deletions

View File

@ -15,6 +15,7 @@ from spoc.image import Image
from . import config, crypto, net, paths, templates from . import config, crypto, net, paths, templates
BIN_ACME_SH = '/usr/bin/acme.sh' BIN_ACME_SH = '/usr/bin/acme.sh'
BIN_APK = '/sbin/apk'
BIN_BLKID = '/sbin/blkid' BIN_BLKID = '/sbin/blkid'
BIN_CRYPTSETUP = '/sbin/cryptsetup' BIN_CRYPTSETUP = '/sbin/cryptsetup'
BIN_NGINX = '/usr/sbin/nginx' BIN_NGINX = '/usr/sbin/nginx'
@ -149,6 +150,17 @@ def install_manual_cert(public_file, private_file):
# Reload nginx # Reload nginx
reload_nginx() reload_nginx()
def check_for_vm_updates():
try:
lines = subprocess.run([BIN_APK, '--no-cache', 'upgrade', '-s'], check=True, stdout=subprocess.PIPE).stdout.decode().splitlines()
# 4 lines means we've got just repo list and total size
return len(lines) > 4
except subprocess.CalledProcessError:
return False
def update_vm():
subprocess.run([BIN_APK, '--no-cache', 'upgrade'], check=True)
def shutdown_vm(): def shutdown_vm():
subprocess.run([BIN_POWEROFF]) subprocess.run([BIN_POWEROFF])

View File

@ -60,6 +60,7 @@ class WSGIApp:
Rule('/uninstall-app', endpoint='uninstall_app_action'), Rule('/uninstall-app', endpoint='uninstall_app_action'),
Rule('/update-app', endpoint='update_app_action'), Rule('/update-app', endpoint='update_app_action'),
Rule('/update-password', endpoint='update_password_action'), Rule('/update-password', endpoint='update_password_action'),
Rule('/update-vm', endpoint='update_vm_action'),
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'),
Rule('/update-ssh-keys', endpoint='update_ssh_keys_action'), Rule('/update-ssh-keys', endpoint='update_ssh_keys_action'),
@ -179,7 +180,8 @@ class WSGIApp:
message = self.get_session_message(request) message = self.get_session_message(request)
repo_conf = vmmgr.get_repo_conf() repo_conf = vmmgr.get_repo_conf()
common = config.get_common() common = config.get_common()
return self.render_html('setup-apps.html', request, repo_conf=repo_conf, repo_error=repo_error, table=table, message=message, common=common) has_vm_updates = False if self.demo else vmmgr.check_for_vm_updates()
return self.render_html('setup-apps.html', request, repo_conf=repo_conf, repo_error=repo_error, table=table, message=message, common=common, has_vm_updates=has_vm_updates)
def render_setup_apps_table(self, request): def render_setup_apps_table(self, request):
lang = request.session.lang lang = request.session.lang
@ -456,6 +458,17 @@ class WSGIApp:
return self.render_json({'error': request.session.lang.bad_password()}) return self.render_json({'error': request.session.lang.bad_password()})
return self.render_json({'ok': request.session.lang.password_changed()}) return self.render_json({'ok': request.session.lang.password_changed()})
def update_vm_action(self, request):
# Do nothing in demo
if self.demo:
return self.render_json({'error': request.session.lang.not_available_in_demo()})
# Updates VM
try:
vmmgr.update_vm()
except subprocess.CalledProcessError:
return self.render_json({'error': request.session.lang.vm_update_failed()})
return self.render_json({'ok': request.session.lang.vm_updated()})
def reboot_vm_action(self, request): def reboot_vm_action(self, request):
# Do nothing in demo # Do nothing in demo
if self.demo: if self.demo:

View File

@ -55,6 +55,8 @@ class WSGILang:
'ssh_keys_installed': 'SSH klíče byly úspěšně změněny.', 'ssh_keys_installed': 'SSH klíče byly úspěšně změněny.',
'vpn_updated': 'Nastavení VPN bylo úspěšně změněno.', 'vpn_updated': 'Nastavení VPN bylo úspěšně změněno.',
'not_available_in_demo': 'Tato funkce není v demo verzi povolena', 'not_available_in_demo': 'Tato funkce není v demo verzi povolena',
'vm_updated': 'Balíky úspěšně aktualizovány. Pro dokončení aktualizace restartujte virtuální stroj.',
'vm_update_failed': 'Došlo k chybě při aktualizaci balíků. Zkuste restartovat virtuální stroj a akci opakovat.',
} }
def __getattr__(self, key): def __getattr__(self, key):

View File

@ -18,6 +18,7 @@ $(function() {
.on('click', '.app-update', update_app) .on('click', '.app-update', update_app)
.on('click', '.app-clear-status', clear_app_status); .on('click', '.app-clear-status', clear_app_status);
$('#update-password').on('submit', update_password); $('#update-password').on('submit', update_password);
$('#update-vm').on('click', update_vm);
$('#reboot-vm').on('click', reboot_vm); $('#reboot-vm').on('click', reboot_vm);
$('#shutdown-vm').on('click', shutdown_vm); $('#shutdown-vm').on('click', shutdown_vm);
if ($('#app-manager').length) { if ($('#app-manager').length) {
@ -206,9 +207,25 @@ function update_password() {
function _do_vm(action) { function _do_vm(action) {
$.get('/'+action+'-vm', function(data) { $.get('/'+action+'-vm', function(data) {
if (data.error) { if (data.error) {
$('#vm-message').attr('class','error').html(data.error).show(); $('#power-vm-message').attr('class','error').html(data.error).show();
} else { } else {
$('#vm-message').attr('class','info').html(data.ok).show(); $('#power-vm-message').attr('class','info').html(data.ok).show();
}
}).fail(lost_connection_alert);
}
function update_vm() {
$('#update-vm').hide();
$('#update-vm-message').hide();
$('#update-vm-wait').show();
$.get('/update-vm', function(data) {
$('#update-vm-wait').hide();
if (data.error) {
$('#update-vm-message').attr('class','error').html(data.error).show();
$('#update-vm').show();
} else {
$('#update-vm-message').attr('class','info').html(data.ok).show();
$('#update-vm').show().prop('disabled', true);
} }
}).fail(lost_connection_alert); }).fail(lost_connection_alert);
} }

View File

@ -107,9 +107,16 @@
</tr> </tr>
</table> </table>
</form> </form>
<p>Aktualizace balíků operačního systému virtuálního stroje.</p>
<input type="button" id="update-vm" value="Aktualizovat balíky"{% if not has_vm_updates %} disabled{% endif %}>
<div id="update-vm-message" class="{% if has_vm_updates %}error{% else %}info{% endif %}">{% if has_vm_updates %}Jsou k dispozici aktualizace{% else %}Balíky jsou aktuální{% endif %}</div>
<div id="update-vm-wait" class="loader-wrap">
<div class="loader"></div>
<span>Provádí se aktualizace balíků, prosím čekejte...</span>
</div>
<p>Restartování nebo vypnutí virtuálního stroje.</p> <p>Restartování nebo vypnutí virtuálního stroje.</p>
<input type="button" id="reboot-vm" value="Restartovat VM"> <input type="button" id="reboot-vm" value="Restartovat VM">
<input type="button" id="shutdown-vm" value="Vypnout VM"> <input type="button" id="shutdown-vm" value="Vypnout VM">
<div id="vm-message"></div> <div id="power-vm-message"></div>
</div> </div>
{% endblock %} {% endblock %}