Example #1
0
    def freeze_unfreeze_xfs(self):
        """ Freeze and unfreeze xfs, as hack for grub(2) installing """
        if not os.path.exists("/usr/bin/xfs_freeze"):
            return

        xfs_boot = False
        xfs_root = False

        call(["sync"])
        with open("/proc/mounts") as mounts_file:
            mounts = mounts_file.readlines()
        # We leave a blank space in the end as we want to search
        # exactly for this mount points
        boot_mount_point = self.dest_dir + "/boot "
        root_mount_point = self.dest_dir + " "
        for line in mounts:
            if " xfs " in line:
                if boot_mount_point in line:
                    xfs_boot = True
                elif root_mount_point in line:
                    xfs_root = True
        if xfs_boot:
            boot_mount_point = boot_mount_point.rstrip()
            call(["xfs_freeze", "-f", boot_mount_point])
            call(["xfs_freeze", "-u", boot_mount_point])
        if xfs_root:
            call(["xfs_freeze", "-f", self.dest_dir])
            call(["xfs_freeze", "-u", self.dest_dir])
Example #2
0
def unmount_all_in_device(device):
    """ Unmounts all partitions from device """

    # Unmount all swap
    cmd = ["swapon", "--show=NAME", "--noheadings"]
    swaps = call(cmd)
    swaps = swaps.split("\n")
    for name in filter(None, swaps):
        if "/dev/zram" not in name:
            call(["swapoff", name])

    # Get all mounted devices
    mount_result = call(["mount"])
    mount_result = mount_result.split("\n")

    # Umount all partitions of device
    dirs = []
    for mount in mount_result:
        if device in mount:
            try:
                directory = mount.split()[0]
                dirs.append(directory)
            except IndexError:
                pass

    for directory in dirs:
        unmount(directory)
Example #3
0
def unmount_all_in_directory(dest_dir):
    """ Unmounts all devices that are mounted inside dest_dir """

    # Unmount all swap devices
    cmd = ["swapon", "--show=NAME", "--noheadings"]
    swaps = call(cmd)
    if swaps:
        swaps = swaps.split("\n")
        for name in filter(None, swaps):
            if "/dev/zram" not in name:
                call(["swapoff", name])

    # Get all mounted devices
    mount_result = call(["mount"]).split("\n")

    # Umount all devices mounted inside dest_dir (if any)
    dirs = []
    for mount in mount_result:
        if dest_dir in mount:
            try:
                directory = mount.split()[2]
                # Do not unmount dest_dir now (we will do it later)
                if directory != dest_dir:
                    dirs.append(directory)
            except IndexError:
                pass

    for directory in dirs:
        unmount(directory)

    # Now is the time to unmount the device that is mounted in dest_dir (if any)
    unmount(dest_dir)
Example #4
0
def label_fs(fstype, part, label):
    """ Set filesystem label """
    ladic = {
        'ext2': 'e2label %(part)s %(label)s',
        'ext3': 'e2label %(part)s %(label)s',
        'ext4': 'e2label %(part)s %(label)s',
        'f2fs': 'blkid -s LABEL -o value %(part)s %(label)s',
        'fat': 'mlabel -i %(part)s ::%(label)s',
        'fat16': 'mlabel -i %(part)s ::%(label)s',
        'fat32': 'mlabel -i %(part)s ::%(label)s',
        'ntfs': 'ntfslabel %(part)s %(label)s',
        'jfs': 'jfs_tune -L %(label)s %(part)s',
        'reiserfs': 'reiserfstune -l %(label)s %(part)s',
        'xfs': 'xfs_admin -l %(label)s %(part)s',
        'btrfs': 'btrfs filesystem label %(part)s %(label)s',
        'swap': 'swaplabel -L %(label)s %(part)s'
    }

    fstype = fstype.lower()

    # OK, the below is a quick cheat.  vars() returns all variables
    # in a dictionary.  So 'part' and 'label' will be defined
    # and replaced in above dic
    if fstype in ladic:
        cmd = shlex.split(ladic[fstype] % vars())
        call(cmd)
    else:
        # Not being able to label a partition shouldn't worry us much
        logging.warning("Can't label %s (%s) with label %s", part, fstype,
                        label)
Example #5
0
def label_fs(fstype, part, label):
    """ Set filesystem label """
    ladic = {'ext2': 'e2label %(part)s %(label)s',
             'ext3': 'e2label %(part)s %(label)s',
             'ext4': 'e2label %(part)s %(label)s',
             'f2fs': 'blkid -s LABEL -o value %(part)s %(label)s',
             'fat': 'mlabel -i %(part)s ::%(label)s',
             'fat16': 'mlabel -i %(part)s ::%(label)s',
             'fat32': 'mlabel -i %(part)s ::%(label)s',
             'ntfs': 'ntfslabel %(part)s %(label)s',
             'jfs': 'jfs_tune -L %(label)s %(part)s',
             'reiserfs': 'reiserfstune -l %(label)s %(part)s',
             'xfs': 'xfs_admin -l %(label)s %(part)s',
             'btrfs': 'btrfs filesystem label %(part)s %(label)s',
             'swap': 'swaplabel -L %(label)s %(part)s'}

    fstype = fstype.lower()

    # OK, the below is a quick cheat.  vars() returns all variables
    # in a dictionary.  So 'part' and 'label' will be defined
    # and replaced in above dic
    if fstype in ladic:
        cmd = shlex.split(ladic[fstype] % vars())
        call(cmd)
    else:
        # Not being able to label a partition shouldn't worry us much
        logging.warning("Can't label %s (%s) with label %s", part, fstype, label)
Example #6
0
def get_os_dict():
    """ Returns all detected OSes in a dict """
    oses = {}

    tmp_dir = tempfile.mkdtemp()

    with open("/proc/partitions", 'r') as partitions_file:
        for line in partitions_file:
            line_split = line.split()
            if len(line_split) > 0:
                device = line_split[3]
                if "sd" in device and re.search(r'\d+$', device):
                    # ok, it has sd and ends with a number
                    device = "/dev/" + device
                    call(["mount", device, tmp_dir])
                    oses[device] = _get_os(tmp_dir)
                    call(["umount", "-l", tmp_dir])
                    if oses[device] == _("unknown"):
                        # As a last resort, try reading partition info
                        # with hexdump
                        oses[device] = _get_partition_info(device)

    try:
        os.rmdir(tmp_dir)
    except OSError:
        pass

    return oses
Example #7
0
    def freeze_unfreeze_xfs(self):
        """ Freeze and unfreeze xfs, as hack for grub(2) installing """
        if not os.path.exists("/usr/bin/xfs_freeze"):
            return

        xfs_boot = False
        xfs_root = False

        call(["sync"])
        with open("/proc/mounts") as mounts_file:
            mounts = mounts_file.readlines()
        # We leave a blank space in the end as we want to search
        # exactly for this mount points
        boot_mount_point = self.dest_dir + "/boot "
        root_mount_point = self.dest_dir + " "
        for line in mounts:
            if " xfs " in line:
                if boot_mount_point in line:
                    xfs_boot = True
                elif root_mount_point in line:
                    xfs_root = True
        if xfs_boot:
            boot_mount_point = boot_mount_point.rstrip()
            call(["xfs_freeze", "-f", boot_mount_point])
            call(["xfs_freeze", "-u", boot_mount_point])
        if xfs_root:
            call(["xfs_freeze", "-f", self.dest_dir])
            call(["xfs_freeze", "-u", self.dest_dir])
Example #8
0
    def create_zfs_vol(self, pool_name, vol_name, swap_size=None):
        """ Creates zfs vol inside the pool
            if size is given, it should be in GB.
            If vol_name is "swap" it will be setup as a swap space """

        cmd = ["zfs", "create"]

        if swap_size:
            # If size is given, mountpoint cannot be set (zfs)
            # Round up
            swap_size = math.ceil(swap_size)
            logging.debug("Creating a zfs vol %s/%s of size %dGB", pool_name,
                          vol_name, swap_size)
            cmd.extend(["-V", "{0}G".format(swap_size)])
        else:
            logging.debug("Creating a zfs vol %s/%s", pool_name, vol_name)
            if vol_name == "swap":
                cmd.extend(["-o", "mountpoint=none"])
            else:
                cmd.extend(
                    ["-o", "mountpoint={0}/{1}".format(DEST_DIR, vol_name)])

        cmd.append("{0}/{1}".format(pool_name, vol_name))
        call(cmd, fatal=True)

        if vol_name == "swap":
            self.create_swap(pool_name, vol_name)
