Exemple #1
0
    def configure_system(self):
        """ Final install steps
            Set clock, language, timezone
            Run mkinitcpio
            Populate pacman keyring
            Setup systemd services
            ... and more """

        self.queue_event('pulse', 'start')
        self.queue_event('info', _("Configuring your new system"))

        # This mounts (binds) /dev and others to /DEST_DIR/dev and others
        chroot.mount_special_dirs(DEST_DIR)

        self.auto_fstab()
        logging.debug("fstab file generated.")

        # If SSD was detected copy udev rule for deadline scheduler
        if self.ssd:
            self.set_scheduler()
            logging.debug("SSD udev rule copied successfully")

        # Copy configured networks in Live medium to target system
        if self.network_manager == 'NetworkManager':
            self.copy_network_config()

        if self.desktop == "base":
            # Setup systemd-networkd for systems that won't use the
            # networkmanager or connman daemons (atm it's just base install)
            # Enable systemd_networkd services
            # See: https://github.com/Antergos/Cnchi/issues/332#issuecomment-108745026
            self.enable_services(["systemd-networkd", "systemd-resolved"])
            # Setup systemd_networkd
            # TODO: Ask user for SSID and passphrase if a wireless link is found
            # (should this be done here or inside systemd_networkd.setup() ?)
            from installation import systemd_networkd
            systemd_networkd.setup()

        logging.debug("Network configuration done.")

        # Copy mirror list
        mirrorlist_src_path = '/etc/pacman.d/mirrorlist'
        mirrorlist_dst_path = os.path.join(DEST_DIR, 'etc/pacman.d/mirrorlist')
        try:
            shutil.copy2(mirrorlist_src_path, mirrorlist_dst_path)
            logging.debug("Mirror list copied.")
        except FileNotFoundError:
            logging.error("Can't copy mirrorlist file. File %s not found", mirrorlist_src_path)
        except FileExistsError:
            logging.warning("File %s already exists.", mirrorlist_dst_path)

        # Add Antergos repo to /etc/pacman.conf
        self.update_pacman_conf()

        logging.debug("pacman.conf has been created successfully")

        # Enable some useful services
        services = []
        if self.desktop != "base":
            # In base there's no desktop manager ;)
            services.append(self.desktop_manager)
            # In base we use systemd-networkd (setup already done above)
            services.append(self.network_manager)
        services.extend(["ModemManager", "haveged"])
        self.enable_services(services)

        # Enable timesyncd service
        if self.settings.get("use_timesyncd"):
            timesyncd_path = os.path.join(DEST_DIR, "etc/systemd/timesyncd.conf")
            with open(timesyncd_path, 'w') as timesyncd:
                timesyncd.write("[Time]\n")
                timesyncd.write("NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org 2.arch.pool.ntp.org 3.arch.pool.ntp.org\n")
                timesyncd.write("FallbackNTP=0.pool.ntp.org 1.pool.ntp.org 0.fr.pool.ntp.org\n")
            chroot_run(['timedatectl', 'set-ntp', 'true'])

        # Set timezone
        zoneinfo_path = os.path.join("/usr/share/zoneinfo", self.settings.get("timezone_zone"))
        chroot_run(['ln', '-s', zoneinfo_path, "/etc/localtime"])
        logging.debug("Timezone set.")

        # Wait FOREVER until the user sets his params
        # FIXME: We can wait here forever!
        while self.settings.get('user_info_done') is False:
            # Wait five seconds and try again
            time.sleep(5)

        # Set user parameters
        username = self.settings.get('username')
        fullname = self.settings.get('fullname')
        password = self.settings.get('password')
        hostname = self.settings.get('hostname')

        sudoers_dir = os.path.join(DEST_DIR, "etc/sudoers.d")
        if not os.path.exists(sudoers_dir):
            os.mkdir(sudoers_dir, 0o710)
        sudoers_path = os.path.join(sudoers_dir, "10-installer")
        try:
            with open(sudoers_path, "w") as sudoers:
                sudoers.write('{0} ALL=(ALL) ALL\n'.format(username))
            os.chmod(sudoers_path, 0o440)
            logging.debug("Sudo configuration for user %s done.", username)
        except IOError as io_error:
            # Do not fail if can't write 10-installer file. Something bad must be happening, though.
            logging.error(io_error)

        # Configure detected hardware
        # NOTE: Because hardware can need extra repos, this code must run
        # always after having called the update_pacman_conf method
        if self.hardware_install:
            try:
                logging.debug("Running hardware drivers post-install jobs...")
                self.hardware_install.post_install(DEST_DIR)
            except Exception as general_error:
                logging.error("Unknown error in hardware module. Output: %s", general_error)

        # Setup user

        default_groups = 'lp,video,network,storage,wheel,audio'

        if self.vbox:
            # Why there is no vboxusers group? Add it ourselves.
            chroot_run(['groupadd', 'vboxusers'])
            default_groups += ',vboxusers,vboxsf'
            self.enable_services(["vboxservice"])

        if self.settings.get('require_password') is False:
            # Prepare system for autologin. LightDM needs the user to be in the autologin group.
            chroot_run(['groupadd', 'autologin'])
            default_groups += ',autologin'

        cmd = ['useradd', '-m', '-s', '/bin/bash', '-g', 'users', '-G', default_groups, username]
        chroot_run(cmd)
        logging.debug("User %s added.", username)

        self.change_user_password(username, password)

        cmd = ['chfn', '-f', fullname, username]
        chroot_run(cmd)

        cmd = ['chown', '-R', '{0}:users'.format(username), os.path.join("/home", username)]
        chroot_run(cmd)

        hostname_path = os.path.join(DEST_DIR, "etc/hostname")
        if not os.path.exists(hostname_path):
            with open(hostname_path, "w") as hostname_file:
                hostname_file.write(hostname)

        logging.debug("Hostname set to %s", hostname)

        # User password is the root password
        self.change_user_password('root', password)
        logging.debug("Set the same password to root.")

        # Generate locales
        locale = self.settings.get("locale")
        self.queue_event('info', _("Generating locales..."))
        self.uncomment_locale_gen(locale)
        chroot_run(['locale-gen'])
        locale_conf_path = os.path.join(DEST_DIR, "etc/locale.conf")
        with open(locale_conf_path, "w") as locale_conf:
            locale_conf.write('LANG={0}\n'.format(locale))
            locale_conf.write('LC_COLLATE={0}\n'.format(locale))

        # environment_path = os.path.join(DEST_DIR, "etc/environment")
        # with open(environment_path, "w") as environment:
        #    environment.write('LANG={0}\n'.format(locale))

        self.queue_event('info', _("Adjusting hardware clock..."))
        self.auto_timesetting()

        self.queue_event('info', _("Configuring keymap..."))

        keyboard_layout = self.settings.get("keyboard_layout")
        keyboard_variant = self.settings.get("keyboard_variant")

        if self.desktop != "base":
            # Set /etc/X11/xorg.conf.d/00-keyboard.conf for the xkblayout
            logging.debug("Set /etc/X11/xorg.conf.d/00-keyboard.conf for the xkblayout")
            xorg_conf_dir = os.path.join(DEST_DIR, "etc/X11/xorg.conf.d")
            if not os.path.exists(xorg_conf_dir):
                os.mkdir(xorg_conf_dir, 0o755)
            xorg_conf_xkb_path = os.path.join(xorg_conf_dir, "00-keyboard.conf")
            try:
                with open(xorg_conf_xkb_path, "w") as xorg_conf_xkb:
                    xorg_conf_xkb.write(
                        "# Read and parsed by systemd-localed. It's probably wise not to edit this file\n")
                    xorg_conf_xkb.write('# manually too freely.\n')
                    xorg_conf_xkb.write('Section "InputClass"\n')
                    xorg_conf_xkb.write('        Identifier "system-keyboard"\n')
                    xorg_conf_xkb.write('        MatchIsKeyboard "on"\n')
                    xorg_conf_xkb.write('        Option "XkbLayout" "{0}"\n'.format(keyboard_layout))
                    if keyboard_variant and len(keyboard_variant) > 0:
                        xorg_conf_xkb.write('        Option "XkbVariant" "{0}"\n'.format(keyboard_variant))
                    xorg_conf_xkb.write('EndSection\n')
                logging.debug("00-keyboard.conf written.")
            except IOError as io_error:
                # Do not fail if 00-keyboard.conf can't be created.
                # Something bad must be happening, though.
                logging.error(io_error)

        # Set vconsole.conf for console keymap
        if keyboard_layout == "gb":
            # The keyboard layout for Great Britain is "uk" in the cli and
            # "gb" (not uk) in X, just to make things more complicated.
            keyboard_layout_cli = "uk"
        else:
            keyboard_layout_cli = keyboard_layout

        vconsole_path = os.path.join(DEST_DIR, "etc/vconsole.conf")
        with open(vconsole_path, 'w') as vconsole:
            vconsole.write("KEYMAP={0}\n".format(keyboard_layout_cli))

        # Install configs for root
        cmd = ['cp', '-av', '/etc/skel/.', '/root/']
        chroot_run(cmd)

        self.queue_event('info', _("Configuring hardware..."))

        # Copy generated xorg.conf to target
        if os.path.exists("/etc/X11/xorg.conf"):
            shutil.copy2(
                "/etc/X11/xorg.conf",
                os.path.join(DEST_DIR, 'etc/X11/xorg.conf'))

        # Configure ALSA
        #self.alsa_mixer_setup()
        #logging.debug("Updated Alsa mixer settings")

        # Set pulse
        #if os.path.exists(os.path.join(DEST_DIR, "usr/bin/pulseaudio-ctl")):
        #    chroot_run(['pulseaudio-ctl', 'normal'])

        # Set fluidsynth audio system (in our case, pulseaudio)
        self.set_fluidsynth()
        logging.debug("Updated fluidsynth configuration file")

        # Let's start without using hwdetect for mkinitcpio.conf.
        # It should work out of the box most of the time.
        # This way we don't have to fix deprecated hooks.
        # NOTE: With LUKS or LVM maybe we'll have to fix deprecated hooks.
        self.queue_event('info', _("Configuring System Startup..."))
        mkinitcpio.run(DEST_DIR, self.settings, self.mount_devices, self.blvm)

        logging.debug("Running Cnchi post-install script")
        # Call post-install script to fine tune our setup
        script_path_postinstall = os.path.join(
            self.settings.get('cnchi'),
            "scripts",
            POSTINSTALL_SCRIPT)
        cmd = ["/usr/bin/bash", script_path_postinstall, username, DEST_DIR, self.desktop, keyboard_layout]
        if keyboard_variant:
            cmd.append(keyboard_variant)
        else:
            cmd.append("")
        cmd.append(str(self.vbox))
        try:
            subprocess.check_call(cmd, timeout=300)
            logging.debug("Post install script completed successfully.")
        except subprocess.CalledProcessError as process_error:
            # Even though Post-install script call has failed we will go on
            logging.error("Error running post-install script, command %s failed: %s",
                process_error.cmd, process_error.output)
        except subprocess.TimeoutExpired as timeout_error:
            logging.error(timeout_error)

        # Set lightdm config including autologin if selected
        if self.desktop != "base":
            self.setup_display_manager()

        # Configure user features (firewall, libreoffice language pack, ...)
        self.setup_features()

        # Encrypt user's home directory if requested
        # FIXME: This is not working atm
        if self.settings.get('encrypt_home'):
            logging.debug("Encrypting user home dir...")
            encfs.setup(username, DEST_DIR)
            logging.debug("User home dir encrypted")

        # Install boot loader (always after running mkinitcpio)
        if self.settings.get('bootloader_install'):
            try:
                logging.debug("Installing bootloader...")
                from installation import bootloader
                boot_loader = bootloader.Bootloader(DEST_DIR, self.settings, self.mount_devices)
                boot_loader.install()
            except Exception as general_error:
                logging.warning("While installing boot loader Cnchi encountered this error: %s", general_error)

        # This unmounts (unbinds) /dev and others to /DEST_DIR/dev and others
        chroot.umount_special_dirs(DEST_DIR)

        # Copy installer log to the new installation (just in case something goes wrong)
        logging.debug("Copying install log to /var/log.")
        self.copy_log()

        self.queue_event('pulse', 'stop')
