def __init__(self, dest_dir, settings, mount_devices): self.dest_dir = dest_dir self.settings = settings self.mount_devices = mount_devices self.method = settings.get("partition_mode") self.root_device = self.mount_devices["/"] self.root_uuid = fs.get_info(self.root_device)['UUID'] if "swap" in self.mount_devices: swap_partition = self.mount_devices["swap"] self.swap_uuid = fs.get_info(swap_partition)['UUID'] if "/boot" in self.mount_devices: boot_device = self.mount_devices["/boot"] self.boot_uuid = fs.get_info(boot_device)['UUID']
def auto_fstab(self): """ Create /etc/fstab file """ partitions = [] for mount_point in self.mount_devices: device = self.mount_devices[mount_point] part_info = fs.get_info(device) partitions.append({ 'device': device, 'fs': self.fs_devices[device], 'mountPoint': mount_point, 'uuid': part_info['UUID'] }) root_mount_point = DEST_DIR with open('/usr/share/thus/thus/installation/fstab.conf', 'r') as f: fstab_config = yaml.load(f) mount_options = fstab_config["mountOptions"] ssd_extra_mount_options = fstab_config.get("ssdExtraMountOptions", {}) use_luks = self.settings.get("use_luks") use_lvm = self.settings.get("use_lvm") method = self.method luks_root_password = self.settings.get("luks_root_password") generator = fstab.FstabGenerator(partitions, root_mount_point, mount_options, ssd_extra_mount_options, use_luks, use_lvm, method, luks_root_password) generator.run() logging.debug(_("fstab written."))
def __init__(self, dest_dir, settings, mount_devices): self.dest_dir = dest_dir self.settings = settings self.mount_devices = mount_devices self.method = settings.get("partition_mode") self.root_device = self.mount_devices["/"] self.root_uuid = fs.get_info(self.root_device)['UUID'] if "swap" in self.mount_devices: swap_partition = self.mount_devices["swap"] self.swap_uuid = fs.get_info(swap_partition)['UUID'] if "/boot" in self.mount_devices: boot_device = self.mount_devices["/boot"] self.boot_uuid = fs.get_info(boot_device)['UUID'] self.vmlinuz = configuration['install']['VMLINUZ'] self.initramfs = configuration['install']['INITRAMFS'] self.fallback = configuration['install']['FALLBACK']
def modify_grub_default(self): """ If using LUKS as root, we need to modify GRUB_CMDLINE_LINUX GRUB_CMDLINE_LINUX : Command-line arguments to add to menu entries for the Linux kernel. GRUB_CMDLINE_LINUX_DEFAULT : Unless ‘GRUB_DISABLE_RECOVERY’ is set to ‘true’, two menu entries will be generated for each Linux kernel: one default entry and one entry for recovery mode. This option lists command-line arguments to add only to the default menu entry, after those listed in ‘GRUB_CMDLINE_LINUX’. """ plymouth_bin = os.path.join(self.dest_dir, "usr/bin/plymouth") if os.path.exists(plymouth_bin): use_splash = "splash" else: use_splash = "" if "swap" in self.mount_devices: cmd_linux_default = 'resume=UUID={0} quiet {1}'.format(self.swap_uuid, use_splash) else: cmd_linux_default = 'quiet {0}'.format(use_splash) self.set_grub_option("GRUB_THEME", "/boot/grub/themes/Elegance_Dark/theme.txt") self.set_grub_option("GRUB_CMDLINE_LINUX_DEFAULT", cmd_linux_default) self.set_grub_option("GRUB_DISTRIBUTOR", "Apricity") if self.settings.get('use_luks'): # Let GRUB automatically add the kernel parameters for root encryption luks_root_volume = self.settings.get('luks_root_volume') logging.debug("Luks Root Volume: %s", luks_root_volume) root_device = self.root_device if self.method == "advanced" and self.settings.get('use_luks_in_root'): # Special case, in advanced when using luks in root device, we store it in luks_root_device root_device = self.settings.get('luks_root_device') root_uuid = fs.get_info(root_device)['UUID'] logging.debug("Root device: %s", root_device) cmd_linux = "cryptdevice=/dev/disk/by-uuid/{0}:{1}".format(root_uuid, luks_root_volume) if self.settings.get("luks_root_password") == "": # No luks password, so user wants to use a keyfile cmd_linux += " cryptkey=/dev/disk/by-uuid/{0}:ext2:/.keyfile-root".format(self.boot_uuid) # Store grub line in settings, we'll use it later in check_root_uuid_in_grub() self.settings.set('GRUB_CMDLINE_LINUX', cmd_linux) # Store grub line in /etc/default/grub file self.set_grub_option("GRUB_CMDLINE_LINUX", cmd_linux) logging.debug(_("/etc/default/grub configuration completed successfully."))
def mkfs(self, device, fs_type, mount_point, label_name, fs_options="", btrfs_devices=""): """ We have two main cases: "swap" and everything else. """ logging.debug("Will mkfs " + device + " as " + fs_type) if fs_type == "swap": try: swap_devices = check_output("swapon -s") if device in swap_devices: subprocess.check_call(["swapoff", device]) subprocess.check_call(["mkswap", "-L", label_name, device]) subprocess.check_call(["swapon", device]) except subprocess.CalledProcessError as err: logging.warning(err.output) else: mkfs = {"xfs": "mkfs.xfs %s -L %s -f %s" % (fs_options, label_name, device), "jfs": "yes | mkfs.jfs %s -L %s %s" % (fs_options, label_name, device), "reiserfs": "yes | mkreiserfs %s -l %s %s" % (fs_options, label_name, device), "ext2": "mkfs.ext2 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext3": "mkfs.ext3 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext4": "mkfs.ext4 -q %s -F -L %s %s" % (fs_options, label_name, device), "btrfs": "mkfs.btrfs %s -L %s %s" % (fs_options, label_name, btrfs_devices), "nilfs2": "mkfs.nilfs2 %s -L %s %s" % (fs_options, label_name, device), "ntfs-3g": "mkfs.ntfs %s -L %s %s" % (fs_options, label_name, device), "vfat": "mkfs.vfat %s -n %s %s" % (fs_options, label_name, device)} # Make sure the fs type is one we can handle if fs_type not in mkfs.keys(): txt = _("Unknown filesystem type %s") % fs_type logging.error(txt) show.error(txt) return command = mkfs[fs_type] try: subprocess.check_call(command.split()) except subprocess.CalledProcessError as err: txt = _("Can't create filesystem %s") % fs_type logging.error(txt) logging.error(err.cmd) logging.error(err.output) show.error(txt) return # Flush filesystem buffers subprocess.check_call(["sync"]) # Create our mount directory path = self.dest_dir + mount_point subprocess.check_call(["mkdir", "-p", path]) # Mount our new filesystem mopts = "rw,relatime" if fs_type == "ext4": mopts = "rw,relatime,data=ordered" elif fs_type == "btrfs": mopts = 'rw,relatime,space_cache,autodefrag,inode_cache' subprocess.check_call(["mount", "-t", fs_type, "-o", mopts, device, path]) logging.debug("AutoPartition done, filesystems mounted:\n" + subprocess.check_output(["mount"]).decode()) # Change permission of base directories to avoid btrfs issues mode = "755" if mount_point == "/tmp": mode = "1777" elif mount_point == "/root": mode = "750" subprocess.check_call(["chmod", mode, path]) fs_uuid = fs.get_info(device)['UUID'] fs_label = fs.get_info(device)['LABEL'] logging.debug("Device details: %s UUID=%s LABEL=%s", device, fs_uuid, fs_label)
def mkfs(self, device, fs_type, mount_point, label_name, fs_options="", btrfs_devices=""): """ We have two main cases: "swap" and everything else. """ logging.debug("Will mkfs " + device + " as " + fs_type) if fs_type == "swap": try: swap_devices = check_output("swapon -s") if device in swap_devices: subprocess.check_call(["swapoff", device]) subprocess.check_call(["mkswap", "-L", label_name, device]) subprocess.check_call(["swapon", device]) except subprocess.CalledProcessError as err: logging.warning(err.output) else: mkfs = { "xfs": "mkfs.xfs %s -L %s -f %s" % (fs_options, label_name, device), "jfs": "yes | mkfs.jfs %s -L %s %s" % (fs_options, label_name, device), "reiserfs": "yes | mkreiserfs %s -l %s %s" % (fs_options, label_name, device), "ext2": "mkfs.ext2 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext3": "mkfs.ext3 -q %s -F -L %s %s" % (fs_options, label_name, device), "ext4": "mkfs.ext4 -q %s -F -L %s %s" % (fs_options, label_name, device), "btrfs": "mkfs.btrfs %s -L %s %s" % (fs_options, label_name, btrfs_devices), "nilfs2": "mkfs.nilfs2 %s -L %s %s" % (fs_options, label_name, device), "ntfs-3g": "mkfs.ntfs %s -L %s %s" % (fs_options, label_name, device), "vfat": "mkfs.vfat %s -n %s %s" % (fs_options, label_name, device) } # Make sure the fs type is one we can handle if fs_type not in mkfs.keys(): txt = _("Unknown filesystem type %s") % fs_type logging.error(txt) show.error(txt) return command = mkfs[fs_type] try: subprocess.check_call(command.split()) except subprocess.CalledProcessError as err: txt = _("Can't create filesystem %s") % fs_type logging.error(txt) logging.error(err.cmd) logging.error(err.output) show.error(txt) return # Flush filesystem buffers subprocess.check_call(["sync"]) # Create our mount directory path = self.dest_dir + mount_point subprocess.check_call(["mkdir", "-p", path]) # Mount our new filesystem mopts = "rw,relatime" if fs_type == "ext4": mopts = "rw,relatime,data=ordered" elif fs_type == "btrfs": mopts = 'rw,relatime,space_cache,autodefrag,inode_cache' subprocess.check_call( ["mount", "-t", fs_type, "-o", mopts, device, path]) logging.debug("AutoPartition done, filesystems mounted:\n" + subprocess.check_output(["mount"]).decode()) # Change permission of base directories to avoid btrfs issues mode = "755" if mount_point == "/tmp": mode = "1777" elif mount_point == "/root": mode = "750" subprocess.check_call(["chmod", mode, path]) fs_uuid = fs.get_info(device)['UUID'] fs_label = fs.get_info(device)['LABEL'] logging.debug("Device details: %s UUID=%s LABEL=%s", device, fs_uuid, fs_label)
def install_gummiboot(self): """ Install Gummiboot bootloader to the EFI System Partition """ # Setup bootloader menu menu_dir = os.path.join(self.dest_dir, "boot/loader") os.makedirs(menu_dir) menu_path = os.path.join(menu_dir, "loader.conf") with open(menu_path, 'w') as menu_file: menu_file.write("default apricity") # Setup boot entries conf = {} if not self.settings.get('use_luks'): conf['default'] = [] conf['default'].append("title\tApricity\n") conf['default'].append("linux\t/vmlinuz-linux\n") conf['default'].append("initrd\t/initramfs-linux.img\n") conf['default'].append("options\troot=UUID={0} rw quiet\n\n".format(self.root_uuid)) conf['fallback'] = [] conf['fallback'].append("title\tApricity (fallback)\n") conf['fallback'].append("linux\t/vmlinuz-linux\n") conf['fallback'].append("initrd\t/initramfs-linux-fallback.img\n") conf['fallback'].append("options\troot=UUID={0} rw quiet\n\n".format(self.root_uuid)) if self.settings.get('feature_lts'): conf['lts'] = [] conf['lts'].append("title\tApricity LTS\n") conf['lts'].append("linux\t/vmlinuz-linux-lts\n") conf['lts'].append("initrd\t/initramfs-linux-lts.img\n") conf['lts'].append("options\troot=UUID={0} rw quiet\n\n".format(self.root_uuid)) conf['lts_fallback'] = [] conf['lts_fallback'].append("title\tApricity LTS (fallback)\n\n") conf['lts_fallback'].append("linux\t/vmlinuz-linux-lts\n") conf['lts_fallback'].append("initrd\t/initramfs-linux-lts-fallback.img\n") conf['lts_fallback'].append("options\troot=UUID={0} rw quiet\n\n".format(self.root_uuid)) else: luks_root_volume = self.settings.get('luks_root_volume') luks_root_volume_device = "/dev/mapper/{0}".format(luks_root_volume) luks_root_volume_uuid = fs.get_info(luks_root_volume_device)['UUID'] # In automatic mode, root_device is in self.mount_devices, as it should be root_device = self.root_device if self.method == "advanced" and self.settings.get('use_luks_in_root'): root_device = self.settings.get('luks_root_device') root_uuid = fs.get_info(root_device)['UUID'] key = "" if self.settings.get("luks_root_password") == "": key = "cryptkey=UUID={0}:ext2:/.keyfile-root".format(self.boot_uuid) root_uuid_line = "cryptdevice=UUID={0}:{1} {2} root=UUID={3} rw quiet" root_uuid_line = root_uuid_line.format(root_uuid, luks_root_volume, key, luks_root_volume_uuid) conf['default'] = [] conf['default'].append("title\tApricity\n") conf['default'].append("linux\t/vmlinuz-linux\n") conf['default'].append("options\tinitrd=/initramfs-linux.img {0}\n\n".format(root_uuid_line)) conf['fallback'] = [] conf['fallback'].append("title\tApricity (fallback)\n") conf['fallback'].append("linux\t/vmlinuz-linux\n") conf['fallback'].append("options\tinitrd=/initramfs-linux-fallback.img {0}\n\n".format(root_uuid_line)) if self.settings.get('feature_lts'): conf['lts'] = [] conf['lts'].append("title\tApricity LTS\n") conf['lts'].append("linux\t/vmlinuz-linux-lts\n") conf['lts'].append("options\tinitrd=/initramfs-linux-lts.img {0}\n\n".format(root_uuid_line)) conf['lts_fallback'] = [] conf['lts_fallback'].append("title\tApricity LTS (fallback)\n") conf['lts_fallback'].append("linux\t/vmlinuz-linux-lts\n") conf['lts_fallback'].append("options\tinitrd=/initramfs-linux-lts-fallback.img {0}\n\n".format(root_uuid_line)) # Write boot entries entries_dir = os.path.join(self.dest_dir, "boot/loader/entries") os.makedirs(entries_dir) entry_path = os.path.join(entries_dir, "apricity.conf") with open(entry_path, 'w') as entry_file: for line in conf['default']: entry_file.write(line) entry_path = os.path.join(entries_dir, "apricity-fallback.conf") with open(entry_path, 'w') as entry_file: for line in conf['fallback']: entry_file.write(line) if self.settings.get('feature_lts'): entry_path = os.path.join(entries_dir, "apricity-lts.conf") with open(entry_path, 'w') as entry_file: for line in conf['lts']: entry_file.write(line) entry_path = os.path.join(entries_dir, "apricity-lts-fallback.conf") with open(entry_path, 'w') as entry_file: for line in conf['lts_fallback']: entry_file.write(line) # Install bootloader logging.debug(_("Installing gummiboot bootloader...")) try: chroot.mount_special_dirs(self.dest_dir) cmd = ['gummiboot', '--path=/boot', 'install'] chroot.run(cmd, self.dest_dir, 300) chroot.umount_special_dirs(self.dest_dir) logging.info(_("Gummiboot install completed successfully")) self.settings.set('bootloader_installation_successful', True) except subprocess.CalledProcessError as process_error: logging.error(_('Command gummiboot failed. Error output: %s'), process_error.output) self.settings.set('bootloader_installation_successful', False) except subprocess.TimeoutExpired: logging.error(_('Command gummiboot timed out.')) self.settings.set('bootloader_installation_successful', False) except Exception as general_error: logging.error(_('Command gummiboot failed. Unknown Error: %s'), general_error) self.settings.set('bootloader_installation_successful', False)
def install_systemd_boot(self): """ Install Systemd-Boot bootloader to the EFI System Partition and configure entry files """ logging.info("Installing the systemd-boot loader") # Setup bootloader menu menu_dir = os.path.join(self.dest_dir, "boot/loader") os.makedirs(menu_dir, exist_ok=True) menu_path = os.path.join(menu_dir, "loader.conf") with open(menu_path, 'w') as menu_file: menu_file.write("default manjaro-default") # Setup boot entries if not self.settings.get('use_luks'): conf = { 'default': [ 'title\tManjaro\n', 'linux\t/{0}\n'.format(self.vmlinuz), 'initrd\t/{0}\n'.format(self.initramfs), 'options\troot=UUID={0} rw quiet\n\n'.format(self.root_uuid) ], 'fallback': [ "title\tManjaro (fallback)\n", "linux\t/{0}\n".format(self.vmlinuz), "initrd\t/{0}\n".format(self.fallback), "options\troot=UUID={0} rw quiet\n\n".format(self.root_uuid) ] } else: luks_root_volume = self.settings.get('luks_root_volume') luks_root_volume_uuid = fs.get_info(luks_root_volume)['UUID'] # In automatic mode, root_device is in self.mount_devices root_device = self.root_device if (self.method == "advanced" and self.settings.get('use_luks_in_root')): root_device = self.settings.get('luks_root_device') root_uuid = fs.get_info(root_device)['UUID'] key = "" if self.settings.get("luks_root_password") == "": key = ("cryptkey=UUID={0}:ext2:/.keyfile-root" .format(self.boot_uuid)) root_uuid_line = "cryptdevice=UUID={0}:{1} {2} root=UUID={3} rw quit"\ .format(root_uuid, luks_root_volume, key, luks_root_volume_uuid) conf = { 'default': [ "title\tManjaro\n", "linux\t/{0}\n".format(self.vmlinuz), "options\tinitrd=/{0} {1}\n\n".format(self.initramfs, root_uuid_line) ], 'fallback': [ "title\tManjaro (fallback)\n", "linux\t/{0}\n".format(self.vmlinuz), "options\tinitrd=/{0} {1}\n\n".format(self.fallback, root_uuid_line) ] } # Write boot entries entries_dir = os.path.join(self.dest_dir, "boot/loader/entries") os.makedirs(entries_dir, exist_ok=True) for fname, entry in conf.items(): entry_path = os.path.join(entries_dir, "manjaro-{}.conf".format(fname)) with open(entry_path, 'w') as file: for line in entry: file.write(line) # Install bootloader try: cmd = ['bootctl', '--path=/boot', 'install'] chroot.run(cmd, self.dest_dir, 300) logging.info(_("Systemd-Boot install completed successfully")) self.settings.set('bootloader_installation_successful', True) except subprocess.CalledProcessError as process_error: logging.error(_('Command {0} failed. Error output: {1}' .format(cmd,process_error.output))) self.settings.set('bootloader_installation_successful', False) except subprocess.TimeoutExpired: logging.error(_('Command {0} timed out.'.format(cmd))) self.settings.set('bootloader_installation_successful', False) except Exception as general_error: logging.error(_('Command {0} failed. Unknown Error: {1}' .format(cmd,general_error))) self.settings.set('bootloader_installation_successful', False)
def install_systemd_boot(self): """ Install Systemd-Boot bootloader to the EFI System Partition and configure entry files """ logging.info("Installing the systemd-boot loader") # Setup bootloader menu menu_dir = os.path.join(self.dest_dir, "boot/loader") os.makedirs(menu_dir, exist_ok=True) menu_path = os.path.join(menu_dir, "loader.conf") with open(menu_path, 'w') as menu_file: menu_file.write("default manjaro-default") # Setup boot entries if not self.settings.get('use_luks'): conf = { 'default': [ 'title\tManjaro\n', 'linux\t/{0}\n'.format(self.vmlinuz), 'initrd\t/{0}\n'.format(self.initramfs), 'options\troot=UUID={0} rw quiet\n\n'.format( self.root_uuid) ], 'fallback': [ "title\tManjaro (fallback)\n", "linux\t/{0}\n".format(self.vmlinuz), "initrd\t/{0}\n".format(self.fallback), "options\troot=UUID={0} rw quiet\n\n".format( self.root_uuid) ] } else: luks_root_volume = self.settings.get('luks_root_volume') luks_root_volume_uuid = fs.get_info(luks_root_volume)['UUID'] # In automatic mode, root_device is in self.mount_devices root_device = self.root_device if (self.method == "advanced" and self.settings.get('use_luks_in_root')): root_device = self.settings.get('luks_root_device') root_uuid = fs.get_info(root_device)['UUID'] key = "" if self.settings.get("luks_root_password") == "": key = ("cryptkey=UUID={0}:ext2:/.keyfile-root".format( self.boot_uuid)) root_uuid_line = "cryptdevice=UUID={0}:{1} {2} root=UUID={3} rw quit"\ .format(root_uuid, luks_root_volume, key, luks_root_volume_uuid) conf = { 'default': [ "title\tManjaro\n", "linux\t/{0}\n".format(self.vmlinuz), "options\tinitrd=/{0} {1}\n\n".format( self.initramfs, root_uuid_line) ], 'fallback': [ "title\tManjaro (fallback)\n", "linux\t/{0}\n".format(self.vmlinuz), "options\tinitrd=/{0} {1}\n\n".format( self.fallback, root_uuid_line) ] } # Write boot entries entries_dir = os.path.join(self.dest_dir, "boot/loader/entries") os.makedirs(entries_dir, exist_ok=True) for fname, entry in conf.items(): entry_path = os.path.join(entries_dir, "manjaro-{}.conf".format(fname)) with open(entry_path, 'w') as file: for line in entry: file.write(line) # Install bootloader try: cmd = ['bootctl', '--path=/boot', 'install'] chroot.run(cmd, self.dest_dir, 300) logging.info(_("Systemd-Boot install completed successfully")) self.settings.set('bootloader_installation_successful', True) except subprocess.CalledProcessError as process_error: logging.error( _('Command {0} failed. Error output: {1}'.format( cmd, process_error.output))) self.settings.set('bootloader_installation_successful', False) except subprocess.TimeoutExpired: logging.error(_('Command {0} timed out.'.format(cmd))) self.settings.set('bootloader_installation_successful', False) except Exception as general_error: logging.error( _('Command {0} failed. Unknown Error: {1}'.format( cmd, general_error))) self.settings.set('bootloader_installation_successful', False)
def modify_grub_default(self): """ If using LUKS as root, we need to modify GRUB_CMDLINE_LINUX GRUB_CMDLINE_LINUX : Command-line arguments to add to menu entries for the Linux kernel. GRUB_CMDLINE_LINUX_DEFAULT : Unless ‘GRUB_DISABLE_RECOVERY’ is set to ‘true’, two menu entries will be generated for each Linux kernel: one default entry and one entry for recovery mode. This option lists command-line arguments to add only to the default menu entry, after those listed in ‘GRUB_CMDLINE_LINUX’. """ plymouth_bin = os.path.join(self.dest_dir, "usr/bin/plymouth") if os.path.exists(plymouth_bin): use_splash = "splash" else: use_splash = "" if "swap" in self.mount_devices: cmd_linux_default = ('resume=UUID={0} quiet {1}'.format( self.swap_uuid, use_splash)) else: cmd_linux_default = 'quiet {0}'.format(use_splash) self.set_grub_option("GRUB_THEME", "/boot/grub/themes/Manjaro-Default/theme.txt") self.set_grub_option("GRUB_CMDLINE_LINUX_DEFAULT", cmd_linux_default) self.set_grub_option("GRUB_DISTRIBUTOR", "Manjaro") if self.settings.get('use_luks'): # GRUB automatically adds the kernel parameters for root encryption luks_root_volume = self.settings.get('luks_root_volume') logging.debug("Luks Root Volume: {0}".format(luks_root_volume)) root_device = self.root_device if (self.method == "advanced" and self.settings.get('use_luks_in_root')): # Special case, in advanced when using luks in root device, # we store it in luks_root_device root_device = self.settings.get('luks_root_device') root_uuid = fs.get_info(root_device)['UUID'] logging.debug("Root device: {0}".format(root_device)) cmd_linux = ("cryptdevice=/dev/disk/by-uuid/{0}:{1}".format( root_uuid, luks_root_volume)) if self.settings.get("luks_root_password") == "": # No luks password, so user wants to use a keyfile cmd_linux += ( " cryptkey=/dev/disk/by-uuid/{0}:ext2:/.keyfile-root". format(self.boot_uuid)) # Store grub line in settings, we'll use it later # in check_root_uuid_in_grub() self.settings.set('GRUB_CMDLINE_LINUX', cmd_linux) # Store grub line in /etc/default/grub file self.set_grub_option("GRUB_CMDLINE_LINUX", cmd_linux) logging.debug( _("/etc/default/grub configuration completed " "successfully."))