Example #9
0
    def run_mkconfig(self):
        """ Create grub.cfg file using grub-mkconfig """
        logging.debug("Generating grub.cfg...")

        # Make sure that /dev and others are mounted (binded).
        special_dirs.mount(self.dest_dir)

        # if self.settings.get("zfs"):
        #     # grub-mkconfig does not properly detect the ZFS filesystem,
        #     # so it is necessary to edit grub.cfg manually.
        #     zfs_pool_name = self.settings.get("zfs_pool_name")
        #     grub_cfg_path = os.path.join(self.dest_dir, "boot/grub/grub.cfg")
        #     with open(grub_cfg_path, "w") as grub_cfg:
        #         grub_cfg.write('set timeout=2\n')
        #         grub_cfg.write('set default=0\n\n')
        #         grub_cfg.write('# (0) Antergos Linux\n')
        #         grub_cfg.write('\tmenuentry "Antergos Linux (zfs)" {\n')
        #         # grub_cfg.write('\tsearch --no-floppy --label --set=root {0}\n'.format(zfs_pool_name))
        #         grub_cfg.write('\tlinux /vmlinuz-linux zfs={0} rw\n'.format(zfs_pool_name))
        #         grub_cfg.write('\tinitrd /initramfs-linux.img\n')
        #         grub_cfg.write('}\n')
        # else:
        # Add -l option to os-prober's umount call so that it does not hang
        self.apply_osprober_patch()
        logging.debug("Running grub-mkconfig...")
        locale = self.settings.get("locale")
        cmd = 'LANG={0} grub-mkconfig -o /boot/grub/grub.cfg'.format(locale)
        cmd_sh = ['sh', '-c', cmd]
        if not chroot_call(cmd_sh, self.dest_dir, timeout=300):
            msg = ("grub-mkconfig does not respond. Killing grub-mount and"
                   "os-prober so we can continue.")
            logging.error(msg)
            call(['killall', 'grub-mount'])
            call(['killall', 'os-prober'])
Example #10
0
    def create_zfs_vol(self, pool_name, vol_name, swap_size=None):
        """ Creates zfs vol inside the pool
            if size is given, it should be in GB.
            If vol_name is "swap" it will be setup as a swap space """

        cmd = ["zfs", "create"]

        if swap_size:
            # If size is given, mountpoint cannot be set (zfs)
            # Round up
            swap_size = math.ceil(swap_size)
            logging.debug("Creating a zfs vol %s/%s of size %dGB", pool_name, vol_name, swap_size)
            cmd.extend(["-V", "{0}G".format(swap_size)])
        else:
            logging.debug("Creating a zfs vol %s/%s", pool_name, vol_name)
            if vol_name == "swap":
                cmd.extend(["-o", "mountpoint=none"])
            else:
                cmd.extend(["-o", "mountpoint={0}/{1}".format(DEST_DIR, vol_name)])

        cmd.append("{0}/{1}".format(pool_name, vol_name))
        call(cmd, fatal=True)

        if vol_name == "swap":
            self.create_swap(pool_name, vol_name)
Example #11
0
def unmount_all_in_directory(dest_dir):
    """ Unmounts all devices that are mounted inside dest_dir """

    # Unmount all swap devices
    cmd = ["swapon", "--show=NAME", "--noheadings"]
    swaps = call(cmd)
    if swaps:
        swaps = swaps.split("\n")
        for name in filter(None, swaps):
            if "/dev/zram" not in name:
                call(["swapoff", name])

    # Get all mounted devices
    mount_result = call(["mount"]).split("\n")

    # Umount all devices mounted inside dest_dir (if any)
    dirs = []
    for mount in mount_result:
        if dest_dir in mount:
            try:
                directory = mount.split()[2]
                # Do not unmount dest_dir now (we will do it later)
                if directory != dest_dir:
                    dirs.append(directory)
            except IndexError:
                pass

    for directory in dirs:
        unmount(directory)

    # Now is the time to unmount the device that is mounted in dest_dir (if any)
    unmount(dest_dir)
Example #12
0
def unmount_all_in_device(device):
    """ Unmounts all partitions from device """

    # Unmount all swap
    cmd = ["swapon", "--show=NAME", "--noheadings"]
    swaps = call(cmd)
    swaps = swaps.split("\n")
    for name in filter(None, swaps):
        if "/dev/zram" not in name:
            call(["swapoff", name])

    # Get all mounted devices
    mount_result = call(["mount"])
    mount_result = mount_result.split("\n")

    # Umount all partitions of device
    dirs = []
    for mount in mount_result:
        if device in mount:
            try:
                directory = mount.split()[0]
                dirs.append(directory)
            except IndexError:
                pass

    for directory in dirs:
        unmount(directory)
Example #13
0
def get_os_dict():
    """ Returns all detected OSes in a dict """
    oses = {}

    tmp_dir = tempfile.mkdtemp()

    with open("/proc/partitions", 'r') as partitions_file:
        for line in partitions_file:
            line_split = line.split()
            if len(line_split) > 0:
                device = line_split[3]
                if "sd" in device and re.search(r'\d+$', device):
                    # ok, it has sd and ends with a number
                    device = "/dev/" + device
                    call(["mount", device, tmp_dir])
                    oses[device] = _get_os(tmp_dir)
                    call(["umount", "-l", tmp_dir])
                    if oses[device] == _("unknown"):
                        # As a last resort, try reading partition info
                        # with hexdump
                        oses[device] = _get_partition_info(device)

    try:
        os.rmdir(tmp_dir)
    except OSError:
        pass

    return oses
Example #14
0
def setup_luks(luks_device, luks_name, luks_pass=None, luks_key=None):
    """ Setups a luks device """

    if (luks_pass is None or luks_pass == "") and luks_key is None:
        txt = "Can't setup LUKS in device {0}. A password or a key file are needed".format(
            luks_device)
        logging.error(txt)
        return

    # For now, we we'll use the same password for root and /home
    # If instead user wants to use a key file, we'll have two different key files.

    logging.debug("Cnchi will setup LUKS on device %s", luks_device)

    # Wipe LUKS header (just in case we're installing on a pre LUKS setup)
    # For 512 bit key length the header is 2MiB
    # If in doubt, just be generous and overwrite the first 10MiB or so
    wrapper.dd("/dev/zero", luks_device, bs=512, count=20480)

    err_msg = "Can't format and open the LUKS device {0}".format(luks_device)

    if luks_pass is None or luks_pass == "":
        # No key password given, let's create a random keyfile
        wrapper.dd("/dev/urandom", luks_key, bs=1024, count=4)

        # Set up luks with a keyfile
        cmd = [
            "cryptsetup", "luksFormat", "-q", "-c", "aes-xts-plain", "-s",
            "512", luks_device, luks_key
        ]
        call(cmd, msg=err_msg, fatal=True)

        cmd = [
            "cryptsetup", "luksOpen", luks_device, luks_name, "-q",
            "--key-file", luks_key
        ]
        call(cmd, msg=err_msg, fatal=True)
    else:
        # Set up luks with a password key

        luks_pass_bytes = bytes(luks_pass, 'UTF-8')

        # https://code.google.com/p/cryptsetup/wiki/Cryptsetup160
        # aes-xts-plain
        # aes-cbc-essiv:sha256
        cmd = [
            "cryptsetup", "luksFormat", "-q", "-c", "aes-xts-plain64", "-s",
            "512", "--key-file=-", luks_device
        ]
        proc = popen(cmd, msg=err_msg, fatal=True)
        proc.communicate(input=luks_pass_bytes)

        cmd = [
            "cryptsetup", "luksOpen", luks_device, luks_name, "-q",
            "--key-file=-"
        ]
        proc = popen(cmd, msg=err_msg, fatal=True)
        proc.communicate(input=luks_pass_bytes)
Example #15
0
    def do_destroy_zfs_pools(self):
        """ Try to destroy existing antergos zfs pools """
        self.load_existing_pools()

        for pool_name in self.existing_pools:
            if "antergos" in pool_name.lower():
                pool_id, pool_state = self.existing_pools[pool_name]
                destroy_cmd = ['zpool', 'destroy', '-f', pool_name]
                if not call(destroy_cmd, warning=False):
                    destroy_cmd = ['zfs', 'destroy', '-R', '-f', pool_name]
                    call(destroy_cmd, warning=False)
Example #16
0
    def do_destroy_zfs_pools(self):
        """ Try to destroy existing antergos zfs pools """
        self.load_existing_pools()

        for pool_name in self.existing_pools:
            if "antergos" in pool_name.lower():
                pool_id, pool_state = self.existing_pools[pool_name]
                destroy_cmd = ['zpool', 'destroy', '-f', pool_name]
                if not call(destroy_cmd, warning=False):
                    destroy_cmd = ['zfs', 'destroy', '-R', '-f', pool_name]
                    call(destroy_cmd, warning=False)
