def populate_devices(self): with misc.raised_privileges(): device_list = parted.getAllDevices() self.device_store.remove_all() self.devices = {} self.bootloader_device_entry.remove_all() self.bootloader_devices.clear() 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"): # hard drives measure themselves assuming kilo=1000, mega=1mil, etc size_in_gigabytes = int((dev.length * dev.sectorSize) / 1000000000) line = '{0} [{1} GB] ({2})'.format(dev.model, size_in_gigabytes, dev.path) self.device_store.append_text(line) self.devices[line] = dev.path self.bootloader_device_entry.append_text(line) self.bootloader_devices[line] = dev.path logging.debug(line) self.select_first_combobox_item(self.device_store) self.select_first_combobox_item(self.bootloader_device_entry)
def unzip_and_copy(self, zip_path): """ Unzip (decompress) a zip file using zipfile standard module """ import zipfile dst_dir = "/tmp" with zipfile.ZipFile(zip_path) as zip_file: for member in zip_file.infolist(): zip_file.extract(member, dst_dir) full_path = os.path.join(dst_dir, member.filename) dst_full_path = os.path.join( "/usr/share/thus", full_path.split("/tmp/thus-{0}/".format(_branch))[1]) if os.path.isfile( dst_full_path) and dst_full_path in self.md5s: if self.md5s[dst_full_path] == get_md5_from_file( full_path): try: with misc.raised_privileges(): shutil.copyfile(full_path, dst_full_path) except FileNotFoundError as file_error: logging.error( _("Can't copy {0} to {1}".format( full_path, dst_full_path))) logging.error(file_error) else: logging.warning( _("Wrong md5. Bad download or wrong file, won't update this one" ))
def uncomment_antergos_mirrors(self): """ Uncomment Antergos mirrors and comment out auto selection so rankmirrors can find the best mirror. """ autoselect = "http://mirrors.antergos.com/$repo/$arch" if os.path.exists(self.antergos_mirrorlist): with open(self.antergos_mirrorlist) as mirrors: lines = [x.strip() for x in mirrors.readlines()] for i in range(len(lines)): if lines[i].startswith("Server") and autoselect in lines[i]: # Comment out auto selection lines[i] = "#" + lines[i] elif lines[i].startswith("#Server") and autoselect not in lines[i]: # Uncomment Antergos mirror lines[i] = lines[i].lstrip("#") # sourceforge server does not get updated as often as necessary if "sourceforge" in lines[i]: lines[i] = "#" + lines[i] with misc.raised_privileges(): # Write new one with open(self.antergos_mirrorlist, 'w') as mirrors: mirrors.write("\n".join(lines) + "\n") self.sync()
def setkb(self): subprocess.check_call(['setxkbmap', '-layout', self.keyboard_layout, "-variant", self.keyboard_variant]) # OpenRC doesn't have localectl if os.path.exists("/usr/bin/localectl"): with misc.raised_privileges(): subprocess.check_call(['localectl', 'set-keymap', '--no-convert', self.keyboard_layout])
def sync(): """ Synchronize cached writes to persistent storage """ with misc.raised_privileges(): try: subprocess.check_call(['sync']) except subprocess.CalledProcessError as why: logging.warning("Can't synchronize cached writes to persistent storage: %s", why)
def unzip_and_copy(self, zip_path): """ Unzip (decompress) a zip file using zipfile standard module """ import zipfile dst_dir = "/tmp" with zipfile.ZipFile(zip_path) as zip_file: for member in zip_file.infolist(): zip_file.extract(member, dst_dir) full_path = os.path.join(dst_dir, member.filename) dst_full_path = os.path.join( "/usr/share/cnchi", full_path.split("/tmp/Cnchi-master/")[1]) if os.path.isfile( dst_full_path) and dst_full_path in self.md5s: if self.md5s[dst_full_path] == get_md5_from_file( full_path): try: with misc.raised_privileges(): shutil.copyfile(full_path, dst_full_path) except FileNotFoundError as file_error: logging.error( _("Can't copy %s to %s"), full_path, dst_full_path) logging.error(file_error) else: logging.warning( _("Wrong md5. Bad download or wrong file, won't update this one" ))
def update_cnchi(): """ Runs updater function to update cnchi to the latest version if necessary """ upd = updater.Updater( force_update=cmd_line.update, local_cnchi_version=info.CNCHI_VERSION) if upd.update(): logging.info("Program updated! Restarting...") misc.remove_temp_files() if cmd_line.update: # Remove -u and --update options from new call new_argv = [] for argv in sys.argv: if argv != "-u" and argv != "--update": new_argv.append(argv) else: new_argv = sys.argv # Do not try to update again now new_argv.append("--disable-update") # Run another instance of Cnchi (which will be the new version) with misc.raised_privileges(): os.execl(sys.executable, *([sys.executable] + new_argv)) sys.exit(0)
def run(self): """ Calculates download package list and then calls run_format and run_install. Takes care of the exceptions, too. """ try: # Before formatting, let's try to calculate package download list # this way, if something fails (a missing package, mostly) we have # not formatted anything yet. pkg = pack.SelectPackages(self.settings, self.callback_queue) pkg.create_package_list() if not pkg.packages or len(pkg.packages) == 0: txt = _("Cannot create package list. Check log output for details.") raise misc.InstallError(txt) down = download.DownloadPackages( package_names=pkg.packages, download_module='requests', pacman_conf_file="/etc/pacman.conf", pacman_cache_dir="/var/cache/pacman/pkg", cache_dir="/var/cache/pacman/pkg", settings=self.settings, callback_queue=self.callback_queue) down.create_metalinks_list() if not down.metalinks or len(down.metalinks) == 0: txt = _("Cannot create download package list (metalinks). Check log output for details.") raise misc.InstallError(txt) # try except if pkg.packages is empty or down.metalinks is empty with misc.raised_privileges(): self.install_screen.run_format() self.install_screen.run_install(pkg.packages, down.metalinks) except subprocess.CalledProcessError as process_error: txt = "Error running command {0}: {1}".format(process_error.cmd, process_error.output) logging.error(txt) exc_type, exc_value, exc_traceback = sys.exc_info() trace = traceback.format_exception(exc_type, exc_value, exc_traceback) for line in trace: logging.error(line.rstrip()) txt = _("Error running command {0}: {1}").format(process_error.cmd, process_error.output) self.queue_fatal_event(txt) except (misc.InstallError, pyalpm.error, KeyboardInterrupt, TypeError, AttributeError, OSError, IOError) as install_error: logging.error(install_error) exc_type, exc_value, exc_traceback = sys.exc_info() trace = traceback.format_exception(exc_type, exc_value, exc_traceback) for line in trace: logging.error(line.rstrip()) self.queue_fatal_event(install_error)
def unzip_and_copy(self, zip_path): """ Unzip (decompress) a zip file using zipfile standard module and copy DSGos_Installer's files to their destinations """ import zipfile dst_dir = "/tmp" # First check all md5 signatures all_md5_ok = True with zipfile.ZipFile(zip_path) as zip_file: # Check md5 sums for member in zip_file.infolist(): zip_file.extract(member, dst_dir) full_path = os.path.join(dst_dir, member.filename) dst_full_path = os.path.join( "/usr/share/DSGos_Installer", full_path.split("/tmp/DSGos_Installer-master/")[1]) if os.path.isfile(dst_full_path): if dst_full_path in self.md5s: if "update.info" not in dst_full_path and self.md5s[dst_full_path] != get_md5_from_file(full_path): logging.warning( _("Wrong md5 (%s). Bad download or wrong file, DSGos_Installer won't update itself"), member.filename) all_md5_ok = False break else: logging.warning( _("File %s is not in md5 signatures list"), member.filename) if all_md5_ok: # All md5 sums where ok. Let's copy all files for member in zip_file.infolist(): full_path = os.path.join(dst_dir, member.filename) dst_full_path = os.path.join( "/usr/share/DSGos_Installer", full_path.split("/tmp/DSGos_Installer-master/")[1]) if os.path.isfile(dst_full_path): try: with misc.raised_privileges(): logging.debug( _("Copying %s to %s..."), full_path, dst_full_path) shutil.copyfile(full_path, dst_full_path) except FileNotFoundError as file_error: logging.error( _("Can't copy %s to %s"), full_path, dst_full_path) logging.error(file_error)
def filter_and_sort_arch_mirrorlist(self): output = '# Arch Linux mirrorlist generated by Cnchi #\n' mlist = self.get_mirror_stats() mirrors = self.sort_mirrors_by_speed(mirrors=mlist) for mirror in mirrors: line = "Server = {0}{1}/os/{2}\n".format(mirror['url'], '$repo', '$arch') output += line # Write modified Arch mirrorlist with misc.raised_privileges(): with open(self.arch_mirrorlist, 'w') as arch_mirrors: arch_mirrors.write(output) self.sync()
def unzip_and_copy(self, zip_path): """ Unzip (decompress) a zip file using zipfile standard module and copy cnchi's files to their destinations """ import zipfile dst_dir = "/tmp" # First check all md5 signatures all_md5_ok = True with zipfile.ZipFile(zip_path) as zip_file: # Check md5 sums for member in zip_file.infolist(): zip_file.extract(member, dst_dir) full_path = os.path.join(dst_dir, member.filename) dst_full_path = os.path.join( "/usr/share/cnchi", full_path.split("/tmp/Cnchi-master/")[1]) if os.path.isfile(dst_full_path): if dst_full_path in self.md5s: if "update.info" not in dst_full_path and self.md5s[ dst_full_path] != get_md5_from_file(full_path): logging.warning( _("Wrong md5 (%s). Bad download or wrong file, Cnchi won't update itself" ), member.filename) all_md5_ok = False break else: logging.warning( _("File %s is not in md5 signatures list"), member.filename) if all_md5_ok: # All md5 sums where ok. Let's copy all files for member in zip_file.infolist(): full_path = os.path.join(dst_dir, member.filename) dst_full_path = os.path.join( "/usr/share/cnchi", full_path.split("/tmp/Cnchi-master/")[1]) if os.path.isfile(dst_full_path): try: with misc.raised_privileges(): logging.debug(_("Copying %s to %s..."), full_path, dst_full_path) shutil.copyfile(full_path, dst_full_path) except FileNotFoundError as file_error: logging.error(_("Can't copy %s to %s"), full_path, dst_full_path) logging.error(file_error)
def update_mirrorlist(self): """ Make sure we have the latest antergos-mirrorlist files """ with misc.raised_privileges(): try: cmd = ['pacman', '-Syy', '--noconfirm', '--noprogressbar', '--quiet', 'antergos-mirrorlist'] with open(os.devnull, 'w') as fnull: subprocess.call(cmd, stdout=fnull, stderr=subprocess.STDOUT) # Use the new downloaded mirrorlist (.pacnew) files (if any) pacnew_path = self.antergos_mirrorlist + ".pacnew" if os.path.exists(pacnew_path): shutil.copy(pacnew_path, self.antergos_mirrorlist) except subprocess.CalledProcessError as why: logging.debug('Update of antergos-mirrorlist package failed with error: %s', why) except OSError as why: logging.debug('Error copying new mirrorlist files: %s', why) self.sync()
def setkb(self): if len(self.keyboard_layout['code']) > 0: cmd = ['setxkbmap', '-layout', self.keyboard_layout['code']] if len(self.keyboard_variant['code']) > 0: cmd.extend(["-variant", self.keyboard_variant['code']]) try: subprocess.check_call(cmd) except subprocess.CalledProcessError as process_error: logging.warning(process_error) with misc.raised_privileges(): cmd = ['localectl', 'set-keymap', '--no-convert', self.keyboard_layout['code']] try: subprocess.check_call(cmd) except subprocess.CalledProcessError as process_error: logging.warning(process_error)
def run_rankmirrors(self): if os.path.exists("/usr/bin/rankmirrors"): # Uncomment Antergos mirrors and comment out auto selection so # rankmirrors can find the best mirror. self.uncomment_antergos_mirrors() with misc.raised_privileges(): try: # Store rankmirrors output in a temporary file with tempfile.TemporaryFile(mode='w+t') as temp_file: cmd = ['rankmirrors', '-n', '0', '-r', 'antergos', self.antergos_mirrorlist] subprocess.call(cmd, stdout=temp_file) temp_file.seek(0) # Copy new mirrorlist to the old one with open(self.antergos_mirrorlist, 'w') as antergos_mirrorlist_file: antergos_mirrorlist_file.write(temp_file.read()) except subprocess.CalledProcessError as why: logging.debug('Error running rankmirrors on Antergos mirrorlist: %s', why) self.sync()
def update_thus(): """ Runs updater function to update thus to the latest version if necessary """ upd = updater.Updater(force_update=cmd_line.update) if upd.update(): logging.info(_("Program updated! Restarting...")) misc.remove_temp_files() if cmd_line.update: # Remove -u and --update options from new call new_argv = [] for argv in sys.argv: if argv != "-u" and argv != "--update": new_argv.append(argv) else: new_argv = sys.argv # Do not try to update again now new_argv.append("--disable-update") # Run another instance of Thus (which will be the new version) with misc.raised_privileges(): os.execl(sys.executable, *([sys.executable] + new_argv)) sys.exit(0)
def run(self): """ Run thread """ # Wait until there is an Internet connection available while not misc.has_connection(): time.sleep(1) # Delay if not os.path.exists(self.reflector_script): logging.warning(_("Can't find update mirrors script")) return # Uncomment Antergos mirrors and comment out auto selection so rankmirrors can find the best mirror. autoselect = "http://mirrors.antergos.com/$repo/$arch" if os.path.exists(self.antergos_mirrorlist): with open(self.antergos_mirrorlist) as mirrors: lines = [x.strip() for x in mirrors.readlines()] for i in range(len(lines)): if lines[i].startswith("Server") and autoselect in lines[i]: # Comment out auto selection lines[i] = "#" + lines[i] elif lines[i].startswith("#Server") and autoselect not in lines[i]: # Uncomment Antergos mirror lines[i] = lines[i].lstrip("#") with misc.raised_privileges(): # Backup original file shutil.copy(self.antergos_mirrorlist, self.antergos_mirrorlist + ".cnchi_backup") # Write new one with open(self.antergos_mirrorlist, 'w') as mirrors: mirrors.write("\n".join(lines) + "\n") # Run rankmirrors command try: with misc.raised_privileges(): self.rankmirrors_pid = subprocess.Popen([self.reflector_script]).pid except subprocess.CalledProcessError as process_error: logging.error(_("Couldn't execute auto mirror selection")) logging.error(process_error) # Check arch mirrorlist against mirror status data, remove any bad mirrors. if os.path.exists(self.arch_mirrorlist): # Use session to avoid silly warning # See https://github.com/kennethreitz/requests/issues/1882 with requests.Session() as session: status = session.get(self.arch_mirror_status).json() mirrors = status['urls'] with open(self.arch_mirrorlist) as arch_mirrors: lines = [x.strip() for x in arch_mirrors.readlines()] for i in range(len(lines)): server_uncommented = lines[i].startswith("Server") server_commented = lines[i].startswith("#Server") if server_commented or server_uncommented: url = lines[i].split('=')[1].strip() check = self.check_mirror_status(mirrors, url) if not check and server_uncommented: # Bad mirror, comment it logging.debug('Removing bad mirror: %s', lines[i]) lines[i] = "#" + lines[i] if check and server_commented: # It's a good mirror, uncomment it lines[i] = lines[i].lstrip("#") with misc.raised_privileges(): # Backup original file shutil.copy(self.arch_mirrorlist, self.arch_mirrorlist + ".cnchi_backup") # Write new one with open(self.arch_mirrorlist, 'w') as arch_mirrors: arch_mirrors.write("\n".join(lines) + "\n") logging.debug(_("Auto mirror selection has been run successfully"))
def run_installation(self): """ Run installation From this point, on a warning situation, Thus should try to continue, so we need to catch the exception here. If we don't catch the exception here, it will be catched in run() and managed as a fatal error. On the other hand, if we want to clarify the exception message we can catch it here and then raise an InstallError exception. """ # Create the directory where we will mount our new root partition try: os.makedirs(DEST_DIR) except OSError: # If we're recovering from a failed/stoped install, there'll be # some mounted directories. Try to unmount them first. auto_partition.unmount_all(DEST_DIR) # Create, format and mount partitions in automatic mode if self.method == 'automatic': logging.debug( _("Creating partitions and their filesystems in {0}".format( self.auto_device))) # If no key password is given a key file is generated and stored in /boot # (see auto_partition.py) auto = auto_partition.AutoPartition( dest_dir=DEST_DIR, auto_device=self.auto_device, use_luks=self.settings.get("use_luks"), luks_password=self.settings.get("luks_root_password"), use_lvm=self.settings.get("use_lvm"), use_home=self.settings.get("use_home"), bootloader=self.settings.get("bootloader"), callback_queue=self.callback_queue) auto.run() # used in modify_grub_default() and fstab self.mount_devices = auto.get_mount_devices() # used when configuring fstab self.fs_devices = auto.get_fs_devices() # In advanced mode we only need to mount partitions if self.method == 'advanced': for path in sorted(self.mount_devices): if path == "" or path == "swap": continue mount_part = self.mount_devices[path] mount_dir = DEST_DIR + path os.makedirs(mount_dir, exist_ok=True) try: logging.debug( _("Mounting partition {0} into {1} directory".format( mount_part, mount_dir))) subprocess.check_call(['mount', mount_part, mount_dir]) except subprocess.CalledProcessError as err: logging.warning( _("Can't mount {0} in {1}".format( mount_part, mount_dir))) logging.warning( _("Command {0} has failed.".format(err.cmd))) logging.warning(_("Output : {0}".format(err.output))) # Nasty workaround: # If pacman was stoped and /var is in another partition than root # (so as to be able to resume install), database lock file will still # be in place. # We must delete it or this new installation will fail db_lock = os.path.join(DEST_DIR, "var/lib/pacman/db.lck") if os.path.exists(db_lock): with misc.raised_privileges(): os.remove(db_lock) logging.debug(_("{0} deleted".format(db_lock))) # Create some needed folders os.makedirs(os.path.join(DEST_DIR, 'var/lib/pacman'), exist_ok=True) os.makedirs(os.path.join(DEST_DIR, 'etc/pacman.d/gnupg'), exist_ok=True) os.makedirs(os.path.join(DEST_DIR, 'var/log'), exist_ok=True) all_ok = True try: logging.debug(_('Install System ...')) self.install_system() logging.debug(_('System installed.')) logging.debug(_('Configuring system ...')) self.configure_system() logging.debug(_('System configured.')) except subprocess.CalledProcessError as err: logging.error(err) self.queue_fatal_event("CalledProcessError.output = {0}".format( err.output)) all_ok = False except InstallError as err: logging.error(err) self.queue_fatal_event(err.value) all_ok = False except Exception as err: try: logging.debug( 'Exception: {0}. Trying to continue.'.format(err)) all_ok = True pass except Exception as err: txt = ('Unknown Error: {0}. Unable to continue.'.format(err)) logging.debug(txt) self.queue_fatal_event(txt) self.running = False self.error = True all_ok = False if all_ok is False: self.error = True return False else: # Last but not least, copy Thus log to new installation datetime = time.strftime("%Y%m%d") + "-" + time.strftime("%H%M%S") dst = os.path.join(DEST_DIR, "var/log/thus-{0}.log".format(datetime)) try: shutil.copy("/tmp/thus.log", dst) except FileNotFoundError: logging.warning(_("Can't copy Thus log to {0}".format(dst))) except FileExistsError: pass source_dirs = ["/source", "/source_desktop"] partition_dirs = [] for path in sorted(self.mount_devices, reverse=True): if path == "" or path == "swap" or path == "/": continue partition_dirs += [DEST_DIR + path] install_dirs = ["/install"] unmount_points = source_dirs + partition_dirs + install_dirs logging.debug("Paths to unmount: {0}".format(unmount_points)) for p in unmount_points: (fsname, fstype, writable) = misc.mount_info(p) if fsname: logging.debug(_("Unmounting {0}".format(p))) try: subprocess.check_call(['umount', p]) except subprocess.CalledProcessError: logging.debug("Can't unmount. Try -l to force it.") try: subprocess.check_call(["umount", "-l", p]) except subprocess.CalledProcessError as err: logging.warning(_( "Unable to umount {0}".format(p))) logging.warning( _("Command {0} has failed.".format(err.cmd))) logging.warning( _("Output : {0}".format(err.output))) # Installation finished successfully self.queue_event("finished", _("Installation finished successfully.")) self.running = False self.error = False return True
def run_installation(self): """ Run installation From this point, on a warning situation, Thus should try to continue, so we need to catch the exception here. If we don't catch the exception here, it will be catched in run() and managed as a fatal error. On the other hand, if we want to clarify the exception message we can catch it here and then raise an InstallError exception. """ # Create the directory where we will mount our new root partition try: os.makedirs(DEST_DIR) except OSError: # If we're recovering from a failed/stoped install, there'll be # some mounted directories. Try to unmount them first. auto_partition.unmount_all(DEST_DIR) # Create, format and mount partitions in automatic mode if self.method == 'automatic': logging.debug(_("Creating partitions and their filesystems in {0}" .format(self.auto_device))) # If no key password is given a key file is generated and stored in /boot # (see auto_partition.py) auto = auto_partition.AutoPartition( dest_dir=DEST_DIR, auto_device=self.auto_device, use_luks=self.settings.get("use_luks"), luks_password=self.settings.get("luks_root_password"), use_lvm=self.settings.get("use_lvm"), use_home=self.settings.get("use_home"), bootloader=self.settings.get("bootloader"), callback_queue=self.callback_queue ) auto.run() # used in modify_grub_default() and fstab self.mount_devices = auto.get_mount_devices() # used when configuring fstab self.fs_devices = auto.get_fs_devices() # In advanced mode we only need to mount partitions if self.method == 'advanced': for path in sorted(self.mount_devices): if path == "" or path == "swap": continue mount_part = self.mount_devices[path] mount_dir = DEST_DIR + path os.makedirs(mount_dir, exist_ok=True) try: logging.debug(_("Mounting partition {0} into {1} directory" .format(mount_part, mount_dir))) subprocess.check_call(['mount', mount_part, mount_dir]) except subprocess.CalledProcessError as err: logging.warning(_("Can't mount {0} in {1}" .format(mount_part, mount_dir))) logging.warning(_("Command {0} has failed." .format(err.cmd))) logging.warning(_("Output : {0}".format(err.output))) # Nasty workaround: # If pacman was stoped and /var is in another partition than root # (so as to be able to resume install), database lock file will still # be in place. # We must delete it or this new installation will fail db_lock = os.path.join(DEST_DIR, "var/lib/pacman/db.lck") if os.path.exists(db_lock): with misc.raised_privileges(): os.remove(db_lock) logging.debug(_("{0} deleted".format(db_lock))) # Create some needed folders os.makedirs(os.path.join(DEST_DIR, 'var/lib/pacman'), exist_ok=True) os.makedirs(os.path.join(DEST_DIR, 'etc/pacman.d/gnupg'), exist_ok=True) os.makedirs(os.path.join(DEST_DIR, 'var/log'), exist_ok=True) all_ok = True try: logging.debug(_('Install System ...')) self.install_system() logging.debug(_('System installed.')) logging.debug(_('Configuring system ...')) self.configure_system() logging.debug(_('System configured.')) except subprocess.CalledProcessError as err: logging.error(err) self.queue_fatal_event("CalledProcessError.output = {0}".format(err.output)) all_ok = False except InstallError as err: logging.error(err) self.queue_fatal_event(err.value) all_ok = False except Exception as err: try: logging.debug('Exception: {0}. Trying to continue.'.format(err)) all_ok = True pass except Exception as err: txt = ('Unknown Error: {0}. Unable to continue.'.format(err)) logging.debug(txt) self.queue_fatal_event(txt) self.running = False self.error = True all_ok = False if all_ok is False: self.error = True return False else: # Last but not least, copy Thus log to new installation datetime = time.strftime("%Y%m%d") + "-" + time.strftime("%H%M%S") dst = os.path.join(DEST_DIR, "var/log/thus-{0}.log".format(datetime)) try: shutil.copy("/tmp/thus.log", dst) except FileNotFoundError: logging.warning(_("Can't copy Thus log to {0}".format(dst))) except FileExistsError: pass source_dirs = ["/source", "/source_desktop"] partition_dirs = [] for path in sorted(self.mount_devices, reverse=True): if path == "" or path == "swap" or path == "/": continue partition_dirs += [DEST_DIR + path] install_dirs = ["/install"] unmount_points = source_dirs + partition_dirs + install_dirs logging.debug("Paths to unmount: {0}".format(unmount_points)) for p in unmount_points: (fsname, fstype, writable) = misc.mount_info(p) if fsname: logging.debug(_("Unmounting {0}".format(p))) try: subprocess.check_call(['umount', p]) except subprocess.CalledProcessError: logging.debug("Can't unmount. Try -l to force it.") try: subprocess.check_call(["umount", "-l", p]) except subprocess.CalledProcessError as err: logging.warning(_("Unable to umount {0}".format(p))) logging.warning(_("Command {0} has failed." .format(err.cmd))) logging.warning(_("Output : {0}" .format(err.output))) # Installation finished successfully self.queue_event("finished", _("Installation finished successfully.")) self.running = False self.error = False return True
def start(self): """ Run installation """ ''' From this point, on a warning situation, Cnchi should try to continue, so we need to catch the exception here. If we don't catch the exception here, it will be catched in run() and managed as a fatal error. On the other hand, if we want to clarify the exception message we can catch it here and then raise an InstallError exception. ''' if not os.path.exists(DEST_DIR): with misc.raised_privileges(): os.makedirs(DEST_DIR, mode=0o755, exist_ok=True) # Mount needed partitions (in automatic it's already done) if self.method == 'alongside' or self.method == 'advanced': self.mount_partitions() # Nasty workaround: # If pacman was stoped and /var is in another partition than root # (so as to be able to resume install), database lock file will still be in place. # We must delete it or this new installation will fail db_lock = os.path.join(DEST_DIR, "var/lib/pacman/db.lck") if os.path.exists(db_lock): with misc.raised_privileges(): os.remove(db_lock) logging.debug("%s deleted", db_lock) # Create some needed folders folders = [ os.path.join(DEST_DIR, 'var/lib/pacman'), os.path.join(DEST_DIR, 'etc/pacman.d/gnupg'), os.path.join(DEST_DIR, 'var/log')] for folder in folders: os.makedirs(folder, mode=0o755, exist_ok=True) # If kernel images exists in /boot they are most likely from a failed install attempt and need # to be removed otherwise pyalpm will raise a fatal exception later on. kernel_imgs = ( "/install/boot/vmlinuz-linux", "/install/boot/vmlinuz-linux-lts", "/install/boot/initramfs-linux.img", "/install/boot/initramfs-linux-fallback.img", "/install/boot/initramfs-linux-lts.img", "/install/boot/initramfs-linux-lts-fallback.img") for img in kernel_imgs: if os.path.exists(img): os.remove(img) logging.debug("Preparing pacman...") self.prepare_pacman() logging.debug("Pacman ready") logging.debug("Downloading packages...") self.download_packages() logging.debug("Installing packages...") self.install_packages() logging.debug("Configuring system...") self.configure_system() self.running = False # Installation finished successfully self.queue_event('finished', _("Installation finished")) self.error = False return True
def run(self): """ Calculates download package list and then calls run_format and run_install. Takes care of the exceptions, too. """ try: # Before formatting, let's try to calculate package download list # this way, if something fails (a missing package, mostly) we have # not formatted anything yet. pkg = pack.SelectPackages(self.settings, self.callback_queue) pkg.create_package_list() if not pkg.packages or len(pkg.packages) == 0: txt = _( "Cannot create package list. Check log output for details." ) raise misc.InstallError(txt) down = download.DownloadPackages( package_names=pkg.packages, download_module='requests', pacman_conf_file="/etc/pacman.conf", pacman_cache_dir="/var/cache/pacman/pkg", cache_dir="/var/cache/pacman/pkg", settings=self.settings, callback_queue=self.callback_queue) down.create_metalinks_list() if not down.metalinks or len(down.metalinks) == 0: txt = _( "Cannot create download package list (metalinks). Check log output for details." ) raise misc.InstallError(txt) # try except if pkg.packages is empty or down.metalinks is empty with misc.raised_privileges(): self.install_screen.run_format() self.install_screen.run_install(pkg.packages, down.metalinks) except subprocess.CalledProcessError as process_error: txt = "Error running command {0}: {1}".format( process_error.cmd, process_error.output) logging.error(txt) exc_type, exc_value, exc_traceback = sys.exc_info() trace = traceback.format_exception(exc_type, exc_value, exc_traceback) for line in trace: logging.error(line.rstrip()) txt = _("Error running command {0}: {1}").format( process_error.cmd, process_error.output) self.queue_fatal_event(txt) except (misc.InstallError, pyalpm.error, KeyboardInterrupt, TypeError, AttributeError, OSError, IOError) as install_error: logging.error(install_error) exc_type, exc_value, exc_traceback = sys.exc_info() trace = traceback.format_exception(exc_type, exc_value, exc_traceback) for line in trace: logging.error(line.rstrip()) self.queue_fatal_event(install_error)