def check_all(self): """ Check that all requirements are meet """ if os.path.exists("/tmp/.cnchi_partitioning_completed"): msg = "You must reboot before retrying again." logging.error(msg) msg = _("You must reboot before retrying again.") show.fatal_error(self.main_window, msg) return False has_internet = misc.has_connection() self.prepare_network_connection.set_state(has_internet) on_power = not self.on_battery() self.prepare_power_source.set_state(on_power) space = self.has_enough_space() self.prepare_enough_space.set_state(space) if has_internet: updated = self.is_updated() else: updated = False self.updated.set_state(updated) if self.checks_are_optional: return True if has_internet and space: return True return False
def manage_events_from_cb_queue(self): if self.fatal_error: return False while self.callback_queue.empty() == False: try: event = self.callback_queue.get_nowait() except queue.Empty: return True if event[0] == 'percent': self.progress_bar.set_fraction(event[1]) elif event[0] == 'global_percent': self.show_global_progress_bar_if_hidden() self.global_progress_bar.set_fraction(event[1]) elif event[0] == 'finished': logging.info(event[1]) self.set_message(self.install_ok) response = show.question(self.install_ok) if response == Gtk.ResponseType.YES: self.reboot() else: tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "Cnchi.log"] for t in tmp_files: p = os.path.join("/tmp", t) if os.path.exists(p): # TODO: some of these tmp files are created with sudo privileges # (this should be fixed) meanwhile, we need sudo privileges to remove them with misc.raised_privileges(): os.remove(p) while Gtk.events_pending(): Gtk.main_iteration() Gtk.main_quit() self.exit_button.show() return False elif event[0] == 'error': self.callback_queue.task_done() # a fatal error has been issued. We empty the queue self.empty_queue() self.fatal_error = True show.fatal_error(event[1]) return False elif event[0] == 'debug': logging.debug(event[1]) elif event[0] == 'warning': logging.warning(event[1]) else: # TODO: Check if logging slows down showing messages # remove logging.info in that case (and at least # use the one at pac.py:queue_event) logging.info(event[1]) self.set_message(event[1]) self.callback_queue.task_done() return True
def populate_treeview(self): if self.treeview_store is not None: self.treeview_store.clear() self.treeview_store = Gtk.TreeStore(str, str, str) oses = {} oses = bootinfo.get_os_dict() self.partitions = {} try: device_list = parted.getAllDevices() except: txt = _("pyparted3 not found!") logging.error(txt) show.fatal_error(txt) device_list = [] for dev in device_list: ## avoid cdrom and any raid, lvm volumes or encryptfs if not dev.path.startswith("/dev/sr") and \ not dev.path.startswith("/dev/mapper"): try: disk = parted.Disk(dev) # create list of partitions for this device (p.e. /dev/sda) partition_list = disk.partitions for p in partition_list: if p.type != pm.PARTITION_EXTENDED: ## Get filesystem fs_type = "" if p.fileSystem and p.fileSystem.type: fs_type = p.fileSystem.type if "swap" not in fs_type: if p.path in oses: row = [p.path, oses[p.path], fs_type] else: row = [p.path, _("unknown"), fs_type] self.treeview_store.append(None, row) self.partitions[p.path] = p except Exception as e: txt = _("Unable to create list of partitions for alongside installation.") logging.warning(txt) #show.warning(txt) # assign our new model to our treeview self.treeview.set_model(self.treeview_store) self.treeview.expand_all()
def on_treeview_cursor_changed(self, widget): selection = self.treeview.get_selection() if not selection: return model, tree_iter = selection.get_selected() if tree_iter is None: return self.row = model[tree_iter] partition_path = self.row[0] other_os_name = self.row[1] self.min_size = 0 self.max_size = 0 self.new_size = 0 try: subprocess.call(["mount", partition_path, "/mnt"], stderr=subprocess.DEVNULL) x = subprocess.check_output(['df', partition_path]).decode() subprocess.call(["umount", "-l", "/mnt"], stderr=subprocess.DEVNULL) x = x.split('\n') x = x[1].split() self.max_size = int(x[1]) / 1000 self.min_size = int(x[2]) / 1000 except subprocess.CalledProcessError as e: txt = "CalledProcessError.output = %s" % e.output logging.error(txt) show.fatal_error(txt) if self.min_size + MIN_ROOT_SIZE < self.max_size: self.new_size = self.ask_shrink_size(other_os_name) else: txt = _("Can't shrink the partition (maybe it's nearly full?)") logging.error(txt) show.error(txt) return if self.new_size > 0 and self.is_room_available(): self.forward_button.set_sensitive(True) else: self.forward_button.set_sensitive(False)
def manage_events_from_cb_queue(self): ''' try: event = self.callback_queue.get_nowait() except queue.Empty: event = () ''' event = self.get_newest_event() if len(event) > 0: if event[0] == "percent": self.progress_bar.set_fraction(event[1]) elif event[0] == "finished": log.debug(event[1]) self.set_message(self.install_ok) response = show.question(self.install_ok) if response == Gtk.ResponseType.YES: self.reboot() else: tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "Cnchi.log"] for t in tmp_files: p = os.path.join("/tmp", t) if os.path.exists(p): # TODO: some of these tmp files are created with sudo privileges # (this should be fixed) meanwhile, we need sudo privileges to remove them with misc.raised_privileges(): os.remove(p) Gtk.main_quit() self.exit_button.show() return False elif event[0] == "error": show.fatal_error(event[1]) else: #with self.lock: log.debug(event[1]) self.set_message(event[1]) # remove old messages from the event queue #self.callback_queue.clear() return True
def check_all(self): """ Check that all requirements are meet """ if os.path.exists("/tmp/.cnchi_partitioning_completed"): msg = "You must reboot before retrying again." logging.error(msg) msg = _("You must reboot before retrying again.") show.fatal_error(self.main_window, msg) return False has_internet = misc.has_connection() self.prepare_network_connection.set_state(has_internet) self.latest_iso.set_state(self.iso_version_ok) #if has_internet and not self.cnchi_notified: # self.cnchi_main.on_has_internet_connection() # logging.debug('on_has_internet_connection() is running') # self.cnchi_notified = True on_power = not self.on_battery() self.prepare_power_source.set_state(on_power) space = self.has_enough_space() if not self.has_space else True self.prepare_enough_space.set_state(space) if self.has_internet or 'development' == info.CNCHI_RELEASE_STAGE: updated = self.is_updated_check() if not self.is_updated else True else: updated = False self.updated.set_state(updated) if self.checks_are_optional: return True if has_internet and space: return True return False
def manage_events_from_cb_queue(self): try: event = self.callback_queue.get_nowait() except queue.Empty: event = () if len(event) > 0: if event[0] == "percent": self.progress_bar.set_fraction(event[1]) elif event[0] == "finished": log.debug(event[1]) self.set_message(self.install_ok) response = show.message(self.install_ok) if response == Gtk.ResponseType.YES: # TODO: This needs testing #subp = subprocess.Popen(['reboot'], stdout=subprocess.PIPE) with misc.raised_privileges(): subp = subprocess.Popen(['shutdown', '-r', 'now']) else: tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup" ] for t in tmp_files: p = os.path.join("/tmp", t) if os.path.exists(p): os.remove(p) Gtk.main_quit() self.exit_button.show() return False elif event[0] == "error": show.fatal_error(event[1]) else: log.debug(event[1]) self.set_message(event[1]) # remove old messages from the event queue with self.callback_queue.mutex: self.callback_queue.queue.clear() return True
def __init__(self): ## This allows to translate all py texts (not the glade ones) #gettext.textdomain(APP_NAME) #gettext.bindtextdomain(APP_NAME, LOCALE_DIR) # #locale_code, encoding = locale.getdefaultlocale() #lang = gettext.translation(APP_NAME, LOCALE_DIR, [locale_code], None, True) #lang.install() # ## With this we can use _("string") to translate #gettext.install(APP_NAME, localedir=LOCALE_DIR, codeset=None, names=[locale_code]) # Check if we have administrative privileges if os.getuid() != 0: show.fatal_error(_('This installer must be run with administrative' ' privileges and cannot continue without them.')) setup_logging() # Check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error(_('You cannot run two instances of this installer.\n\n' 'If you are sure that another installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) super().__init__() # workaround for dconf os.system("mkdir -p /root/.cache/dconf") os.system("chmod -R 777 /root/.cache") logging.info(_("Thus installer version %s"), info.THUS_VERSION) current_process = multiprocessing.current_process() logging.debug("[%d] %s started", current_process.pid, current_process.name) self.settings = config.Settings() thus_dir = os.path.join(os.path.dirname(__file__), './') if os.path.exists(thus_dir): self.settings.set('thus', thus_dir) else: thus_dir = self.settings.get('thus') ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') if os.path.exists(ui_dir): self.settings.set('ui', ui_dir) else: ui_dir = self.settings.get('ui') data_dir = os.path.join(os.path.dirname(__file__), 'data/') if os.path.exists(data_dir): self.settings.set('data', data_dir) else: data_dir = self.settings.get('data') if os.path.exists("/sys/firmware/efi"): self.settings.set('efi', True) self.ui = Gtk.Builder() self.ui.add_from_file(ui_dir + "thus.ui") self.add(self.ui.get_object("main")) self.header = self.ui.get_object("header") self.forward_button = self.ui.get_object("forward_button") self.logo = self.ui.get_object("logo") logo_dir = os.path.join(data_dir, "manjaro-logo-mini.png") self.logo.set_from_file(logo_dir) self.title = self.ui.get_object("title") # To honor our css self.title.set_name("header") self.logo.set_name("header") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("progressbar1") self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # Create a queue. Will be used to report pacman messages (pac.py) # to the main thread (installer_*.py) self.callback_queue = multiprocessing.JoinableQueue() # Load all pages # (each one is a screen, a step in the install process) self.pages = dict() params = dict() params['title'] = self.title params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['exit_button'] = self.exit_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings params['main_progressbar'] = self.ui.get_object('progressbar1') params['alternate_package_list'] = "" params['testing'] = cmd_line.testing self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk(params) self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params) self.pages["installation_alongside"] = installation_alongside.InstallationAlongside(params) self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect("delete-event", Gtk.main_quit) self.ui.connect_signals(self) self.set_title(_('Manjaro Installer')) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT) # Set window icon icon_dir = os.path.join(data_dir, 'manjaro-icon.png') self.set_icon_from_file(icon_dir) # Set the first page to show self.current_page = self.pages["language"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(data_dir, "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # Show main window self.show_all() self.current_page.prepare('forwards') # Hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration self.get_window().set_accept_focus(True) #self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # Hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) with open(tmp_running, "w") as tmp_file: tmp_file.write("Thus %d\n" % 1234) GLib.timeout_add(1000, self.pages["slides"].manage_events_from_cb_queue)
def __init__(self): # This allows to translate all py texts (not the glade ones) gettext.textdomain(APP_NAME) gettext.bindtextdomain(APP_NAME, LOCALE_DIR) locale_code, encoding = locale.getdefaultlocale() lang = gettext.translation(APP_NAME, LOCALE_DIR, [locale_code], None, True) lang.install() # With this we can use _("string") to translate gettext.install(APP_NAME, localedir=LOCALE_DIR, codeset=None, names=[locale_code]) # Check if we have administrative privileges if os.getuid() != 0: show.fatal_error(_('This installer must be run with administrative' ' privileges, and cannot continue without them.')) setup_logging() # Check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error(_('You cannot run two instances of this installer.\n\n' 'If you are sure that the installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) super().__init__() logging.info("Cnchi installer version %s" % info.cnchi_VERSION) p = multiprocessing.current_process() logging.debug("[%d] %s started" % (p.pid, p.name)) self.settings = config.Settings() self.ui_dir = self.settings.get('ui') if not os.path.exists(self.ui_dir): cnchi_dir = os.path.join(os.path.dirname(__file__), './') self.settings.set('cnchi', cnchi_dir) ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') self.settings.set('ui', ui_dir) data_dir = os.path.join(os.path.dirname(__file__), 'data/') self.settings.set('data', data_dir) self.ui_dir = self.settings.get('ui') self.settings.set('cache', _cache_dir) # Set enabled desktops self.settings.set("desktops", _desktops) # Set if a grub type must be installed (user choice) self.settings.set("force_grub_type", _force_grub_type) self.ui = Gtk.Builder() self.ui.add_from_file(self.ui_dir + "cnchi.ui") self.add(self.ui.get_object("main")) self.header = self.ui.get_object("header") self.forward_button = self.ui.get_object("forward_button") self.logo = self.ui.get_object("logo") data_dir = self.settings.get('data') logo_dir = os.path.join(data_dir, "antergos-logo-mini.png") self.logo.set_from_file(logo_dir) self.title = self.ui.get_object("title") # To honor our css self.title.set_name("title") self.logo.set_name("logo") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("progressbar1") self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # Create a queue. Will be used to report pacman messages (pac.py) # to the main thread (installer_*.py) self.callback_queue = multiprocessing.JoinableQueue() # Save in config if we have to use aria2 to download pacman packages self.settings.set("use_aria2", _use_aria2) if _use_aria2: logging.info(_("Using Aria2 to download packages - EXPERIMENTAL")) # Load all pages # (each one is a screen, a step in the install process) self.pages = dict() params = dict() params['title'] = self.title params['ui_dir'] = self.ui_dir params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['exit_button'] = self.exit_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings params['main_progressbar'] = self.ui.get_object('progressbar1') params['alternate_package_list'] = _alternate_package_list params['disable_tryit'] = _disable_tryit if len(_alternate_package_list) > 0: logging.info(_("Using '%s' file as package list") % _alternate_package_list) self.pages["welcome"] = welcome.Welcome(params) self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["desktop"] = desktop.DesktopAsk(params) self.pages["features"] = features.Features(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk(params) self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params) self.pages["installation_alongside"] = installation_alongside.InstallationAlongside(params) self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect("delete-event", Gtk.main_quit) self.ui.connect_signals(self) self.set_title(_('Antergos Installer')) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(_main_window_width, _main_window_height); # Set window icon icon_dir = os.path.join(data_dir, 'antergos-icon.png') self.set_icon_from_file(icon_dir) # Set the first page to show self.current_page = self.pages["welcome"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(data_dir, "css", "gtk-style.css") with open(style_css, 'rb') as css: css_data = css.read() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # Show main window self.show_all() self.vertical_image = self.ui.get_object('vertical_image') self.vertical_image.hide() #logo_90_dir = os.path.join(data_dir, "antergos-logo-mini-90.png") #self.vertical_image.set_from_file(logo_90_dir) self.current_page.prepare('forwards') # Hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration self.get_window().set_accept_focus(True) self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # Hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) # We drop privileges, but where we should do it? before this? ¿? misc.drop_privileges() with open(tmp_running, "wt") as tmp_file: tmp_file.write("Cnchi %d\n" % 1234) GLib.timeout_add(1000, self.pages["slides"].manage_events_from_cb_queue)
def manage_events_from_cb_queue(self): """ We should do as less as possible here, we want to maintain our queue message as empty as possible """ if self.fatal_error: return False while self.callback_queue.empty() == False: try: event = self.callback_queue.get_nowait() except queue.Empty: return True if event[0] == 'percent': self.progress_bar.set_fraction(event[1]) elif event[0] == 'text': if event[1] == 'hide': self.progress_bar.set_show_text(False) self.progress_bar.set_text("") else: self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[0] == 'finished': logging.info(event[1]) if not self.settings.get('bootloader_ok'): # Warn user about GRUB and ask if we should open wiki page. boot_warn = _("IMPORTANT: There may have been a problem with the Grub(2) bootloader\n" "installation which could prevent your system from booting properly. Before\n" "rebooting, you may want to verify whether or not GRUB(2) is installed and\n" "configured. The Arch Linux Wiki contains troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n" "\nWould you like to view the wiki page now?") response = show.question(boot_warn) if response == Gtk.ResponseType.YES: import webbrowser misc.drop_privileges() webbrowser.open('https://wiki.archlinux.org/index.php/GRUB') install_ok = _("Installation Complete!\nDo you want to restart your system now?") response = show.question(install_ok) self.remove_temp_files() self.settings.set('stop_all_threads', True) #while Gtk.events_pending(): # Gtk.main_iteration() logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Show the error show.fatal_error(event[1]) # Ask if user wants to retry res = show.question(_("Do you want to retry the installation using the same configuration?")) if res == GTK_RESPONSE_YES: # Restart installation process logging.debug(_("Restarting installation process...")) p = self.settings.get('installer_thread_call') self.process = installation_process.InstallationProcess(self.settings, self.callback_queue, p['mount_devices'], p['fs_devices'], p['ssd'], p['alternate_package_list'], p['blvm']) self.process.start() return True else: self.fatal_error = True return False elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) self.callback_queue.task_done() return True
def manage_events_from_cb_queue(self): """ We should do as less as possible here, we want to maintain our queue message as empty as possible """ if self.fatal_error: return False if self.callback_queue is None: return True while not self.callback_queue.empty(): try: event = self.callback_queue.get_nowait() except queue.Empty: return True if event[0] == 'percent': self.progress_bar.set_fraction(float(event[1])) elif event[0] == 'downloads_percent': self.downloads_progress_bar.set_fraction(float(event[1])) elif event[0] == 'text': if event[1] == 'hide': self.progress_bar.set_show_text(False) self.progress_bar.set_text("") else: self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[0] == 'downloads_progress_bar': if event[1] == 'hide': self.downloads_progress_bar.hide() if event[1] == 'show': self.downloads_progress_bar.show() elif event[0] == 'finished': logging.info(event[1]) if not self.settings.get('bootloader_installation_successful'): # Warn user about GRUB and ask if we should open wiki page. boot_warn = _("IMPORTANT: There may have been a problem with the bootloader\n" "installation which could prevent your system from booting properly. Before\n" "rebooting, you may want to verify whether or not the bootloader is installed and\n" "configured. The Arch Linux Wiki contains troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n" "\nWould you like to view the wiki page now?") response = show.question(self.get_toplevel(), boot_warn) if response == Gtk.ResponseType.YES: import webbrowser misc.drop_privileges() webbrowser.open('https://wiki.archlinux.org/index.php/GRUB') install_ok = _("Installation Complete!\nDo you want to restart your system now?") response = show.question(self.get_toplevel(), install_ok) misc.remove_temp_files() self.settings.set('stop_all_threads', True) logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Show the error show.fatal_error(self.get_toplevel(), event[1]) elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) self.callback_queue.task_done() return True
def manage_events_from_cb_queue(self): """ This function is called from cnchi.py with a timeout function We should do as less as possible here, we want to maintain our queue message as empty as possible """ if self.fatal_error: return False while self.callback_queue.empty() is False: try: event = self.callback_queue.get_nowait() except queue.Empty: return True if event[0] == 'percent': self.progress_bar.set_fraction(event[1]) elif event[0] == 'global_percent': self.show_global_progress_bar_if_hidden() self.global_progress_bar.set_fraction(event[1]) elif event[0] == 'pulse': self.do_progress_pulse() elif event[0] == 'stop_pulse': self.stop_pulse() elif event[0] == 'finished': logging.info(event[1]) self.should_pulse = False # Warn user about GRUB and ask if we should open wiki page. if not self.settings.get('bootloader_ok'): import webbrowser self.boot_warn = _("IMPORTANT: There may have been a problem with the Grub(2) bootloader\n" "installation which could prevent your system from booting properly. Before\n" "rebooting, you may want to verify whether or not GRUB(2) is installed and\n" "configured. The Arch Linux Wiki contains troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n" "\nWould you like to view the wiki page now?") response = show.question(self.boot_warn) if response == Gtk.ResponseType.YES: webbrowser.open('https://wiki.archlinux.org/index.php/GRUB') self.set_message(self.install_ok) response = show.question(self.install_ok) if response == Gtk.ResponseType.YES: logging.shutdown() self.reboot() else: tmp_files = [".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "thus.log"] for t in tmp_files: p = os.path.join("/tmp", t) if os.path.exists(p): # TODO: some of these tmp files are created with sudo privileges # (this should be fixed) meanwhile, we need sudo privileges to remove them with misc.raised_privileges(): os.remove(p) self.callback_queue.task_done() logging.shutdown() os._exit(0) return False elif event[0] == 'error': self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() self.fatal_error = True show.fatal_error(event[1]) # Ask if user wants to retry res = show.question(_("Do you want to retry?")) if res == GTK_RESPONSE_YES: # Restart installation process logging.debug("Restarting installation process...") p = self.settings.get('installer_thread_call') self.process = installation_process.InstallationProcess( self.settings, self.callback_queue, p['mount_devices'], p['fs_devices'], p['ssd'], p['alternate_package_list'], p['blvm']) self.process.start() return True else: self.fatal_error = True return False elif event[0] == 'debug': logging.debug(event[1]) elif event[0] == 'warning': logging.warning(event[1]) else: logging.info(event[1]) self.set_message(event[1]) self.callback_queue.task_done() return True
def manage_events_from_cb_queue(self): """ This function is called from cnchi.py with a timeout function We should do as less as possible here, we want to maintain our queue message as empty as possible """ if self.fatal_error: return False while self.callback_queue.empty() is False: try: event = self.callback_queue.get_nowait() except queue.Empty: return True if event[0] == "percent": self.progress_bar.set_fraction(event[1]) elif event[0] == "global_percent": self.show_global_progress_bar_if_hidden() self.global_progress_bar.set_fraction(event[1]) elif event[0] == "pulse": self.do_progress_pulse() elif event[0] == "stop_pulse": self.stop_pulse() elif event[0] == "finished": logging.info(event[1]) self.should_pulse = False self.set_message(self.install_ok) response = show.question(self.install_ok) if response == Gtk.ResponseType.YES: self.reboot() else: tmp_files = [ ".setup-running", ".km-running", "setup-pacman-running", "setup-mkinitcpio-running", ".tz-running", ".setup", "thus.log", ] for t in tmp_files: p = os.path.join("/tmp", t) if os.path.exists(p): # TODO: some of these tmp files are created with sudo privileges # (this should be fixed) meanwhile, we need sudo privileges to remove them with misc.raised_privileges(): os.remove(p) self.callback_queue.task_done() os._exit(0) return False elif event[0] == "error": self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() self.fatal_error = True show.fatal_error(event[1]) # Ask if user wants to retry res = show.question(_("Do you want to retry?")) if res == GTK_RESPONSE_YES: # Restart installation process logging.debug("Restarting installation process...") p = self.settings.get("installer_thread_call") self.process = installation_process.InstallationProcess( self.settings, self.callback_queue, p["mount_devices"], p["fs_devices"], p["ssd"], p["alternate_package_list"], p["blvm"], ) self.process.start() return True else: self.fatal_error = True return False elif event[0] == "debug": logging.debug(event[1]) elif event[0] == "warning": logging.warning(event[1]) else: logging.info(event[1]) self.set_message(event[1]) self.callback_queue.task_done() return True
def __init__(self): # This allows to translate all py texts (not the glade ones) gettext.textdomain(APP) gettext.bindtextdomain(APP, DIR) locale_code, encoding = locale.getdefaultlocale() lang = gettext.translation (APP, DIR, [locale_code], None, True) lang.install() # With this we can use _("string") to translate gettext.install(APP, localedir=DIR, codeset=None, names=[locale_code]) if os.getuid() != 0: fatal_error(_('This installer must be run with administrative' ' privileges, and cannot continue without them.')) super().__init__() self.ui_dir = installer_settings["UI_DIR"] if not os.path.exists(self.ui_dir): cnchi_dir = os.path.join(os.path.dirname(__file__), './') installer_settings["CNCHI_DIR"] = cnchi_dir ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') installer_settings["UI_DIR"] = ui_dir data_dir = os.path.join(os.path.dirname(__file__), 'data/') installer_settings["DATA_DIR"] = data_dir self.ui_dir = installer_settings["UI_DIR"] self.ui = Gtk.Builder() self.ui.add_from_file(self.ui_dir + "cnchi.ui") self.add(self.ui.get_object("main")) self.header = self.ui.get_object("box5") self.forward_button = self.ui.get_object("forward_button") self.logo = self.ui.get_object("logo") logo_dir = os.path.join(installer_settings["DATA_DIR"], "logo_mini.png") self.logo.set_from_file(logo_dir) self.title = self.ui.get_object("title") # To honor our css self.title.set_name("header") self.logo.set_name("header") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("progressbar1") self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # load all pages # (each one is a screen, a step in the install process) self.pages = dict() params = dict() params['title'] = self.title params['ui_dir'] = self.ui_dir params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['exit_button'] = self.exit_button self.pages["language"] = language.Language(params) self.pages["check"] = check.Check(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk(params) self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params) self.pages["installation_easy"] = installation_easy.InstallationEasy(params) self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect("delete-event", Gtk.main_quit) self.ui.connect_signals(self) self.set_title(_('Cinnarch Installer')) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(_main_window_width, _main_window_height); # set window icon icon_dir = os.path.join(installer_settings["DATA_DIR"], 'cinnarch-icon.png') self.set_icon_from_file(icon_dir) # set the first page to show #self.current_page = self.pages["language"] #self.current_page = self.pages["installation_ask"] self.current_page = self.pages["installation_advanced"] #self.current_page = self.pages["installation_easy"] #self.current_page = self.pages["slides"] #self.current_page = self.pages["timezone"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(installer_settings["DATA_DIR"], "gtk-style.css") css = open(style_css, 'rb') css_data = css.read() css.close() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # show main window self.show_all() self.current_page.prepare() # hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration self.get_window().set_accept_focus(True) self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # we drop privileges, but where we should do it? before this? ¿? misc.drop_privileges()
def manage_events_from_cb_queue(self): """ We should be quick here and do as less as possible """ if self.fatal_error: return False if self.callback_queue is None: return True while not self.callback_queue.empty(): try: event = self.callback_queue.get_nowait() except ValueError as queue_error: # Calling get_nowait so many times can issue a ValueError # exception with this error: semaphore or lock released too # many times. Log it anyways to keep an eye on this error logging.error(queue_error) return True except queue.Empty: # Queue is empty, just quit. return True if event[0] == 'percent': self.progress_bar.set_fraction(float(event[1])) elif event[0] == 'downloads_percent': self.downloads_progress_bar.set_fraction(float(event[1])) elif event[0] == 'progress_bar_show_text': if len(event[1]) > 0: # self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) else: # self.progress_bar.set_show_text(False) self.progress_bar.set_text("") elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[1] == 'show': self.progress_bar.show() elif event[0] == 'downloads_progress_bar': if event[1] == 'hide': self.downloads_progress_bar.hide() elif event[1] == 'show': self.downloads_progress_bar.show() elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'finished': logging.info(event[1]) log_util = ContextFilter() log_util.send_install_result("True") if (self.settings.get('bootloader_install') and not self.settings.get('bootloader_installation_successful')): # Warn user about GRUB and ask if we should open wiki page. boot_warn = _("IMPORTANT: There may have been a problem " "with the bootloader installation which " "could prevent your system from booting " "properly. Before rebooting, you may want " "to verify whether or not the bootloader is " "installed and configured.\n\n" "The Arch Linux Wiki contains " "troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n\n" "Would you like to view the wiki page now?") response = show.question(self.get_main_window(), boot_warn) if response == Gtk.ResponseType.YES: import webbrowser misc.drop_privileges() wiki_url = 'https://wiki.archlinux.org/index.php/GRUB' webbrowser.open(wiki_url) install_ok = _("Installation Complete!\n" "Do you want to restart your system now?") response = show.question(self.get_main_window(), install_ok) misc.remove_temp_files() logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': log_util = ContextFilter() log_util.send_install_result("False") self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Show the error show.fatal_error(self.get_main_window(), event[1]) elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) elif event[0] == 'cache_pkgs_md5_check_failed': logging.debug( 'Adding %s to cache_pkgs_md5_check_failed list', event[1]) self.settings.set('cache_pkgs_md5_check_failed', event[1]) self.callback_queue.task_done() return True
def __init__(self): # This allows to translate all py texts (not the glade ones) gettext.textdomain(APP) gettext.bindtextdomain(APP, DIR) locale_code, encoding = locale.getdefaultlocale() lang = gettext.translation (APP, DIR, [locale_code], None, True) lang.install() # With this we can use _("string") to translate gettext.install(APP, localedir=DIR, codeset=None, names=[locale_code]) if os.getuid() != 0: show.fatal_error(_('This installer must be run with administrative' ' privileges, and cannot continue without them.')) # check if we're already running tmp_running = "/tmp/.setup-running" if os.path.exists(tmp_running): show.error(_('You cannot run two instances of this installer.\n\n' 'If you are sure that the installer is not already running\n' 'you can manually delete the file %s\n' 'and run this installer again.') % tmp_running) sys.exit(1) super().__init__() self.settings = config.Settings() self.ui_dir = self.settings.get("UI_DIR") if not os.path.exists(self.ui_dir): cnchi_dir = os.path.join(os.path.dirname(__file__), './') self.settings.set("CNCHI_DIR", cnchi_dir) ui_dir = os.path.join(os.path.dirname(__file__), 'ui/') self.settings.set("UI_DIR", ui_dir) data_dir = os.path.join(os.path.dirname(__file__), 'data/') self.settings.set("DATA_DIR", data_dir) self.ui_dir = self.settings.get("UI_DIR") self.ui = Gtk.Builder() self.ui.add_from_file(self.ui_dir + "cnchi.ui") self.add(self.ui.get_object("main")) self.header = self.ui.get_object("box5") self.forward_button = self.ui.get_object("forward_button") self.logo = self.ui.get_object("logo") logo_dir = os.path.join(self.settings.get("DATA_DIR"), "logo_mini.png") self.logo.set_from_file(logo_dir) self.title = self.ui.get_object("title") # To honor our css self.title.set_name("header") self.logo.set_name("header") self.main_box = self.ui.get_object("main_box") self.progressbar = self.ui.get_object("progressbar1") self.forward_button = self.ui.get_object("forward_button") self.exit_button = self.ui.get_object("exit_button") self.backwards_button = self.ui.get_object("backwards_button") # Create a queue. Will be used to report pacman messages (pac.py) # to the main thread (installer_*.py) #self.callback_queue = queue.Queue(0) # Doing some tests with a LIFO queue self.callback_queue = queue.LifoQueue(0) # load all pages # (each one is a screen, a step in the install process) self.pages = dict() params = dict() params['title'] = self.title params['ui_dir'] = self.ui_dir params['forward_button'] = self.forward_button params['backwards_button'] = self.backwards_button params['exit_button'] = self.exit_button params['callback_queue'] = self.callback_queue params['settings'] = self.settings self.pages["welcome"] = welcome.Welcome(params) self.pages["language"] = language.Language(params) self.pages["location"] = location.Location(params) self.pages["check"] = check.Check(params) self.pages["keymap"] = keymap.Keymap(params) self.pages["timezone"] = timezone.Timezone(params) self.pages["installation_ask"] = installation_ask.InstallationAsk(params) self.pages["installation_automatic"] = installation_automatic.InstallationAutomatic(params) self.pages["installation_easy"] = installation_easy.InstallationEasy(params) self.pages["installation_advanced"] = installation_advanced.InstallationAdvanced(params) self.pages["user_info"] = user_info.UserInfo(params) self.pages["slides"] = slides.Slides(params) self.connect("delete-event", Gtk.main_quit) self.ui.connect_signals(self) self.set_title(_('Cinnarch Installer')) self.set_position(Gtk.WindowPosition.CENTER) self.set_resizable(False) self.set_size_request(_main_window_width, _main_window_height); # set window icon icon_dir = os.path.join(self.settings.get("DATA_DIR"), 'cinnarch-icon.png') self.set_icon_from_file(icon_dir) # set the first page to show #self.current_page = self.pages["language"] self.current_page = self.pages["welcome"] self.main_box.add(self.current_page) # Header style testing style_provider = Gtk.CssProvider() style_css = os.path.join(self.settings.get("DATA_DIR"), "gtk-style.css") css = open(style_css, 'rb') css_data = css.read() css.close() style_provider.load_from_data(css_data) Gtk.StyleContext.add_provider_for_screen( Gdk.Screen.get_default(), style_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION ) # show main window self.show_all() self.current_page.prepare('forwards') # hide backwards button self.backwards_button.hide() # Hide titlebar but show border decoration self.get_window().set_accept_focus(True) self.get_window().set_decorations(Gdk.WMDecoration.BORDER) # hide progress bar as it's value is zero self.progressbar.set_fraction(0) self.progressbar.hide() self.progressbar_step = 1.0 / (len(self.pages) - 2) # we drop privileges, but where we should do it? before this? ¿? misc.drop_privileges() with open(tmp_running, "wt") as tmp_file: tmp_file.write("Cnchi %d\n" % 1234) GLib.timeout_add(100, self.pages["slides"].manage_events_from_cb_queue)
def manage_events_from_cb_queue(self): """ We should do as less as possible here, we want to maintain our queue message as empty as possible """ if self.fatal_error: return False if self.callback_queue is None: return True while not self.callback_queue.empty(): try: event = self.callback_queue.get_nowait() except queue.Empty: return True if event[0] == 'percent': self.progress_bar.set_fraction(float(event[1])) elif event[0] == 'downloads_percent': self.downloads_progress_bar.set_fraction(float(event[1])) elif event[0] == 'text': if event[1] == 'hide': self.progress_bar.set_show_text(False) self.progress_bar.set_text("") else: self.progress_bar.set_show_text(True) self.progress_bar.set_text(event[1]) elif event[0] == 'pulse': if event[1] == 'stop': self.stop_pulse() elif event[1] == 'start': self.start_pulse() elif event[0] == 'progress_bar': if event[1] == 'hide': self.progress_bar.hide() elif event[0] == 'downloads_progress_bar': if event[1] == 'hide': self.downloads_progress_bar.hide() if event[1] == 'show': self.downloads_progress_bar.show() elif event[0] == 'finished': logging.info(event[1]) if not self.settings.get('bootloader_installation_successful'): # Warn user about GRUB and ask if we should open wiki page. boot_warn = _( "IMPORTANT: There may have been a problem with the bootloader\n" "installation which could prevent your system from booting properly. Before\n" "rebooting, you may want to verify whether or not the bootloader is installed and\n" "configured. The Arch Linux Wiki contains troubleshooting information:\n" "\thttps://wiki.archlinux.org/index.php/GRUB\n" "\nWould you like to view the wiki page now?") response = show.question(self.get_toplevel(), boot_warn) if response == Gtk.ResponseType.YES: import webbrowser misc.drop_privileges() webbrowser.open( 'https://wiki.archlinux.org/index.php/GRUB') install_ok = _( "Installation Complete!\nDo you want to restart your system now?" ) response = show.question(self.get_toplevel(), install_ok) misc.remove_temp_files() self.settings.set('stop_all_threads', True) logging.shutdown() if response == Gtk.ResponseType.YES: self.reboot() else: sys.exit(0) return False elif event[0] == 'error': self.callback_queue.task_done() # A fatal error has been issued. We empty the queue self.empty_queue() # Show the error show.fatal_error(self.get_toplevel(), event[1]) elif event[0] == 'info': logging.info(event[1]) if self.should_pulse: self.progress_bar.set_text(event[1]) else: self.set_message(event[1]) self.callback_queue.task_done() return True