package: Remove old package installation methods

This commit is contained in:
Sunil Mohan Adapa 2016-02-12 21:03:17 +05:30
parent 60c4c17f94
commit 1f5fa31e53
No known key found for this signature in database
GPG Key ID: 36C361440C9BC971
4 changed files with 2 additions and 287 deletions

View File

@ -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()

View File

@ -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."""

View File

@ -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 %}

View File

@ -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'