Example #17
0
def close_antergos_luks_devices():
    """ Close LUKS devices (they may have been left open because of a previous
    failed installation) """

    volumes = ["/dev/mapper/cryptAntergos", "/dev/mapper/cryptAntergosHome"]

    err_msg = "Can't close already opened LUKS devices"

    for volume in volumes:
        if os.path.exists(volume):
            cmd = ["cryptsetup", "luksClose", volume]
            call(cmd, msg=err_msg)
Example #18
0
def setup_luks(luks_device, luks_name, luks_pass=None, luks_key=None):
    """ Setups a luks device """

    if (luks_pass is None or luks_pass == "") and luks_key is None:
        txt = "Can't setup LUKS in device {0}. A password or a key file are needed".format(luks_device)
        logging.error(txt)
        return

    # For now, we we'll use the same password for root and /home
    # If instead user wants to use a key file, we'll have two different key files.

    logging.debug("Cnchi will setup LUKS on device %s", luks_device)

    # Wipe LUKS header (just in case we're installing on a pre LUKS setup)
    # For 512 bit key length the header is 2MiB
    # If in doubt, just be generous and overwrite the first 10MiB or so
    wrapper.dd("/dev/zero", luks_device, bs=512, count=20480)

    err_msg = "Can't format and open the LUKS device {0}".format(luks_device)

    if luks_pass is None or luks_pass == "":
        # No key password given, let's create a random keyfile
        wrapper.dd("/dev/urandom", luks_key, bs=1024, count=4)

        # Set up luks with a keyfile
        cmd = [
            "cryptsetup", "luksFormat", "-q", "-c", "aes-xts-plain",
            "-s", "512", luks_device, luks_key]
        call(cmd, msg=err_msg, fatal=True)

        cmd = [
            "cryptsetup", "luksOpen", luks_device, luks_name, "-q",
            "--key-file", luks_key]
        call(cmd, msg=err_msg, fatal=True)
    else:
        # Set up luks with a password key

        luks_pass_bytes = bytes(luks_pass, 'UTF-8')

        # https://code.google.com/p/cryptsetup/wiki/Cryptsetup160
        # aes-xts-plain
        # aes-cbc-essiv:sha256
        cmd = [
            "cryptsetup", "luksFormat", "-q", "-c", "aes-xts-plain64",
            "-s", "512", "--key-file=-", luks_device]
        proc = popen(cmd, msg=err_msg, fatal=True)
        proc.communicate(input=luks_pass_bytes)

        cmd = [
            "cryptsetup", "luksOpen", luks_device, luks_name, "-q",
            "--key-file=-"]
        proc = popen(cmd, msg=err_msg, fatal=True)
        proc.communicate(input=luks_pass_bytes)
Example #19
0
def close_reborn_luks_devices():
    """ Close LUKS devices (they may have been left open because of a previous
    failed installation) """

    volumes = ["/dev/mapper/cryptReborn", "/dev/mapper/cryptRebornHome"]

    err_msg = "Can't close already opened LUKS devices"

    for volume in volumes:
        if os.path.exists(volume):
            cmd = ["cryptsetup", "luksClose", volume]
            call(cmd, msg=err_msg)
Example #20
0
    def init_device(self, device_path, scheme="GPT"):
        """ Initialize device """

        logging.debug("Zapping device %s...", device_path)

        offset = 20480

        # Zero out all GPT and MBR data structures
        wrapper.sgdisk("zap-all", device_path)

        # Clear all magic strings/signatures
        # Wipe out first "offset" sectors
        wrapper.dd("/dev/zero", device_path, bs=512, count=offset)

        # Clear the end "offset" sectors of the disk, too.
        try:
            seek = int(call(["blockdev", "--getsz", device_path])) - offset
            wrapper.dd("/dev/zero",
                       device_path,
                       bs=512,
                       count=offset,
                       seek=seek)
        except ValueError as ex:
            logging.warning(ex)

        wrapper.wipefs(device_path, fatal=True)

        if scheme == "GPT":
            # Create fresh GPT table
            wrapper.sgdisk("clear", device_path)

            # Inform the kernel of the partition change.
            # Needed if the hard disk had a MBR partition table.
            call(["partprobe", device_path])
        else:
            # Create fresh MBR table
            wrapper.parted_mklabel(device_path, "msdos")
        """
        if self.zfs_options["encrypt_disk"]:
            from installation import auto_partition as ap
            vol_name = device_path.split("/")[-1]
            ap.setup_luks(
                luks_device=device_path,
                luks_name=vol_name,
                luks_pass=self.zfs_options["encrypt_password"])
            self.settings.set("use_luks", True)
        """

        call(["sync"])
Example #21
0
def _hexdump8081(partition):
    """ Runs hexdump on partition to try to identify the boot sector """
    cmd = [
        "hexdump", "-v", "-n", "2", "-s", "0x80", "-e", '2/1 "%02x"', partition
    ]
    hexdump = call(cmd)
    return hexdump
Example #22
0
    def get_part_sizes(self, disk_size, start_part_sizes=1):
        part_sizes = {'disk': disk_size, 'boot': 256, 'efi': 0}

        if self.gpt and self.bootloader == "grub2":
            part_sizes['efi'] = 200

        cmd = ["grep", "MemTotal", "/proc/meminfo"]
        mem_total = call(cmd)
        mem_total = int(mem_total.split()[1])
        mem = mem_total / 1024

        # Suggested sizes from Anaconda installer
        if mem < 2048:
            part_sizes['swap'] = 2 * mem
        elif 2048 <= mem < 8192:
            part_sizes['swap'] = mem
        elif 8192 <= mem < 65536:
            part_sizes['swap'] = mem // 2
        else:
            part_sizes['swap'] = 4096

        # Max swap size is 10% of all available disk size
        max_swap = disk_size * 0.1
        if part_sizes['swap'] > max_swap:
            part_sizes['swap'] = max_swap

        part_sizes['swap'] = math.ceil(part_sizes['swap'])

        other_than_root_size = start_part_sizes + part_sizes['efi'] + part_sizes['boot'] + part_sizes['swap']
        part_sizes['root'] = disk_size - other_than_root_size

        if self.home:
            # Decide how much we leave to root and how much we leave to /home
            # Question: why 5?
            new_root_part_size = part_sizes['root'] // 5
            if new_root_part_size > MAX_ROOT_SIZE:
                new_root_part_size = MAX_ROOT_SIZE
            elif new_root_part_size < MIN_ROOT_SIZE:
                new_root_part_size = MIN_ROOT_SIZE

            if new_root_part_size >= part_sizes['root']:
                # new_root_part_size can't be bigger than part_sizes['root'] !
                # this could happen if new_root_part_size == MIN_ROOT_SIZE but
                # our harddisk is smaller (detected using vbox)
                # Should we fail here or install without a separated /home partition?
                logging.warning("There's not enough free space to have a separate /home partition")
                self.home = False
                part_sizes['home'] = 0
            else:
                part_sizes['home'] = part_sizes['root'] - new_root_part_size
                part_sizes['root'] = new_root_part_size
        else:
            part_sizes['home'] = 0

        part_sizes['lvm_pv'] = part_sizes['swap'] + part_sizes['root'] + part_sizes['home']

        for part in part_sizes:
            part_sizes[part] = int(part_sizes[part])

        return part_sizes
Example #23
0
    def get_part_sizes(self, disk_size, start_part_sizes=1):
        part_sizes = {"disk": disk_size, "boot": 256, "efi": 0}

        if self.gpt and self.bootloader == "grub2":
            part_sizes["efi"] = 200

        cmd = ["grep", "MemTotal", "/proc/meminfo"]
        mem_total = call(cmd)
        mem_total = int(mem_total.split()[1])
        mem = mem_total / 1024

        # Suggested sizes from Anaconda installer
        if mem < 2048:
            part_sizes["swap"] = 2 * mem
        elif 2048 <= mem < 8192:
            part_sizes["swap"] = mem
        elif 8192 <= mem < 65536:
            part_sizes["swap"] = mem // 2
        else:
            part_sizes["swap"] = 4096

        # Max swap size is 10% of all available disk size
        max_swap = disk_size * 0.1
        if part_sizes["swap"] > max_swap:
            part_sizes["swap"] = max_swap

        part_sizes["swap"] = math.ceil(part_sizes["swap"])

        other_than_root_size = start_part_sizes + part_sizes["efi"] + part_sizes["boot"] + part_sizes["swap"]
        part_sizes["root"] = disk_size - other_than_root_size

        if self.home:
            # Decide how much we leave to root and how much we leave to /home
            # Question: why 5?
            new_root_part_size = part_sizes["root"] // 5
            if new_root_part_size > MAX_ROOT_SIZE:
                new_root_part_size = MAX_ROOT_SIZE
            elif new_root_part_size < MIN_ROOT_SIZE:
                new_root_part_size = MIN_ROOT_SIZE

            if new_root_part_size >= part_sizes["root"]:
                # new_root_part_size can't be bigger than part_sizes['root'] !
                # this could happen if new_root_part_size == MIN_ROOT_SIZE but
                # our harddisk is smaller (detected using vbox)
                # Should we fail here or install without a separated /home partition?
                logging.warning("There's not enough free space to have a separate /home partition")
                self.home = False
                part_sizes["home"] = 0
            else:
                part_sizes["home"] = part_sizes["root"] - new_root_part_size
                part_sizes["root"] = new_root_part_size
        else:
            part_sizes["home"] = 0

        part_sizes["lvm_pv"] = part_sizes["swap"] + part_sizes["root"] + part_sizes["home"]

        for part in part_sizes:
            part_sizes[part] = int(part_sizes[part])

        return part_sizes
