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
This commit is contained in:
Chris MacNaughton 2017-04-21 10:15:14 +02:00
parent 8a7e9753c5
commit 6df877339c
5 changed files with 75 additions and 94 deletions

View File

@ -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)

View File

@ -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():

View File

@ -10,6 +10,7 @@ series:
- xenial
- zesty
- yakkety
- zesty
subordinate: true
peers:
lxd-migration:

View File

@ -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,

0
tests/gate-basic-zesty-ocata Normal file → Executable file
View File