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

Last change on this file since 3069 was 3069, checked in by kbut, 3 years ago

Update from upstream

File size: 16.5 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.disable_secureboot.set_active(True)
128        self.on_nonfree_toggled(None)
129        self.info_loop(None)
130
131    def enable_download_updates(self, val):
132        if (val):
133            template = 'ubiquity/text/label_download_updates'
134        else:
135            template = 'ubiquity/text/label_download_updates_na'
136        self.label_download_updates.set_label(
137            self.controller.get_string(template))
138        self.prepare_download_updates.set_sensitive(val)
139
140    def set_download_updates(self, val):
141        self.prepare_download_updates.set_active(val)
142
143    def get_download_updates(self):
144        return self.prepare_download_updates.get_active()
145
146    def set_allow_nonfree(self, allow):
147        if not allow:
148            self.prepare_nonfree_software.set_active(False)
149            self.nonfree_vbox.set_property('visible', False)
150
151    def set_use_nonfree(self, val):
152        if osextras.find_on_path('ubuntu-drivers'):
153            self.prepare_nonfree_software.set_active(val)
154        else:
155            self.debug('Could not find ubuntu-drivers on the executable path.')
156            self.set_allow_nonfree(False)
157
158    def get_use_nonfree(self):
159        return self.prepare_nonfree_software.get_active()
160
161    def get_disable_secureboot(self):
162        return self.disable_secureboot.get_active()
163
164    def plugin_translate(self, lang):
165        PreparePageBase.plugin_translate(self, lang)
166        release = misc.get_release()
167
168        from gi.repository import Gtk
169        for widget in [self.prepare_download_updates,
170                       self.label_required_space,
171                       self.label_free_space]:
172            text = i18n.get_string(Gtk.Buildable.get_name(widget), lang)
173            text = text.replace('${RELEASE}', release.name)
174            widget.set_label(text)
175
176    def on_nonfree_toggled(self, widget):
177        enabled = self.get_use_nonfree()
178        self.secureboot_box.set_sensitive(enabled)
179        self.info_loop(None)
180
181    def on_secureboot_toggled(self, widget):
182        enabled = self.get_disable_secureboot()
183        self.password_grid.set_sensitive(enabled)
184        self.info_loop(None)
185
186    def info_loop(self, unused_widget):
187        if not self.get_use_nonfree() \
188                or not self.password_grid.get_sensitive():
189            self.controller.allow_go_forward(True)
190            return True
191
192        complete = False
193        passw = self.password.get_text()
194        vpassw = self.verified_password.get_text()
195
196        if len(passw) == 0:
197            self.password_strength.set_current_page(
198                self.password_strength_pages['empty'])
199        elif len(passw) >= 8:
200            self.password_strength.set_current_page(
201                self.password_strength_pages['good'])
202        else:
203            self.password_strength.set_current_page(
204                self.password_strength_pages['too_short'])
205
206        if len(passw) == 0 or len(vpassw) == 0:
207            self.password_match.set_current_page(
208                self.password_match_pages['empty'])
209        elif passw != vpassw or (passw and len(passw) < 8):
210            self.password_match.set_current_page(
211                self.password_match_pages['empty'])
212            if len(passw) >= 8 and (not passw.startswith(vpassw) or
213                                    len(vpassw) / len(passw) > 0.6):
214                self.password_match.set_current_page(
215                    self.password_match_pages['mismatch'])
216        else:
217            complete = True
218            self.password_match.set_current_page(
219                self.password_match_pages['ok'])
220
221        self.controller.allow_go_forward(complete)
222        return complete
223
224    def get_secureboot_key(self):
225        return self.password.get_text()
226
227    def show_learn_more(self, unused):
228        from gi.repository import Gtk
229
230        sb_title_template = 'ubiquity/text/efi_secureboot'
231        sb_info_template = 'ubiquity/text/efi_secureboot_info'
232        secureboot_title = self.controller.get_string(sb_title_template)
233        secureboot_msg = self.controller.get_string(sb_info_template)
234
235        dialog = Gtk.MessageDialog(
236            self.current_page.get_toplevel(), Gtk.DialogFlags.MODAL,
237            Gtk.MessageType.INFO, Gtk.ButtonsType.CLOSE, None)
238        dialog.set_title(secureboot_title)
239        dialog.set_markup(secureboot_msg)
240        dialog.run()
241        dialog.destroy()
242
243
244class PageKde(PreparePageBase):
245    plugin_breadcrumb = 'ubiquity/text/breadcrumb_prepare'
246    restricted_package_name = 'kubuntu-restricted-addons'
247
248    def __init__(self, controller, *args, **kwargs):
249        from ubiquity.qtwidgets import StateBox
250        if self.is_automatic:
251            self.page = None
252            return
253        self.controller = controller
254        try:
255            from PyQt4 import uic
256            from PyQt4 import QtGui
257            self.page = uic.loadUi('/usr/share/ubiquity/qt/stepPrepare.ui')
258            self.prepare_download_updates = self.page.prepare_download_updates
259            self.prepare_nonfree_software = self.page.prepare_nonfree_software
260            self.prepare_foss_disclaimer = self.page.prepare_foss_disclaimer
261            self.prepare_sufficient_space = StateBox(self.page)
262            self.secureboot_label = self.page.secureboot_label
263            self.disable_secureboot = self.page.disable_secureboot
264            self.password = self.page.password
265            self.verified_password = self.page.verified_password
266            self.password_extra_label = self.page.password_extra_label
267            self.badPassword = self.page.badPassword
268            self.badPassword.setPixmap(QtGui.QPixmap(
269                "/usr/share/icons/oxygen/16x16/status/dialog-warning.png"))
270            # TODO we should set these up and tear them down while on this
271            # page.
272            try:
273                self.prepare_power_source = StateBox(self.page)
274                if upower.has_battery():
275                    upower.setup_power_watch(self.prepare_power_source)
276                else:
277                    self.prepare_power_source.hide()
278            except Exception as e:
279                # TODO use an inconsistent state?
280                print('unable to set up power source watch:', e)
281            try:
282                self.prepare_network_connection = StateBox(self.page)
283            except Exception as e:
284                print('unable to set up network connection watch:', e)
285        except Exception as e:
286            print("Could not create prepare page:", str(e), file=sys.stderr)
287            self.debug('Could not create prepare page: %s', e)
288            self.page = None
289        self.set_using_secureboot(False)
290        self.plugin_widgets = self.page
291
292    def show_insufficient_space_page(self, required, free):
293        return
294
295    def set_using_secureboot(self, secureboot):
296        self.using_secureboot = secureboot
297        self.secureboot_label.setVisible(secureboot)
298        self.disable_secureboot.setVisible(secureboot)
299        self.password.setVisible(secureboot)
300        self.verified_password.setVisible(secureboot)
301        self.password_extra_label.setVisible(secureboot)
302        self.badPassword.hide()
303        if (secureboot):
304            self.password.textChanged.connect(self.verify_password)
305            self.verified_password.textChanged.connect(self.verify_password)
306
307    # show warning if passwords do not match
308    def verify_password(self):
309        complete = False
310
311        if self.password.text() == self.verified_password.text():
312            self.badPassword.hide()
313            complete = True
314        else:
315            self.badPassword.show()
316
317        if not self.password.text():
318            complete = False
319
320        self.controller.allow_go_forward(complete)
321
322    def get_secureboot_key(self):
323        return str(self.page.password.text())
324
325    def enable_download_updates(self, val):
326        self.prepare_download_updates.setEnabled(val)
327
328    def set_download_updates(self, val):
329        self.prepare_download_updates.setChecked(val)
330
331    def get_download_updates(self):
332        from PyQt4.QtCore import Qt
333        return self.prepare_download_updates.checkState() == Qt.Checked
334
335    def set_allow_nonfree(self, allow):
336        if not allow:
337            self.prepare_nonfree_software.setChecked(False)
338            self.prepare_nonfree_software.setVisible(False)
339            self.prepare_foss_disclaimer.setVisible(False)
340
341    def set_use_nonfree(self, val):
342        if osextras.find_on_path('ubuntu-drivers'):
343            self.prepare_nonfree_software.setChecked(val)
344        else:
345            self.debug('Could not find ubuntu-drivers on the executable path.')
346            self.set_allow_nonfree(False)
347
348    def get_use_nonfree(self):
349        from PyQt4.QtCore import Qt
350        return self.prepare_nonfree_software.checkState() == Qt.Checked
351
352    def plugin_translate(self, lang):
353        PreparePageBase.plugin_translate(self, lang)
354        # gtk does the ${RELEASE} replace for the title in gtk_ui but we do
355        # it per plugin because our title widget is per plugin
356        release = misc.get_release()
357        widgets = (
358            self.page.prepare_heading_label,
359            self.page.prepare_download_updates,
360        )
361        for widget in widgets:
362            text = widget.text()
363            text = text.replace('${RELEASE}', release.name)
364            text = text.replace('Ubuntu', 'Kubuntu')
365            widget.setText(text)
366
367
368class Page(plugin.Plugin):
369    def prepare(self):
370        if (self.db.get('apt-setup/restricted') == 'false' or
371                self.db.get('apt-setup/multiverse') == 'false'):
372            self.ui.set_allow_nonfree(False)
373        else:
374            use_nonfree = self.db.get('ubiquity/use_nonfree') == 'true'
375            self.ui.set_use_nonfree(use_nonfree)
376
377        arch, subarch = archdetect()
378        if 'efi' in subarch:
379            if is_secure_boot():
380                self.ui.set_using_secureboot(True)
381
382        download_updates = self.db.get('ubiquity/download_updates') == 'true'
383        self.ui.set_download_updates(download_updates)
384        self.apply_debconf_branding()
385        self.setup_sufficient_space()
386        command = ['/usr/share/ubiquity/simple-plugins', 'prepare']
387        questions = ['ubiquity/use_nonfree']
388        return command, questions
389
390    def apply_debconf_branding(self):
391        release = misc.get_release()
392        for template in ['ubiquity/text/required_space',
393                         'ubiquity/text/free_space']:
394            self.db.subst(template, 'RELEASE', release.name)
395
396    def setup_sufficient_space(self):
397        # TODO move into prepare.
398        size = misc.install_size()
399        self.db.subst(
400            'ubiquity/text/required_space', 'SIZE',
401            misc.format_size(size))
402        free = self.free_space()
403        self.db.subst(
404            'ubiquity/text/free_space', 'SIZE',
405            misc.format_size(free))
406        required_text = self.description('ubiquity/text/required_space')
407        free_text = self.description('ubiquity/text/free_space')
408        self.ui.set_sufficient_space(size < free, required_text, free_text)
409
410    def free_space(self):
411        biggest = 0
412        with misc.raised_privileges():
413            proc = subprocess.Popen(
414                ['parted_devices'],
415                stdout=subprocess.PIPE, universal_newlines=True)
416            devices = proc.communicate()[0].rstrip('\n').split('\n')
417            for device in devices:
418                if device and int(device.split('\t')[1]) > biggest:
419                    biggest = int(device.split('\t')[1])
420        return biggest
421
422    def ok_handler(self):
423        download_updates = self.ui.get_download_updates()
424        use_nonfree = self.ui.get_use_nonfree()
425        secureboot_key = self.ui.get_secureboot_key()
426        self.preseed_bool('ubiquity/use_nonfree', use_nonfree)
427        self.preseed_bool('ubiquity/download_updates', download_updates)
428        if self.ui.using_secureboot and secureboot_key:
429            self.preseed('ubiquity/secureboot_key', secureboot_key, seen=True)
430        if use_nonfree:
431            with misc.raised_privileges():
432                # Install ubuntu-restricted-addons.
433                self.preseed_bool('apt-setup/universe', True)
434                self.preseed_bool('apt-setup/multiverse', True)
435                if self.db.fget('ubiquity/nonfree_package', 'seen') != 'true':
436                    self.preseed(
437                        'ubiquity/nonfree_package',
438                        self.ui.restricted_package_name)
439        plugin.Plugin.ok_handler(self)
Note: See TracBrowser for help on using the repository browser.