Example #24
0
File: zfs.py Project: imsory/Cnchi
    def init_device(self, device_path, scheme="GPT"):
        """ Initialize device """

        logging.debug("Zapping device %s...", device_path)

        offset = 20480

        # Zero out all GPT and MBR data structures
        wrapper.sgdisk("zap-all", device_path)

        # Clear all magic strings/signatures
        # Wipe out first "offset" sectors
        wrapper.dd("/dev/zero", device_path, bs=512, count=offset)

        # Clear the end "offset" sectors of the disk, too.
        try:
            seek = int(call(["blockdev", "--getsz", device_path])) - offset
            wrapper.dd("/dev/zero", device_path, bs=512, count=offset, seek=seek)
        except ValueError as ex:
            logging.warning(ex)

        if not wrapper.wipefs(device_path, fatal=False):
            pname, pid, _n = self.get_pool_id('_', include_offline=True)

            if self.do_destroy_zfs_pool():
                call(["udevadm", "settle"])
                call(["sync"])
                wrapper.wipefs(device_path, fatal=True)

        if scheme == "GPT":
            # Create fresh GPT table
            wrapper.sgdisk("clear", device_path)

            # Inform the kernel of the partition change.
            # Needed if the hard disk had a MBR partition table.
            call(["partprobe", device_path])
        else:
            # Create fresh MBR table
            wrapper.parted_mklabel(device_path, "msdos")

        """
        if self.zfs_options["encrypt_disk"]:
            from installation import auto_partition as ap
            vol_name = device_path.split("/")[-1]
            ap.setup_luks(
                luks_device=device_path,
                luks_name=vol_name,
                luks_pass=self.zfs_options["encrypt_password"])
            self.settings.set("use_luks", True)
        """

        call(["sync"])
Example #25
0
def get_info(part):
    """ Get partition info using blkid """

    ret = ''
    partdic = {}
    # Do not try to get extended partition info
    if part and not misc.is_partition_extended(part):
        # -c /dev/null means no cache
        cmd = ['blkid', '-c', '/dev/null', part]
        call(cmd)

        for info in ret.split():
            if '=' in info:
                info = info.split('=')
                partdic[info[0]] = info[1].strip('"')

    return partdic
Example #26
0
def get_type(part):
    """ Get filesystem type using blkid """
    ret = ''
    if part and not misc.is_partition_extended(part):
        cmd = ['blkid', '-o', 'value', '-s', 'TYPE', part]
        ret = call(cmd)

    return ret
Example #27
0
def get_info(part):
    """ Get partition info using blkid """

    ret = ''
    partdic = {}
    # Do not try to get extended partition info
    if part and not misc.is_partition_extended(part):
        # -c /dev/null means no cache
        cmd = ['blkid', '-c', '/dev/null', part]
        call(cmd)

        for info in ret.split():
            if '=' in info:
                info = info.split('=')
                partdic[info[0]] = info[1].strip('"')

    return partdic
Example #28
0
def get_type(part):
    """ Get filesystem type using blkid """
    ret = ''
    if part and not misc.is_partition_extended(part):
        cmd = ['blkid', '-o', 'value', '-s', 'TYPE', part]
        ret = call(cmd)

    return ret
Example #29
0
    def run_mkconfig(self):
        """ Create grub.cfg file using grub-mkconfig """
        logging.debug("Generating grub.cfg...")

        # Make sure that /dev and others are mounted (binded).
        special_dirs.mount(self.dest_dir)

        # Add -l option to os-prober's umount call so that it does not hang
        self.apply_osprober_patch()
        logging.debug("Running grub-mkconfig...")
        locale = self.settings.get("locale")
        cmd = "LANG={0} grub-mkconfig -o /boot/grub/grub.cfg".format(locale)
        cmd_sh = ["sh", "-c", cmd]
        if not chroot_call(cmd_sh, self.dest_dir, timeout=300):
            msg = "grub-mkconfig does not respond. Killing grub-mount and" "os-prober so we can continue."
            logging.error(msg)
            call(["killall", "grub-mount"])
            call(["killall", "os-prober"])
Example #30
0
    def run_mkconfig(self):
        """ Create grub.cfg file using grub-mkconfig """
        logging.debug("Generating grub.cfg...")

        # Make sure that /dev and others are mounted (binded).
        special_dirs.mount(self.dest_dir)

        # Add -l option to os-prober's umount call so that it does not hang
        self.apply_osprober_patch()
        logging.debug("Running grub-mkconfig...")
        locale = self.settings.get("locale")
        cmd = 'LANG={0} grub-mkconfig -o /boot/grub/grub.cfg'.format(locale)
        cmd_sh = ['sh', '-c', cmd]
        if not chroot_call(cmd_sh, self.dest_dir, timeout=300):
            msg = ("grub-mkconfig does not respond. Killing grub-mount and"
                   "os-prober so we can continue.")
            logging.error(msg)
            call(['killall', 'grub-mount'])
            call(['killall', 'os-prober'])
Example #31
0
    def set_keymap(self, layout, variant=None):
        self.settings.keyboard_layout = layout
        self.settings.keyboard_variant = variant

        # setxkbmap sets the keyboard layout for the current X session only
        cmd = ['setxkbmap', '-layout', layout]

        if variant:
            cmd.extend(['-variant', variant])
            txt = 'Set keyboard to "{0}" ({1}), variant "{2}" ({3})'
            txt = txt.format('', layout, '', variant)
        else:
            txt = 'Set keyboard to "{0}" ({1})'.format('', layout)

        try:
            call(cmd)
            self.logger.debug(txt)
        except (OSError, subprocess.CalledProcessError) as setxkbmap_error:
            self.logger.warning(setxkbmap_error)
Example #32
0
    def set_keymap(self, layout, variant=None):
        self.settings.keyboard_layout = layout
        self.settings.keyboard_variant = variant

        # setxkbmap sets the keyboard layout for the current X session only
        cmd = ['setxkbmap', '-layout', layout]

        if variant:
            cmd.extend(['-variant', variant])
            txt = 'Set keyboard to "{0}" ({1}), variant "{2}" ({3})'
            txt = txt.format('', layout, '', variant)
        else:
            txt = 'Set keyboard to "{0}" ({1})'.format('', layout)

        try:
            call(cmd)
            self.logger.debug(txt)
        except (OSError, subprocess.CalledProcessError) as setxkbmap_error:
            self.logger.warning(setxkbmap_error)
Example #33
0
File: zfs.py Project: imsory/Cnchi
    def create_zfs_vol(self, pool_name, vol_name, size):
        """ Creates zfs vol inside the pool
            size is in GB """

        # Round up
        size = math.ceil(size)
        logging.debug(
            "Creating a zfs vol %s/%s of size %dGB",
            pool_name,
            vol_name,
            size)
        cmd = [
            "zfs", "create",
            "-V", "{0}G".format(size),
            "-b", str(os.sysconf("SC_PAGE_SIZE")),
            "-o", "primarycache=metadata",
            "-o", "checksum=off",
            "-o", "com.sun:auto-snapshot=false",
            "{0}/{1}".format(pool_name, vol_name)]
        call(cmd, fatal=True)
Example #34
0
    def create_swap(self, pool_name, vol_name):
        """ mkswap on a zfs zvol """

        zvol = "{0}/{1}".format(pool_name, vol_name)

        cmd = ["zfs", "set", "com.sun:auto-snapshot=false", zvol]
        call(cmd)

        cmd = ["zfs", "set", "sync=always", zvol]
        call(cmd)

        path = "/dev/zvol/{0}/swap".format(pool_name)
        if os.path.exists(path):
            logging.debug("Formatting swap (%s)", path)
            cmd = ["mkswap", "-f", path]
            if call(cmd):
                self.devices["swap"] = path
                self.fs_devices[path] = "swap"
                self.mount_devices["swap"] = path
        else:
            logging.warning("Can't find %s to create swap on it", path)
