source: ubiquity/trunk/fuentes/ubiquity/plugins/ubi-prepare.py @ 1475

Last change on this file since 1475 was 1475, checked in by daduve, 3 years ago

Upgrading ubiquity

File size: 16.1 KB
Line 
1# -*- coding: utf-8; Mode: Python; indent-tabs-mode: nil; tab-width: 4 -*-
2
3# Copyright (C) 2013 Canonical Ltd.
4# Written by Evan Dandrea <evan.dandrea@canonical.com>
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
20from __future__ import print_function
21
22import os
23import subprocess
24import sys
25
26from ubiquity import i18n, misc, osextras, plugin, upower
27from ubiquity.install_misc import archdetect, is_secure_boot
28
29NAME = 'prepare'
30AFTER = 'wireless'
31WEIGHT = 11
32OEM = False
33
34
35# TODO: This cannot be a non-debconf plugin after all as OEMs may want to
36# preseed the 'install updates' and 'install non-free software' options.  So?
37# Just db_get them.  No need for any other overhead, surely.  Actually, you
38# need the dbfilter for that get.
39
40class PreparePageBase(plugin.PluginUI):
41    plugin_title = 'ubiquity/text/prepare_heading_label'
42
43    def __init__(self, *args, **kwargs):
44        plugin.PluginUI.__init__(self)
45
46    def plugin_set_online_state(self, state):
47        self.prepare_network_connection.set_state(state)
48        self.enable_download_updates(state)
49        if not state:
50            self.set_download_updates(False)
51
52    def set_sufficient_space(self, state, required, free):
53        if not state:
54            # There's either no drives present, or not enough free space.
55            # Either way, we cannot continue.
56            self.show_insufficient_space_page(required, free)
57            self.controller.allow_go_forward(False)
58        self.prepare_sufficient_space.set_state(state)
59
60    def plugin_translate(self, lang):
61        return
62
63
64class PageGtk(PreparePageBase):
65    restricted_package_name = 'ubuntu-restricted-addons'
66
67    def __init__(self, controller, *args, **kwargs):
68        if self.is_automatic:
69            self.page = None
70            return
71        self.controller = controller
72        from ubiquity.gtkwidgets import Builder
73        builder = Builder()
74        self.controller.add_builder(builder)
75        builder.add_from_file(os.path.join(
76            os.environ['UBIQUITY_GLADE'], 'stepPrepare.ui'))
77        builder.connect_signals(self)
78
79        # Get all objects + add internal child(s)
80        all_widgets = builder.get_object_ids()
81        for wdg in all_widgets:
82            setattr(self, wdg, builder.get_object(wdg))
83
84        self.password_strength_pages = {
85            'empty': 0,
86            'too_short': 1,
87            'good': 2,
88        }
89        self.password_match_pages = {
90            'empty': 0,
91            'mismatch': 1,
92            'ok': 2,
93        }
94
95        if upower.has_battery():
96            upower.setup_power_watch(self.prepare_power_source)
97        else:
98            self.prepare_power_source.hide()
99        self.prepare_network_connection = builder.get_object(
100            'prepare_network_connection')
101
102        self.using_secureboot = False
103
104        self.secureboot_box.set_sensitive(False)
105        self.password_grid.set_sensitive(False)
106
107        self.prepare_page = builder.get_object('stepPrepare')
108        self.insufficient_space_page = builder.get_object('stepNoSpace')
109        self.current_page = self.prepare_page
110        self.plugin_widgets = self.prepare_page
111        self.plugin_optional_widgets = [self.insufficient_space_page]
112
113    def plugin_get_current_page(self):
114        return self.current_page
115
116    def show_insufficient_space_page(self, required, free):
117        self.current_page = self.insufficient_space_page
118
119        self.label_required_space.set_label(required)
120        self.label_free_space.set_label(free)
121
122        self.controller.go_to_page(self.current_page)
123
124    def set_using_secureboot(self, secureboot):
125        self.using_secureboot = secureboot
126        self.secureboot_box.set_visible(secureboot)
127        self.on_nonfree_toggled(None)
128
129    def enable_download_updates(self, val):
130        if (val):
131            template = 'ubiquity/text/label_download_updates'
132        else:
133            template = 'ubiquity/text/label_download_updates_na'
134        self.label_download_updates.set_label(
135            self.controller.get_string(template))
136        self.prepare_download_updates.set_sensitive(val)
137
138    def set_download_updates(self, val):
139        self.prepare_download_updates.set_active(val)
140
141    def get_download_updates(self):
142        return self.prepare_download_updates.get_active()
143
144    def set_allow_nonfree(self, allow):
145        if not allow:
146            self.prepare_nonfree_software.set_active(False)
147            self.nonfree_vbox.set_property('visible', False)
148
149    def set_use_nonfree(self, val):
150        if osextras.find_on_path('ubuntu-drivers'):
151            self.prepare_nonfree_software.set_active(val)
152        else:
153            self.debug('Could not find ubuntu-drivers on the executable path.')
154            self.set_allow_nonfree(False)
155
156    def get_use_nonfree(self):
157        return self.prepare_nonfree_software.get_active()
158
159    def get_disable_secureboot(self):
160        return self.disable_secureboot.get_active()
161
162    def plugin_translate(self, lang):
163        PreparePageBase.plugin_translate(self, lang)
164        release = misc.get_release()
165
166        from gi.repository import Gtk
167        for widget in [self.prepare_download_updates,
168                       self.label_required_space,
169                       self.label_free_space]:
170            text = i18n.get_string(Gtk.Buildable.get_name(widget), lang)
171            text = text.replace('${RELEASE}', release.name)
172            widget.set_label(text)
173
174    def on_nonfree_toggled(self, widget):
175        enabled = self.get_use_nonfree()
176        self.secureboot_box.set_sensitive(enabled)
177
178    def on_secureboot_toggled(self, widget):
179        enabled = self.get_disable_secureboot()
180        self.password_grid.set_sensitive(enabled)
181        self.info_loop(None)
182
183    def info_loop(self, unused_widget):
184        complete = False
185        passw = self.password.get_text()
186        vpassw = self.verified_password.get_text()
187
188        if len(passw) == 0:
189            self.password_strength.set_current_page(
190                self.password_strength_pages['empty'])
191        elif len(passw) >= 8:
192            self.password_strength.set_current_page(
193                self.password_strength_pages['good'])
194        else:
195            self.password_strength.set_current_page(
196                self.password_strength_pages['too_short'])
197
198        if passw != vpassw or (passw and len(passw) < 8):
199            self.password_match.set_current_page(
200                self.password_match_pages['empty'])
201            if len(passw) >= 8 and (not passw.startswith(vpassw) or
202                                    len(vpassw) / len(passw) > 0.6):
203                self.password_match.set_current_page(
204                    self.password_match_pages['mismatch'])
205        else:
206            complete = True
207            self.password_match.set_current_page(
208                self.password_match_pages['ok'])
209
210        self.controller.allow_go_forward(complete)
211        return complete
212
213    def get_secureboot_key(self):
214        return self.password.get_text()
215
216    def show_learn_more(self, unused):
217        from gi.repository import Gtk
218
219        sb_title_template = 'ubiquity/text/efi_secureboot'
220        sb_info_template = 'ubiquity/text/efi_secureboot_info'
221        secureboot_title = self.controller.get_string(sb_title_template)
222        secureboot_msg = self.controller.get_string(sb_info_template)
223
224        dialog = Gtk.MessageDialog(
225            self.current_page.get_toplevel(), Gtk.DialogFlags.MODAL,
226            Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, None)
227        dialog.set_title(secureboot_title)
228        dialog.set_markup(secureboot_msg)
229        dialog.run()
230        dialog.destroy()
231
232
233class PageKde(PreparePageBase):
234    plugin_breadcrumb = 'ubiquity/text/breadcrumb_prepare'
235    restricted_package_name = 'kubuntu-restricted-addons'
236
237    def __init__(self, controller, *args, **kwargs):
238        from ubiquity.qtwidgets import StateBox
239        if self.is_automatic:
240            self.page = None
241            return
242        self.controller = controller
243        try:
244            from PyQt4 import uic
245            from PyQt4 import QtGui
246            self.page = uic.loadUi('/usr/share/ubiquity/qt/stepPrepare.ui')
247            self.prepare_download_updates = self.page.prepare_download_updates
248            self.prepare_nonfree_software = self.page.prepare_nonfree_software
249            self.prepare_foss_disclaimer = self.page.prepare_foss_disclaimer
250            self.prepare_sufficient_space = StateBox(self.page)
251            self.secureboot_label = self.page.secureboot_label
252            self.disable_secureboot = self.page.disable_secureboot
253            self.password = self.page.password
254            self.verified_password = self.page.verified_password
255            self.password_extra_label = self.page.password_extra_label
256            self.badPassword = self.page.badPassword
257            self.badPassword.setPixmap(QtGui.QPixmap(
258                "/usr/share/icons/oxygen/16x16/status/dialog-warning.png"))
259            # TODO we should set these up and tear them down while on this
260            # page.
261            try:
262                self.prepare_power_source = StateBox(self.page)
263                if upower.has_battery():
264                    upower.setup_power_watch(self.prepare_power_source)
265                else:
266                    self.prepare_power_source.hide()
267            except Exception as e:
268                # TODO use an inconsistent state?
269                print('unable to set up power source watch:', e)
270            try:
271                self.prepare_network_connection = StateBox(self.page)
272            except Exception as e:
273                print('unable to set up network connection watch:', e)
274        except Exception as e:
275            print("Could not create prepare page:", str(e), file=sys.stderr)
276            self.debug('Could not create prepare page: %s', e)
277            self.page = None
278        self.set_using_secureboot(False)
279        self.plugin_widgets = self.page
280
281    def show_insufficient_space_page(self, required, free):
282        return
283
284    def set_using_secureboot(self, secureboot):
285        self.using_secureboot = secureboot
286        self.secureboot_label.setVisible(secureboot)
287        self.disable_secureboot.setVisible(secureboot)
288        self.password.setVisible(secureboot)
289        self.verified_password.setVisible(secureboot)
290        self.password_extra_label.setVisible(secureboot)
291        self.badPassword.hide()
292        if (secureboot):
293            self.password.textChanged.connect(self.verify_password)
294            self.verified_password.textChanged.connect(self.verify_password)
295
296    # show warning if passwords do not match
297    def verify_password(self):
298        complete = False
299
300        if self.password.text() == self.verified_password.text():
301            self.badPassword.hide()
302            complete = True
303        else:
304            self.badPassword.show()
305
306        if not self.password.text():
307            complete = False
308
309        self.controller.allow_go_forward(complete)
310
311    def get_secureboot_key(self):
312        return str(self.page.password.text())
313
314    def enable_download_updates(self, val):
315        self.prepare_download_updates.setEnabled(val)
316
317    def set_download_updates(self, val):
318        self.prepare_download_updates.setChecked(val)
319
320    def get_download_updates(self):
321        from PyQt4.QtCore import Qt
322        return self.prepare_download_updates.checkState() == Qt.Checked
323
324    def set_allow_nonfree(self, allow):
325        if not allow:
326            self.prepare_nonfree_software.setChecked(False)
327            self.prepare_nonfree_software.setVisible(False)
328            self.prepare_foss_disclaimer.setVisible(False)
329
330    def set_use_nonfree(self, val):
331        if osextras.find_on_path('ubuntu-drivers'):
332            self.prepare_nonfree_software.setChecked(val)
333        else:
334            self.debug('Could not find ubuntu-drivers on the executable path.')
335            self.set_allow_nonfree(False)
336
337    def get_use_nonfree(self):
338        from PyQt4.QtCore import Qt
339        return self.prepare_nonfree_software.checkState() == Qt.Checked
340
341    def plugin_translate(self, lang):
342        PreparePageBase.plugin_translate(self, lang)
343        # gtk does the ${RELEASE} replace for the title in gtk_ui but we do
344        # it per plugin because our title widget is per plugin
345        release = misc.get_release()
346        widgets = (
347            self.page.prepare_heading_label,
348            self.page.prepare_download_updates,
349        )
350        for widget in widgets:
351            text = widget.text()
352            text = text.replace('${RELEASE}', release.name)
353            text = text.replace('Ubuntu', 'Kubuntu')
354            widget.setText(text)
355
356
357class Page(plugin.Plugin):
358    def prepare(self):
359        if (self.db.get('apt-setup/restricted') == 'false' or
360                self.db.get('apt-setup/multiverse') == 'false'):
361            self.ui.set_allow_nonfree(False)
362        else:
363            use_nonfree = self.db.get('ubiquity/use_nonfree') == 'true'
364            self.ui.set_use_nonfree(use_nonfree)
365
366        arch, subarch = archdetect()
367        if 'efi' in subarch:
368            if is_secure_boot():
369                self.ui.set_using_secureboot(True)
370
371        download_updates = self.db.get('ubiquity/download_updates') == 'true'
372        self.ui.set_download_updates(download_updates)
373        self.apply_debconf_branding()
374        self.setup_sufficient_space()
375        command = ['/usr/share/ubiquity/simple-plugins', 'prepare']
376        questions = ['ubiquity/use_nonfree']
377        return command, questions
378
379    def apply_debconf_branding(self):
380        release = misc.get_release()
381        for template in ['ubiquity/text/required_space',
382                         'ubiquity/text/free_space']:
383            self.db.subst(template, 'RELEASE', release.name)
384
385    def setup_sufficient_space(self):
386        # TODO move into prepare.
387        size = misc.install_size()
388        self.db.subst(
389            'ubiquity/text/required_space', 'SIZE',
390            misc.format_size(size))
391        free = self.free_space()
392        self.db.subst(
393            'ubiquity/text/free_space', 'SIZE',
394            misc.format_size(free))
395        required_text = self.description('ubiquity/text/required_space')
396        free_text = self.description('ubiquity/text/free_space')
397        self.ui.set_sufficient_space(size < free, required_text, free_text)
398
399    def free_space(self):
400        biggest = 0
401        with misc.raised_privileges():
402            proc = subprocess.Popen(
403                ['parted_devices'],
404                stdout=subprocess.PIPE, universal_newlines=True)
405            devices = proc.communicate()[0].rstrip('\n').split('\n')
406            for device in devices:
407                if device and int(device.split('\t')[1]) > biggest:
408                    biggest = int(device.split('\t')[1])
409        return biggest
410
411    def ok_handler(self):
412        download_updates = self.ui.get_download_updates()
413        use_nonfree = self.ui.get_use_nonfree()
414        secureboot_key = self.ui.get_secureboot_key()
415        self.preseed_bool('ubiquity/use_nonfree', use_nonfree)
416        self.preseed_bool('ubiquity/download_updates', download_updates)
417        if self.ui.using_secureboot and secureboot_key:
418            self.preseed('ubiquity/secureboot_key', secureboot_key, seen=True)
419        if use_nonfree:
420            with misc.raised_privileges():
421                # Install ubuntu-restricted-addons.
422                self.preseed_bool('apt-setup/universe', True)
423                self.preseed_bool('apt-setup/multiverse', True)
424                if self.db.fget('ubiquity/nonfree_package', 'seen') != 'true':
425                    self.preseed(
426                        'ubiquity/nonfree_package',
427                        self.ui.restricted_package_name)
428        plugin.Plugin.ok_handler(self)
Note: See TracBrowser for help on using the repository browser.