mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-07-29 12:09:37 +00:00
package: Remove old package installation methods
This commit is contained in:
parent
60c4c17f94
commit
1f5fa31e53
@ -19,13 +19,9 @@
|
||||
Framework for installing and updating distribution packages
|
||||
"""
|
||||
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext as _
|
||||
import functools
|
||||
import logging
|
||||
import threading
|
||||
|
||||
import plinth
|
||||
from plinth.utils import import_from_gi
|
||||
glib = import_from_gi('GLib', '2.0')
|
||||
packagekit = import_from_gi('PackageKitGlib', '1.0')
|
||||
@ -55,15 +51,12 @@ class PackageException(Exception):
|
||||
class Transaction(object):
|
||||
"""Information about an ongoing transaction."""
|
||||
|
||||
def __init__(self, package_names, before_install=None, on_install=None):
|
||||
def __init__(self, package_names):
|
||||
"""Initialize transaction object.
|
||||
|
||||
Set most values to None until they are sent as progress update.
|
||||
"""
|
||||
self.package_names = package_names
|
||||
# XXX: This is hack, remove after implementing proper setup mechanism.
|
||||
self.before_install = before_install
|
||||
self.on_install = on_install
|
||||
|
||||
# Progress
|
||||
self.allow_cancel = None
|
||||
@ -79,10 +72,6 @@ class Transaction(object):
|
||||
self.download_size_remaining = None
|
||||
self.speed = None
|
||||
|
||||
# Completion
|
||||
self.is_finished = False
|
||||
self.exception = None
|
||||
|
||||
def get_id(self):
|
||||
"""Return a identifier to use as a key in a map of transactions."""
|
||||
return frozenset(self.package_names)
|
||||
@ -94,43 +83,12 @@ class Transaction(object):
|
||||
self.package_names, self.allow_cancel, self.status_string,
|
||||
self.percentage, self.package, self.item_progress)
|
||||
|
||||
def start_install_in_thread(self):
|
||||
"""Start a PackageKit transaction to install given list of packages.
|
||||
|
||||
This operation is non-blocking at it spawns a new thread.
|
||||
"""
|
||||
thread = threading.Thread(target=self.install)
|
||||
thread.start()
|
||||
|
||||
def install(self):
|
||||
"""Run a PackageKit transaction to install given packages."""
|
||||
try:
|
||||
if self.before_install:
|
||||
self.before_install()
|
||||
except Exception as exception:
|
||||
logger.exception('Error during setup before install - %s',
|
||||
exception)
|
||||
self.finish(exception)
|
||||
return
|
||||
|
||||
try:
|
||||
self._do_install()
|
||||
except PackageException as exception:
|
||||
self.finish(exception)
|
||||
return
|
||||
except glib.Error as exception:
|
||||
self.finish(PackageException(exception.message))
|
||||
return
|
||||
|
||||
try:
|
||||
if self.on_install:
|
||||
self.on_install()
|
||||
except Exception as exception:
|
||||
logger.exception('Error during setup - %s', exception)
|
||||
self.finish(exception)
|
||||
return
|
||||
|
||||
self.finish()
|
||||
raise PackageException(exception.message)
|
||||
|
||||
def _do_install(self):
|
||||
"""Run a PackageKit transaction to install given packages.
|
||||
@ -208,115 +166,3 @@ class Transaction(object):
|
||||
else:
|
||||
logger.info('Unhandle packagekit progress callback - %s, %s',
|
||||
progress, progress_type)
|
||||
|
||||
def finish(self, exception=None):
|
||||
"""Mark transaction as complected and store exception if any."""
|
||||
self.is_finished = True
|
||||
self.exception = exception
|
||||
|
||||
def collect_result(self):
|
||||
"""Retrieve the result of this transaction.
|
||||
|
||||
Also remove self from global transactions list.
|
||||
"""
|
||||
assert self.is_finished
|
||||
|
||||
del transactions[self.get_id()]
|
||||
return self.exception
|
||||
|
||||
|
||||
def required(package_names, before_install=None, on_install=None):
|
||||
"""Decorate a view to check and install required packages."""
|
||||
|
||||
def wrapper2(func):
|
||||
"""Return a function to check and install packages."""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
"""Check and install packages required by a view."""
|
||||
if not _should_show_install_view(request, package_names):
|
||||
return func(request, *args, **kwargs)
|
||||
|
||||
view = plinth.views.PackageInstallView.as_view()
|
||||
return view(request, package_names=package_names,
|
||||
before_install=before_install, on_install=on_install,
|
||||
*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return wrapper2
|
||||
|
||||
|
||||
def _should_show_install_view(request, package_names):
|
||||
"""Return whether the installation view should be shown."""
|
||||
transaction_id = frozenset(package_names)
|
||||
|
||||
# No transaction in progress
|
||||
if transaction_id not in transactions:
|
||||
is_installed = check_installed(package_names)
|
||||
return not is_installed
|
||||
|
||||
# Installing
|
||||
transaction = transactions[transaction_id]
|
||||
if not transaction.is_finished:
|
||||
return True
|
||||
|
||||
# Transaction finished, waiting to show the result
|
||||
exception = transaction.collect_result()
|
||||
if not exception:
|
||||
messages.success(request,
|
||||
_('Installed and configured packages successfully.'))
|
||||
return False
|
||||
else:
|
||||
error_string = getattr(exception, 'error_string', str(exception))
|
||||
error_details = getattr(exception, 'error_details', '')
|
||||
messages.error(request, _('Error installing packages: {string} {details}')
|
||||
.format(string=error_string, details=error_details))
|
||||
return True
|
||||
|
||||
|
||||
def check_installed(package_names):
|
||||
"""Return a boolean installed status of package.
|
||||
|
||||
This operation is blocking and waits until the check is finished.
|
||||
"""
|
||||
def _callback(progress, progress_type, user_data):
|
||||
"""Process progress updates on package resolve operation."""
|
||||
pass
|
||||
|
||||
client = packagekit.Client()
|
||||
response = client.resolve(packagekit.FilterEnum.INSTALLED,
|
||||
tuple(package_names) + (None, ), None,
|
||||
_callback, None)
|
||||
|
||||
installed_package_names = []
|
||||
for package in response.get_package_array():
|
||||
if package.get_info() == packagekit.InfoEnum.INSTALLED:
|
||||
installed_package_names.append(package.get_name())
|
||||
|
||||
packages_resolved[package.get_name()] = package
|
||||
|
||||
# When package names could not be resolved
|
||||
for package_name in package_names:
|
||||
if package_name not in packages_resolved:
|
||||
packages_resolved[package_name] = None
|
||||
|
||||
return set(installed_package_names) == set(package_names)
|
||||
|
||||
|
||||
def is_installing(package_names):
|
||||
"""Return whether a set of packages are currently being installed."""
|
||||
return frozenset(package_names) in transactions
|
||||
|
||||
|
||||
def start_install(package_names, before_install=None, on_install=None):
|
||||
"""Start a PackageKit transaction to install given list of packages.
|
||||
|
||||
This operation is non-blocking at it spawns a new thread.
|
||||
"""
|
||||
transaction = Transaction(package_names,
|
||||
before_install=before_install,
|
||||
on_install=on_install)
|
||||
transactions[frozenset(package_names)] = transaction
|
||||
|
||||
transaction.start_install_in_thread()
|
||||
|
||||
@ -98,9 +98,6 @@ class Helper(object):
|
||||
}
|
||||
|
||||
transaction.install()
|
||||
if transaction.exception:
|
||||
logger.error('Error running install - %s', transaction.exception)
|
||||
raise transaction.exception
|
||||
|
||||
def call(self, step, method, *args, **kwargs):
|
||||
"""Call an arbitrary method during setup and note down its stage."""
|
||||
|
||||
@ -1,94 +0,0 @@
|
||||
{% 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 %}
|
||||
|
||||
{% load bootstrap %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block page_head %}
|
||||
|
||||
{% if is_installing %}
|
||||
<meta http-equiv="refresh" content="3" />
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
<h2>{% trans "Installation" %}</h2>
|
||||
|
||||
{% if not is_installing %}
|
||||
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
This feature requires addtional packages to be installed. Do
|
||||
you wish to install them?
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans "Package" %}</th>
|
||||
<th>{% trans "Summary" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for package_name, package in packages.items %}
|
||||
<tr>
|
||||
<td>{{ package_name }}</td>
|
||||
<td>{{ package.get_summary }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
<input type="submit" class="btn btn-md btn-primary"
|
||||
value="{% trans "Install" %}" />
|
||||
</form>
|
||||
|
||||
{% else %}
|
||||
|
||||
{% for key, transaction in transactions.items %}
|
||||
<div>
|
||||
{% blocktrans trimmed with package_names=transaction.package_names|join:", " status=transaction.status_string %}
|
||||
Installing {{ package_names }}: {{ status }}
|
||||
{% endblocktrans %}
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped active"
|
||||
role="progressbar" aria-valuemin="0" aria-valuemax="100"
|
||||
aria-valuenow="{{ transaction.percentage }}"
|
||||
style="width: {{ transaction.percentage }}%">
|
||||
<span class="sr-only">
|
||||
{% blocktrans trimmed with percentage=transaction.percentage %}
|
||||
{{ percentage }}% complete
|
||||
{% endblocktrans %}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
||||
@ -24,46 +24,12 @@ from django.http.response import HttpResponseRedirect
|
||||
from django.views.generic import TemplateView
|
||||
import time
|
||||
|
||||
from plinth import package as package_module
|
||||
|
||||
|
||||
def index(request):
|
||||
"""Serve the main index page."""
|
||||
return HttpResponseRedirect(reverse('apps:index'))
|
||||
|
||||
|
||||
class PackageInstallView(TemplateView):
|
||||
"""View to prompt and install packages."""
|
||||
template_name = 'package_install.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Return the context data rendering the template."""
|
||||
context = super(PackageInstallView, self).get_context_data(**kwargs)
|
||||
|
||||
if 'packages_names' not in context:
|
||||
context['package_names'] = self.kwargs.get('package_names', [])
|
||||
context['packages'] = {
|
||||
package_name: package_module.packages_resolved[package_name]
|
||||
for package_name in context['package_names']}
|
||||
context['is_installing'] = \
|
||||
package_module.is_installing(context['package_names'])
|
||||
context['transactions'] = package_module.transactions
|
||||
|
||||
return context
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
"""Handle installing packages
|
||||
|
||||
Start the package installation, and refresh the page every x seconds to
|
||||
keep displaying PackageInstallView.get() with the installation status.
|
||||
"""
|
||||
package_module.start_install(
|
||||
self.kwargs['package_names'],
|
||||
before_install=self.kwargs.get('before_install'),
|
||||
on_install=self.kwargs.get('on_install'))
|
||||
return self.render_to_response(self.get_context_data())
|
||||
|
||||
|
||||
class SetupView(TemplateView):
|
||||
"""View to prompt and setup applications."""
|
||||
template_name = 'setup.html'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user