Example #35
0
    def create_swap(self, pool_name, vol_name):
        """ mkswap on a zfs zvol """

        zvol = "{0}/{1}".format(pool_name, vol_name)

        cmd = ["zfs", "set", "com.sun:auto-snapshot=false", zvol]
        call(cmd)

        cmd = ["zfs", "set", "sync=always", zvol]
        call(cmd)

        path = "/dev/zvol/{0}/swap".format(pool_name)
        if os.path.exists(path):
            logging.debug("Formatting swap (%s)", path)
            cmd = ["mkswap", "-f", path]
            if call(cmd):
                self.devices["swap"] = path
                self.fs_devices[path] = "swap"
                self.mount_devices["swap"] = path
        else:
            logging.warning("Can't find %s to create swap on it", path)
Example #36
0
def get_info(part):
    """ Get partition info using blkid """

    ret = ''
    partdic = {}
    # Do not try to get extended partition info
    if part and not misc.is_partition_extended(part):
        # -c /dev/null means no cache
        cmd = ['blkid', '-c', '/dev/null', part]
        call(cmd)
        try:

            ret = subprocess.check_output(cmd).decode().strip()
        except subprocess.CalledProcessError as err:
            logging.warning("Error running %s: %s", err.cmd, err.output)

        for info in ret.split():
            if '=' in info:
                info = info.split('=')
                partdic[info[0]] = info[1].strip('"')

    return partdic
Example #37
0
    def init_device(self, device_path, scheme="GPT"):
        """ Initialize device """

        logging.debug("Zapping device %s...", device_path)

        offset = 20480

        # Zero out all GPT and MBR data structures
        wrapper.sgdisk("zap-all", device_path)

        # Clear all magic strings/signatures
        # Wipe out first "offset" sectors
        wrapper.dd("/dev/zero", device_path, bs=512, count=offset)

        # Clear the end "offset" sectors of the disk, too.
        try:
            seek = int(call(["blockdev", "--getsz", device_path])) - offset
            wrapper.dd("/dev/zero",
                       device_path,
                       bs=512,
                       count=offset,
                       seek=seek)
        except ValueError as ex:
            logging.warning(ex)

        wrapper.wipefs(device_path, fatal=True)

        if scheme == "GPT":
            # Create fresh GPT table
            wrapper.sgdisk("clear", device_path)

            # Inform the kernel of the partition change.
            # Needed if the hard disk had a MBR partition table.
            call(["partprobe", device_path])
        else:
            # Create fresh MBR table
            wrapper.parted_mklabel(device_path, "msdos")

        call(["sync"])
Example #38
0
    def prepare_pacman_keyring():
        """ Add gnupg pacman files to installed system """

        dirs = ["var/cache/pacman/pkg", "var/lib/pacman"]
        for pacman_dir in dirs:
            mydir = os.path.join(DEST_DIR, pacman_dir)
            os.makedirs(mydir, mode=0o755, exist_ok=True)

        # Be sure that haveged is running (liveCD)
        # haveged is a daemon that generates system entropy; this speeds up
        # critical operations in cryptographic programs such as gnupg
        # (including the generation of new keyrings)
        cmd = ["systemctl", "start", "haveged"]
        call(cmd)

        # Delete old gnupg files
        dest_path = os.path.join(DEST_DIR, "etc/pacman.d/gnupg")
        cmd = ["rm", "-rf", dest_path]
        call(cmd)
        os.mkdir(dest_path)

        # Tell pacman-key to regenerate gnupg files
        # Initialize the pacman keyring
        cmd = ["pacman-key", "--init", "--gpgdir", dest_path]
        call(cmd)

        # Load the signature keys
        cmd = ["pacman-key", "--populate", "--gpgdir", dest_path, "archlinux", "antergos"]
        call(cmd)

        # path = os.path.join(DEST_DIR, "root/.gnupg/dirmngr_ldapservers.conf")
        # Run dirmngr
        # https://bbs.archlinux.org/viewtopic.php?id=190380
        with open(os.devnull, "r") as dev_null:
            cmd = ["dirmngr"]
            call(cmd, stdin=dev_null)
Example #39
0
    def load_codes(self):
        """ Load keyboard codes """
        if self.layout is None:
            return

        cmd = [
            "/usr/share/cnchi/scripts/ckbcomp",
            "-model",
            "pc106",
            "-layout",
            self.layout]

        if self.variant:
            cmd.extend(["-variant", self.variant])

        cmd.append("-compact")

        try:
            with raised_privileges() as privileged:
                cfile = call(cmd).split('\n')
        except subprocess.CalledProcessError as process_error:
            logging.error(
                "Error running command %s: %s",
                process_error.cmd,
                process_error)
            return

        # Clear current codes
        del self.codes[:]

        for line in cfile:
            if line[:7] != "keycode":
                continue

            codes = line.split('=')[1].strip().split(' ')

            plain = unicode_to_string(codes[0])
            shift = unicode_to_string(codes[1])
            ctrl = unicode_to_string(codes[2])
            alt = unicode_to_string(codes[3])

            if ctrl == plain:
                ctrl = ""

            if alt == plain:
                alt = ""

            self.codes.append((plain, shift, ctrl, alt))
Example #40
0
    def clear_dest_dir():
        """ Empties /install """

        # Check that /install/boot and /install are not mounted
        call(["umount", "{0}/boot".format(DEST_DIR)], warning=False)
        call(["umount", "{0}".format(DEST_DIR)], warning=False)
        call(["zfs", "umount", "{0}/boot".format(DEST_DIR)], warning=False)
        call(["zfs", "umount", "{0}".format(DEST_DIR)], warning=False)

        # Delete /install contents
        for file_name in os.listdir(DEST_DIR):
            file_path = os.path.join(DEST_DIR, file_name)
            try:
                if os.path.isfile(file_path):
                    os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except OSError as err:
                logging.warning(err)
Example #41
0
    def clear_dest_dir():
        """ Empties /install """

        # Check that /install/boot and /install are not mounted
        call(["umount", "{0}/boot".format(DEST_DIR)], warning=False)
        call(["umount", "{0}".format(DEST_DIR)], warning=False)
        call(["zfs", "umount", "{0}/boot".format(DEST_DIR)], warning=False)
        call(["zfs", "umount", "{0}".format(DEST_DIR)], warning=False)

        # Delete /install contents
        for file_name in os.listdir(DEST_DIR):
            file_path = os.path.join(DEST_DIR, file_name)
            try:
                if os.path.isfile(file_path):
                    os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except OSError as err:
                logging.warning(err)
Example #42
0
    def has_enough_space():
        """ Check that we have a disk or partition with enough space """

        output = call(cmd=["lsblk", "-lnb"], debug=False).split("\n")

        max_size = 0

        for item in output:
            col = item.split()
            if len(col) >= 5:
                if col[5] == "disk" or col[5] == "part":
                    size = int(col[3])
                    if size > max_size:
                        max_size = size

        if max_size >= MIN_ROOT_SIZE:
            return True

        return False
Example #43
0
    def has_enough_space():
        """ Check that we have a disk or partition with enough space """

        output = call(cmd=["lsblk", "-lnb"], debug=False).split("\n")

        max_size = 0

        for item in output:
            col = item.split()
            if len(col) >= 5:
                if col[5] == "disk" or col[5] == "part":
                    size = int(col[3])
                    if size > max_size:
                        max_size = size

        if max_size >= MIN_ROOT_SIZE:
            return True

        return False
Example #44
0
File: zfs.py Project: imsory/Cnchi
    def get_pool_id(pool_name, include_offline=False):
        """ Get zpool id number """
        output = call(["zpool", "import"])
        if not output:
            return None

        name = identifier = state = None
        lines = output.split("\n")
        for line in lines:
            if "pool:" in line:
                name = line.split(": ")[1]
            elif "id:" in line:
                identifier = line.split(": ")[1]
            elif "state:" in line:
                state = line.split(": ")[1]

        if not name or (name == pool_name and state != "ONLINE" and not include_offline):
            name = identifier = state = None

        return name, identifier, state
Example #45
0
    def get_pool_id(pool_name):
        """ Get zpool id number """
        output = call(["zpool", "import"])
        if not output:
            return None

        name = identifier = state = None
        lines = output.split("\n")
        for line in lines:
            if "pool:" in line:
                name = line.split(": ")[1]
            elif "id:" in line:
                identifier = line.split(": ")[1]
            elif "state:" in line:
                state = line.split(": ")[1]
                if name == pool_name and state == "ONLINE":
                    return identifier
                else:
                    name = identifier = state = None
        return None
Example #46
0
    def load_existing_pools(self):
        """ Fills existing_pools dict with pool's name,
            identifier and status """

        output = call(["zpool", "import"])
        if not output:
            return

        self.existing_pools = {}

        name = identifier = state = None
        lines = output.split("\n")
        for line in lines:
            if "pool:" in line:
                # Pool info starts
                name = line.split(": ")[1]
                identifier = state = None
            elif "id:" in line:
                identifier = line.split(": ")[1]
            elif "state:" in line:
                state = line.split(": ")[1]
                self.existing_pools[name] = (identifier, state)
