From 6df877339c55435a3e87774d7232f4cc0f51bd35 Mon Sep 17 00:00:00 2001 From: Chris MacNaughton Date: Fri, 21 Apr 2017 10:15:14 +0200 Subject: [PATCH] Migrate to LXD storage pools We need to continue with the previous style of managing storage until zesty or a specified -updates channel LXD This additionally reinforces our suggested deployment with ZFS for a deployment, rather than using LVM as the defualt in testing. Closes-Bug: 1676742 Related-Bug: 1573681 Depends-On: I5c38766c4be66d63ef4a07eccc780fcab5973d49 Change-Id: I3ddbd11382c34ff9200e721fa3c90fe67bdce534 --- hooks/lxd_hooks.py | 4 ++ hooks/lxd_utils.py | 98 ++++++++++++++++++++++++------------ metadata.yaml | 1 + tests/basic_deployment.py | 66 ++---------------------- tests/gate-basic-zesty-ocata | 0 5 files changed, 75 insertions(+), 94 deletions(-) mode change 100644 => 100755 tests/gate-basic-zesty-ocata diff --git a/hooks/lxd_hooks.py b/hooks/lxd_hooks.py index 69d7467..9dc6766 100755 --- a/hooks/lxd_hooks.py +++ b/hooks/lxd_hooks.py @@ -46,6 +46,8 @@ from lxd_utils import ( configure_lxd_remote, configure_lxd_host, assess_status, + has_storage, + LXD_POOL, ) from charmhelpers.fetch import ( @@ -84,6 +86,8 @@ def lxd_relation_joined(rid=None): settings['password'] = lxd_trust_password() settings['hostname'] = gethostname() settings['address'] = unit_get('private-address') + if has_storage(): + settings['pool'] = LXD_POOL relation_set(relation_id=rid, relation_settings=settings) diff --git a/hooks/lxd_utils.py b/hooks/lxd_utils.py index 4b01891..74151dd 100644 --- a/hooks/lxd_utils.py +++ b/hooks/lxd_utils.py @@ -100,6 +100,8 @@ DEFAULT_LOOPBACK_SIZE = '10G' PW_LENGTH = 16 ZFS_POOL_NAME = 'lxd' EXT4_USERNS_MOUNTS = "/sys/module/ext4/parameters/userns_mounts" +LXD_POOL = 'juju_lxd' +VG_NAME = 'lxd_vg' def install_lxd(): @@ -222,8 +224,21 @@ def configure_lxd_block(): mkdir('/var/lib/lxd') if config('storage-type') == 'btrfs': - status_set('maintenance', - 'Configuring btrfs container storage') + config_btrfs(dev) + elif config('storage-type') == 'lvm': + config_lvm(dev) + elif config('storage-type') == 'zfs': + config_zfs(dev) + + +def config_btrfs(dev): + status_set('maintenance', + 'Configuring btrfs container storage') + if has_storage(): + cmd = ['lxc', 'storage', 'create', LXD_POOL, 'btrfs', + 'source={}'.format(dev)] + check_call(cmd) + else: lxd_stop() cmd = ['mkfs.btrfs', '-f', dev] check_call(cmd) @@ -235,43 +250,64 @@ def configure_lxd_block(): cmd = ['btrfs', 'quota', 'enable', '/var/lib/lxd'] check_call(cmd) lxd_start() - elif config('storage-type') == 'lvm': - if (is_lvm_physical_volume(dev) and - list_lvm_volume_group(dev) == 'lxd_vg'): - log('Device already configured for LVM/LXD, skipping') - return - status_set('maintenance', - 'Configuring LVM container storage') - # Enable and startup lvm2-lvmetad to avoid extra output - # in lvm2 commands, which confused lxd. - cmd = ['systemctl', 'enable', 'lvm2-lvmetad'] - check_call(cmd) - cmd = ['systemctl', 'start', 'lvm2-lvmetad'] + + +def config_lvm(dev): + if (is_lvm_physical_volume(dev) and + list_lvm_volume_group(dev) == VG_NAME): + log('Device already configured for LVM/LXD, skipping') + return + status_set('maintenance', + 'Configuring LVM container storage') + + cmd = ['systemctl', 'enable', 'lvm2-lvmetad'] + check_call(cmd) + cmd = ['systemctl', 'start', 'lvm2-lvmetad'] + check_call(cmd) + if has_storage(): + cmd = ['lxc', 'storage', 'create', LXD_POOL, 'lvm', + 'source={}'.format(dev), 'lvm.vg_name={}'.format(VG_NAME)] check_call(cmd) + else: create_lvm_physical_volume(dev) - create_lvm_volume_group('lxd_vg', dev) - cmd = ['lxc', 'config', 'set', 'storage.lvm_vg_name', 'lxd_vg'] + create_lvm_volume_group(VG_NAME, dev) + cmd = ['lxc', 'config', 'set', 'storage.lvm_vg_name', VG_NAME] check_call(cmd) - # The LVM thinpool logical volume is lazily created, either on - # image import or container creation. This will force LV creation. - create_and_import_busybox_image() - elif config('storage-type') == 'zfs': - status_set('maintenance', - 'Configuring zfs container storage') - if ZFS_POOL_NAME in zpools(): - log('ZFS pool already exist; skipping zfs configuration') - return + # The LVM thinpool logical volume is lazily created, either on + # image import or container creation. This will force LV creation. + create_and_import_busybox_image() - if config('overwrite'): - cmd = ['zpool', 'create', '-f', ZFS_POOL_NAME, dev] - else: - cmd = ['zpool', 'create', ZFS_POOL_NAME, dev] - check_call(cmd) +def config_zfs(dev): + status_set('maintenance', + 'Configuring zfs container storage') + if ZFS_POOL_NAME in zpools(): + log('ZFS pool already exist; skipping zfs configuration') + return + + if config('overwrite'): + cmd = ['zpool', 'create', '-f', ZFS_POOL_NAME, dev] + else: + cmd = ['zpool', 'create', ZFS_POOL_NAME, dev] + check_call(cmd) + + if has_storage(): + cmd = ["lxc", "storage", "create", LXD_POOL, "zfs", + "source={}".format(ZFS_POOL_NAME)] + else: cmd = ['lxc', 'config', 'set', 'storage.zfs_pool_name', ZFS_POOL_NAME] - check_call(cmd) + + check_call(cmd) + + +def has_storage(): + try: + check_call(['lxc', 'storage', 'list']) + return True + except subprocess.CalledProcessError: + return False def create_and_import_busybox_image(): diff --git a/metadata.yaml b/metadata.yaml index 4b7306b..620000f 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -10,6 +10,7 @@ series: - xenial - zesty - yakkety + - zesty subordinate: true peers: lxd-migration: diff --git a/tests/basic_deployment.py b/tests/basic_deployment.py index 5bb4310..2c66190 100644 --- a/tests/basic_deployment.py +++ b/tests/basic_deployment.py @@ -136,7 +136,7 @@ class LXDBasicDeployment(OpenStackAmuletDeployment): lxd_config = { 'block-devices': '/dev/vdb', 'ephemeral-unmount': '/mnt', - 'storage-type': 'lvm', + 'storage-type': 'zfs', 'overwrite': True } @@ -244,16 +244,7 @@ class LXDBasicDeployment(OpenStackAmuletDeployment): u.log.debug('Checking system services on units...') services = { - self.lxd0_sentry: ['lxd'], - self.compute0_sentry: ['nova-compute'], - self.compute1_sentry: ['nova-compute'], - self.rabbitmq_sentry: ['rabbitmq-server'], - self.nova_cc_sentry: ['nova-api-os-compute', - 'nova-conductor', - 'nova-cert', - 'nova-scheduler'], - self.glance_sentry: ['glance-registry', - 'glance-api'] + self.lxd0_sentry: ['lxd'] } # XXX: rockstar (6 Mar 2016) - See related XXX comment # above. @@ -291,56 +282,6 @@ class LXDBasicDeployment(OpenStackAmuletDeployment): # TODO: Add bi-directional lxd service relation introspection - def test_400_check_logical_volume_groups(self): - """Inspect and validate vgs on all lxd units.""" - u.log.debug('Checking logical volume groups on lxd units...') - - cmd = 'sudo vgs' - expected = ['lxd_vg'] - - invalid = [] - for sentry_unit in self.d.sentry['lxd']: - host = sentry_unit.info['public-address'] - unit_name = sentry_unit.info['unit_name'] - - output, _ = u.run_cmd_unit(sentry_unit, cmd) - for expected_content in expected: - if expected_content not in output: - invalid.append('{} {} vgs does not contain ' - '{}'.format(unit_name, host, - expected_content)) - - if invalid: - u.log.error('Logical volume group check failed.') - amulet.raise_status(amulet.FAIL, msg='; '.join(invalid)) - - u.log.debug('Ok') - - def test_401_check_logical_volumes(self): - """Inspect and validate lvs on all lxd units.""" - u.log.debug('Checking logical volumes on lxd units...') - - cmd = 'sudo lvs' - expected = ['LXDPool'] - - invalid = [] - for sentry_unit in self.d.sentry['lxd']: - host = sentry_unit.info['public-address'] - unit_name = sentry_unit.info['unit_name'] - - output, _ = u.run_cmd_unit(sentry_unit, cmd) - for expected_content in expected: - if expected_content not in output: - invalid.append('{} {} lvs does not contain ' - '{}'.format(unit_name, host, - expected_content)) - - if invalid: - u.log.error('Logical volume check failed.') - amulet.raise_status(amulet.FAIL, msg='; '.join(invalid)) - - u.log.debug('Ok') - def test_402_lxc_config_validate(self): """Inspect and validate lxc running config on all lxd units.""" u.log.debug('Checking lxc config on lxd units...') @@ -349,9 +290,7 @@ class LXDBasicDeployment(OpenStackAmuletDeployment): expected = [ 'core.https_address: \'[::]\'', 'core.trust_password: true', - 'storage.lvm_vg_name: lxd_vg', ] - invalid = [] for sentry_unit in self.d.sentry['lxd']: host = sentry_unit.info['public-address'] @@ -359,6 +298,7 @@ class LXDBasicDeployment(OpenStackAmuletDeployment): output, _ = u.run_cmd_unit(sentry_unit, cmd) for expected_content in expected: + version, _ = u.run_cmd_unit(sentry_unit, 'sudo lxc --version') if expected_content not in output: invalid.append('{} {} lxc config does not contain ' '{}'.format(unit_name, host, diff --git a/tests/gate-basic-zesty-ocata b/tests/gate-basic-zesty-ocata old mode 100644 new mode 100755