def run(self, step, settings, state): device = step['kpartx'] tags = state.tags.get_tags() devs = self.kpartx(device) for tag, dev in zip(tags, devs): vmdb.progress('remembering {} as {}'.format(dev, tag)) state.tags.set_dev(tag, dev)
def run(self, step, settings, state): label_type = step['mklabel'] device = step['device'] vmdb.progress( 'Creating partition table ({}) on {}'.format(label_type, device)) vmdb.runcmd(['parted', '-s', device, 'mklabel', label_type]) state.parts = {}
def run(self, values, settings, state): device = values["kpartx"] tags = state.tags.get_tags() devs = self.kpartx(device) for tag, dev in zip(tags, devs): vmdb.progress("remembering {} as {}".format(dev, tag)) state.tags.set_dev(tag, dev)
def build(self): spec = self.load_spec_file(self._specfile) state = vmdb.State() state.tags = vmdb.Tags() state.arch = vmdb.runcmd(["dpkg", "--print-architecture" ]).decode("UTF-8").strip() self.add_template_vars(state.as_dict()) steps = spec.get_steps(self._tvars) # Check that we have step runners for each step self.load_step_runners() for step in steps: self.step_runners.find(step) steps_taken, core_meltdown = self.run_steps(steps, state) if core_meltdown: vmdb.progress("Something went wrong, cleaning up!") self.run_teardowns(steps_taken, state) else: self.run_teardowns(steps_taken, state) vmdb.progress("All went fine.") if core_meltdown: logging.error("An error occurred, exiting") sys.exit(1)
def process_args(self, args): if len(args) != 1: sys.exit("No image specification was given on the command line.") vmdb.set_verbose_progress(self.settings['verbose']) spec = self.load_spec_file(args[0]) state = vmdb.State() state.tags = vmdb.Tags() params = self.create_template_vars(state) steps = spec.get_steps(params) # Check that we have step runners for each step for step in steps: self.step_runners.find(step) steps_taken, core_meltdown = self.run_steps(steps, state) if core_meltdown: vmdb.progress('Something went wrong, cleaning up!') else: vmdb.progress('All went fine, cleaning up.') self.run_teardowns(steps_taken, state) if core_meltdown: logging.error('An error occurred, exiting with non-zero exit code') sys.exit(1)
def run(self, values, settings, state): tag = values["ansible"] playbook = values["playbook"] mount_point = state.tags.get_builder_mount_point(tag) rootfs_tarball = settings["rootfs-tarball"] state.ansible_inventory = self.create_inventory(mount_point) vmdb.progress("Created {} for Ansible inventory".format( state.ansible_inventory)) vars_filename = self.create_vars(rootfs_tarball) vmdb.progress("Created {} for Ansible variables".format(vars_filename)) env = dict(os.environ) env["ANSIBLE_NOCOWS"] = "1" vmdb.runcmd( [ "ansible-playbook", "-c", "chroot", "-i", state.ansible_inventory, "-e", "@{}".format(vars_filename), playbook, ], env=env, )
def run(self, step, settings, state): part_type = step['mkpart'] device = step['device'] start = step['start'] end = step['end'] part_tag = step['part-tag'] vmdb.progress( 'Creating partition ({}) on {} ({} to {})'.format( part_type, device, start, end)) vmdb.runcmd(['parted', '-s', device, 'mkpart', part_type, start, end]) vmdb.runcmd(['kpartx', '-dsv', device]) output = vmdb.runcmd(['kpartx', '-asv', device]).decode('UTF-8') device_file = None for line in output.splitlines(): words = line.split() if words[0] == 'add': name = words[2] device_file = '/dev/mapper/{}'.format(name) assert device_file is not None parts = getattr(state, 'parts', {}) parts[part_tag] = device_file state.parts = parts
def install_package(self, chroot, package): vmdb.progress('Install {} in chroot {}'.format(package, chroot)) env = os.environ.copy() env['DEBIAN_FRONTEND'] = 'noninteractive' vmdb.runcmd_chroot( chroot, ['apt-get', '-y', '--no-show-progress', 'install', package], env=env)
def run(self, step, settings, state): shell = step['shell'] fs_tag = step['root-fs'] vmdb.progress('run shell {}'.format(' '.join(shell.split('\n')))) env = dict(os.environ) env['ROOT'] = state.mounts[fs_tag] vmdb.runcmd(['sh', '-c', shell], env=env)
def install_uefi(self, step, settings, state): if not 'efi' in step and 'efi-part' not in step: raise Exception( '"efi" or "efi-part" required in UEFI GRUB installtion') vmdb.progress('Installing GRUB for UEFI') grub_package = 'grub-efi-amd64' grub_target = 'x86_64-efi' self.install_grub(step, settings, state, grub_package, grub_target)
def run(self, step, settings, state): fs_tag = step['chroot'] shell = step['shell'] mount_point = state.mounts[fs_tag] vmdb.progress('chroot {} to {}'.format(mount_point, ' '.join(shell.split('\n')))) vmdb.runcmd(['chroot', mount_point, 'sh', '-c', shell])
def run(self, step, settings, state): fs_tag = step['unpack-rootfs'] rootdir = state.mounts[fs_tag] tar_path = settings['rootfs-tarball'] if os.path.exists(tar_path): vmdb.progress('Unpacking rootfs from {} to {}'.format( tar_path, rootdir)) vmdb.runcmd( ['tar', '-C', rootdir, '-xf', tar_path, '--numeric-owner']) state.rootfs_unpacked = True
def install_uefi(self, values, settings, state): efi = values["efi"] or None efi_part = values["efi-part"] or None if efi is None and efi_part is None: raise Exception( '"efi" or "efi-part" required in UEFI GRUB installation') vmdb.progress("Installing GRUB for UEFI") (grub_package, grub_target) = self.grub_uefi_variant(state) self.install_grub(values, settings, state, grub_package, grub_target)
def load_spec_file(self, filename): spec = vmdb.Spec() if filename == "-": vmdb.progress("Load spec from stdin") spec.load_file(sys.stdin) else: vmdb.progress("Load spec file {}".format(filename)) with open(filename) as f: spec.load_file(f) return spec
def run(self, step, settings, state): fs_tag = step['cache-rootfs'] rootdir = state.mounts[fs_tag] tar_path = settings['rootfs-tarball'] if not os.path.exists(tar_path): vmdb.progress('Caching contents of {} to {}'.format( rootdir, tar_path)) vmdb.runcmd([ 'tar', '-C', rootdir, '--one-file-system', '-caf', tar_path, '.' ])
def run(self, step, settings, state): suite = step['debootstrap'] tag = step['target'] target = state.mounts[tag] mirror = step['mirror'] variant = step.get('variant', '-') if not (suite and tag and target and mirror): raise Exception('missing arg for debootstrap step') vmdb.progress('Debootstrap {} {} {}'.format(suite, target, mirror)) vmdb.runcmd( ['debootstrap', '--variant', variant, suite, target, mirror])
def run(self, step, settings, state): tag = step['ansible'] playbook = step['playbook'] mount_point = state.tags.get_mount_point(tag) state.ansible_inventory = self.create_inventory(mount_point) vmdb.progress('Created {} for Ansible inventory'.format( state.ansible_inventory)) env = dict(os.environ) env['ANSIBLE_NOCOWS'] = '1' vmdb.runcmd([ 'ansible-playbook', '-c', 'chroot', '-i', state.ansible_inventory, playbook ], env=env)
def run(self, step, settings, state): suite = step['qemu-debootstrap'] tag = step['target'] target = state.mounts[tag] mirror = step['mirror'] variant = step.get('variant', '-') arch = step['arch'] components = step.get('components', ['main']) if not (suite and tag and target and mirror and arch): raise Exception('missing arg for qemu-debootstrap step') vmdb.progress('Qemu-debootstrap {} {} {} {}'.format( suite, target, mirror, arch)) vmdb.runcmd([ 'qemu-debootstrap', '--arch', arch, '--variant', variant, '--components', ','.join(components), suite, target, mirror ])
def run(self, step, settings, state): fstag = step['ansible'] playbook = step['playbook'] mount_point = state.mounts[fstag] vmdb.progress( 'Running ansible playbook {} on filesystem at {} ({})'.format( playbook, mount_point, fstag)) state.ansible_inventory = self.create_inventory(mount_point) vmdb.progress('Created {} for Ansible inventory'.format( state.ansible_inventory)) env = dict(os.environ) env['ANSIBLE_NOCOWS'] = '1' vmdb.runcmd([ 'ansible-playbook', '-c', 'chroot', '-i', state.ansible_inventory, playbook ], env=env)
def process_args(self, args): vmdb.set_verbose_progress(self.settings['verbose']) spec = self.load_spec_file(args[0]) steps = spec['steps'] # Check that we have step runners for each step for step in steps: self.step_runners.find(step) state = vmdb.State() steps_taken, core_meltdown = self.run_steps(steps, state) if core_meltdown: vmdb.progress('Something went wrong, cleaning up!') else: vmdb.progress('All went fine, cleaning up.') self.run_teardowns(steps_taken, state) if core_meltdown: logging.error('An error occurred, exiting with non-zero exit code') sys.exit(1)
def run(self, values, settings, state): part_type = values["mkpart"] device = values["device"] start = values["start"] end = values["end"] tag = values["tag"] or values["part-tag"] or None fs_type = values["fs-type"] device = os.path.realpath(device) orig = self.list_partitions(device) vmdb.runcmd([ "parted", "-s", device, "--", "mkpart", part_type, fs_type, start, end ]) new = self.list_partitions(device) diff = self.diff_partitions(orig, new) if len(diff) == 0: raise ExpectedNewPartition() if len(diff) > 1: raise UnexpectedNewPartitions(diff) state.tags.append(tag) # If device is a real block device (e.g, /dev/sdb), the # parition we have in diff are also real devices (e.g., # /dev/sdb1), and we should remember those in tags. # # If, however, device is a disk image file (e.g, foo.img), the # partition in diff is not a device file but something like # foo.img1. We don't need to remember that in tags. The user # will use the kpartx step later to add those partitions into # tags. if self.is_block_dev(device): self.wait_for_file_to_exist(diff[0]) vmdb.progress("remembering partition {} as {}".format( diff[0], tag)) state.tags.set_dev(tag, diff[0])
def run(self, step, settings, state): part_type = step['mkpart'] device = step['device'] start = step['start'] end = step['end'] tag = step.get('tag') if tag is None: tag = step['part-tag'] fs_type = step.get('fs-type', 'ext2') orig = self.list_partitions(device) vmdb.runcmd( ['parted', '-s', device, 'mkpart', part_type, fs_type, start, end]) state.tags.append(tag) if self.is_block_dev(device): new = self.list_partitions(device) diff = self.diff_partitions(orig, new) assert len(diff) == 1 vmdb.progress('remembering partition {} as {}'.format( diff[0], tag)) state.tags.set_dev(tag, diff[0])
def run(self, values, settings, state): fs_tag = values["cache-rootfs"] rootdir = state.tags.get_builder_mount_point(fs_tag) tar_path = settings["rootfs-tarball"] opts = values["options"].split() if not tar_path: raise Exception("--rootfs-tarball MUST be set") dirs = self._find_cacheable_mount_points(state.tags, rootdir) tags = state.tags for tag in tags.get_tags(): vmdb.progress("tag {} mounted {} cached {}".format( tag, tags.get_builder_mount_point(tag), tags.is_cached(tag))) vmdb.progress("caching rootdir {}".format(rootdir)) vmdb.progress("caching relative {}".format(dirs)) if not os.path.exists(tar_path): vmdb.runcmd(["tar"] + opts + ["-C", rootdir, "-caf", tar_path] + dirs)
def install_bios(self, step, settings, state): vmdb.progress('Installing GRUB for BIOS') grub_package = 'grub-pc' grub_target = 'i386-pc' self.install_grub(step, settings, state, grub_package, grub_target)
def run(self, step, settings, state): filename = step['mkimg'] size = step['size'] vmdb.progress( 'Creating image file {} (size {})'.format(filename, size)) vmdb.runcmd(['qemu-img', 'create', '-f', 'raw', filename, size])
def teardown(self, step, settings, state): if 'teardown' in step: text = step['teardown'] vmdb.progress('{}'.format(text)) logging.info('%s', text)
def run(self, step, settings, state): text = step['echo'] vmdb.progress('{}'.format(text))
def teardown(self, values, settings, state): if hasattr(state, "ansible_inventory"): vmdb.progress("Removing {}".format(state.ansible_inventory)) os.remove(state.ansible_inventory)
def load_spec_file(self, filename): vmdb.progress('Load spec file {}'.format(filename)) with open(filename) as f: return yaml.safe_load(f)
def teardown(self, step, settings, state): device = step['device'] vmdb.progress( 'Undoing loopback devices for partitions on {}'.format(device)) vmdb.runcmd(['kpartx', '-dsv', device])