Example #47
0
    def load_existing_pools(self):
        """ Fills existing_pools dict with pool's name,
            identifier and status """

        output = call(["zpool", "import"])
        if not output:
            return

        self.existing_pools = {}

        name = identifier = state = None
        lines = output.split("\n")
        for line in lines:
            if "pool:" in line:
                # Pool info starts
                name = line.split(": ")[1]
                identifier = state = None
            elif "id:" in line:
                identifier = line.split(": ")[1]
            elif "state:" in line:
                state = line.split(": ")[1]
                self.existing_pools[name] = (identifier, state)
Example #48
0
def get_pknames():
    """ PKNAME: internal parent kernel device name """
    pknames = {}
    info = None
    cmd = ['lsblk', '-o', 'NAME,PKNAME', '-l']
    info = call(cmd)
    if info:
        info = info.split('\n')
        # skip header
        info = info[1:]
        skip_list = ["disk", "rom", "loop", "arch_root-image"]
        for line in info:
            skip_line = False
            for skip in skip_list:
                if skip in line:
                    skip_line = True
                    break
            if not skip_line:
                line = line.split()
                try:
                    pknames[line[0]] = line[1]
                except IndexError as err:
                    pass
    return pknames
Example #49
0
def get_pknames():
    """ PKNAME: internal parent kernel device name """
    pknames = {}
    info = None
    cmd = ['lsblk', '-o', 'NAME,PKNAME', '-l']
    info = call(cmd)
    if info:
        info = info.split('\n')
        # skip header
        info = info[1:]
        skip_list = ["disk", "rom", "loop", "arch_root-image"]
        for line in info:
            skip_line = False
            for skip in skip_list:
                if skip in line:
                    skip_line = True
                    break
            if not skip_line:
                line = line.split()
                try:
                    pknames[line[0]] = line[1]
                except IndexError as err:
                    pass
    return pknames
Example #50
0
def unmount(directory):
    """ Unmount """
    logging.debug("Unmounting %s", directory)
    call(["umount", "-l", directory])
Example #51
0
    def create_zfs_pool(self, pool_name, pool_type, device_paths):
        """ Create zpool """

        if pool_type not in self.pool_types.values():
            raise InstallError("Unknown pool type: {0}".format(pool_type))

        #for device_path in device_paths:
        #    cmd = ["zpool", "labelclear", device_path]
        #    call(cmd)

        cmd = ["zpool", "create"]

        if self.zfs_options["force_4k"]:
            cmd.extend(["-o", "ashift=12"])

        cmd.extend(["-m", DEST_DIR, pool_name])

        pool_type = pool_type.lower().replace("-", "")

        if pool_type in ["none", "stripe"]:
            # Add first device
            cmd.append(device_paths[0])
        elif pool_type == "mirror":
            if len(device_paths) > 2 and len(device_paths) % 2 == 0:
                # Try to mirror pair of devices
                # (mirrors of two devices each)
                for i,k in zip(device_paths[0::2], device_paths[1::2]):
                    cmd.append(pool_type)
                    cmd.extend([i, k])
            else:
                cmd.append(pool_type)
                cmd.extend(device_paths)
        else:
            cmd.append(pool_type)
            cmd.extend(device_paths)

        # Wait until /dev initialized correct devices
        call(["udevadm", "settle"])
        call(["sync"])

        logging.debug("Creating zfs pool %s...", pool_name)
        if call(cmd, warning=False) is False:
            # Try again, now with -f
            cmd.insert(2, "-f")
            if call(cmd, warning=False) is False:
                # Wait 10 seconds more and try again.
                # (Waiting a bit sometimes works)
                time.sleep(10)
                call(cmd, fatal=True)

        # Wait until /dev initialized correct devices
        call(["udevadm", "settle"])
        call(["sync"])

        if pool_type == "stripe":
            # Add the other devices that were left out
            cmd = ["zpool", "add", pool_name]
            cmd.extend(device_paths[1:])
            call(cmd, fatal=True)

        logging.debug("Pool %s created.", pool_name)
Example #52
0
    def install_efi(self):
        """ Install Grub2 bootloader in a UEFI system """
        uefi_arch = "x86_64"
        spec_uefi_arch = "x64"
        spec_uefi_arch_caps = "X64"
        fpath = '/install/boot/efi/EFI/grub_reborn'
        bootloader_id = 'grub_reborn' if not os.path.exists(fpath) else \
            'grub_reborn_{0}'.format(random_generator())

        # grub2 in efi needs efibootmgr
        if not os.path.exists("/usr/bin/efibootmgr"):
            txt = _(
                "Please install efibootmgr package to install Grub2 for x86_64-efi platform."
            )
            logging.warning(txt)
            txt = _("GRUB(2) will NOT be installed")
            logging.warning(txt)
            self.settings.set('bootloader_installation_successful', False)
            return

        txt = _("Installing GRUB(2) UEFI {0} boot loader").format(uefi_arch)
        logging.info(txt)

        grub_install = [
            'grub-install', '--target={0}-efi'.format(uefi_arch),
            '--efi-directory=/install/boot/efi',
            '--bootloader-id={0}'.format(bootloader_id),
            '--boot-directory=/install/boot', '--recheck'
        ]
        load_module = ['modprobe', '-a', 'efivarfs']

        call(load_module, timeout=15)
        call(grub_install, timeout=120)

        self.install_locales()

        # Copy grub into dirs known to be used as default by some OEMs
        # if they do not exist yet.
        grub_defaults = [
            os.path.join(self.dest_dir, "boot/efi/EFI/BOOT",
                         "BOOT{0}.efi".format(spec_uefi_arch_caps)),
            os.path.join(self.dest_dir, "boot/efi/EFI/Microsoft/Boot",
                         "bootmgfw.efi")
        ]

        grub_path = os.path.join(self.dest_dir, "boot/efi/EFI/antergos_grub",
                                 "grub{0}.efi".format(spec_uefi_arch))

        for grub_default in grub_defaults:
            path = grub_default.split()[0]
            if not os.path.exists(path):
                msg = _("No OEM loader found in %s. Copying Grub(2) into dir.")
                logging.info(msg, path)
                os.makedirs(path, mode=0o755)
                msg_failed = _("Copying Grub(2) into OEM dir failed: %s")
                try:
                    shutil.copy(grub_path, grub_default)
                except FileNotFoundError:
                    logging.warning(msg_failed, _("File not found."))
                except FileExistsError:
                    logging.warning(msg_failed, _("File already exists."))
                except Exception as ex:
                    template = "An exception of type {0} occured. Arguments:\n{1!r}"
                    message = template.format(type(ex).__name__, ex.args)
                    logging.error(message)

        self.run_mkconfig()

        paths = [
            os.path.join(self.dest_dir, "boot/grub/x86_64-efi/core.efi"),
            os.path.join(self.dest_dir,
                         "boot/efi/EFI/{0}".format(bootloader_id),
                         "grub{0}.efi".format(spec_uefi_arch))
        ]

        exists = True
        for path in paths:
            if not os.path.exists(path):
                exists = False
                logging.debug("Path '%s' doesn't exist, when it should", path)

        if exists:
            logging.info("GRUB(2) UEFI install completed successfully")
            self.settings.set('bootloader_installation_successful', True)
        else:
            logging.warning(
                "GRUB(2) UEFI install may not have completed successfully.")
            self.settings.set('bootloader_installation_successful', False)
