mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-08-26 12:46:08 +00:00
Add upgrades module that can run unattended-upgrades.
This commit is contained in:
parent
c72c03890c
commit
80eff7fd6e
111
actions/upgrades
Executable file
111
actions/upgrades
Executable file
@ -0,0 +1,111 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- mode: python -*-
|
||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Configures or runs unattended-upgrades
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
CONF_FILE = '/etc/apt/apt.conf.d/50unattended-upgrades'
|
||||||
|
AUTO_CONF_FILE = '/etc/apt/apt.conf.d/20auto-upgrades'
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arguments():
|
||||||
|
"""REturn parsed command line arguments as dictionary"""
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')
|
||||||
|
|
||||||
|
# Run unattended-upgrades
|
||||||
|
subparsers.add_parser('run', help='Upgrade packages on the system')
|
||||||
|
|
||||||
|
# Enable automatic upgrades
|
||||||
|
subparsers.add_parser('enable-auto', help='Enable automatic upgrades')
|
||||||
|
|
||||||
|
# Disable automatic upgrades
|
||||||
|
subparsers.add_parser('disable-auto', help='Disable automatic upgrades.')
|
||||||
|
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_run(_):
|
||||||
|
"""Run unattended-upgrades"""
|
||||||
|
try:
|
||||||
|
setup()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Error: Could not configure unattended-upgrades.')
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(['unattended-upgrades', '-v'])
|
||||||
|
except subprocess.CalledProcessError as error:
|
||||||
|
print('Error: %s', error)
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Error: unattended-upgrades is not available.')
|
||||||
|
else:
|
||||||
|
print('%s', output.decode())
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_enable_auto(_):
|
||||||
|
"""Enable automatic upgrades"""
|
||||||
|
try:
|
||||||
|
setup()
|
||||||
|
except FileNotFoundError:
|
||||||
|
print('Error: Could not configure unattended-upgrades.')
|
||||||
|
return
|
||||||
|
|
||||||
|
with open(AUTO_CONF_FILE, 'w') as conffile:
|
||||||
|
conffile.write('APT::Periodic::Update-Package-Lists "1";\n')
|
||||||
|
conffile.write('APT::Periodic::Unattended-Upgrade "1";\n')
|
||||||
|
|
||||||
|
|
||||||
|
def subcommand_disable_auto(_):
|
||||||
|
"""Disable automatic upgrades"""
|
||||||
|
os.remove(AUTO_CONF_FILE)
|
||||||
|
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
"""Sets unattended-upgrades config to upgrade any package from Debian."""
|
||||||
|
with open(CONF_FILE, 'r') as conffile:
|
||||||
|
lines = conffile.readlines()
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
if '"origin=Debian";' in line:
|
||||||
|
return # already configured
|
||||||
|
|
||||||
|
with open(CONF_FILE, 'w') as conffile:
|
||||||
|
for line in lines:
|
||||||
|
conffile.write(line)
|
||||||
|
if 'Unattended-Upgrade::Origins-Pattern {' in line:
|
||||||
|
conffile.write(' "origin=Debian";\n')
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Parse arguments and perform all duties"""
|
||||||
|
arguments = parse_arguments()
|
||||||
|
|
||||||
|
subcommand = arguments.subcommand.replace('-', '_')
|
||||||
|
subcommand_method = globals()['subcommand_' + subcommand]
|
||||||
|
subcommand_method(arguments)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
1
data/etc/plinth/modules-enabled/upgrades
Normal file
1
data/etc/plinth/modules-enabled/upgrades
Normal file
@ -0,0 +1 @@
|
|||||||
|
plinth.modules.upgrades
|
||||||
27
plinth/modules/upgrades/__init__.py
Normal file
27
plinth/modules/upgrades/__init__.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Plinth module for upgrades
|
||||||
|
"""
|
||||||
|
|
||||||
|
from . import upgrades
|
||||||
|
from .upgrades import init
|
||||||
|
|
||||||
|
__all__ = ['upgrades', 'init']
|
||||||
|
|
||||||
|
depends = ['plinth.modules.system']
|
||||||
32
plinth/modules/upgrades/templates/upgrades.html
Normal file
32
plinth/modules/upgrades/templates/upgrades.html
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% comment %}
|
||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>{{ title }}</h2>
|
||||||
|
|
||||||
|
<p>This will run unattended-upgrades, which will attempt to upgrade your system
|
||||||
|
with the latest Debian packages. It may take a minute to complete.</p>
|
||||||
|
|
||||||
|
<p><a class="btn btn-primary btn-lg" href="{% url 'upgrades:run' %}">
|
||||||
|
Upgrade now »
|
||||||
|
</a></p>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
35
plinth/modules/upgrades/templates/upgrades_run.html
Normal file
35
plinth/modules/upgrades/templates/upgrades_run.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% comment %}
|
||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>{{title}}</h2>
|
||||||
|
|
||||||
|
{% if upgrades_error %}
|
||||||
|
<p>There was an error while upgrading:<p>
|
||||||
|
<pre>{{ upgrades_error }}</pre>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if upgrades_output %}
|
||||||
|
<p>Output from unattended-upgrades:</p>
|
||||||
|
<pre>{{ upgrades_output }}</pre>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
63
plinth/modules/upgrades/upgrades.py
Normal file
63
plinth/modules/upgrades/upgrades.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Plinth module for upgrades
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
from django.template.response import TemplateResponse
|
||||||
|
from gettext import gettext as _
|
||||||
|
|
||||||
|
from plinth import actions
|
||||||
|
from plinth import cfg
|
||||||
|
from plinth import package
|
||||||
|
from plinth.errors import ActionError
|
||||||
|
|
||||||
|
|
||||||
|
def init():
|
||||||
|
"""Initialize the module"""
|
||||||
|
menu = cfg.main_menu.get('system:index')
|
||||||
|
menu.add_urlname("Upgrades", "glyphicon-refresh",
|
||||||
|
"upgrades:index", 21)
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@package.required('unattended-upgrades')
|
||||||
|
def index(request):
|
||||||
|
"""Serve the index page"""
|
||||||
|
return TemplateResponse(request, 'upgrades.html',
|
||||||
|
{'title': _('Package Upgrades')})
|
||||||
|
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
@package.required('unattended-upgrades')
|
||||||
|
def run(request):
|
||||||
|
"""Run upgrades and show the output page"""
|
||||||
|
output = ''
|
||||||
|
error = ''
|
||||||
|
try:
|
||||||
|
output = actions.superuser_run('upgrades', ['run'])
|
||||||
|
except ActionError as exception:
|
||||||
|
output, error = exception.args[1:]
|
||||||
|
except Exception as exception:
|
||||||
|
error = str(exception)
|
||||||
|
|
||||||
|
return TemplateResponse(request, 'upgrades_run.html',
|
||||||
|
{'title': _('Package Upgrades'),
|
||||||
|
'upgrades_output': output,
|
||||||
|
'upgrades__error': error})
|
||||||
29
plinth/modules/upgrades/urls.py
Normal file
29
plinth/modules/upgrades/urls.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# This file is part of Plinth.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
URLs for the upgrades module
|
||||||
|
"""
|
||||||
|
|
||||||
|
from django.conf.urls import patterns, url
|
||||||
|
|
||||||
|
|
||||||
|
urlpatterns = patterns(
|
||||||
|
'plinth.modules.upgrades.upgrades',
|
||||||
|
url(r'^sys/upgrades/$', 'index', name='index'),
|
||||||
|
url(r'^sys/upgrades/run/$', 'run', name='run'),
|
||||||
|
)
|
||||||
Loading…
x
Reference in New Issue
Block a user