def apt_command(args): """ Main entry point for curtin apt-config standalone command This does not read the global config as handled by curthooks, but instead one can specify a different "target" and a new cfg via --config """ cfg = config.load_command_config(args, {}) if args.target is not None: target = args.target else: state = util.load_command_environment() target = state['target'] if target is None: sys.stderr.write("Unable to find target. " "Use --target or set TARGET_MOUNT_POINT\n") sys.exit(2) apt_cfg = cfg.get("apt") # if no apt config section is available, do nothing if apt_cfg is not None: LOG.debug("Handling apt to target %s with config %s", target, apt_cfg) try: with util.ChrootableTarget(target, sys_resolvconf=True): handle_apt(apt_cfg, target) except (RuntimeError, TypeError, ValueError, IOError): LOG.exception("Failed to configure apt features '%s'", apt_cfg) sys.exit(1) else: LOG.info("No apt config provided, skipping") sys.exit(0)
def interfaces_custom(args): state = util.load_command_environment() cfg = config.load_command_config(args, state) network_config = cfg.get('network', []) if not network_config: raise Exception("network configuration is required by mode '%s' " "but not provided in the config file" % 'custom') return {'network': network_config}
def install_grub_main(args): state = util.load_command_environment() if args.target is not None: target = args.target else: target = state['target'] if target is None: sys.stderr.write("Unable to find target. " "Use --target or set TARGET_MOUNT_POINT\n") sys.exit(2) cfg = config.load_command_config(args, state) stack_prefix = state.get('report_stack_prefix', '') uefi = util.is_uefi_bootable() grubcfg = cfg.get('grub') with events.ReportEventStack( name=stack_prefix, reporting_enabled=True, level="INFO", description="Installing grub to target devices"): install_grub(args.devices, target, uefi=uefi, grubcfg=grubcfg) sys.exit(0)
def net_meta(args): # curtin net-meta --devices connected dhcp # curtin net-meta --devices configured dhcp # curtin net-meta --devices netboot dhcp # curtin net-meta --devices connected custom # if network-config hook exists in target, # we do not run the builtin if util.run_hook_if_exists(args.target, 'network-config'): sys.exit(0) state = util.load_command_environment() cfg = config.load_command_config(args, state) if cfg.get("network") is not None: args.mode = "custom" eni = "etc/network/interfaces" if args.mode == "auto": if not args.devices: args.devices = ["connected"] t_eni = None if args.target: t_eni = os.path.sep.join(( args.target, eni, )) if not os.path.isfile(t_eni): t_eni = None if t_eni: args.mode = "copy" else: args.mode = "dhcp" devices = [] if args.devices: for dev in args.devices: if dev in DEVNAME_ALIASES: devices += resolve_alias(dev) else: devices.append(dev) LOG.debug("net-meta mode is '%s'. devices=%s", args.mode, devices) output_network_config = os.environ.get("OUTPUT_NETWORK_CONFIG", "") if args.mode == "copy": if not args.target: raise argparse.ArgumentTypeError("mode 'copy' requires --target") t_eni = os.path.sep.join(( args.target, "etc/network/interfaces", )) with open(t_eni, "r") as fp: content = fp.read() LOG.warn( "net-meta mode is 'copy', static network interfaces files" "can be brittle. Copied interfaces: %s", content) target = args.output elif args.mode == "dhcp": target = output_network_config content = config.dump_config(interfaces_basic_dhcp(devices)) elif args.mode == 'custom': target = output_network_config content = config.dump_config(interfaces_custom(args)) else: raise Exception("Unexpected network config mode '%s'." % args.mode) if not target: raise Exception( "No target given for mode = '%s'. No where to write content: %s" % (args.mode, content)) LOG.debug("writing to file %s with network config: %s", target, content) if target == "-": sys.stdout.write(content) else: with open(target, "w") as fp: fp.write(content) sys.exit(0)
def curthooks(args): state = util.load_command_environment() if args.target is not None: target = args.target else: target = state['target'] if target is None: sys.stderr.write("Unable to find target. " "Use --target or set TARGET_MOUNT_POINT\n") sys.exit(2) cfg = config.load_command_config(args, state) stack_prefix = state.get('report_stack_prefix', '') # if curtin-hooks hook exists in target we can defer to the in-target hooks if util.run_hook_if_exists(target, 'curtin-hooks'): # For vmtests to force execute centos_apply_network_config, uncomment # the value in examples/tests/centos_defaults.yaml if cfg.get('_ammend_centos_curthooks'): if cfg.get('cloudconfig'): handle_cloudconfig(cfg['cloudconfig'], base_dir=util.target_path( target, 'etc/cloud/cloud.cfg.d')) if target_is_centos(target) or target_is_rhel(target): LOG.info('Detected RHEL/CentOS image, running extra hooks') with events.ReportEventStack( name=stack_prefix, reporting_enabled=True, level="INFO", description="Configuring CentOS for first boot"): centos_apply_network_config(cfg.get('network', {}), target) sys.exit(0) if target_is_ubuntu_core(target): LOG.info('Detected Ubuntu-Core image, running hooks') with events.ReportEventStack( name=stack_prefix, reporting_enabled=True, level="INFO", description="Configuring Ubuntu-Core for first boot"): ubuntu_core_curthooks(cfg, target) sys.exit(0) with events.ReportEventStack( name=stack_prefix + '/writing-config', reporting_enabled=True, level="INFO", description="configuring apt configuring apt"): do_apt_config(cfg, target) disable_overlayroot(cfg, target) # LP: #1742560 prevent zfs-dkms from being installed (Xenial) if util.lsb_release(target=target)['codename'] == 'xenial': util.apt_update(target=target) with util.ChrootableTarget(target) as in_chroot: in_chroot.subp(['apt-mark', 'hold', 'zfs-dkms']) # packages may be needed prior to installing kernel with events.ReportEventStack(name=stack_prefix + '/installing-missing-packages', reporting_enabled=True, level="INFO", description="installing missing packages"): install_missing_packages(cfg, target) # If a /etc/iscsi/nodes/... file was created by block_meta then it # needs to be copied onto the target system nodes_location = os.path.join(os.path.split(state['fstab'])[0], "nodes") if os.path.exists(nodes_location): copy_iscsi_conf(nodes_location, target) # do we need to reconfigure open-iscsi? # If a mdadm.conf file was created by block_meta than it needs to be copied # onto the target system mdadm_location = os.path.join( os.path.split(state['fstab'])[0], "mdadm.conf") if os.path.exists(mdadm_location): copy_mdadm_conf(mdadm_location, target) # as per https://bugs.launchpad.net/ubuntu/+source/mdadm/+bug/964052 # reconfigure mdadm util.subp(['dpkg-reconfigure', '--frontend=noninteractive', 'mdadm'], data=None, target=target) with events.ReportEventStack(name=stack_prefix + '/installing-kernel', reporting_enabled=True, level="INFO", description="installing kernel"): setup_zipl(cfg, target) install_kernel(cfg, target) run_zipl(cfg, target) restore_dist_interfaces(cfg, target) with events.ReportEventStack(name=stack_prefix + '/setting-up-swap', reporting_enabled=True, level="INFO", description="setting up swap"): add_swap(cfg, target, state.get('fstab')) with events.ReportEventStack(name=stack_prefix + '/apply-networking-config', reporting_enabled=True, level="INFO", description="apply networking config"): apply_networking(target, state) with events.ReportEventStack(name=stack_prefix + '/writing-etc-fstab', reporting_enabled=True, level="INFO", description="writing etc/fstab"): copy_fstab(state.get('fstab'), target) with events.ReportEventStack(name=stack_prefix + '/configuring-multipath', reporting_enabled=True, level="INFO", description="configuring multipath"): detect_and_handle_multipath(cfg, target) with events.ReportEventStack( name=stack_prefix + '/system-upgrade', reporting_enabled=True, level="INFO", description="updating packages on target system"): system_upgrade(cfg, target) with events.ReportEventStack( name=stack_prefix + '/pollinate-user-agent', reporting_enabled=True, level="INFO", description="configuring pollinate user-agent on target system"): handle_pollinate_user_agent(cfg, target) # If a crypttab file was created by block_meta than it needs to be copied # onto the target system, and update_initramfs() needs to be run, so that # the cryptsetup hooks are properly configured on the installed system and # it will be able to open encrypted volumes at boot. crypttab_location = os.path.join( os.path.split(state['fstab'])[0], "crypttab") if os.path.exists(crypttab_location): copy_crypttab(crypttab_location, target) update_initramfs(target) # If udev dname rules were created, copy them to target udev_rules_d = os.path.join(state['scratch'], "rules.d") if os.path.isdir(udev_rules_d): copy_dname_rules(udev_rules_d, target) # As a rule, ARMv7 systems don't use grub. This may change some # day, but for now, assume no. They do require the initramfs # to be updated, and this also triggers boot loader setup via # flash-kernel. machine = platform.machine() if (machine.startswith('armv7') or machine.startswith('s390x') or machine.startswith('aarch64') and not util.is_uefi_bootable()): update_initramfs(target) else: setup_grub(cfg, target) sys.exit(0)