Exemple #2
0
    def configure_system(self):
        """ Final install steps
            Set clock, language, timezone
            Run mkinitcpio
            Populate pacman keyring
            Setup systemd services
            ... and more """

        self.queue_event("pulse", "start")
        self.queue_event("info", _("Configuring your new system"))

        self.auto_fstab()
        logging.debug("fstab file generated.")

        # If SSD was detected copy udev rule for deadline scheduler
        if self.ssd:
            self.set_scheduler()
            logging.debug("SSD udev rule copied successfully")

        # Copy configured networks in Live medium to target system
        if self.settings.get("network_manager") == "NetworkManager":
            self.copy_network_config()

        if self.desktop == "base":
            # Setup systemd-networkd for systems that won't use the
            # networkmanager or connman daemons (atm it's just base install)
            # Enable systemd_networkd services
            # https://github.com/Antergos/Cnchi/issues/332#issuecomment-108745026
            self.enable_services(["systemd-networkd", "systemd-resolved"])
            # Setup systemd_networkd
            # TODO: Ask user for SSID and passphrase if a wireless link is
            # found (here or inside systemd_networkd.setup() ?)
            from installation import systemd_networkd

            systemd_networkd.setup()

        logging.debug("Network configuration done.")

        # Copy mirror list
        mirrorlist_src_path = "/etc/pacman.d/mirrorlist"
        mirrorlist_dst_path = os.path.join(DEST_DIR, "etc/pacman.d/mirrorlist")
        try:
            shutil.copy2(mirrorlist_src_path, mirrorlist_dst_path)
            logging.debug("Mirror list copied.")
        except FileNotFoundError:
            logging.error("Can't copy mirrorlist file. File %s not found", mirrorlist_src_path)
        except FileExistsError:
            logging.warning("File %s already exists.", mirrorlist_dst_path)

        # Add Antergos repo to /etc/pacman.conf
        self.update_pacman_conf()

        logging.debug("pacman.conf has been created successfully")

        # Enable some useful services
        services = []

        if self.desktop != "base":
            # In base there's no desktop manager ;)
            services.append(self.settings.get("desktop_manager"))
            # In base we use systemd-networkd (setup already done above)
            services.append(self.settings.get("network_manager"))

        services.extend(["ModemManager", "haveged"])

        if self.method == "zfs":
            services.extend(["zfs", "zfs-mount"])

        self.enable_services(services)

        # Enable timesyncd service
        if self.settings.get("use_timesyncd"):
            timesyncd_path = os.path.join(DEST_DIR, "etc/systemd/timesyncd.conf")
            try:
                with open(timesyncd_path, "w") as timesyncd:
                    timesyncd.write("[Time]\n")
                    timesyncd.write(
                        "NTP=0.arch.pool.ntp.org 1.arch.pool.ntp.org " "2.arch.pool.ntp.org 3.arch.pool.ntp.org\n"
                    )
                    timesyncd.write("FallbackNTP=0.pool.ntp.org 1.pool.ntp.org " "0.fr.pool.ntp.org\n")
            except FileNotFoundError as err:
                logging.warning("Can't find %s file.", timesyncd_path)
            chroot_call(["timedatectl", "set-ntp", "true"])

        # Set timezone
        zoneinfo_path = os.path.join("/usr/share/zoneinfo", self.settings.get("timezone_zone"))
        chroot_call(["ln", "-s", zoneinfo_path, "/etc/localtime"])
        logging.debug("Timezone set.")

        # Wait FOREVER until the user sets his params
        # FIXME: We can wait here forever!
        while self.settings.get("user_info_done") is False:
            # Wait five seconds and try again
            time.sleep(5)

        # Set user parameters
        username = self.settings.get("username")
        fullname = self.settings.get("fullname")
        password = self.settings.get("password")
        hostname = self.settings.get("hostname")

        sudoers_dir = os.path.join(DEST_DIR, "etc/sudoers.d")
        if not os.path.exists(sudoers_dir):
            os.mkdir(sudoers_dir, 0o710)
        sudoers_path = os.path.join(sudoers_dir, "10-installer")
        try:
            with open(sudoers_path, "w") as sudoers:
                sudoers.write("{0} ALL=(ALL) ALL\n".format(username))
            os.chmod(sudoers_path, 0o440)
            logging.debug("Sudo configuration for user %s done.", username)
        except IOError as io_error:
            # Do not fail if can't write 10-installer file.
            # Something bad must be happening, though.
            logging.error(io_error)

        # Configure detected hardware
        # NOTE: Because hardware can need extra repos, this code must run
        # always after having called the update_pacman_conf method
        if self.hardware_install:
            try:
                logging.debug("Running hardware drivers post-install jobs...")
                self.hardware_install.post_install(DEST_DIR)
            except Exception as ex:
                template = "Error in hardware module. An exception of type {0} occured. Arguments:\n{1!r}"
                message = template.format(type(ex).__name__, ex.args)
                logging.error(message)

        # Setup user

        default_groups = "lp,video,network,storage,wheel,audio"

        if self.vbox:
            # Why there is no vboxusers group? Add it ourselves.
            chroot_call(["groupadd", "vboxusers"])
            default_groups += ",vboxusers,vboxsf"
            self.enable_services(["vboxservice"])

        if self.settings.get("require_password") is False:
            # Prepare system for autologin.
            # LightDM needs the user to be in the autologin group.
            chroot_call(["groupadd", "autologin"])
            default_groups += ",autologin"

        cmd = ["useradd", "-m", "-s", "/bin/bash", "-g", "users", "-G", default_groups, username]
        chroot_call(cmd)
        logging.debug("User %s added.", username)

        self.change_user_password(username, password)

        chroot_call(["chfn", "-f", fullname, username])
        home_dir = os.path.join("/home", username)
        cmd = ["chown", "-R", "{0}:users".format(username), home_dir]
        chroot_call(cmd)

        # Set hostname
        hostname_path = os.path.join(DEST_DIR, "etc/hostname")
        if not os.path.exists(hostname_path):
            with open(hostname_path, "w") as hostname_file:
                hostname_file.write(hostname)

        logging.debug("Hostname set to %s", hostname)

        # User password is the root password
        self.change_user_password("root", password)
        logging.debug("Set the same password to root.")

        # Generate locales
        locale = self.settings.get("locale")
        self.queue_event("info", _("Generating locales..."))
        self.uncomment_locale_gen(locale)
        chroot_call(["locale-gen"])
        locale_conf_path = os.path.join(DEST_DIR, "etc/locale.conf")
        with open(locale_conf_path, "w") as locale_conf:
            locale_conf.write("LANG={0}\n".format(locale))
            locale_conf.write("LC_COLLATE={0}\n".format(locale))

        # environment_path = os.path.join(DEST_DIR, "etc/environment")
        # with open(environment_path, "w") as environment:
        #    environment.write('LANG={0}\n'.format(locale))

        self.queue_event("info", _("Adjusting hardware clock..."))
        self.auto_timesetting()

        self.queue_event("info", _("Configuring keymap..."))

        if self.desktop != "base":
            self.set_keyboard_conf()

        self.set_vconsole_conf()

        # Install configs for root
        chroot_call(["cp", "-av", "/etc/skel/.", "/root/"])

        self.queue_event("info", _("Configuring hardware..."))

        # Copy generated xorg.conf to target
        if os.path.exists("/etc/X11/xorg.conf"):
            src = "/etc/X11/xorg.conf"
            dst = os.path.join(DEST_DIR, "etc/X11/xorg.conf")
            shutil.copy2(src, dst)

        # Configure ALSA
        # self.alsa_mixer_setup()
        # logging.debug("Updated Alsa mixer settings")

        # Set pulse
        # if os.path.exists(os.path.join(DEST_DIR, "usr/bin/pulseaudio-ctl")):
        #    chroot_run(['pulseaudio-ctl', 'normal'])

        # Set fluidsynth audio system (in our case, pulseaudio)
        self.set_fluidsynth()
        logging.debug("Updated fluidsynth configuration file")

        # Workaround for pacman-key bug FS#45351
        # https://bugs.archlinux.org/task/45351
        # We have to kill gpg-agent because if it stays around we can't
        # reliably unmount the target partition.
        logging.debug("Stopping gpg agent...")
        chroot_call(["killall", "-9", "gpg-agent"])

        # FIXME: Temporary workaround for spl and zfs packages
        if self.method == "zfs":
            zfs_version = self.get_zfs_version()
            logging.debug("Installing zfs modules v%s...", zfs_version)
            chroot_call(["dkms", "install", "spl/{0}".format(zfs_version)])
            chroot_call(["dkms", "install", "zfs/{0}".format(zfs_version)])

        # Let's start without using hwdetect for mkinitcpio.conf.
        # It should work out of the box most of the time.
        # This way we don't have to fix deprecated hooks.
        # NOTE: With LUKS or LVM maybe we'll have to fix deprecated hooks.
        self.queue_event("info", _("Configuring System Startup..."))
        mkinitcpio.run(DEST_DIR, self.settings, self.mount_devices, self.blvm)

        logging.debug("Running Cnchi post-install script")
        keyboard_layout = self.settings.get("keyboard_layout")
        keyboard_variant = self.settings.get("keyboard_variant")
        # Call post-install script to fine tune our setup
        script_path_postinstall = os.path.join(self.settings.get("cnchi"), "scripts", POSTINSTALL_SCRIPT)
        cmd = [
            "/usr/bin/bash",
            script_path_postinstall,
            username,
            DEST_DIR,
            self.desktop,
            locale,
            str(self.vbox),
            keyboard_layout,
        ]
        # Keyboard variant is optional
        if keyboard_variant:
            cmd.append(keyboard_variant)

        call(cmd, timeout=300)
        logging.debug("Post install script completed successfully.")

        # Patch user-dirs-update-gtk.desktop
        self.patch_user_dirs_update_gtk()
        logging.debug("File user-dirs-update-gtk.desktop patched.")

        # Set lightdm config including autologin if selected
        if self.desktop != "base":
            self.setup_display_manager()

        # Configure user features (firewall, libreoffice language pack, ...)
        self.setup_features()

        # Encrypt user's home directory if requested
        # FIXME: This is not working atm
        if self.settings.get("encrypt_home"):
            self.queue_event("info", _("Encrypting user home dir..."))
            encfs.setup(username, DEST_DIR)
            logging.debug("User home dir encrypted")

        # Install boot loader (always after running mkinitcpio)
        if self.settings.get("bootloader_install"):
            try:
                self.queue_event("info", _("Installing bootloader..."))
                from installation.boot import loader

                boot_loader = loader.Bootloader(DEST_DIR, self.settings, self.mount_devices)
                boot_loader.install()
            except Exception as ex:
                template = "Cannot install bootloader. An exception of type {0} occured. Arguments:\n{1!r}"
                message = template.format(type(ex).__name__, ex.args)
                logging.error(message)

        # Create an initial database for mandb
        self.queue_event("info", _("Updating man pages..."))
        chroot_call(["mandb", "--quiet"])

        # Initialise pkgfile (pacman .files metadata explorer) database
        logging.debug("Updating pkgfile database")
        chroot_call(["pkgfile", "--update"])

        # Copy installer log to the new installation
        logging.debug("Copying install log to /var/log.")
        self.copy_log()

        self.queue_event("pulse", "stop")
        self.queue_event("progress_bar", "hide")