diff --git a/hooks/lxd_utils.py b/hooks/lxd_utils.py index 2a25b69..6621c60 100644 --- a/hooks/lxd_utils.py +++ b/hooks/lxd_utils.py @@ -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 [] diff --git a/unit_tests/test_lxd_utils.py b/unit_tests/test_lxd_utils.py index 1a7daa9..c5357e5 100644 --- a/unit_tests/test_lxd_utils.py +++ b/unit_tests/test_lxd_utils.py @@ -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'])