Example #53
0
    def run_format(self):
        """ Create partitions and file systems """
        # https://wiki.archlinux.org/index.php/Installing_Arch_Linux_on_ZFS
        # https://wiki.archlinux.org/index.php/ZFS#GRUB-compatible_pool_creation

        device_paths = self.zfs_options["device_paths"]
        logging.debug("Configuring ZFS in %s", ",".join(device_paths))

        # Read all preexisting zfs pools. If there's an antergos one, delete it.
        self.do_destroy_zfs_pools()

        # Wipe all disks that will be part of the installation.
        # This cannot be undone!
        self.init_device(device_paths[0], self.zfs_options["scheme"])
        for device_path in device_paths[1:]:
            self.init_device(device_path, "GPT")

        device_path = device_paths[0]
        solaris_partition_number = -1

        self.settings.set('bootloader_device', device_path)

        if self.zfs_options["scheme"] == "GPT":
            part_num = 1

            if not self.uefi:
                # BIOS and GPT
                # Create BIOS Boot Partition
                # GPT GUID: 21686148-6449-6E6F-744E-656564454649
                # This partition is not required if the system is UEFI based,
                # as there is no such embedding of the second-stage code in that case
                wrapper.sgdisk_new(device_path, part_num, "BIOS_BOOT", 2,
                                   "EF02")
                part_num += 1

                # Create BOOT partition
                wrapper.sgdisk_new(device_path, part_num, "ANTERGOS_BOOT", 512,
                                   "8300")
                fs.create_fs(device_path + str(part_num), "ext4",
                             "ANTERGOS_BOOT")
                self.devices['boot'] = "{0}{1}".format(device_path, part_num)
                self.fs_devices[self.devices['boot']] = "ext4"
                self.mount_devices['/boot'] = self.devices['boot']
                part_num += 1
            else:
                # UEFI and GPT
                if self.bootloader == "grub2":
                    # Create EFI System Partition (ESP)
                    # GPT GUID: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
                    wrapper.sgdisk_new(device_path, part_num, "UEFI_SYSTEM",
                                       200, "EF00")
                    self.devices['efi'] = "{0}{1}".format(
                        device_path, part_num)
                    self.fs_devices[self.devices['efi']] = "vfat"
                    self.mount_devices['/boot/efi'] = self.devices['efi']
                    part_num += 1

                    # Create BOOT partition
                    wrapper.sgdisk_new(device_path, part_num, "ANTERGOS_BOOT",
                                       512, "8300")
                    fs.create_fs(device_path + str(part_num), "ext4",
                                 "ANTERGOS_BOOT")
                    self.devices['boot'] = "{0}{1}".format(
                        device_path, part_num)
                    self.fs_devices[self.devices['boot']] = "ext4"
                    self.mount_devices['/boot'] = self.devices['boot']
                    part_num += 1
                else:
                    # systemd-boot, refind
                    # Create BOOT partition
                    wrapper.sgdisk_new(device_path, part_num, "ANTERGOS_BOOT",
                                       512, "EF00")
                    fs.create_fs(device_path + str(part_num), "vfat",
                                 "ANTERGOS_BOOT")
                    self.devices['boot'] = "{0}{1}".format(
                        device_path, part_num)
                    self.fs_devices[self.devices['boot']] = "vfat"
                    self.mount_devices['/boot'] = self.devices['boot']
                    part_num += 1

            # The rest of the disk will be of solaris type
            wrapper.sgdisk_new(device_path, part_num, "ANTERGOS_ZFS", 0,
                               "BF00")
            solaris_partition_number = part_num
            self.devices['root'] = "{0}{1}".format(device_path, part_num)
            # self.fs_devices[self.devices['root']] = "zfs"
            self.mount_devices['/'] = self.devices['root']
        else:
            # MBR

            # Create boot partition (all sizes are in MiB)
            # if start is -1 wrapper.parted_mkpart assumes that our partition
            # starts at 1 (first partition in disk)
            start = -1
            end = 512
            part = "1"
            wrapper.parted_mkpart(device_path, "primary", start, end)

            # Set boot partition as bootable
            wrapper.parted_set(device_path, part, "boot", "on")

            # Format the boot partition as well as any other system partitions.
            # Do not do anything to the Solaris partition nor to the BIOS boot
            # partition. ZFS will manage the first, and the bootloader the
            # second.

            if self.uefi:
                fs_boot = "vfat"
            else:
                fs_boot = "ext4"

            fs.create_fs(device_path + part, fs_boot, "ANTERGOS_BOOT")
            self.devices['boot'] = "{0}{1}".format(device_path, part)
            self.fs_devices[self.devices['boot']] = fs_boot
            self.mount_devices['/boot'] = self.devices['boot']

            # The rest of the disk will be of solaris type
            start = end
            wrapper.parted_mkpart(device_path, "primary", start, "-1s")
            solaris_partition_number = 2
            self.devices['root'] = "{0}{1}".format(device_path, 2)
            # self.fs_devices[self.devices['root']] = "zfs"
            self.mount_devices['/'] = self.devices['root']

        # Wait until /dev initialized correct devices
        call(["udevadm", "settle"])
        call(["sync"])
        '''
        if self.zfs_options["encrypt_disk"]:
            vol_name = self.devices['root'].split("/")[-1]
            password = self.zfs_options["encrypt_password"]

            ap.setup_luks(
                luks_device=self.devices['root'],
                luks_name=vol_name,
                luks_pass=password)

            self.settings.set("use_luks", True)
            self.settings.set("luks_root_password",  password)
            self.settings.set("luks_root_device",  self.devices['root'])

            # Encrypt the rest of drives
            for device_path in device_paths[1:]:
                vol_name = device_path.split("/")[-1]
                ap.setup_luks(
                    luks_device=device_path,
                    luks_name=vol_name,
                    luks_pass=password)
        '''

        self.create_zfs(solaris_partition_number)
Example #54
0
def wipefs(device, fatal=True):
    """ Wipe fs from device """
    err_msg = "Cannot wipe the filesystem of device {0}".format(device)
    cmd = ["wipefs", "-a", device]
    call(cmd, msg=err_msg, fatal=fatal)
Example #55
0
    def create_zfs(self, solaris_partition_number):
        """ Setup ZFS system """

        # Empty DEST_DIR or zfs pool will fail to mount on it
        # (this will delete preexisting installing attempts, too)
        if os.path.exists(DEST_DIR):
            self.clear_dest_dir()

        device_paths = self.zfs_options["device_paths"]
        if not device_paths:
            txt = _("No devices were selected for the ZFS pool")
            raise InstallError(txt)

        # Make sure the ZFS modules are loaded
        call(["modprobe", "zfs"])

        # Using by-id (recommended) does not work atm
        # https://github.com/zfsonlinux/zfs/issues/3708

        # Can't use the whole first disk, just the dedicated zfs partition
        device_paths[0] = self.get_partition_path(device_paths[0],
                                                  solaris_partition_number)

        line = ", ".join(device_paths)
        logging.debug("Cnchi will create a ZFS pool using %s devices", line)

        # Just in case...
        if os.path.exists("/etc/zfs/zpool.cache"):
            os.remove("/etc/zfs/zpool.cache")

        try:
            os.mkdir(DEST_DIR, mode=0o755)
        except OSError:
            pass

        pool_name = self.zfs_options["pool_name"]
        pool_type = self.zfs_options["pool_type"]

        if not self.pool_name_is_valid(pool_name):
            txt = _(
                "Pool name is invalid. It must contain only alphanumeric characters (a-zA-Z0-9_), "
                "hyphens (-), colons (:), and/or spaces ( ). Names starting with the letter 'c' "
                "followed by a number (c[0-9]) are not allowed. The following names are also not "
                "allowed: 'mirror', 'raidz', 'spare', 'log'.")
            raise InstallError(txt)

        # Create zpool
        self.create_zfs_pool(pool_name, pool_type, device_paths)

        # Set the mount point of the root filesystem
        self.set_zfs_mountpoint(pool_name, "/")

        # Set the bootfs property on the descendant root filesystem so the
        # boot loader knows where to find the operating system.
        cmd = ["zpool", "set", "bootfs={0}".format(pool_name), pool_name]
        call(cmd, fatal=True)

        # Create zpool.cache file
        cmd = ["zpool", "set", "cachefile=/etc/zfs/zpool.cache", pool_name]
        call(cmd, fatal=True)

        if self.settings.get('use_home'):
            # Create home zvol
            logging.debug("Creating zfs subvolume 'home'")
            self.create_zfs_vol(pool_name, "home")
            self.set_zfs_mountpoint("{0}/home".format(pool_name), "/home")
            # ZFS automounts, we have to unmount /install/home and delete it,
            # otherwise we won't be able to import the zfs pool
            home_path = "{0}/home".format(DEST_DIR)
            call(["zfs", "umount", home_path], warning=False)
            shutil.rmtree(path=home_path, ignore_errors=True)

        # Create swap zvol (it has to be named "swap")
        swap_size = self.get_swap_size(pool_name)
        self.create_zfs_vol(pool_name, "swap", swap_size)

        # Wait until /dev initialized correct devices
        call(["udevadm", "settle"])
        call(["sync"])

        # Export the pool
        # Makes the kernel to flush all pending data to disk, writes data to
        # the disk acknowledging that the export was done, and removes all
        # knowledge that the storage pool existed in the system
        logging.debug("Exporting pool %s...", pool_name)
        cmd = ["zpool", "export", "-f", pool_name]
        call(cmd, fatal=True)

        # Let's get the id of the pool (to import it)
        pool_id, _status = self.get_pool_id(pool_name)

        if not pool_id:
            # Something bad has happened. Will use the pool name instead.
            logging.warning("Can't get %s zpool id", pool_name)
            pool_id = pool_name

        # Save pool id
        self.settings.set("zfs_pool_id", pool_id)

        # Finally, re-import the pool by-id
        # DEST_DIR must be empty or importing will fail!
        logging.debug("Importing pool %s (%s)...", pool_name, pool_id)
        cmd = [
            "zpool", "import", "-f", "-d", "/dev/disk/by-id", "-R", DEST_DIR,
            pool_id
        ]
        call(cmd, fatal=True)

        # Copy created cache file to destination
        try:
            dst_dir = os.path.join(DEST_DIR, "etc/zfs")
            os.makedirs(dst_dir, mode=0o755, exist_ok=True)
            src = "/etc/zfs/zpool.cache"
            dst = os.path.join(dst_dir, "zpool.cache")
            shutil.copyfile(src, dst)
        except OSError as copy_error:
            logging.warning(copy_error)

        # Store hostid
        hostid = call(["hostid"])
        if hostid:
            hostid_path = os.path.join(DEST_DIR, "etc/hostid")
            with open(hostid_path, "w") as hostid_file:
                hostid_file.write("{0}\n".format(hostid))
