def request_backup(self, app_config: dict, key: str, i18n: I18n, root_password: str = None) -> bool: if bool(app_config['backup']['enabled']) and timeshift.is_available(): val = app_config['backup'][key] if key else None if val is None: # ask mode if self.request_confirmation( title=i18n['core.config.tab.backup'], body=i18n['action.backup.msg'], confirmation_label=i18n['yes'].capitalize(), deny_label=i18n['no'].capitalize()): res = self._generate_backup(app_config, i18n, root_password) self.change_substatus('') return res elif val is True: # direct mode res = self._generate_backup(app_config, i18n, root_password) self.change_substatus('') return res return True
def _check_backup_requirements(self, app_config: dict, pkg: Optional[PackageView], action_key: Optional[str]) -> bool: if pkg and not pkg.model.supports_backup(): return False if action_key and app_config['backup'][action_key] is False: return False return bool(app_config['backup']['enabled']) and timeshift.is_available()
def _gen_backup_settings(self, core_config: dict, screen_width: int, screen_height: int) -> TabComponent: if timeshift.is_available(): default_width = floor(0.22 * screen_width) enabled_opt = self._gen_bool_component(label=self.i18n['core.config.backup'], tooltip=None, value=bool(core_config['backup']['enabled']), id_='enabled', max_width=default_width) ops_opts = [(self.i18n['yes'].capitalize(), True, None), (self.i18n['no'].capitalize(), False, None), (self.i18n['ask'].capitalize(), None, None)] install_mode = self._gen_select(label=self.i18n['core.config.backup.install'], tip=None, value=core_config['backup']['install'], opts=ops_opts, max_width=default_width, id_='install') uninstall_mode = self._gen_select(label=self.i18n['core.config.backup.uninstall'], tip=None, value=core_config['backup']['uninstall'], opts=ops_opts, max_width=default_width, id_='uninstall') upgrade_mode = self._gen_select(label=self.i18n['core.config.backup.upgrade'], tip=None, value=core_config['backup']['upgrade'], opts=ops_opts, max_width=default_width, id_='upgrade') downgrade_mode = self._gen_select(label=self.i18n['core.config.backup.downgrade'], tip=None, value=core_config['backup']['downgrade'], opts=ops_opts, max_width=default_width, id_='downgrade') mode = self._gen_select(label=self.i18n['core.config.backup.mode'], tip=None, value=core_config['backup']['mode'], opts=[ (self.i18n['core.config.backup.mode.incremental'], 'incremental', self.i18n['core.config.backup.mode.incremental.tip']), (self.i18n['core.config.backup.mode.only_one'], 'only_one', self.i18n['core.config.backup.mode.only_one.tip']) ], max_width=default_width, id_='mode') sub_comps = [FormComponent([enabled_opt, mode, install_mode, uninstall_mode, upgrade_mode, downgrade_mode], spaces=False)] return TabComponent(self.i18n['core.config.tab.backup'].capitalize(), PanelComponent(sub_comps), None, 'core.bkp')
def _generate_backup(self, app_config: dict, i18n: I18n, root_password: str) -> bool: if timeshift.is_available(): if app_config['backup']['mode'] not in ('only_one', 'incremental'): self.show_message(title=self.i18n['error'].capitalize(), body='{}: {}'.format( self.i18n['action.backup.invalid_mode'], bold(app_config['backup']['mode'])), type_=MessageType.ERROR) return False if not user.is_root() and not root_password: root_pwd, valid = self.request_root_password() else: root_pwd, valid = root_password, True if not valid: return False handler = ProcessHandler(self) if app_config['backup']['mode'] == 'only_one': self.change_substatus('[{}] {}'.format( i18n['core.config.tab.backup'].lower(), i18n['action.backup.substatus.delete'])) deleted, _ = handler.handle_simple( timeshift.delete_all_snapshots(root_pwd)) if not deleted and not self.request_confirmation( title=i18n['core.config.tab.backup'], body='{}. {}'.format( i18n['action.backup.error.delete'], i18n['action.backup.error.proceed']), confirmation_label=i18n['yes'].capitalize(), deny_label=i18n['no'].capitalize()): return False self.change_substatus('[{}] {}'.format( i18n['core.config.tab.backup'].lower(), i18n['action.backup.substatus.create'])) created, _ = handler.handle_simple( timeshift.create_snapshot(root_pwd, app_config['backup']['type'])) if not created and not self.request_confirmation( title=i18n['core.config.tab.backup'], body='{}. {}'.format(i18n['action.backup.error.create'], i18n['action.backup.error.proceed']), confirmation_label=i18n['yes'].capitalize(), deny_label=i18n['no'].capitalize()): return False return True
def run(self): valid_password, root_password = self._request_password() if not valid_password: self.notify_finished({ 'success': False, 'updated': 0, 'types': set(), 'id': None }) self.pkgs = None return to_update = [ pkg for pkg in self.pkgs if pkg.model.update and not pkg.model.is_update_ignored() and pkg.update_checked ] if len(to_update) > 1: self.disable_progress_controll() else: self.enable_progress_controll() success = False updated, updated_types = 0, set() models = [view.model for view in to_update] self.change_substatus(self.i18n['action.update.requirements.status']) requirements = self.manager.get_upgrade_requirements( models, root_password, self) if not requirements: self.pkgs = None self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) return comps, required_size, extra_size = [], 0, 0 if requirements.cannot_upgrade: comps.append( self._gen_cannot_update_form(requirements.cannot_upgrade)) if requirements.to_install: req_form, reqs_size = self._gen_to_install_form( requirements.to_install) required_size += reqs_size[0] extra_size += reqs_size[1] comps.append(req_form) if requirements.to_remove: comps.append(self._gen_to_remove_form(requirements.to_remove)) updates_form, updates_size = self._gen_to_update_form( requirements.to_upgrade) required_size += updates_size[0] extra_size += updates_size[1] comps.append(updates_form) extra_size_text = '{}: {}'.format( self.i18n['action.update.total_size'].capitalize(), get_human_size_str(extra_size)) req_size_text = '{}: {}'.format( self.i18n['action.update.required_size'].capitalize(), get_human_size_str(required_size)) comps.insert( 0, TextComponent('{} | {}'.format(extra_size_text, req_size_text), size=14)) comps.insert(1, TextComponent('')) if not self.request_confirmation( title=self.i18n['action.update.summary'].capitalize(), body='', components=comps, confirmation_label=self.i18n['proceed'].capitalize(), deny_label=self.i18n['cancel'].capitalize()): self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) self.pkgs = None return self.change_substatus('') app_config = read_config() # trim dialog if app_config['disk']['trim']['after_upgrade'] is not False: should_trim = app_config['disk']['trim'][ 'after_upgrade'] or self._ask_for_trim() else: should_trim = False # backup process ( if enabled, supported and accepted ) if bool(app_config['backup'] ['enabled']) and app_config['backup']['upgrade'] in ( True, None) and timeshift.is_available(): any_requires_bkp = False for dep in requirements.to_upgrade: if dep.pkg.supports_backup(): any_requires_bkp = True break if any_requires_bkp: if not self.request_backup(app_config, 'upgrade', self.i18n, root_password): self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': None }) self.pkgs = None return self.change_substatus('') timestamp = datetime.now() upgrade_id = 'upgrade_{}{}{}_{}'.format(timestamp.year, timestamp.month, timestamp.day, int(time.time())) self._write_summary_log(upgrade_id, requirements) success = bool(self.manager.upgrade(requirements, root_password, self)) self.change_substatus('') if success: updated = len(requirements.to_upgrade) updated_types.update( (req.pkg.__class__ for req in requirements.to_upgrade)) if should_trim: self._trim_disk(root_password) if bool(app_config['updates']['ask_for_reboot']): msg = '<p>{}</p>{}</p><br/><p>{}</p>'.format( self.i18n['action.update.success.reboot.line1'], self.i18n['action.update.success.reboot.line2'], self.i18n['action.update.success.reboot.line3']) self.request_reboot(msg) self.notify_finished({ 'success': success, 'updated': updated, 'types': updated_types, 'id': upgrade_id }) self.pkgs = None
def _gen_backup_settings(self, core_config: dict) -> Optional[TabComponent]: if timeshift.is_available(): enabled_opt = self._gen_bool_component( label=self.i18n['core.config.backup'], tooltip=None, value=bool(core_config['backup']['enabled']), id_='enabled') ops_opts = [(self.i18n['yes'].capitalize(), True, None), (self.i18n['no'].capitalize(), False, None), (self.i18n['ask'].capitalize(), None, None)] install_mode = new_select( label=self.i18n['core.config.backup.install'], tip=None, value=core_config['backup']['install'], opts=ops_opts, id_='install') uninstall_mode = new_select( label=self.i18n['core.config.backup.uninstall'], tip=None, value=core_config['backup']['uninstall'], opts=ops_opts, id_='uninstall') upgrade_mode = new_select( label=self.i18n['core.config.backup.upgrade'], tip=None, value=core_config['backup']['upgrade'], opts=ops_opts, id_='upgrade') downgrade_mode = new_select( label=self.i18n['core.config.backup.downgrade'], tip=None, value=core_config['backup']['downgrade'], opts=ops_opts, id_='downgrade') mode = new_select( label=self.i18n['core.config.backup.mode'], tip=None, value=core_config['backup']['mode'], opts=[ (self.i18n['core.config.backup.mode.incremental'], 'incremental', self.i18n['core.config.backup.mode.incremental.tip']), (self.i18n['core.config.backup.mode.only_one'], 'only_one', self.i18n['core.config.backup.mode.only_one.tip']) ], id_='mode') type_ = new_select(label=self.i18n['type'].capitalize(), tip=None, value=core_config['backup']['type'], opts=[('rsync', 'rsync', None), ('btrfs', 'btrfs', None)], id_='type') remove_method = core_config['backup']['remove_method'] if not remove_method or remove_method not in BACKUP_REMOVE_METHODS: remove_method = BACKUP_DEFAULT_REMOVE_METHOD remove_i18n = 'core.config.backup.remove_method' remove_opts = ((self.i18n[f'{remove_i18n}.{m}'], m, self.i18n[f'{remove_i18n}.{m}.tip']) for m in sorted(BACKUP_REMOVE_METHODS)) remove_label = f'{self.i18n[remove_i18n]} ({self.i18n["core.config.backup.mode"]} ' \ f'"{self.i18n["core.config.backup.mode.only_one"].capitalize()}")' sel_remove = new_select(label=remove_label, tip=None, value=remove_method, opts=remove_opts, capitalize_label=False, id_='remove_method') inputs = [ enabled_opt, type_, mode, sel_remove, install_mode, uninstall_mode, upgrade_mode, downgrade_mode ] panel = PanelComponent([FormComponent(inputs, spaces=False)], id_='backup') return TabComponent( self.i18n['core.config.tab.backup'].capitalize(), panel, None, 'core.bkp')