Ensure ZFS pool management is idempotent
As block device configuration is called from the config-changed hook, it's vital that the code for managing the zfs pool is idempotent. Add a helper to query pool information and ensure that the ZFS pool does not already exist before attempting creation. Change-Id: I4f4ad9c4cdb73b77e8b3a9367b81ec1566bacd59 Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
parent
a1f354a0dc
commit
abc021285c
@ -74,6 +74,7 @@ LXD_SOURCE_PACKAGES = [
|
||||
LXD_GIT = 'github.com/lxc/lxd'
|
||||
DEFAULT_LOOPBACK_SIZE = '10G'
|
||||
PW_LENGTH = 16
|
||||
ZFS_POOL_NAME = 'lxd'
|
||||
|
||||
|
||||
def install_lxd():
|
||||
@ -232,13 +233,18 @@ def configure_lxd_block():
|
||||
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
|
||||
|
||||
if config('overwrite'):
|
||||
cmd = ['zpool', 'create', '-f', 'lxd', dev]
|
||||
cmd = ['zpool', 'create', '-f', ZFS_POOL_NAME, dev]
|
||||
else:
|
||||
cmd = ['zpool', 'create', 'lxd', dev]
|
||||
cmd = ['zpool', 'create', ZFS_POOL_NAME, dev]
|
||||
check_call(cmd)
|
||||
|
||||
cmd = ['lxc', 'config', 'set', 'storage.zfs_pool_name', 'lxd']
|
||||
cmd = ['lxc', 'config', 'set', 'storage.zfs_pool_name',
|
||||
ZFS_POOL_NAME]
|
||||
check_call(cmd)
|
||||
|
||||
|
||||
@ -447,3 +453,20 @@ def assess_status():
|
||||
status_set('active', 'Unit is ready')
|
||||
else:
|
||||
status_set('blocked', 'LXD is not running')
|
||||
|
||||
|
||||
def zpools():
|
||||
'''
|
||||
Query the currently configured ZFS pools
|
||||
|
||||
@return: list of strings of pool names
|
||||
'''
|
||||
try:
|
||||
zpools = check_output(['zpool', 'list', '-H']).splitlines()
|
||||
pools = []
|
||||
for l in zpools:
|
||||
l = l.decode('UTF-8')
|
||||
pools.append(l.split()[0])
|
||||
return pools
|
||||
except CalledProcessError:
|
||||
return []
|
||||
|
@ -119,3 +119,36 @@ class TestGetBlockDevices(testing.CharmTestCase):
|
||||
devices = lxd_utils.get_block_devices()
|
||||
|
||||
self.assertEqual(['/dev/vdb', '/dev/vdc'], devices)
|
||||
|
||||
|
||||
ZFS_SINGLE_POOL = """testpool 232G 976M 231G - 7% 0% 1.04x ONLINE -
|
||||
"""
|
||||
|
||||
ZFS_MULTIPLE_POOLS = """testpool 232G 976M 231G - 7% 0% 1.04x ONLINE -
|
||||
testpool2 232G 976M 231G - 7% 0% 1.04x ONLINE -
|
||||
"""
|
||||
|
||||
|
||||
class TestZFSPool(testing.CharmTestCase):
|
||||
"""Tests for hooks.lxd_utils.zpools"""
|
||||
TO_PATCH = [
|
||||
'check_output',
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
super(TestZFSPool, self).setUp(lxd_utils, self.TO_PATCH)
|
||||
|
||||
def test_no_pools(self):
|
||||
"""When no pools are configured, an empty list is returned"""
|
||||
self.check_output.return_value = ""
|
||||
self.assertEqual(lxd_utils.zpools(), [])
|
||||
|
||||
def test_single_pool(self):
|
||||
"""Return a list with a single pool"""
|
||||
self.check_output.return_value = ZFS_SINGLE_POOL
|
||||
self.assertEqual(lxd_utils.zpools(), ['testpool'])
|
||||
|
||||
def test_multiple_pools(self):
|
||||
"""Return a list with a multiple pools"""
|
||||
self.check_output.return_value = ZFS_MULTIPLE_POOLS
|
||||
self.assertEqual(lxd_utils.zpools(), ['testpool', 'testpool2'])
|
||||
|
Loading…
Reference in New Issue
Block a user