Example #56
0
    def install_efi(self):
        """ Install Grub2 bootloader in a UEFI system """
        uefi_arch = "x86_64"
        spec_uefi_arch = "x64"
        spec_uefi_arch_caps = "X64"
        fpath = '/install/boot/efi/EFI/antergos_grub'
        bootloader_id = 'antergos_grub' if not os.path.exists(fpath) else \
            'antergos_grub_{0}'.format(random_generator())

        txt = _("Installing GRUB(2) UEFI {0} boot loader").format(uefi_arch)
        logging.info(txt)

        grub_install = [
            'grub-install',
            '--target={0}-efi'.format(uefi_arch),
            '--efi-directory=/install/boot/efi',
            '--bootloader-id={0}'.format(bootloader_id),
            '--boot-directory=/install/boot',
            '--recheck']
        load_module = ['modprobe', '-a', 'efivarfs']

        call(load_module, timeout=15)
        call(grub_install, timeout=120)

        self.install_locales()

        # Copy grub into dirs known to be used as default by some OEMs
        # if they do not exist yet.
        grub_defaults = [
            os.path.join(
                self.dest_dir,
                "boot/efi/EFI/BOOT",
                "BOOT{0}.efi".format(spec_uefi_arch_caps)),
            os.path.join(
                self.dest_dir,
                "boot/efi/EFI/Microsoft/Boot",
                "bootmgfw.efi")]

        grub_path = os.path.join(
            self.dest_dir,
            "boot/efi/EFI/antergos_grub",
            "grub{0}.efi".format(spec_uefi_arch))

        for grub_default in grub_defaults:
            path = grub_default.split()[0]
            if not os.path.exists(path):
                msg = _("No OEM loader found in %s. Copying Grub(2) into dir.")
                logging.info(msg, path)
                os.makedirs(path, mode=0o755)
                msg_failed = _("Copying Grub(2) into OEM dir failed: %s")
                try:
                    shutil.copy(grub_path, grub_default)
                except FileNotFoundError:
                    logging.warning(msg_failed, _("File not found."))
                except FileExistsError:
                    logging.warning(msg_failed, _("File already exists."))
                except Exception as ex:
                    template = "An exception of type {0} occured. Arguments:\n{1!r}"
                    message = template.format(type(ex).__name__, ex.args)
                    logging.error(message)

        self.run_mkconfig()

        paths = [
            os.path.join(self.dest_dir, "boot/grub/x86_64-efi/core.efi"),
            os.path.join(
                self.dest_dir,
                "boot/efi/EFI/{0}".format(bootloader_id),
                "grub{0}.efi".format(spec_uefi_arch))]

        exists = True
        for path in paths:
            if not os.path.exists(path):
                exists = False
                logging.debug("Path '%s' doesn't exist, when it should", path)

        if exists:
            logging.info("GRUB(2) UEFI install completed successfully")
            self.settings.set('bootloader_installation_successful', True)
        else:
            logging.warning("GRUB(2) UEFI install may not have completed successfully.")
            self.settings.set('bootloader_installation_successful', False)
Example #57
0
    def create_zfs_pool(self, pool_name, pool_type, device_paths):
        """ Create zpool """

        if pool_type not in self.pool_types.values():
            raise InstallError("Unknown pool type: {0}".format(pool_type))

        #for device_path in device_paths:
        #    cmd = ["zpool", "labelclear", device_path]
        #    call(cmd)

        cmd = ["zpool", "create"]

        if self.zfs_options["force_4k"]:
            cmd.extend(["-o", "ashift=12"])

        cmd.extend(["-m", DEST_DIR, pool_name])

        pool_type = pool_type.lower().replace("-", "")

        if pool_type in ["none", "stripe"]:
            # Add first device
            cmd.append(device_paths[0])
        elif pool_type == "mirror":
            if len(device_paths) > 2 and len(device_paths) % 2 == 0:
                # Try to mirror pair of devices
                # (mirrors of two devices each)
                for i, k in zip(device_paths[0::2], device_paths[1::2]):
                    cmd.append(pool_type)
                    cmd.extend([i, k])
            else:
                cmd.append(pool_type)
                cmd.extend(device_paths)
        else:
            cmd.append(pool_type)
            cmd.extend(device_paths)

        # Wait until /dev initialized correct devices
        call(["udevadm", "settle"])
        call(["sync"])

        logging.debug("Creating zfs pool %s...", pool_name)
        if call(cmd, warning=False) is False:
            # Try again, now with -f
            cmd.insert(2, "-f")
            if call(cmd, warning=False) is False:
                # Wait 10 seconds more and try again.
                # (Waiting a bit sometimes works)
                time.sleep(10)
                call(cmd, fatal=True)

        # Wait until /dev initialized correct devices
        call(["udevadm", "settle"])
        call(["sync"])

        if pool_type == "stripe":
            # Add the other devices that were left out
            cmd = ["zpool", "add", pool_name]
            cmd.extend(device_paths[1:])
            call(cmd, fatal=True)

        logging.debug("Pool %s created.", pool_name)
Example #58
0
def create_fs(part, fstype, label='', other_opts=''):
    """ Create filesystem using mkfs
        Set some default options
        -m 1 reserves one percent for root, because I think five percent
        is too much on newer bigger drives.
        Also turn on dir_index for ext.  Not sure about other fs opts
        The return value is tuple.
        (failed, msg)
        First arg is False for success, True for fail
        Second arg is either output from call if successful
        or exception message error if failure """

    if not fstype:
        logging.error("Cannot make a filesystem of type None in partition %s", part)
        return False

    fstype = fstype.lower()

    comdic = {'ext2': 'mkfs.ext2 -F -q',
              'ext3': 'mkfs.ext3 -F -q',
              'ext4': 'mkfs.ext4 -F -q',
              'f2fs': 'mkfs.f2fs',
              'fat': 'mkfs.vfat -F 32',
              'fat16': 'mkfs.vfat -F 16',
              'fat32': 'mkfs.vfat -F 32',
              'vfat': 'mkfs.vfat -F 32',
              'ntfs': 'mkfs.ntfs',
              'jfs': 'mkfs.jfs -q',
              'reiserfs': 'mkfs.reiserfs -q',
              'xfs': 'mkfs.xfs -f',
              'btrfs': 'mkfs.btrfs -f',
              'swap': 'mkswap'}

    if fstype not in comdic.keys():
        logging.error("Unknown filesystem %s for partition %s", fstype, part)
        return False

    cmd = comdic[fstype]

    if label:
        lbldic = {'ext2': '-L "%(label)s"',
                  'ext3': '-L "%(label)s"',
                  'ext4': '-L "%(label)s"',
                  'f2fs': '-l "%(label)s"',
                  'fat': '-n "%(label)s"',
                  'fat16': '-n "%(label)s"',
                  'fat32': '-n "%(label)s"',
                  'vfat': '-n "%(label)s"',
                  'ntfs': '-L "%(label)s"',
                  'jfs': '-L "%(label)s"',
                  'reiserfs': '-l "%(label)s"',
                  'xfs': '-L "%(label)s"',
                  'btrfs': '-L "%(label)s"',
                  'swap': '-L "%(label)s"'}
        cmd += " " + lbldic[fstype]

    if not other_opts:
        default_opts = {'ext2': '-m 1',
                        'ext3': '-m 1 -O dir_index',
                        'ext4': '-m 1 -O dir_index',
                        'f2fs': '',
                        'fat': '',
                        'fat16': '',
                        'fat32': '',
                        'vfat': '',
                        'ntfs': '',
                        'jfs': '',
                        'reiserfs': '',
                        'btrfs': '',
                        'xfs': '',
                        'swap': ''}
        other_opts = default_opts[fstype]

    if other_opts:
        cmd += " %(other_opts)s"

    cmd += " %(part)s"

    cmd = shlex.split(cmd % vars())
    return call(cmd)