Commit 6a52dda9 authored by Lars Wirzenius's avatar Lars Wirzenius

Change: systematize how tags are used

parent bbf93e52
...@@ -9,37 +9,35 @@ steps: ...@@ -9,37 +9,35 @@ steps:
device: "{{ output }}" device: "{{ output }}"
start: 0% start: 0%
end: 100% end: 100%
part-tag: root-part tag: rootfs
- mkfs: ext4 - mkfs: ext4
partition: root-part partition: rootfs
label: smoke label: smoke
- mount: root-part - mount: rootfs
fs-tag: root-fs
- unpack-rootfs: root-fs - unpack-rootfs: rootfs
- debootstrap: stretch - debootstrap: stretch
mirror: http://deb.debian.org/debian mirror: http://deb.debian.org/debian
target: root-fs target: rootfs
unless: rootfs_unpacked unless: rootfs_unpacked
- apt: install - apt: install
packages: packages:
- linux-image-amd64 - linux-image-amd64
fs-tag: root-fs tag: rootfs
unless: rootfs_unpacked unless: rootfs_unpacked
- cache-rootfs: root-fs - cache-rootfs: rootfs
unless: rootfs_unpacked unless: rootfs_unpacked
- chroot: root-fs - chroot: rootfs
shell: | shell: |
sed -i '/^root:[^:]*:/s//root::/' /etc/passwd sed -i '/^root:[^:]*:/s//root::/' /etc/passwd
echo pc-vmdb2 > /etc/hostname echo pc-vmdb2 > /etc/hostname
- grub: bios - grub: bios
root-fs: root-fs tag: rootfs
root-part: root-part
console: serial console: serial
...@@ -46,6 +46,5 @@ steps: ...@@ -46,6 +46,5 @@ steps:
unless: rootfs_unpacked unless: rootfs_unpacked
- grub: uefi - grub: uefi
root-fs: root-fs rootfs: root-fs
root-part: root-part
efi-part: efi-part efi-part: efi-part
...@@ -47,6 +47,7 @@ class Vmdb2(cliapp.Application): ...@@ -47,6 +47,7 @@ class Vmdb2(cliapp.Application):
spec = self.load_spec_file(args[0]) spec = self.load_spec_file(args[0])
state = vmdb.State() state = vmdb.State()
state.tags = vmdb.Image()
params = self.create_template_vars(state) params = self.create_template_vars(state)
steps = spec.get_steps(params) steps = spec.get_steps(params)
......
...@@ -33,6 +33,9 @@ class Image: ...@@ -33,6 +33,9 @@ class Image:
def get_tags(self): def get_tags(self):
return list(self._tags.keys()) return list(self._tags.keys())
def has_tag(self, tag):
return tag in self._tags
def get_dev(self, tag): def get_dev(self, tag):
item = self._tags.get(tag) item = self._tags.get(tag)
if item is None: if item is None:
......
...@@ -28,6 +28,12 @@ class ImageTests(unittest.TestCase): ...@@ -28,6 +28,12 @@ class ImageTests(unittest.TestCase):
image = vmdb.Image() image = vmdb.Image()
self.assertEqual(image.get_tags(), []) self.assertEqual(image.get_tags(), [])
def test_tells_if_tag_is_used(self):
image = vmdb.Image()
self.assertFalse(image.has_tag('foo'))
image.add_partition('foo', 'bar')
self.assertTrue(image.has_tag('foo'))
def test_get_dev_raises_error_for_unknown_tag(self): def test_get_dev_raises_error_for_unknown_tag(self):
image = vmdb.Image() image = vmdb.Image()
with self.assertRaises(vmdb.UnknownTag): with self.assertRaises(vmdb.UnknownTag):
......
...@@ -37,13 +37,9 @@ class AnsibleStepRunner(vmdb.StepRunnerInterface): ...@@ -37,13 +37,9 @@ class AnsibleStepRunner(vmdb.StepRunnerInterface):
return ['ansible', 'playbook'] return ['ansible', 'playbook']
def run(self, step, settings, state): def run(self, step, settings, state):
fstag = step['ansible'] tag = step['ansible']
playbook = step['playbook'] playbook = step['playbook']
mount_point = state.mounts[fstag] mount_point = state.tags.get_mount_point(tag)
vmdb.progress(
'Running ansible playbook {} on filesystem at {} ({})'.format(
playbook, mount_point, fstag))
state.ansible_inventory = self.create_inventory(mount_point) state.ansible_inventory = self.create_inventory(mount_point)
vmdb.progress( vmdb.progress(
......
...@@ -33,7 +33,7 @@ class AptPlugin(cliapp.Plugin): ...@@ -33,7 +33,7 @@ class AptPlugin(cliapp.Plugin):
class AptStepRunner(vmdb.StepRunnerInterface): class AptStepRunner(vmdb.StepRunnerInterface):
def get_required_keys(self): def get_required_keys(self):
return ['apt', 'fs-tag', 'packages'] return ['apt', 'tag', 'packages']
def run(self, step, settings, state): def run(self, step, settings, state):
operation = step['apt'] operation = step['apt']
...@@ -41,8 +41,8 @@ class AptStepRunner(vmdb.StepRunnerInterface): ...@@ -41,8 +41,8 @@ class AptStepRunner(vmdb.StepRunnerInterface):
raise Exception('"apt" must always have value "install"') raise Exception('"apt" must always have value "install"')
packages = step['packages'] packages = step['packages']
fstag = step['fs-tag'] tag = step['tag']
mount_point = state.mounts[fstag] mount_point = state.tags.get_mount_point(tag)
if not self.got_eatmydata(state): if not self.got_eatmydata(state):
self.install_packages(mount_point, [], ['eatmydata']) self.install_packages(mount_point, [], ['eatmydata'])
......
...@@ -40,10 +40,7 @@ class ChrootStepRunner(vmdb.StepRunnerInterface): ...@@ -40,10 +40,7 @@ class ChrootStepRunner(vmdb.StepRunnerInterface):
fs_tag = step['chroot'] fs_tag = step['chroot']
shell = step['shell'] shell = step['shell']
mount_point = state.mounts[fs_tag] mount_point = state.tags.get_mount_point(fs_tag)
vmdb.progress(
'chroot {} to {}'.format(mount_point, ' '.join(shell.split('\n'))))
vmdb.runcmd_chroot(mount_point, ['sh', '-c', shell]) vmdb.runcmd_chroot(mount_point, ['sh', '-c', shell])
...@@ -59,5 +56,5 @@ class ShellStepRunner(vmdb.StepRunnerInterface): ...@@ -59,5 +56,5 @@ class ShellStepRunner(vmdb.StepRunnerInterface):
vmdb.progress( vmdb.progress(
'run shell {}'.format(' '.join(shell.split('\n')))) 'run shell {}'.format(' '.join(shell.split('\n'))))
env = dict(os.environ) env = dict(os.environ)
env['ROOT'] = state.mounts[fs_tag] env['ROOT'] = state.get_mount_point(fs_tag)
vmdb.runcmd(['sh', '-c', shell], env=env) vmdb.runcmd(['sh', '-c', shell], env=env)
...@@ -36,7 +36,7 @@ class DebootstrapStepRunner(vmdb.StepRunnerInterface): ...@@ -36,7 +36,7 @@ class DebootstrapStepRunner(vmdb.StepRunnerInterface):
def run(self, step, settings, state): def run(self, step, settings, state):
suite = step['debootstrap'] suite = step['debootstrap']
tag = step['target'] tag = step['target']
target = state.mounts[tag] target = state.get_mount_point(tag)
mirror = step['mirror'] mirror = step['mirror']
variant = step.get('variant', '-') variant = step.get('variant', '-')
if not (suite and tag and target and mirror): if not (suite and tag and target and mirror):
......
...@@ -60,17 +60,16 @@ ...@@ -60,17 +60,16 @@
# root filesystem. Then install grub with a step like this: # root filesystem. Then install grub with a step like this:
# #
# - grub: uefi # - grub: uefi
# root-fs: root-fs # tag: root-part
# root-part: root-part # efi: efi-part
# efi-part: efi-part
# #
# Here: root-fs is the tag for the root filesystem, root-part is the # Here: "tag" is the tag for the root filesystem (and corresponding
# tag for the partition with the root filesystem, and efi-part is tag # partition), and efi is tag for the EFI partition.
# for the EFI partition.
# #
# The grub step will take of the rest. # The grub step will take of the rest.
import logging
import os import os
import re import re
...@@ -88,9 +87,10 @@ class GrubPlugin(cliapp.Plugin): ...@@ -88,9 +87,10 @@ class GrubPlugin(cliapp.Plugin):
class GrubStepRunner(vmdb.StepRunnerInterface): class GrubStepRunner(vmdb.StepRunnerInterface):
def get_required_keys(self): def get_required_keys(self):
return ['grub', 'root-fs'] return ['grub', 'tag']
def run(self, step, settings, state): def run(self, step, settings, state):
state.grub_mounts = []
flavor = step['grub'] flavor = step['grub']
if flavor == 'uefi': if flavor == 'uefi':
self.install_uefi(step, settings, state) self.install_uefi(step, settings, state)
...@@ -100,18 +100,16 @@ class GrubStepRunner(vmdb.StepRunnerInterface): ...@@ -100,18 +100,16 @@ class GrubStepRunner(vmdb.StepRunnerInterface):
raise Exception('Unknown GRUB flavor {}'.format(flavor)) raise Exception('Unknown GRUB flavor {}'.format(flavor))
def install_uefi(self, step, settings, state): def install_uefi(self, step, settings, state):
vmdb.progress('Installing GRUB for UEFI') if not 'efi' in step:
raise Exception('"efi" is required in UEFI GRUB installtion')
if not 'efi-part' in step:
raise Exception('"efi-part" is required in UEFI GRUB installtion')
vmdb.progress('Installing GRUB for UEFI')
grub_package = 'grub-efi-amd64' grub_package = 'grub-efi-amd64'
grub_target = 'x86_64-efi' grub_target = 'x86_64-efi'
self.install_grub(step, settings, state, grub_package, grub_target) self.install_grub(step, settings, state, grub_package, grub_target)
def install_bios(self, step, settings, state): def install_bios(self, step, settings, state):
vmdb.progress('Installing GRUB for BIOS') vmdb.progress('Installing GRUB for BIOS')
grub_package = 'grub-pc' grub_package = 'grub-pc'
grub_target = 'i386-pc' grub_target = 'i386-pc'
self.install_grub(step, settings, state, grub_package, grub_target) self.install_grub(step, settings, state, grub_package, grub_target)
...@@ -119,19 +117,17 @@ class GrubStepRunner(vmdb.StepRunnerInterface): ...@@ -119,19 +117,17 @@ class GrubStepRunner(vmdb.StepRunnerInterface):
def install_grub(self, step, settings, state, grub_package, grub_target): def install_grub(self, step, settings, state, grub_package, grub_target):
console = step.get('console', None) console = step.get('console', None)
rootfs = step['root-fs'] tag = step['tag']
chroot = state.mounts[rootfs] root_dev = state.tags.get_dev(tag)
chroot = state.tags.get_mount_point(tag)
root_part = step['root-part']
root_dev = state.parts[root_part]
image_dev = step.get('image-dev') image_dev = step.get('image-dev')
if image_dev is None: if image_dev is None:
image_dev = self.get_image_loop_device(root_dev) image_dev = self.get_image_loop_device(root_dev)
if 'efi-part' in step: if 'efi' in step:
efi_part = step['efi-part'] efi = step['efi']
efi_dev = state.parts[efi_part] efi_dev = state.tags.get_dev(efi)
else: else:
efi_dev = None efi_dev = None
...@@ -218,12 +214,7 @@ class GrubStepRunner(vmdb.StepRunnerInterface): ...@@ -218,12 +214,7 @@ class GrubStepRunner(vmdb.StepRunnerInterface):
mount_opts = [] mount_opts = []
vmdb.runcmd(['mount'] + mount_opts + [path, chroot_path]) vmdb.runcmd(['mount'] + mount_opts + [path, chroot_path])
state.grub_mounts.append(chroot_path)
binds = getattr(state, 'grub_mounts', None)
if binds is None:
binds = []
binds.append(chroot_path)
state.grub_mounts = binds
def chroot_path(self, chroot, path): def chroot_path(self, chroot, path):
return os.path.normpath(os.path.join(chroot, '.' + path)) return os.path.normpath(os.path.join(chroot, '.' + path))
......
...@@ -35,10 +35,9 @@ class MkfsStepRunner(vmdb.StepRunnerInterface): ...@@ -35,10 +35,9 @@ class MkfsStepRunner(vmdb.StepRunnerInterface):
def run(self, step, settings, state): def run(self, step, settings, state):
fstype = step['mkfs'] fstype = step['mkfs']
part_tag = step['partition'] tag = step['partition']
device = state.parts[part_tag] device = state.tags.get_dev(tag)
vmdb.progress(
'Creating {} filesystem on {}'.format(fstype, device))
cmd = ['/sbin/mkfs', '-t', fstype] cmd = ['/sbin/mkfs', '-t', fstype]
if 'label' in step: if 'label' in step:
if fstype == 'vfat': if fstype == 'vfat':
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
import logging
import os import os
import tempfile import tempfile
...@@ -34,7 +35,7 @@ class MountPlugin(cliapp.Plugin): ...@@ -34,7 +35,7 @@ class MountPlugin(cliapp.Plugin):
class MountStepRunner(vmdb.StepRunnerInterface): class MountStepRunner(vmdb.StepRunnerInterface):
def get_required_keys(self): def get_required_keys(self):
return ['mount', 'fs-tag'] return ['mount']
def run(self, step, settings, state): def run(self, step, settings, state):
self.mount_rootfs(step, settings, state) self.mount_rootfs(step, settings, state)
...@@ -43,42 +44,37 @@ class MountStepRunner(vmdb.StepRunnerInterface): ...@@ -43,42 +44,37 @@ class MountStepRunner(vmdb.StepRunnerInterface):
self.unmount_rootfs(step, settings, state) self.unmount_rootfs(step, settings, state)
def mount_rootfs(self, step, settings, state): def mount_rootfs(self, step, settings, state):
if not hasattr(state, 'mounts'): tag = step['mount']
state.mounts = {}
part_tag = step['mount']
fs_tag = step['fs-tag']
dirname = step.get('dirname') dirname = step.get('dirname')
mount_on = step.get('mount-on') mount_on = step.get('mount-on')
if fs_tag in state.mounts: device = state.tags.get_dev(tag)
raise Exception('fs-tag {} already used'.format(fs_tag))
if dirname: if dirname:
if not mount_on: if not mount_on:
raise Exception('no mount-on tag given') raise Exception('no mount-on tag given')
if mount_on not in state.mounts: if not state.tags.has_tag(mount_on):
raise Exception('cannot find tag {}'.format(mount_on)) raise Exception('cannot find tag {}'.format(mount_on))
mount_point = os.path.join( mount_point = os.path.join(
state.mounts[mount_on], './' + step['dirname']) state.tags.get_mount_point(mount_on), './' + dirname)
if not os.path.exists(mount_point): if not os.path.exists(mount_point):
os.makedirs(mount_point) os.makedirs(mount_point)
else: else:
mount_point = tempfile.mkdtemp() mount_point = tempfile.mkdtemp()
device = state.parts[part_tag]
vmdb.runcmd(['mount', device, mount_point]) vmdb.runcmd(['mount', device, mount_point])
state.mounts[fs_tag] = mount_point state.tags.add_mount_point(tag, mount_point)
return mount_point return mount_point
def unmount_rootfs(self, step, settings, state): def unmount_rootfs(self, step, settings, state):
fs_tag = step['fs-tag'] tag = step['mount']
mount_point = state.mounts[fs_tag] mount_point = state.tags.get_mount_point(tag)
if mount_point is None:
return
try: try:
vmdb.unmount(mount_point) vmdb.unmount(mount_point)
......
...@@ -35,28 +35,25 @@ class PartitionPlugin(cliapp.Plugin): ...@@ -35,28 +35,25 @@ class PartitionPlugin(cliapp.Plugin):
class MklabelStepRunner(vmdb.StepRunnerInterface): class MklabelStepRunner(vmdb.StepRunnerInterface):
def get_required_keys(self): def get_required_keys(self):
return ['mklabel'] return ['mklabel', 'device']
def run(self, step, settings, state): def run(self, step, settings, state):
label_type = step['mklabel'] label_type = step['mklabel']
device = step['device'] device = step['device']
vmdb.progress(
'Creating partition table ({}) on {}'.format(label_type, device))
vmdb.runcmd(['parted', '-s', device, 'mklabel', label_type]) vmdb.runcmd(['parted', '-s', device, 'mklabel', label_type])
state.parts = {}
class MkpartStepRunner(vmdb.StepRunnerInterface): class MkpartStepRunner(vmdb.StepRunnerInterface):
def get_required_keys(self): def get_required_keys(self):
return ['mkpart'] return ['mkpart', 'device', 'start', 'end', 'tag']
def run(self, step, settings, state): def run(self, step, settings, state):
part_type = step['mkpart'] part_type = step['mkpart']
device = step['device'] device = step['device']
start = step['start'] start = step['start']
end = step['end'] end = step['end']
part_tag = step['part-tag'] part_tag = step['tag']
fs_type = step.get('fs-type', 'ext2') fs_type = step.get('fs-type', 'ext2')
vmdb.progress( vmdb.progress(
...@@ -103,9 +100,7 @@ class MkpartStepRunner(vmdb.StepRunnerInterface): ...@@ -103,9 +100,7 @@ class MkpartStepRunner(vmdb.StepRunnerInterface):
def remember_partition(self, state, part_dev, part_tag): def remember_partition(self, state, part_dev, part_tag):
print('remembering partition', part_dev, 'as', part_tag) print('remembering partition', part_dev, 'as', part_tag)
parts = getattr(state, 'parts', {}) state.tags.add_partition(part_tag, part_dev)
parts[part_tag] = part_dev
state.parts = parts
def create_loop_dev(self, device): def create_loop_dev(self, device):
vmdb.runcmd(['kpartx', '-dsv', device]) vmdb.runcmd(['kpartx', '-dsv', device])
...@@ -120,6 +115,4 @@ class MkpartStepRunner(vmdb.StepRunnerInterface): ...@@ -120,6 +115,4 @@ class MkpartStepRunner(vmdb.StepRunnerInterface):
def teardown(self, step, settings, state): def teardown(self, step, settings, state):
device = step['device'] device = step['device']
vmdb.progress(
'Undoing loopback devices for partitions on {}'.format(device))
vmdb.runcmd(['kpartx', '-dsv', device]) vmdb.runcmd(['kpartx', '-dsv', device])
...@@ -36,7 +36,7 @@ class QemuDebootstrapStepRunner(vmdb.StepRunnerInterface): ...@@ -36,7 +36,7 @@ class QemuDebootstrapStepRunner(vmdb.StepRunnerInterface):
def run(self, step, settings, state): def run(self, step, settings, state):
suite = step['qemu-debootstrap'] suite = step['qemu-debootstrap']
tag = step['target'] tag = step['target']
target = state.mounts[tag] target = state.get_mount_point(tag)
mirror = step['mirror'] mirror = step['mirror']
variant = step.get('variant', '-') variant = step.get('variant', '-')
arch = step['arch'] arch = step['arch']
......
...@@ -43,7 +43,7 @@ class MakeCacheStepRunner(vmdb.StepRunnerInterface): ...@@ -43,7 +43,7 @@ class MakeCacheStepRunner(vmdb.StepRunnerInterface):
def run(self, step, settings, state): def run(self, step, settings, state):
fs_tag = step['cache-rootfs'] fs_tag = step['cache-rootfs']
rootdir = state.mounts[fs_tag] rootdir = state.get_mount_point(fs_tag)
tar_path = settings['rootfs-tarball'] tar_path = settings['rootfs-tarball']
opts = step.get('options', '--one-file-system').split() opts = step.get('options', '--one-file-system').split()
if not tar_path: if not tar_path:
...@@ -61,7 +61,7 @@ class UnpackCacheStepRunner(vmdb.StepRunnerInterface): ...@@ -61,7 +61,7 @@ class UnpackCacheStepRunner(vmdb.StepRunnerInterface):
def run(self, step, settings, state): def run(self, step, settings, state):
fs_tag = step['unpack-rootfs'] fs_tag = step['unpack-rootfs']
rootdir = state.mounts[fs_tag] rootdir = state.tags.get_mount_point(fs_tag)
tar_path = settings['rootfs-tarball'] tar_path = settings['rootfs-tarball']
if not tar_path: if not tar_path:
raise Exception('--rootfs-tarball MUST be set') raise Exception('--rootfs-tarball MUST be set')
......
...@@ -48,7 +48,7 @@ class VirtualFilesystemMountStepRunner(vmdb.StepRunnerInterface): ...@@ -48,7 +48,7 @@ class VirtualFilesystemMountStepRunner(vmdb.StepRunnerInterface):
def run(self, step, settings, state): def run(self, step, settings, state):
fstag = step['mount-virtual-filesystems'] fstag = step['mount-virtual-filesystems']
mount_point = state.mounts[fstag] mount_point = state.get_mount_point(fstag)
self.mount_virtuals(mount_point, state) self.mount_virtuals(mount_point, state)
def teardown(self, step, settings, state): def teardown(self, step, settings, state):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment