def testExecution(self): """ The pool was just created, so it must always be possible to destroy it. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool1, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={'Pool': pool1}).search(managed_objects) self.assertEqual( frozenset(MOBlockDev(b).Devnode() for (_, b) in blockdevs1), frozenset(d for d in self._devices)) (result, rc, _) = \ Manager.Methods.DestroyPool(self._proxy, {'pool': pool1}) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) blockdevs2 = blockdevs(props={'Pool': pool1}).search(managed_objects) pool2 = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects), None) self.assertEqual(rc, StratisdErrors.OK) self.assertIsNone(pool2) self.assertTrue(result) self.assertEqual(len(list(blockdevs2)), 0)
def testNewName(self): """ Test rename to new name. """ new_name = "new" (result, rc, _) = Pool.Methods.SetName(self._pool_object, {'name': new_name}) self.assertTrue(result) self.assertEqual(rc, StratisdErrors.OK) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) self.assertIsNone( next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects), None)) result = next( pools(props={ 'Name': new_name }).search(managed_objects), None) self.assertIsNotNone(result) (pool, _) = result self.assertEqual(pool, self._pool_object_path)
def testExecution(self): """ The pool was just created and has no devices. It should always be possible to destroy it. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) (result, rc, _) = \ Manager.Methods.DestroyPool(self._proxy, {'pool': pool}) self.assertEqual(rc, StratisdErrors.OK) self.assertEqual(result, True) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) self.assertIsNone( next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects), None))
def testCreate(self): """ Create should fail trying to create new pool with same name as previous. """ pools1 = pools().search( ObjectManager.Methods.GetManagedObjects(self._proxy, {})) (_, rc, _) = Manager.Methods.CreatePool( self._proxy, { 'name': self._POOLNAME, 'redundancy': (True, 0), 'devices': _DEVICE_STRATEGY(), }) expected_rc = StratisdErrors.ALREADY_EXISTS self.assertEqual(rc, expected_rc) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) pools2 = [x for x in pools().search(managed_objects)] pool = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects), None) self.assertIsNotNone(pool) self.assertEqual(frozenset(x for (x, y) in pools1), frozenset(x for (x, y) in pools2))
def testCreate(self): """ Type of result should always be correct. If rc is OK, then pool must exist. """ devs = _DEVICE_STRATEGY() ((poolpath, devnodes), rc, _) = Manager.Methods.CreatePool(self._proxy, { 'name': self._POOLNAME, 'redundancy': (True, 0), 'devices': devs }) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) all_pools = [x for x in pools().search(managed_objects)] result = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects), None) if rc == StratisdErrors.OK: self.assertIsNotNone(result) (pool, table) = result self.assertEqual(pool, poolpath) self.assertEqual(len(all_pools), 1) self.assertLessEqual(len(devnodes), len(devs)) pool_info = MOPool(table) self.assertLessEqual(int(pool_info.TotalPhysicalUsed()), int(pool_info.TotalPhysicalSize())) else: self.assertIsNone(result) self.assertEqual(len(all_pools), 0)
def test_create_different_blockdevs(self): """ Create should fail trying to create new pool with same name and different blockdevs from previous. """ pools1 = pools().search( ObjectManager.Methods.GetManagedObjects(self._proxy, {})) (_, return_code, _) = Manager.Methods.CreatePool( self._proxy, { "name": self._POOLNAME, "redundancy": (True, 0), "devices": _DEVICE_STRATEGY(), }, ) self.assertEqual(return_code, StratisdErrors.ERROR) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) pools2 = list(pools().search(managed_objects)) pool = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects), None) self.assertIsNotNone(pool) self.assertEqual(frozenset(x for (x, y) in pools1), frozenset(x for (x, y) in pools2))
def test_create_same_blockdevs(self): """ Create should succeed trying to create new pool with same name and same blockdevs as previous. """ pools1 = pools().search( ObjectManager.Methods.GetManagedObjects(self._proxy, {})) ((is_some, _), return_code, _) = Manager.Methods.CreatePool( self._proxy, { "name": self._POOLNAME, "redundancy": (True, 0), "devices": self._blockdevs, }, ) self.assertEqual(return_code, StratisdErrors.OK) self.assertFalse(is_some) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) pools2 = list(pools().search(managed_objects)) pool = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects), None) self.assertIsNotNone(pool) self.assertEqual(frozenset(x for (x, y) in pools1), frozenset(x for (x, y) in pools2))
def test_create(self): """ Type of result should always be correct. If return_code is OK, then pool must exist. """ ((_, (poolpath, devnodes)), return_code, _) = Manager.Methods.CreatePool( self._proxy, { "name": self._POOLNAME, "redundancy": (True, 0), "devices": self._devs }, ) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) all_pools = list(pools().search(managed_objects)) result = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects), None) if return_code == StratisdErrors.OK: self.assertIsNotNone(result) (pool, _) = result self.assertEqual(pool, poolpath) self.assertEqual(len(all_pools), 1) self.assertLessEqual(len(devnodes), len(self._devs)) else: self.assertIsNone(result) self.assertEqual(len(all_pools), 0)
def testExecution(self): """ This should fail since the pool has a filesystem on it. """ managed_objects = ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next(pools(props={"Name": self._POOLNAME}).search(managed_objects)) ((is_some, _), rc, _) = Manager.Methods.DestroyPool(self._proxy, {"pool": pool}) self.assertEqual(rc, StratisdErrors.BUSY) self.assertFalse(is_some) managed_objects = ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool1, _) = next(pools(props={"Name": self._POOLNAME}).search(managed_objects)) self.assertEqual(pool, pool1)
def testEmptyDevs(self): """ Adding an empty list of cache devs should have no effect. """ managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) (pool, _) = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects)) ((is_some, result), rc, _) = Pool.Methods.AddCacheDevs(self._pool_object, {"devices": []}) self.assertFalse(is_some) self.assertEqual(len(result), 0) self.assertEqual(rc, StratisdErrors.OK) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) blockdevs2 = blockdevs(props={"Pool": pool}).search(managed_objects) self.assertEqual(list(blockdevs2), []) blockdevs3 = blockdevs().search(managed_objects) self.assertEqual(list(blockdevs3), [])
def testExecution(self): """ Destroy should succeed since there is nothing to pass to DestroyPool. """ managed_objects = ObjectManager.Methods.GetManagedObjects(self._proxy, {}) pool = next(pools(props={"Name": self._POOLNAME}).search(managed_objects), None) self.assertIsNone(pool)
def testEmptyDevs(self): """ Adding an empty list of devs should leave the pool empty. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={'Pool': pool}).search(managed_objects) self.assertEqual(list(blockdevs1), []) (result, rc, _) = Pool.Methods.AddDataDevs(self._pool_object, {'devices': []}) self.assertEqual(result, []) self.assertEqual(rc, StratisdErrors.OK) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) blockdevs2 = blockdevs(props={'Pool': pool}).search(managed_objects) self.assertEqual(list(blockdevs2), []) blockdevs3 = blockdevs(props={}).search(managed_objects) self.assertEqual(list(blockdevs3), [])
def testEmptyDevs(self): """ Adding an empty list of cache devs should have no effect. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={ 'Pool': pool, 'Tier': 0 }).search(managed_objects) self.assertEqual(self._devpaths, frozenset(op for (op, _) in blockdevs1)) blockdevs2 = blockdevs(props={ 'Pool': pool, 'Tier': 1 }).search(managed_objects) self.assertEqual(list(blockdevs2), []) (result, rc, _) = Pool.Methods.AddCacheDevs(self._pool_object, {'devices': []}) self.assertEqual(len(result), 0) self.assertEqual(rc, StratisdErrors.OK) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) blockdevs3 = blockdevs(props={'Pool': pool}).search(managed_objects) self.assertEqual(frozenset(op for (op, _) in blockdevs3), self._devpaths)
def test_empty_devs(self): """ Adding an empty list of devs should fail. """ managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) (pool, _) = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={"Pool": pool}).search(managed_objects) self.assertEqual(len(list(blockdevs1)), len(self._data_devices)) ((is_some, _), return_code, _) = Pool.Methods.AddDataDevs(self._pool_object, {"devices": []}) self.assertFalse(is_some) self.assertEqual(return_code, StratisdErrors.OK) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) blockdevs2 = blockdevs(props={"Pool": pool}).search(managed_objects) self.assertEqual(len(list(blockdevs2)), len(self._data_devices)) blockdevs3 = blockdevs(props={}).search(managed_objects) self.assertEqual(len(list(blockdevs3)), len(self._data_devices))
def _test_cap_size(self, pool_name, prediction): """ Helper function to verify that the cap device is the correct size. :param str pool_name: the name of the pool to test :param prediction: JSON output from script """ proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) _pool_object_path, pool = next( pools(props={ "Name": pool_name }).require_unique_match(True).search(managed_objects)) pool_uuid = MOPool(pool).Uuid() cap_name = self._CAP_DEVICE_STR % pool_uuid with subprocess.Popen( ["blockdev", "--getsize64", "/dev/mapper/%s" % cap_name], stdout=subprocess.PIPE, universal_newlines=True, ) as command: cap_device_size, _ = command.communicate() self.assertEqual(cap_device_size.rstrip("\n"), prediction["free"])
def testEmptyDevs(self): """ Adding an empty list of cache devs should have no effect. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) (result, rc, _) = Pool.Methods.AddCacheDevs(self._pool_object, { 'force': False, 'devices': [] }) self.assertEqual(len(result), 0) self.assertEqual(rc, StratisdErrors.OK) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) blockdevs2 = blockdevs(props={'Pool': pool}).search(managed_objects) self.assertEqual(list(blockdevs2), []) blockdevs3 = blockdevs().search(managed_objects) self.assertEqual(list(blockdevs3), [])
def testExecution(self): """ This should fail since the pool has a filesystem on it. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next(pools(managed_objects, {'Name': self._POOLNAME})) (result, rc, _) = \ Manager.Methods.DestroyPool(self._proxy, {'pool': pool}) self.assertEqual(rc, StratisdErrors.BUSY) self.assertEqual(result, False) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool1, _) = next(pools(managed_objects, {'Name': self._POOLNAME})) self.assertEqual(pool, pool1)
def testSomeDevs(self): """ Adding a non-empty list of cache devs should succeed. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={ 'Pool': pool, 'Tier': 0 }).search(managed_objects) self.assertEqual(self._devpaths, frozenset(op for (op, _) in blockdevs1)) (result, rc, _) = Pool.Methods.AddCacheDevs(self._pool_object, { 'force': False, 'devices': _DEVICE_STRATEGY.example() }) num_devices_added = len(result) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) if rc == StratisdErrors.OK: self.assertGreater(num_devices_added, 0) else: self.assertEqual(num_devices_added, 0) blockdev_object_paths = frozenset(result) # cache blockdevs exported on the D-Bus are exactly those added blockdevs2 = list( blockdevs(props={ 'Pool': pool, 'Tier': 1 }).search(managed_objects)) self.assertEqual(frozenset(op for (op, _) in blockdevs2), blockdev_object_paths) # no duplicates in the object paths self.assertEqual(len(blockdevs2), num_devices_added) # There are no blockdevs but for those in this pool blockdevs3 = blockdevs(props={'Pool': pool}).search(managed_objects) blockdevs4 = blockdevs().search(managed_objects) self.assertEqual(len(list(blockdevs3)), len(list(blockdevs4))) # The number of datadevs has remained the same blockdevs5 = blockdevs(props={ 'Pool': pool, 'Tier': 0 }).search(managed_objects) self.assertEqual(frozenset(op for (op, _) in blockdevs5), self._devpaths)
def test_some_devs(self): """ Adding a non-empty list of devs should increase the number of devs in the pool. """ managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) (pool, _) = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={"Pool": pool}).search(managed_objects) self.assertEqual(len(list(blockdevs1)), len(self._data_devices)) ((is_some, result), return_code, _) = Pool.Methods.AddDataDevs(self._pool_object, {"devices": _DEVICE_STRATEGY()}) num_devices_added = len(result) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) if return_code == StratisdErrors.OK: self.assertTrue(is_some) self.assertGreater(num_devices_added, 0) else: self.assertFalse(is_some) self.assertEqual(num_devices_added, 0) blockdev_object_paths = frozenset(result) # blockdevs exported on the D-Bus are those added and the existing data devs blockdevs2 = list( blockdevs(props={ "Pool": pool }).search(managed_objects)) blockdevs2_object_paths = frozenset([op for (op, _) in blockdevs2]) self.assertEqual( blockdevs2_object_paths, blockdev_object_paths.union(frozenset(self._blockdev_paths)), ) # no duplicates in the object paths self.assertEqual( len(blockdevs2) - len(self._blockdev_paths), num_devices_added) # There are no blockdevs but for those in this pool blockdevs3 = blockdevs(props={}).search(managed_objects) self.assertEqual(len(list(blockdevs3)), num_devices_added + len(self._data_devices)) # There are no cachedevs belonging to this pool blockdevs4 = blockdevs(props={ "Pool": pool, "Tier": 1 }).search(managed_objects) self.assertEqual(list(blockdevs4), [])
def test_new_name(self): """ Test rename to new name. """ new_name = "new" ((is_some, _), return_code, _) = Pool.Methods.SetName( self._pool_object, {"name": new_name} ) self.assertTrue(is_some) self.assertEqual(return_code, StratisdErrors.OK) managed_objects = ObjectManager.Methods.GetManagedObjects(self._proxy, {}) self.assertIsNone( next(pools(props={"Name": self._POOLNAME}).search(managed_objects), None) ) result = next(pools(props={"Name": new_name}).search(managed_objects), None) self.assertIsNotNone(result) (pool, _) = result self.assertEqual(pool, self._pool_object_path)
def _get_pools(name=None): """ Returns a list of the pools or a list with 1 element if name is set and found, else empty list :param name: Optional filter for pool name :return: """ managed_objects = ObjectManager.Methods.GetManagedObjects( get_object(TOP_OBJECT), {}) selector = {} if name is None else {'Name': name} return list(pools(props=selector).search(managed_objects))
def testSomeDevs(self): """ Adding a non-empty list of devs should increase the number of devs in the pool. """ managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) (pool, _) = next( pools(props={ 'Name': self._POOLNAME }).search(managed_objects)) blockdevs1 = blockdevs(props={'Pool': pool}).search(managed_objects) self.assertEqual(list(blockdevs1), []) (result, rc, _) = Pool.Methods.AddDataDevs(self._pool_object, {'devices': _DEVICE_STRATEGY.example()}) num_devices_added = len(result) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) if rc == StratisdErrors.OK: self.assertGreater(num_devices_added, 0) else: self.assertEqual(num_devices_added, 0) blockdev_object_paths = frozenset(result) # blockdevs exported on the D-Bus are exactly those added blockdevs2 = list( blockdevs(props={ 'Pool': pool }).search(managed_objects)) blockdevs2_object_paths = frozenset([op for (op, _) in blockdevs2]) self.assertEqual(blockdevs2_object_paths, blockdev_object_paths) # no duplicates in the object paths self.assertEqual(len(blockdevs2), num_devices_added) # There are no blockdevs but for those in this pool blockdevs3 = blockdevs(props={}).search(managed_objects) self.assertEqual(len(list(blockdevs3)), num_devices_added) # There are no cachedevs belonging to this pool blockdevs4 = blockdevs(props={ 'Pool': pool, 'Tier': 1 }).search(managed_objects) self.assertEqual(list(blockdevs4), [])
def testSomeDevs(self): """ Adding a non-empty list of cache devs should succeed. """ managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) (pool, _) = next( pools(props={ "Name": self._POOLNAME }).search(managed_objects)) ((is_some, result), rc, _) = Pool.Methods.AddCacheDevs(self._pool_object, {"devices": _DEVICE_STRATEGY()}) num_devices_added = len(result) managed_objects = ObjectManager.Methods.GetManagedObjects( self._proxy, {}) if rc == StratisdErrors.OK: self.assertTrue(is_some) self.assertGreater(num_devices_added, 0) else: self.assertFalse(is_some) self.assertEqual(num_devices_added, 0) blockdev_paths = frozenset(result) # blockdevs exported on the D-Bus are exactly those added blockdevs2 = list( blockdevs(props={ "Pool": pool }).search(managed_objects)) blockdevs2_paths = frozenset([op for (op, _) in blockdevs2]) self.assertEqual(blockdevs2_paths, blockdev_paths) # no duplicates in the object paths self.assertEqual(len(blockdevs2), num_devices_added) # There are no blockdevs but for those in this pool blockdevs3 = blockdevs().search(managed_objects) self.assertEqual(len(list(blockdevs3)), num_devices_added) # There are no datadevs belonging to this pool blockdevs4 = blockdevs(props={ "Pool": pool, "Tier": 0 }).search(managed_objects) self.assertEqual(list(blockdevs4), [])
def get_pools(name=None): """ Returns a list of all pools found by GetManagedObjects, or a list of pools with names matching the specified name, if passed. :param name: filter for pool name :type name: str or NoneType :return: list of pool information found :rtype: list of (str * MOPool) """ managed_objects = ObjectManager.Methods.GetManagedObjects( get_object(TOP_OBJECT), {}) return [(op, MOPool(info)) for op, info in pools(props={} if name is None else { "Name": name }).search(managed_objects)]
def testNullMapping(self): """ Test rename to same name. """ (result, rc, _) = Pool.Methods.SetName(self._pool_object, {'name': self._POOLNAME}) self.assertEqual(rc, StratisdErrors.OK) self.assertFalse(result) managed_objects = \ ObjectManager.Methods.GetManagedObjects(self._proxy, {}) result = next(pools(managed_objects, {'Name': self._POOLNAME}), None) self.assertIsNotNone(result) (pool, _) = result self.assertEqual(pool, self._pool_object_path)
def testNullMapping(self): """ Test rename to same name. """ ((is_some, _), rc, _) = Pool.Methods.SetName( self._pool_object, {"name": self._POOLNAME} ) self.assertEqual(rc, StratisdErrors.OK) self.assertFalse(is_some) managed_objects = ObjectManager.Methods.GetManagedObjects(self._proxy, {}) result = next( pools(props={"Name": self._POOLNAME}).search(managed_objects), None ) self.assertIsNotNone(result) (pool, _) = result self.assertEqual(pool, self._pool_object_path)
def _test_prediction(self, pool_name, *, fs_specs=None, overprovision=True): """ Helper function to verify that the prediction matches the reality to an acceptable degree. :param str pool_name: the name of the pool to test :param fs_specs: filesystems to create and test :type fs_specs: list of of str * Range or NoneType :param bool overprovision: True if overprovisioning is allowed """ proxy = get_object(TOP_OBJECT) managed_objects = ObjectManager.Methods.GetManagedObjects(proxy, {}) pool_object_path, pool = next( pools(props={"Name": pool_name}) .require_unique_match(True) .search(managed_objects) ) mopool = MOPool(pool) physical_sizes = _get_block_device_sizes(pool_object_path, managed_objects) pre_prediction = _call_predict_usage( mopool.Encrypted(), physical_sizes, overprovision=overprovision ) self._check_prediction(pre_prediction, mopool) change = _possibly_add_filesystems(pool_object_path, fs_specs=fs_specs) post_prediction = _call_predict_usage( mopool.Encrypted(), physical_sizes, fs_specs=fs_specs, overprovision=overprovision, ) self._check_fs_prediction( pre_prediction, post_prediction, change, overprovision=overprovision )