summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-03-21 09:57:36 +0200
committerLars Wirzenius <liw@liw.fi>2020-03-21 14:05:34 +0200
commit6f3a666cecc9972985ce31f151528dc5749c112f (patch)
tree4059e3786e119156d15db772f466f7b57f477233
parentaebe12f5b1edbbf221ea06dc0b41c58ad1f3c118 (diff)
downloadvmdb2-6f3a666cecc9972985ce31f151528dc5749c112f.tar.gz
Change: make step runners check the values for the step at init
-rw-r--r--vmdb/__init__.py2
-rw-r--r--vmdb/app.py3
-rw-r--r--vmdb/plugins/ansible_plugin.py17
-rw-r--r--vmdb/plugins/apt_plugin.py24
-rw-r--r--vmdb/plugins/cache_rootfs_plugin.py15
-rw-r--r--vmdb/plugins/chroot_plugin.py15
-rw-r--r--vmdb/plugins/copy_file_plugin.py24
-rw-r--r--vmdb/plugins/create_dir_plugin.py25
-rw-r--r--vmdb/plugins/create_file_plugin.py31
-rw-r--r--vmdb/plugins/debootstrap_plugin.py37
-rw-r--r--vmdb/plugins/echo_plugin.py19
-rw-r--r--vmdb/plugins/error_plugin.py14
-rw-r--r--vmdb/plugins/fstab_plugin.py10
-rw-r--r--vmdb/plugins/grub_plugin.py60
-rw-r--r--vmdb/plugins/kpartx_plugin.py14
-rw-r--r--vmdb/plugins/luks_plugin.py25
-rw-r--r--vmdb/plugins/lvcreate_plugin.py18
-rw-r--r--vmdb/plugins/mkfs_plugin.py19
-rw-r--r--vmdb/plugins/mkimg_plugin.py15
-rw-r--r--vmdb/plugins/mklabel_plugin.py15
-rw-r--r--vmdb/plugins/mkpart_plugin.py30
-rw-r--r--vmdb/plugins/mount_plugin.py30
-rw-r--r--vmdb/plugins/qemudebootstrap_plugin.py32
-rw-r--r--vmdb/plugins/unpack_rootfs_plugin.py10
-rw-r--r--vmdb/plugins/vgcreate_plugin.py25
-rw-r--r--vmdb/plugins/virtuals_plugin.py12
-rw-r--r--vmdb/step_list.py48
-rw-r--r--vmdb/step_list_tests.py69
28 files changed, 443 insertions, 215 deletions
diff --git a/vmdb/__init__.py b/vmdb/__init__.py
index 0b9ddc1..5308c5a 100644
--- a/vmdb/__init__.py
+++ b/vmdb/__init__.py
@@ -25,6 +25,8 @@ from .step_list import (
NoMatchingRunner,
NotString,
StepError,
+ StepKeyMissing,
+ StepKeyWrongValueType,
)
from .runcmd import (
runcmd,
diff --git a/vmdb/app.py b/vmdb/app.py
index cf6fc39..4668bc3 100644
--- a/vmdb/app.py
+++ b/vmdb/app.py
@@ -102,9 +102,10 @@ class Vmdb2(cliapp.Application):
if hasattr(runner, name)
]
+ values = runner.get_values(step)
for method in methods:
logging.info('Calling %s', method)
- method(step, self.settings, state)
+ method(values, self.settings, state)
except KeyError as e:
vmdb.error('Key error: %s' % str(e))
vmdb.error(repr(e))
diff --git a/vmdb/plugins/ansible_plugin.py b/vmdb/plugins/ansible_plugin.py
index edce52f..a223735 100644
--- a/vmdb/plugins/ansible_plugin.py
+++ b/vmdb/plugins/ansible_plugin.py
@@ -33,12 +33,15 @@ class AnsiblePlugin(cliapp.Plugin):
class AnsibleStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['ansible', 'playbook']
-
- def run(self, step, settings, state):
- tag = step['ansible']
- playbook = step['playbook']
+ def get_key_spec(self):
+ return {
+ 'ansible': str,
+ 'playbook': str,
+ }
+
+ 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']
@@ -59,7 +62,7 @@ class AnsibleStepRunner(vmdb.StepRunnerInterface):
playbook],
env=env)
- def teardown(self, step, settings, state):
+ def teardown(self, values, settings, state):
if hasattr(state, 'ansible_inventory'):
vmdb.progress('Removing {}'.format(state.ansible_inventory))
os.remove(state.ansible_inventory)
diff --git a/vmdb/plugins/apt_plugin.py b/vmdb/plugins/apt_plugin.py
index 7356369..4ebaf38 100644
--- a/vmdb/plugins/apt_plugin.py
+++ b/vmdb/plugins/apt_plugin.py
@@ -32,18 +32,24 @@ class AptPlugin(cliapp.Plugin):
class AptStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['apt', 'packages']
-
- def run(self, step, settings, state):
- operation = step['apt']
+ def get_key_spec(self):
+ return {
+ 'apt': str,
+ 'packages': [],
+ 'tag': '',
+ 'fs-tag': '',
+ 'clean': True,
+ }
+
+ def run(self, values, settings, state):
+ operation = values['apt']
if operation != 'install':
raise Exception('"apt" must always have value "install"')
- packages = step['packages']
- tag = step.get('tag')
+ packages = values['packages']
+ tag = values.get('tag') or None
if tag is None:
- tag = step['fs-tag']
+ tag = values['fs-tag']
mount_point = state.tags.get_builder_mount_point(tag)
if not self.got_eatmydata(state):
@@ -51,7 +57,7 @@ class AptStepRunner(vmdb.StepRunnerInterface):
state.got_eatmydata = True
self.install_packages(mount_point, ['eatmydata'], packages)
- if step.get('clean', True):
+ if values['clean']:
self.clean_cache(mount_point)
def got_eatmydata(self, state):
diff --git a/vmdb/plugins/cache_rootfs_plugin.py b/vmdb/plugins/cache_rootfs_plugin.py
index c114945..eb4f75a 100644
--- a/vmdb/plugins/cache_rootfs_plugin.py
+++ b/vmdb/plugins/cache_rootfs_plugin.py
@@ -37,14 +37,17 @@ class CacheRootFSPlugin(cliapp.Plugin):
class MakeCacheStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['cache-rootfs']
-
- def run(self, step, settings, state):
- fs_tag = step['cache-rootfs']
+ def get_key_spec(self):
+ return {
+ 'cache-rootfs': str,
+ 'options': '--one-file-system',
+ }
+
+ 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 = step.get('options', '--one-file-system').split()
+ opts = values['options'].split()
if not tar_path:
raise Exception('--rootfs-tarball MUST be set')
dirs = self._find_cacheable_mount_points(state.tags, rootdir)
diff --git a/vmdb/plugins/chroot_plugin.py b/vmdb/plugins/chroot_plugin.py
index 4eb5847..bded609 100644
--- a/vmdb/plugins/chroot_plugin.py
+++ b/vmdb/plugins/chroot_plugin.py
@@ -32,12 +32,15 @@ class ChrootPlugin(cliapp.Plugin):
class ChrootStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['chroot', 'shell']
-
- def run(self, step, settings, state):
- fs_tag = step['chroot']
- shell = step['shell']
+ def get_key_spec(self):
+ return {
+ 'chroot': str,
+ 'shell': str,
+ }
+
+ def run(self, values, settings, state):
+ fs_tag = values['chroot']
+ shell = values['shell']
mount_point = state.tags.get_builder_mount_point(fs_tag)
vmdb.runcmd_chroot(mount_point, ['sh', '-ec', shell])
diff --git a/vmdb/plugins/copy_file_plugin.py b/vmdb/plugins/copy_file_plugin.py
index 7683d7e..b82497b 100644
--- a/vmdb/plugins/copy_file_plugin.py
+++ b/vmdb/plugins/copy_file_plugin.py
@@ -28,16 +28,22 @@ class CopyFilePlugin(cliapp.Plugin):
class CopyFileStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['copy-file', 'src']
-
- def run(self, step, settings, state):
+ def get_key_spec(self):
+ return {
+ 'copy-file': str,
+ 'src': str,
+ 'perm': 0o644,
+ 'uid': 0,
+ 'gid': 0,
+ }
+
+ def run(self, values, settings, state):
root = state.tags.get_builder_from_target_mount_point('/')
- newfile = step['copy-file']
- src = step['src']
- perm = step.get('perm', 0o644)
- uid = step.get('uid', 0)
- gid = step.get('gid', 0)
+ newfile = values['copy-file']
+ src = values['src']
+ perm = values['perm']
+ uid = values['uid']
+ gid = values['gid']
filename = '/'.join([root,newfile])
diff --git a/vmdb/plugins/create_dir_plugin.py b/vmdb/plugins/create_dir_plugin.py
index c48b662..77fc72a 100644
--- a/vmdb/plugins/create_dir_plugin.py
+++ b/vmdb/plugins/create_dir_plugin.py
@@ -28,18 +28,25 @@ class CreateDirPlugin(cliapp.Plugin):
class CreateDirStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['create-dir']
-
- def run(self, step, settings, state):
+ def get_key_spec(self):
+ return {
+ 'create-dir': str,
+ 'perm': 0o755,
+ 'uid': 0,
+ 'gid': 0,
+ }
+
+ def run(self, values, settings, state):
root = state.tags.get_builder_from_target_mount_point('/')
- newdir = step['create-dir']
+ newdir = values['create-dir']
path = '/'.join([root, newdir])
- perm = step.get('perm', 0o755)
- uid = step.get('uid', 0)
- gid = step.get('gid', 0)
+ perm = values['perm']
+ uid = values['uid']
+ gid = values['gid']
- logging.info('Creating directory %s, uid %d, gid %d, perms %o' % (path, uid, gid, perm))
+ logging.info(
+ 'Creating directory %s, uid %d, gid %d, perms %o' % (
+ path, uid, gid, perm))
os.makedirs(path, perm)
os.chown(path, uid, gid)
diff --git a/vmdb/plugins/create_file_plugin.py b/vmdb/plugins/create_file_plugin.py
index d6f9d7a..6d5621c 100644
--- a/vmdb/plugins/create_file_plugin.py
+++ b/vmdb/plugins/create_file_plugin.py
@@ -29,20 +29,29 @@ class CreateFilePlugin(cliapp.Plugin):
class CreateFileStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['create-file', 'contents']
-
- def run(self, step, settings, state):
+ def get_key_spec(self):
+ return {
+ 'create-file': str,
+ 'contents': str,
+ 'perm': 0o644,
+ 'uid': 0,
+ 'gid': 0,
+ }
+
+ def run(self, values, settings, state):
root = state.tags.get_builder_from_target_mount_point('/')
- newfile = step['create-file']
- contents = step['contents']
- perm = step.get('perm', 0o644)
- uid = step.get('uid', 0)
- gid = step.get('gid', 0)
+ newfile = values['create-file']
+ contents = values['contents']
+ perm = values['perm']
+ uid = values['uid']
+ gid = values['gid']
+
+ filename = '/'.join([root, newfile])
- filename = '/'.join([root,newfile])
+ logging.info(
+ 'Creating file %s, uid %d, gid %d, perms %o' % (
+ filename, uid, gid, perm))
- logging.info('Creating file %s, uid %d, gid %d, perms %o' % (filename, uid, gid, perm))
fd = open(filename, 'w')
fd.write(contents)
fd.close
diff --git a/vmdb/plugins/debootstrap_plugin.py b/vmdb/plugins/debootstrap_plugin.py
index cf2fb43..f2f284b 100644
--- a/vmdb/plugins/debootstrap_plugin.py
+++ b/vmdb/plugins/debootstrap_plugin.py
@@ -30,24 +30,41 @@ class DebootstrapPlugin(cliapp.Plugin):
class DebootstrapStepRunner(vmdb.StepRunnerInterface):
+ def get_key_spec(self):
+ return {
+ 'debootstrap': str,
+ 'target': str,
+ 'mirror': str,
+ 'keyring': '',
+ 'variant': '-',
+ }
+
def get_required_keys(self):
return ['debootstrap', 'target', 'mirror']
- def run(self, step, settings, state):
- suite = step['debootstrap']
- tag = step['target']
+ def run(self, values, settings, state):
+ suite = values['debootstrap']
+ tag = values['target']
target = state.tags.get_builder_mount_point(tag)
- mirror = step['mirror']
- keyring = step.get('keyring', None)
- variant = step.get('variant', '-')
+ mirror = values['mirror']
+ keyring = values['keyring'] or None
+ variant = values['variant']
+
if not (suite and tag and target and mirror):
raise Exception('missing arg for debootstrap step')
if keyring:
- vmdb.runcmd(['debootstrap', '--keyring', keyring, '--variant', variant, suite, target, mirror])
+ vmdb.runcmd([
+ 'debootstrap',
+ '--keyring', keyring,
+ '--variant', variant,
+ suite, target, mirror])
else:
- vmdb.runcmd(['debootstrap', '--variant', variant, suite, target, mirror])
+ vmdb.runcmd([
+ 'debootstrap',
+ '--variant', variant,
+ suite, target, mirror])
- def run_even_if_skipped(self, step, settings, state):
- tag = step['target']
+ def run_even_if_skipped(self, values, settings, state):
+ tag = values['target']
target = state.tags.get_builder_mount_point(tag)
vmdb.runcmd_chroot(target, ['apt-get', 'update'])
diff --git a/vmdb/plugins/echo_plugin.py b/vmdb/plugins/echo_plugin.py
index c09a387..d7748d7 100644
--- a/vmdb/plugins/echo_plugin.py
+++ b/vmdb/plugins/echo_plugin.py
@@ -32,15 +32,18 @@ class EchoPlugin(cliapp.Plugin):
class EchoStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['echo']
-
- def run(self, step, settings, state):
- text = step['echo']
+ def get_key_spec(self):
+ return {
+ 'echo': str,
+ 'teardown': '',
+ }
+
+ def run(self, values, settings, state):
+ text = values['echo']
vmdb.progress('{}'.format(text))
- def teardown(self, step, settings, state):
- if 'teardown' in step:
- text = step['teardown']
+ def teardown(self, values, settings, state):
+ text = values['teardown']
+ if text:
vmdb.progress('{}'.format(text))
logging.info('%s', text)
diff --git a/vmdb/plugins/error_plugin.py b/vmdb/plugins/error_plugin.py
index e40e1ec..7c5ce8c 100644
--- a/vmdb/plugins/error_plugin.py
+++ b/vmdb/plugins/error_plugin.py
@@ -30,16 +30,22 @@ class ErrorPlugin(cliapp.Plugin):
class ErrorStepRunner(vmdb.StepRunnerInterface):
+ def get_key_spec(self):
+ return {
+ 'error': str,
+ 'teardown': str,
+ }
+
def get_required_keys(self):
return ['error', 'teardown']
- def run(self, step, settings, state):
+ def run(self, values, settings, state):
# We use vmdb.progress here to get output to go to stdout,
# instead of stderr. We want that for tests.
- vmdb.progress('{}'.format(step['error']))
+ vmdb.progress('{}'.format(values['error']))
raise vmdb.StepError('an error occurred')
- def teardown(self, step, settings, state):
+ def teardown(self, values, settings, state):
# We use vmdb.progress here to get output to go to stdout,
# instead of stderr. We want that for tests.
- vmdb.progress('{}'.format(step['teardown']))
+ vmdb.progress('{}'.format(values['teardown']))
diff --git a/vmdb/plugins/fstab_plugin.py b/vmdb/plugins/fstab_plugin.py
index e0bd29d..508ef07 100644
--- a/vmdb/plugins/fstab_plugin.py
+++ b/vmdb/plugins/fstab_plugin.py
@@ -30,11 +30,13 @@ class FstabPlugin(cliapp.Plugin):
class FstabStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['fstab']
+ def get_key_spec(self):
+ return {
+ 'fstab': str,
+ }
- def run(self, step, setting, state):
- tag = step['fstab']
+ def run(self, values, setting, state):
+ tag = values['fstab']
chroot = state.tags.get_builder_mount_point(tag)
filesystems = []
diff --git a/vmdb/plugins/grub_plugin.py b/vmdb/plugins/grub_plugin.py
index 937fffc..e38ca27 100644
--- a/vmdb/plugins/grub_plugin.py
+++ b/vmdb/plugins/grub_plugin.py
@@ -86,53 +86,63 @@ class GrubPlugin(cliapp.Plugin):
class GrubStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['grub', 'tag']
-
- def run(self, step, settings, state):
+ def get_key_spec(self):
+ return {
+ 'grub': str,
+ 'tag': str,
+ 'root-fs': '',
+ 'efi': '',
+ 'efi-part': '',
+ 'console': '',
+ 'tag': '',
+ 'image-dev': '',
+ }
+
+ def run(self, values, settings, state):
state.grub_mounts = []
- flavor = step['grub']
+ flavor = values['grub']
if flavor == 'uefi':
- self.install_uefi(step, settings, state)
+ self.install_uefi(values, settings, state)
elif flavor == 'bios':
- self.install_bios(step, settings, state)
+ self.install_bios(values, settings, state)
else:
raise Exception('Unknown GRUB flavor {}'.format(flavor))
- 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')
+ 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-efi-amd64'
grub_target = 'x86_64-efi'
- self.install_grub(step, settings, state, grub_package, grub_target)
+ self.install_grub(values, settings, state, grub_package, grub_target)
- def install_bios(self, step, settings, state):
+ def install_bios(self, values, 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)
+ self.install_grub(values, settings, state, grub_package, grub_target)
- def install_grub(self, step, settings, state, grub_package, grub_target):
- console = step.get('console', None)
+ def install_grub(self, values, settings, state, grub_package, grub_target):
+ console = values['console'] or None
- tag = step.get('tag')
- if tag is None:
- tag = step['root-fs']
+ tag = values['tag'] or values['root-fs'] or None
root_dev = state.tags.get_dev(tag)
chroot = state.tags.get_builder_mount_point(tag)
- image_dev = step.get('image-dev')
+ image_dev = values['image-dev'] or None
if image_dev is None:
image_dev = self.get_image_loop_device(root_dev)
- if 'efi' in step:
- efi = step['efi']
- efi_dev = state.tags.get_dev(efi)
- elif 'efi-part' in step:
- efi = step['efi-part']
+ efi = values['efi'] or None
+ efi_part = values['efi-part'] or None
+ if efi is not None:
efi_dev = state.tags.get_dev(efi)
+ elif efi_part is not None:
+ efi_dev = state.tags.get_dev(efi_part)
else:
efi_dev = None
@@ -181,7 +191,7 @@ class GrubStepRunner(vmdb.StepRunnerInterface):
# self.unmount(state)
- def teardown(self, step, settings, state):
+ def teardown(self, values, settings, state):
self.unmount(state)
def unmount(self, state):
diff --git a/vmdb/plugins/kpartx_plugin.py b/vmdb/plugins/kpartx_plugin.py
index dca61bb..5d320ea 100644
--- a/vmdb/plugins/kpartx_plugin.py
+++ b/vmdb/plugins/kpartx_plugin.py
@@ -33,11 +33,13 @@ class KpartxPlugin(cliapp.Plugin):
class KpartxStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['kpartx']
+ def get_key_spec(self):
+ return {
+ 'kpartx': str,
+ }
- def run(self, step, settings, state):
- device = step['kpartx']
+ 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):
@@ -52,6 +54,6 @@ class KpartxStepRunner(vmdb.StepRunnerInterface):
name = words[2]
yield '/dev/mapper/{}'.format(name)
- def teardown(self, step, settings, state):
- device = step['kpartx']
+ def teardown(self, values, settings, state):
+ device = values['kpartx']
vmdb.runcmd(['kpartx', '-dsv', device])
diff --git a/vmdb/plugins/luks_plugin.py b/vmdb/plugins/luks_plugin.py
index c95d07f..9ea066c 100644
--- a/vmdb/plugins/luks_plugin.py
+++ b/vmdb/plugins/luks_plugin.py
@@ -34,12 +34,17 @@ class LuksPlugin(cliapp.Plugin):
class CryptsetupStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['cryptsetup']
-
- def run(self, step, settings, state):
- underlying = step['cryptsetup']
- crypt_name = step['tag']
+ def get_key_spec(self):
+ return {
+ 'cryptsetup': str,
+ 'tag': str,
+ 'key-file': '',
+ 'key-cmd': '',
+ }
+
+ def run(self, values, settings, state):
+ underlying = values['cryptsetup']
+ crypt_name = values['tag']
if not isinstance(underlying, str):
raise vmdb.NotString('cryptsetup', underlying)
@@ -47,8 +52,8 @@ class CryptsetupStepRunner(vmdb.StepRunnerInterface):
raise vmdb.NotString('cryptsetup: tag', crypt_name)
state.tmp_key_file = None
- key_file = step.get('key-file')
- key_cmd = step.get('key-cmd')
+ key_file = values['key-file'] or None
+ key_cmd = values['key-cmd'] or None
if key_file is None and key_cmd is None:
raise Exception(
'cryptsetup step MUST define one of key-file or key-cmd')
@@ -80,12 +85,12 @@ class CryptsetupStepRunner(vmdb.StepRunnerInterface):
state.tags.append(crypt_name)
state.tags.set_dev(crypt_name, crypt_dev)
- def teardown(self, step, settings, state):
+ def teardown(self, values, settings, state):
x = state.tmp_key_file
if x is not None and os.path.exists(x):
os.remove(x)
- crypt_name = step['tag']
+ crypt_name = values['tag']
crypt_dev = '/dev/mapper/{}'.format(crypt_name)
vmdb.runcmd(['cryptsetup', 'close', crypt_dev])
diff --git a/vmdb/plugins/lvcreate_plugin.py b/vmdb/plugins/lvcreate_plugin.py
index c8a83b8..4b135bc 100644
--- a/vmdb/plugins/lvcreate_plugin.py
+++ b/vmdb/plugins/lvcreate_plugin.py
@@ -32,13 +32,17 @@ class LvcreatePlugin(cliapp.Plugin):
class LvcreateStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['lvcreate']
-
- def run(self, step, settings, state):
- vgname = step['lvcreate']
- lvname = step['name']
- size = step['size']
+ def get_key_spec(self):
+ return {
+ 'lvcreate': str,
+ 'name': str,
+ 'size': str,
+ }
+
+ def run(self, values, settings, state):
+ vgname = values['lvcreate']
+ lvname = values['name']
+ size = values['size']
vmdb.runcmd(['lvcreate', '--name', lvname, '--size', size, vgname])
diff --git a/vmdb/plugins/mkfs_plugin.py b/vmdb/plugins/mkfs_plugin.py
index 49ca86b..967493f 100644
--- a/vmdb/plugins/mkfs_plugin.py
+++ b/vmdb/plugins/mkfs_plugin.py
@@ -30,12 +30,16 @@ class MkfsPlugin(cliapp.Plugin):
class MkfsStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['mkfs', 'partition']
+ def get_key_spec(self):
+ return {
+ 'mkfs': str,
+ 'partition': str,
+ 'label': '',
+ }
- def run(self, step, settings, state):
- fstype = step['mkfs']
- tag = step['partition']
+ def run(self, values, settings, state):
+ fstype = values['mkfs']
+ tag = values['partition']
device = state.tags.get_dev(tag)
if not isinstance(fstype, str):
@@ -46,14 +50,15 @@ class MkfsStepRunner(vmdb.StepRunnerInterface):
raise vmdb.NotString('mkfs: device (for tag)', device)
cmd = ['/sbin/mkfs', '-t', fstype]
- if 'label' in step:
+ label = values['label'] or None
+ if label:
if fstype == 'vfat':
cmd.append('-n')
elif fstype == 'f2fs':
cmd.append('-l')
else:
cmd.append('-L')
- cmd.append(step['label'])
+ cmd.append(label)
cmd.append(device)
vmdb.runcmd(cmd)
diff --git a/vmdb/plugins/mkimg_plugin.py b/vmdb/plugins/mkimg_plugin.py
index f68f7c3..15467e1 100644
--- a/vmdb/plugins/mkimg_plugin.py
+++ b/vmdb/plugins/mkimg_plugin.py
@@ -34,12 +34,15 @@ class MkimgPlugin(cliapp.Plugin):
class MkimgStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['mkimg']
-
- def run(self, step, settings, state):
- filename = step['mkimg']
- size = step['size']
+ def get_key_spec(self):
+ return {
+ 'mkimg': str,
+ 'size': str,
+ }
+
+ def run(self, values, settings, state):
+ filename = values['mkimg']
+ size = values['size']
if not isinstance(filename, str):
raise vmdb.NotString('mkimg', filename)
diff --git a/vmdb/plugins/mklabel_plugin.py b/vmdb/plugins/mklabel_plugin.py
index 39e8c8d..5b5fd5a 100644
--- a/vmdb/plugins/mklabel_plugin.py
+++ b/vmdb/plugins/mklabel_plugin.py
@@ -33,10 +33,13 @@ class MklabelPlugin(cliapp.Plugin):
class MklabelStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['mklabel', 'device']
-
- def run(self, step, settings, state):
- label_type = step['mklabel']
- device = step['device']
+ def get_key_spec(self):
+ return {
+ 'mklabel': str,
+ 'device': str,
+ }
+
+ def run(self, values, settings, state):
+ label_type = values['mklabel']
+ device = values['device']
vmdb.runcmd(['parted', '-s', device, 'mklabel', label_type])
diff --git a/vmdb/plugins/mkpart_plugin.py b/vmdb/plugins/mkpart_plugin.py
index 45c4148..6b37d8c 100644
--- a/vmdb/plugins/mkpart_plugin.py
+++ b/vmdb/plugins/mkpart_plugin.py
@@ -33,18 +33,24 @@ class MkpartPlugin(cliapp.Plugin):
class MkpartStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['mkpart', 'device', 'start', 'end']
-
- def run(self, step, settings, state):
- part_type = step['mkpart']
- device = step['device']
- start = step['start']
- end = step['end']
- tag = step.get('tag') or step.get('part-tag')
- if tag is None:
- tag = step['part-tag']
- fs_type = step.get('fs-type', 'ext2')
+ def get_key_spec(self):
+ return {
+ 'mkpart': str,
+ 'device': str,
+ 'start': str,
+ 'end': str,
+ 'tag': '',
+ 'part-tag': '',
+ 'fs-type': 'ext2',
+ }
+
+ 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']
orig = self.list_partitions(device)
vmdb.runcmd(['parted', '-s', device, 'mkpart', part_type, fs_type, start, end])
diff --git a/vmdb/plugins/mount_plugin.py b/vmdb/plugins/mount_plugin.py
index f3c736e..fc5ffeb 100644
--- a/vmdb/plugins/mount_plugin.py
+++ b/vmdb/plugins/mount_plugin.py
@@ -34,19 +34,23 @@ class MountPlugin(cliapp.Plugin):
class MountStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['mount']
+ def get_key_spec(self):
+ return {
+ 'mount': str,
+ 'dirname': '',
+ 'mount-on': '',
+ }
- def run(self, step, settings, state):
- self.mount_rootfs(step, settings, state)
+ def run(self, values, settings, state):
+ self.mount_rootfs(values, settings, state)
- def teardown(self, step, settings, state):
- self.unmount_rootfs(step, settings, state)
+ def teardown(self, values, settings, state):
+ self.unmount_rootfs(values, settings, state)
- def mount_rootfs(self, step, settings, state):
- tag = step['mount']
- dirname = step.get('dirname')
- mount_on = step.get('mount-on')
+ def mount_rootfs(self, values, settings, state):
+ tag = values['mount']
+ dirname = values['dirname'] or None
+ mount_on = values['mount-on'] or None
device = state.tags.get_dev(tag)
@@ -72,8 +76,8 @@ class MountStepRunner(vmdb.StepRunnerInterface):
return mount_point
- def unmount_rootfs(self, step, settings, state):
- tag = step['mount']
+ def unmount_rootfs(self, values, settings, state):
+ tag = values['mount']
mount_point = state.tags.get_builder_mount_point(tag)
if mount_point is None:
return
@@ -83,5 +87,5 @@ class MountStepRunner(vmdb.StepRunnerInterface):
except vmdb.NotMounted as e:
logging.warning(str(e))
- if not step.get('mount-on'):
+ if not values['mount-on']:
os.rmdir(mount_point)
diff --git a/vmdb/plugins/qemudebootstrap_plugin.py b/vmdb/plugins/qemudebootstrap_plugin.py
index 75755ac..a195d29 100644
--- a/vmdb/plugins/qemudebootstrap_plugin.py
+++ b/vmdb/plugins/qemudebootstrap_plugin.py
@@ -30,18 +30,26 @@ class QemuDebootstrapPlugin(cliapp.Plugin):
class QemuDebootstrapStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['qemu-debootstrap', 'target', 'mirror', 'arch']
+ def get_key_spec(self):
+ return {
+ 'debootstrap': str,
+ 'target': str,
+ 'mirror': str,
+ 'arch': str,
+ 'keyring': '',
+ 'variant': '-',
+ 'components': ['main'],
+ }
- def run(self, step, settings, state):
- suite = step['qemu-debootstrap']
- tag = step['target']
+ def run(self, values, settings, state):
+ suite = values['qemu-debootstrap']
+ tag = values['target']
target = state.tags.get_builder_mount_point(tag)
- mirror = step['mirror']
- keyring = step.get('keyring', None)
- variant = step.get('variant', '-')
- arch = step['arch']
- components = step.get('components', ['main'])
+ mirror = values['mirror']
+ keyring = values['keyring'] or None
+ variant = values['variant']
+ arch = values['arch']
+ components = values['compontents']
if not (suite and tag and target and mirror and arch):
raise Exception('missing arg for qemu-debootstrap step')
if keyring:
@@ -63,7 +71,7 @@ class QemuDebootstrapStepRunner(vmdb.StepRunnerInterface):
mirror])
vmdb.runcmd_chroot(target, ['apt-get', 'update'])
- def run_even_if_skipped(self, step, settings, state):
- tag = step['target']
+ def run_even_if_skipped(self, values, settings, state):
+ tag = values['target']
target = state.tags.get_builder_mount_point(tag)
vmdb.runcmd_chroot(target, ['apt-get', 'update'])
diff --git a/vmdb/plugins/unpack_rootfs_plugin.py b/vmdb/plugins/unpack_rootfs_plugin.py
index 8e6aada..9143143 100644
--- a/vmdb/plugins/unpack_rootfs_plugin.py
+++ b/vmdb/plugins/unpack_rootfs_plugin.py
@@ -32,11 +32,13 @@ class UnpackRootFSPlugin(cliapp.Plugin):
class UnpackCacheStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['unpack-rootfs']
+ def get_key_spec(self):
+ return {
+ 'unpack-rootfs': str,
+ }
- def run(self, step, settings, state):
- fs_tag = step['unpack-rootfs']
+ def run(self, values, settings, state):
+ fs_tag = values['unpack-rootfs']
rootdir = state.tags.get_builder_mount_point(fs_tag)
tar_path = settings['rootfs-tarball']
if not tar_path:
diff --git a/vmdb/plugins/vgcreate_plugin.py b/vmdb/plugins/vgcreate_plugin.py
index 2816265..d6b3c45 100644
--- a/vmdb/plugins/vgcreate_plugin.py
+++ b/vmdb/plugins/vgcreate_plugin.py
@@ -32,26 +32,29 @@ class VgcreatePlugin(cliapp.Plugin):
class VgcreateStepRunner(vmdb.StepRunnerInterface):
- def get_required_keys(self):
- return ['vgcreate', 'physical']
+ def get_key_spec(self):
+ return {
+ 'vgcreate': str,
+ 'physical': [],
+ }
- def run(self, step, settings, state):
- vgname = self.get_vg(step)
- physical = self.get_pv(step, state)
+ def run(self, values, settings, state):
+ vgname = self.get_vg(values)
+ physical = self.get_pv(values, state)
for phys in physical:
vmdb.runcmd(['pvcreate', '-ff', '--yes', phys])
vmdb.runcmd(['vgcreate', vgname] + physical)
- def teardown(self, step, settings, state):
- vgname = self.get_vg(step)
+ def teardown(self, values, settings, state):
+ vgname = self.get_vg(values)
vmdb.runcmd(['vgchange', '-an', vgname])
- def get_vg(self, step):
- return step['vgcreate']
+ def get_vg(self, values):
+ return values['vgcreate']
- def get_pv(self, step, state):
+ def get_pv(self, values, state):
return [
state.tags.get_dev(tag)
- for tag in step['physical']
+ for tag in values['physical']
]
diff --git a/vmdb/plugins/virtuals_plugin.py b/vmdb/plugins/virtuals_plugin.py
index 10ae586..71176f8 100644
--- a/vmdb/plugins/virtuals_plugin.py
+++ b/vmdb/plugins/virtuals_plugin.py
@@ -43,15 +43,17 @@ class VirtualFilesystemMountStepRunner(vmdb.StepRunnerInterface):
['none', '/sys', 'sysfs'],
]
- def get_required_keys(self):
- return ['mount-virtual-filesystems']
+ def get_key_spec(self):
+ return {
+ 'mount-virtual-filesystems': str,
+ }
- def run(self, step, settings, state):
- fstag = step['mount-virtual-filesystems']
+ def run(self, values, settings, state):
+ fstag = values['mount-virtual-filesystems']
mount_point = state.tags.get_builder_mount_point(fstag)
self.mount_virtuals(mount_point, state)
- def teardown(self, step, settings, state):
+ def teardown(self, values, settings, state):
self.unmount_virtuals(state)
def mount_virtuals(self, rootfs, state):
diff --git a/vmdb/step_list.py b/vmdb/step_list.py
index 468cf35..16bdb5f 100644
--- a/vmdb/step_list.py
+++ b/vmdb/step_list.py
@@ -24,9 +24,40 @@ import cliapp
class StepRunnerInterface: # pragma: no cover
- def get_required_keys(self):
+ def get_key_spec(self):
raise NotImplementedError()
+ def get_values(self, step):
+ keyspec = self.get_key_spec()
+ values = {}
+
+ # Get keys from step or defaults from spec.
+ for key, specvalue in keyspec.items():
+ if specvalue.__class__ == type:
+ if key not in step:
+ raise StepKeyMissing(key)
+ values[key] = step[key]
+ else:
+ values[key] = step.get(key, specvalue)
+
+ # Check types of values.
+ for key, specvalue in keyspec.items():
+ if specvalue.__class__ == type:
+ wanted = specvalue
+ else:
+ wanted = specvalue.__class__
+ if not isinstance(values[key], wanted):
+ raise StepKeyWrongValueType(key, wanted, values[key])
+
+ return values
+
+ def get_required_keys(self):
+ return [
+ key
+ for key, value in self.get_key_spec().items()
+ if value.__class__ == type
+ ]
+
def run(self, step_spec, settings, state):
raise NotImplementedError()
@@ -72,6 +103,7 @@ class StepRunnerList:
for runner in self._runners:
required = set(runner.get_required_keys())
if actual.intersection(required) == required:
+ runner.get_values(step_spec)
return runner
raise NoMatchingRunner(actual)
@@ -83,6 +115,20 @@ class StepError(cliapp.AppException):
super().__init__(msg)
+class StepKeyMissing(StepError):
+
+ def __init__(self, key):
+ super().__init__('Step is missing key {}'.format(key))
+
+
+class StepKeyWrongValueType(StepError):
+
+ def __init__(self, key, wanted, actual):
+ super().__init__(
+ 'Step key {} has value {!r}, expected {!r}'.format(
+ key, wanted, actual))
+
+
class NoMatchingRunner(StepError):
def __init__(self, keys):
diff --git a/vmdb/step_list_tests.py b/vmdb/step_list_tests.py
index 4d052d7..13836a5 100644
--- a/vmdb/step_list_tests.py
+++ b/vmdb/step_list_tests.py
@@ -35,23 +35,80 @@ class StepRunnerListTests(unittest.TestCase):
def test_finds_correct_runner(self):
steps = vmdb.StepRunnerList()
- runner = DummyStepRunner()
+ keyspec = {
+ 'foo': str,
+ 'bar': str,
+ }
+ runner = DummyStepRunner(keyspec=keyspec)
steps.add(runner)
- found = steps.find({'foo': None, 'bar': None})
+ found = steps.find({'foo': 'foo', 'bar': 'bar'})
self.assertEqual(runner, found)
def test_raises_error_if_runner_not_found(self):
steps = vmdb.StepRunnerList()
- runner = DummyStepRunner()
+ keyspec = {
+ 'foo': str,
+ 'bar': str,
+ }
+ runner = DummyStepRunner(keyspec=keyspec)
steps.add(runner)
with self.assertRaises(vmdb.NoMatchingRunner):
- steps.find({'foo': None})
+ steps.find({'foo': 'foo'})
+
+ def test_raises_error_if_wrong_step_key_values(self):
+ steps = vmdb.StepRunnerList()
+ keyspec = {
+ 'foo': str,
+ }
+ runner = DummyStepRunner(keyspec=keyspec)
+ steps.add(runner)
+ with self.assertRaises(vmdb.StepKeyWrongValueType):
+ steps.find({'foo': 42})
class DummyStepRunner(vmdb.StepRunnerInterface):
+ def __init__(self, keyspec=None):
+ self.keyspec = keyspec
+
+ def get_key_spec(self):
+ return self.keyspec
+
def run(self, *args):
pass
- def get_required_keys(self):
- return ['foo', 'bar']
+
+class StepRunnerGetKeyValuesTests(unittest.TestCase):
+
+ def test_returns_values_from_step_for_mandatory_keys(self):
+ keyspec = {'foo': str}
+ runner = DummyStepRunner(keyspec=keyspec)
+ self.assertEqual(runner.get_values({'foo': 'bar'}), {'foo': 'bar'})
+
+ def test_raises_error_for_missing_mandatory_key(self):
+ keyspec = {'foo': str}
+ runner = DummyStepRunner(keyspec=keyspec)
+ with self.assertRaises(vmdb.StepKeyMissing):
+ runner.get_values({})
+
+ def test_raises_error_for_wrong_type_of_value_for_mandatory_key(self):
+ keyspec = {'foo': str}
+ runner = DummyStepRunner(keyspec=keyspec)
+ with self.assertRaises(vmdb.StepKeyWrongValueType):
+ runner.get_values({'foo': 42})
+
+ def test_returns_default_value_for_missing_optional_key(self):
+ keyspec = {'foo': 'bar'}
+ runner = DummyStepRunner(keyspec=keyspec)
+ self.assertEqual(runner.get_values({}), {'foo': 'bar'})
+
+ def test_returns_actual_value_for_optional_key(self):
+ keyspec = {'foo': 'bar'}
+ runner = DummyStepRunner(keyspec=keyspec)
+ self.assertEqual(runner.get_values({'foo': 'yo'}), {'foo': 'yo'})
+
+ def test_raises_error_for_wrong_type_of_value_for_optional_key(self):
+ keyspec = {'foo': 'bar'}
+ runner = DummyStepRunner(keyspec=keyspec)
+ with self.assertRaises(vmdb.StepKeyWrongValueType):
+ runner.get_values({'foo': 42})