def test_create_consistencygroup_from_src_volumes(self, create_snapshot, create_volume, delete_snapshot): src_cgroup = fake_cgroup(self.ctxt) dst_cgroup_spec = {'id': fake.CONSISTENCY_GROUP2_ID} dst_cgroup = fake_cgroup(self.ctxt, **dst_cgroup_spec) src_volume = fake_volume(self.ctxt) src_volumes = [src_volume] dst_volume_spec = {'id': fake.VOLUME2_ID} dst_volume = fake_volume(self.ctxt, **dst_volume_spec) dst_volumes = [dst_volume] create_snapshot.return_value = {} create_volume.return_value = {} delete_snapshot.return_value = {} result = self.drv.create_consistencygroup_from_src( self.ctxt, dst_cgroup, dst_volumes, None, None, src_cgroup, src_volumes) snapshot_name = (self.cfg.nexenta_origin_snapshot_template % dst_cgroup['id']) snapshot_path = '%s@%s' % (self.drv.root_path, snapshot_name) create_payload = {'path': snapshot_path, 'recursive': True} create_snapshot.assert_called_with(create_payload) snapshot = { 'name': snapshot_name, 'volume_id': src_volume['id'], 'volume_name': src_volume['name'], 'volume_size': src_volume['size'] } create_volume.assert_called_with(dst_volume, snapshot) delete_payload = {'defer': True, 'recursive': True} delete_snapshot.assert_called_with(snapshot_path, delete_payload) expected = ({}, []) self.assertEqual(expected, result)
def test_create_cloned_volume(self, create_snapshot, create_volume, delete_snapshot): volume = fake_volume(self.ctxt) clone_spec = {'id': fake.VOLUME2_ID} clone = fake_volume(self.ctxt, **clone_spec) create_snapshot.return_value = {} create_volume.return_value = {} delete_snapshot.return_value = {} self.assertIsNone(self.drv.create_cloned_volume(clone, volume)) snapshot = { 'name': self.drv.origin_snapshot_template % clone['id'], 'volume_id': volume['id'], 'volume_name': volume['name'], 'volume_size': volume['size'] } create_snapshot.assert_called_with(snapshot) create_volume.assert_called_with(clone, snapshot) create_volume.side_effect = jsonrpc.NefException({ 'message': 'Failed to create volume', 'code': 'EBUSY' }) self.assertRaises(jsonrpc.NefException, self.drv.create_cloned_volume, clone, volume) create_snapshot.side_effect = jsonrpc.NefException({ 'message': 'Failed to open dataset', 'code': 'ENOENT' }) self.assertRaises(jsonrpc.NefException, self.drv.create_cloned_volume, clone, volume)
def test_create_volume_from_snapshot(self, clone_snapshot, unmount_filesystem, mount_filesystem, extend_volume): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume clone_size = 10 clone_spec = { 'id': fake.VOLUME2_ID, 'size': clone_size } clone = fake_volume(self.ctxt, **clone_spec) snapshot_path = self.drv._get_snapshot_path(snapshot) clone_path = self.drv._get_volume_path(clone) clone_snapshot.return_value = {} unmount_filesystem.return_value = {} mount_filesystem.return_value = {} extend_volume.return_value = None self.assertIsNone( self.drv.create_volume_from_snapshot(clone, snapshot) ) clone_payload = {'targetPath': clone_path} clone_snapshot.assert_called_with(snapshot_path, clone_payload) unmount_filesystem.assert_called_with(clone_path) mount_filesystem.assert_called_with(clone_path) extend_volume.assert_called_with(clone, clone_size)
def test_delete_consistencygroup(self, delete_volume): cgroup = fake_cgroup(self.ctxt) volume1 = fake_volume(self.ctxt) volume2_spec = {'id': fake.VOLUME2_ID} volume2 = fake_volume(self.ctxt, **volume2_spec) volumes = [volume1, volume2] delete_volume.return_value = {} result = self.drv.delete_consistencygroup(self.ctxt, cgroup, volumes) expected = ({}, []) self.assertEqual(expected, result)
def test_delete_consistencygroup(self, delete_volume): cgroup = fake_cgroup(self.ctxt) volume1 = fake_volume(self.ctxt) volume2_spec = {'id': fake.VOLUME2_ID} volume2 = fake_volume(self.ctxt, **volume2_spec) volumes = [volume1, volume2] delete_volume.return_value = {} result = self.drv.delete_consistencygroup(self.ctxt, cgroup, volumes) expected = ({}, []) self.assertEqual(expected, result)
def test_update_consistencygroup(self): cgroup = fake_cgroup(self.ctxt) volume1 = fake_volume(self.ctxt) volume2_spec = {'id': fake.VOLUME2_ID} volume2 = fake_volume(self.ctxt, **volume2_spec) volume3_spec = {'id': fake.VOLUME3_ID} volume3 = fake_volume(self.ctxt, **volume3_spec) volume4_spec = {'id': fake.VOLUME4_ID} volume4 = fake_volume(self.ctxt, **volume4_spec) add_volumes = [volume1, volume2] remove_volumes = [volume3, volume4] result = self.drv.update_consistencygroup(self.ctxt, cgroup, add_volumes, remove_volumes) expected = ({}, [], []) self.assertEqual(expected, result)
def test_create_consistencygroup_from_src_snapshots(self, create_volume): cgroup = fake_cgroup(self.ctxt) cgsnapshot = fake_cgsnapshot(self.ctxt) volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume snapshots = [snapshot] clone_spec = {'id': fake.VOLUME2_ID} clone = fake_volume(self.ctxt, **clone_spec) clones = [clone] create_volume.return_value = {} result = self.drv.create_consistencygroup_from_src( self.ctxt, cgroup, clones, cgsnapshot, snapshots, None, None) create_volume.assert_called_with(clone, snapshot) expected = ({}, []) self.assertEqual(expected, result)
def test_extend_volume(self, mount_volume, get_volume_local_path, execute_command, unmount_volume): volume = fake_volume(self.ctxt) root_helper = 'sudo cinder-rootwrap /etc/cinder/rootwrap.conf' local_path = '/path/to/volume/file' new_size = volume['size'] * 2 bs = 1 * units.Mi seek = volume['size'] * units.Ki count = (new_size - volume['size']) * units.Ki mount_volume.return_value = True get_volume_local_path.return_value = local_path execute_command.return_value = True unmount_volume.return_value = True with mock.patch.object(self.drv, 'sparsed_volumes', False): self.assertIsNone(self.drv.extend_volume(volume, new_size)) execute_command.assert_called_with('dd', 'if=/dev/zero', 'of=%s' % local_path, 'bs=%d' % bs, 'seek=%d' % seek, 'count=%d' % count, run_as_root=True, root_helper=root_helper) with mock.patch.object(self.drv, 'sparsed_volumes', True): self.assertIsNone(self.drv.extend_volume(volume, new_size)) execute_command.assert_called_with('truncate', '-s', '%dG' % new_size, local_path, run_as_root=True, root_helper=root_helper) mount_volume.assert_called_with(volume) unmount_volume.assert_called_with(volume)
def test_get_manageable_volumes(self, list_filesystems): volume = fake_volume(self.ctxt) volumes = [volume] size = volume['size'] path = self.drv._get_volume_path(volume) guid = 12345 parent = self.drv.root_path list_filesystems.return_value = [{ 'guid': guid, 'parent': parent, 'path': path, 'bytesUsed': size * units.Gi }] result = self.drv.get_manageable_volumes(volumes, None, 1, 0, 'size', 'asc') payload = { 'parent': parent, 'fields': 'guid,parent,path,bytesUsed', 'recursive': False } list_filesystems.assert_called_with(payload) expected = [{ 'cinder_id': volume['id'], 'extra_info': None, 'reason_not_safe': 'Volume already managed', 'reference': { 'source-guid': guid, 'source-name': volume['name'] }, 'safe_to_manage': False, 'size': volume['size'] }] self.assertEqual(expected, result)
def test__check_already_managed_snapshot(self): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume result = self.drv._check_already_managed_snapshot(snapshot) expected = False self.assertEqual(expected, result)
def test_create_cgsnapshot(self, create_snapshot, rename_snapshot, delete_snapshot): cgsnapshot = fake_cgsnapshot(self.ctxt) volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume snapshots = [snapshot] cgsnapshot_name = ( self.cfg.nexenta_group_snapshot_template % cgsnapshot['id']) cgsnapshot_path = '%s@%s' % (self.drv.root_path, cgsnapshot_name) snapshot_path = '%s/%s@%s' % (self.drv.root_path, snapshot['volume_name'], cgsnapshot_name) create_snapshot.return_value = {} rename_snapshot.return_value = {} delete_snapshot.return_value = {} result = self.drv.create_cgsnapshot(self.ctxt, cgsnapshot, snapshots) create_payload = {'path': cgsnapshot_path, 'recursive': True} create_snapshot.assert_called_with(create_payload) rename_payload = {'newName': snapshot['name']} rename_snapshot.assert_called_with(snapshot_path, rename_payload) delete_payload = {'defer': True, 'recursive': True} delete_snapshot.assert_called_with(cgsnapshot_path, delete_payload) expected = ({}, []) self.assertEqual(expected, result)
def test_create_volume(self, create_volume, set_volume_acl, mount_volume, get_volume_local_path, create_sparsed_file, created_regular_file, set_volume, delete_volume, umount_volume): volume = fake_volume(self.ctxt) local_path = '/local/volume/path' create_volume.return_value = {} set_volume_acl.return_value = {} mount_volume.return_value = True get_volume_local_path.return_value = local_path create_sparsed_file.return_value = True created_regular_file.return_value = True set_volume.return_value = {} delete_volume.return_value = {} umount_volume.return_value = {} with mock.patch.object(self.drv, 'sparsed_volumes', True): self.assertIsNone(self.drv.create_volume(volume)) create_sparsed_file.assert_called_with(local_path, volume['size']) with mock.patch.object(self.drv, 'sparsed_volumes', False): self.assertIsNone(self.drv.create_volume(volume)) created_regular_file.assert_called_with(local_path, volume['size']) volume_path = self.drv._get_volume_path(volume) payload = { 'path': volume_path, 'compressionMode': 'off' } create_volume.assert_called_with(payload) set_volume_acl.assert_called_with(volume) payload = {'compressionMode': self.cfg.nexenta_dataset_compression} set_volume.assert_called_with(volume_path, payload) umount_volume.assert_called_with(volume)
def test_manage_existing_snapshot(self, get_existing_snapshot, rename_snapshot): volume = fake_volume(self.ctxt) existing_snapshot = fake_snapshot(self.ctxt) existing_snapshot.volume = volume manage_snapshot_spec = {'id': fake.SNAPSHOT2_ID} manage_snapshot = fake_snapshot(self.ctxt, **manage_snapshot_spec) manage_snapshot.volume = volume existing_name = existing_snapshot['name'] manage_name = manage_snapshot['name'] volume_name = volume['name'] volume_size = volume['size'] existing_path = self.drv._get_snapshot_path(existing_snapshot) get_existing_snapshot.return_value = { 'name': existing_name, 'path': existing_path, 'volume_name': volume_name, 'volume_size': volume_size } rename_snapshot.return_value = {} payload = {'source-name': existing_name} self.assertIsNone( self.drv.manage_existing_snapshot(manage_snapshot, payload) ) get_existing_snapshot.assert_called_with(manage_snapshot, payload) payload = {'newName': manage_name} rename_snapshot.assert_called_with(existing_path, payload)
def test__get_existing_snapshot(self, list_snapshots): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume name = snapshot['name'] path = self.drv._get_snapshot_path(snapshot) parent = self.drv._get_volume_path(volume) list_snapshots.return_value = [{ 'name': name, 'path': path }] payload = {'source-name': name} result = self.drv._get_existing_snapshot(snapshot, payload) payload = { 'parent': parent, 'fields': 'name,path', 'recursive': False, 'name': name } list_snapshots.assert_called_with(payload) expected = { 'name': name, 'path': path, 'volume_name': volume['name'], 'volume_size': volume['size'] } self.assertEqual(expected, result)
def test__get_volume_path(self): volume = fake_volume(self.ctxt) result = self.drv._get_volume_path(volume) expected = '%s/%s/%s' % (self.cfg.nexenta_volume, self.cfg.nexenta_volume_group, volume['name']) self.assertEqual(expected, result)
def test__get_volume_path(self): volume = fake_volume(self.ctxt) result = self.drv._get_volume_path(volume) expected = '%s/%s/%s' % (self.cfg.nexenta_volume, self.cfg.nexenta_volume_group, volume['name']) self.assertEqual(expected, result)
def test_extend_volume(self, extend_volume): volume = fake_volume(self.ctxt) size = volume['size'] * 2 self.assertIsNone(self.drv.extend_volume(volume, size)) path = self.drv._get_volume_path(volume) size = size * units.Gi payload = {'volumeSize': size} extend_volume.assert_called_with(path, payload)
def test_update_consistencygroup(self): cgroup = fake_cgroup(self.ctxt) volume1 = fake_volume(self.ctxt) volume2_spec = {'id': fake.VOLUME2_ID} volume2 = fake_volume(self.ctxt, **volume2_spec) volume3_spec = {'id': fake.VOLUME3_ID} volume3 = fake_volume(self.ctxt, **volume3_spec) volume4_spec = {'id': fake.VOLUME4_ID} volume4 = fake_volume(self.ctxt, **volume4_spec) add_volumes = [volume1, volume2] remove_volumes = [volume3, volume4] result = self.drv.update_consistencygroup(self.ctxt, cgroup, add_volumes, remove_volumes) expected = ({}, [], []) self.assertEqual(expected, result)
def test_local_path(self, get_local): volume = fake_volume(self.ctxt) local_dir = '/path/to' get_local.return_value = local_dir result = self.drv.local_path(volume) get_local.assert_called_with(volume) expected = os.path.join(local_dir, 'volume') self.assertEqual(expected, result)
def test_manage_existing(self, get_existing_volume, rename_volume): existing_volume = fake_volume(self.ctxt) manage_volume_spec = {'id': fake.VOLUME2_ID} manage_volume = fake_volume(self.ctxt, **manage_volume_spec) existing_name = existing_volume['name'] existing_path = self.drv._get_volume_path(existing_volume) manage_path = self.drv._get_volume_path(manage_volume) get_existing_volume.return_value = { 'name': existing_name, 'path': existing_path } rename_volume.return_value = {} payload = {'source-name': existing_name} self.assertIsNone(self.drv.manage_existing(manage_volume, payload)) get_existing_volume.assert_called_with(payload) payload = {'newPath': manage_path} rename_volume.assert_called_with(existing_path, payload)
def test_extend_volume(self, extend_volume): volume = fake_volume(self.ctxt) size = volume['size'] * 2 self.assertIsNone(self.drv.extend_volume(volume, size)) path = self.drv._get_volume_path(volume) size = size * units.Gi payload = {'volumeSize': size} extend_volume.assert_called_with(path, payload)
def test__get_snapshot_path(self): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume result = self.drv._get_snapshot_path(snapshot) expected = '%s/%s@%s' % (self.drv.root_path, snapshot['volume_name'], snapshot['name']) self.assertEqual(expected, result)
def test_create_consistencygroup_from_src_snapshots(self, create_volume): cgroup = fake_cgroup(self.ctxt) cgsnapshot = fake_cgsnapshot(self.ctxt) volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume snapshots = [snapshot] clone_spec = {'id': fake.VOLUME2_ID} clone = fake_volume(self.ctxt, **clone_spec) clones = [clone] create_volume.return_value = {} result = self.drv.create_consistencygroup_from_src(self.ctxt, cgroup, clones, cgsnapshot, snapshots, None, None) create_volume.assert_called_with(clone, snapshot) expected = ({}, []) self.assertEqual(expected, result)
def test_delete_volume(self, unmount_volume, delete_filesystem): volume = fake_volume(self.ctxt) path = self.drv._get_volume_path(volume) unmount_volume.return_value = {} delete_filesystem.return_value = {} self.assertIsNone(self.drv.delete_volume(volume)) unmount_volume.assert_called_with(volume) payload = {'force': True, 'snapshots': True} delete_filesystem.assert_called_with(path, payload)
def test__unmount_volume(self, get_share, unmount_share): volume = fake_volume(self.ctxt) mount_point = '/path/to/volume' share = '%s:%s' % (self.drv.nas_host, mount_point) get_share.return_value = share unmount_share.return_value = True self.assertIsNone(self.drv._unmount_volume(volume)) get_share.assert_called_with(volume) unmount_share.assert_called_with(share)
def test_delete_snapshot(self, delete_snapshot): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume delete_snapshot.return_value = {} self.assertIsNone(self.drv.delete_snapshot(snapshot)) path = self.drv._get_snapshot_path(snapshot) payload = {'defer': True} delete_snapshot.assert_called_with(path, payload)
def test_create_snapshot(self, create_snapshot): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume create_snapshot.return_value = {} self.assertIsNone(self.drv.create_snapshot(snapshot)) path = self.drv._get_snapshot_path(snapshot) payload = {'path': path} create_snapshot.assert_called_with(payload)
def test_terminate_connection(self, unmount_volume): unmount_volume.return_value = True volume = fake_volume(self.ctxt) connector = { 'initiator': 'iqn:cinder-client', 'multipath': True } self.assertIsNone(self.drv.terminate_connection(volume, connector)) unmount_volume.assert_called_with(volume)
def test__local_volume_dir(self, get_share): volume = fake_volume(self.ctxt) share = '1.1.1.1:/path/to/share' get_share.return_value = share result = self.drv._local_volume_dir(volume) get_share.assert_called_with(volume) share = share.encode('utf-8') digest = hashlib.md5(share).hexdigest() expected = os.path.join(self.cfg.nexenta_mount_point_base, digest) self.assertEqual(expected, result)
def test_revert_to_snapshot(self, rollback_volume): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume rollback_volume.return_value = {} self.assertIsNone( self.drv.revert_to_snapshot(self.ctxt, volume, snapshot)) path = self.drv._get_volume_path(volume) payload = {'snapshot': snapshot['name']} rollback_volume.assert_called_with(path, payload)
def test_manage_existing_get_size(self, get_volume): volume = fake_volume(self.ctxt) name = volume['name'] size = volume['size'] path = self.drv._get_volume_path(volume) get_volume.return_value = {'name': name, 'path': path, 'size': size} payload = {'source-name': name} result = self.drv.manage_existing_get_size(volume, payload) expected = size self.assertEqual(expected, result)
def test__get_volume_share(self, get_filesystem): volume = fake_volume(self.ctxt) path = self.drv._get_volume_path(volume) mount_point = '/path/to' get_filesystem.return_value = {'mountPoint': mount_point} result = self.drv._get_volume_share(volume) payload = {'fields': 'mountPoint'} get_filesystem.assert_called_with(path, payload) expected = '%s:%s' % (self.drv.nas_host, mount_point) self.assertEqual(expected, result)
def test_revert_to_snapshot(self, rollback_volume): volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume rollback_volume.return_value = {} self.assertIsNone( self.drv.revert_to_snapshot(self.ctxt, volume, snapshot) ) path = self.drv._get_volume_path(volume) payload = {'snapshot': snapshot['name']} rollback_volume.assert_called_with(path, payload)
def test_delete_cgsnapshot(self, delete_snapshot): cgsnapshot = fake_cgsnapshot(self.ctxt) volume = fake_volume(self.ctxt) snapshot = fake_snapshot(self.ctxt) snapshot.volume = volume snapshots = [snapshot] delete_snapshot.return_value = {} result = self.drv.delete_cgsnapshot(self.ctxt, cgsnapshot, snapshots) delete_snapshot.assert_called_with(snapshot) expected = ({}, []) self.assertEqual(expected, result)
def test_migrate_volume(self, create_service, start_service, get_service, delete_service, delete_volume): create_service.return_value = {} start_service.return_value = {} get_service.return_value = { 'state': 'disabled' } delete_service.return_value = {} delete_volume.return_value = {} volume = fake_volume(self.ctxt) dst_host = '4.4.4.4' dst_port = 8443 dst_path = 'tank/nfs' location_info = 'NexentaNfsDriver:%s:/%s' % (dst_host, dst_path) host = { 'host': 'stack@nexenta_nfs#fake_nfs', 'capabilities': { 'vendor_name': 'Nexenta', 'nef_url': dst_host, 'nef_port': dst_port, 'storage_protocol': 'NFS', 'free_capacity_gb': 32, 'location_info': location_info } } result = self.drv.migrate_volume(self.ctxt, volume, host) expected = (True, None) svc = 'cinder-migrate-%s' % volume['name'] src = self.drv._get_volume_path(volume) dst = '%s/%s' % (dst_path, volume['name']) payload = { 'name': svc, 'sourceDataset': src, 'destinationDataset': dst, 'type': 'scheduled', 'sendShareNfs': True, 'isSource': True, 'remoteNode': { 'host': dst_host, 'port': dst_port } } create_service.assert_called_with(payload) start_service.assert_called_with(svc) get_service.assert_called_with(svc) payload = { 'destroySourceSnapshots': True, 'destroyDestinationSnapshots': True } delete_service.assert_called_with(svc, payload) delete_volume.assert_called_with(volume) self.assertEqual(expected, result)
def test__set_volume_acl(self, set_acl): volume = fake_volume(self.ctxt) set_acl.return_value = {} path = self.drv._get_volume_path(volume) payload = { 'type': 'allow', 'principal': 'everyone@', 'permissions': ['full_set'], 'flags': ['file_inherit', 'dir_inherit'] } self.assertIsNone(self.drv._set_volume_acl(volume)) set_acl.assert_called_with(path, payload)
def test_delete_cgsnapshot(self, delete_snapshot): cgsnapshot = fake_cgsnapshot(self.ctxt) snapshot = fake_snapshot(self.ctxt) volume = fake_volume(self.ctxt) snapshot.volume = volume snapshots = [snapshot] delete_snapshot.return_value = {} result = self.drv.delete_cgsnapshot(self.ctxt, cgsnapshot, snapshots) delete_snapshot.assert_called_with(snapshot) expected = ({}, []) self.assertEqual(expected, result)
def test_manage_existing_get_size(self, get_volume): volume = fake_volume(self.ctxt) name = volume['name'] size = volume['size'] path = self.drv._get_volume_path(volume) get_volume.return_value = { 'name': name, 'path': path, 'size': size } payload = {'source-name': name} result = self.drv.manage_existing_get_size(volume, payload) expected = size self.assertEqual(expected, result)
def test__mount_volume(self, get_filesystem, mount_share): volume = fake_volume(self.ctxt) mount_point = '/path/to/volume' get_filesystem.return_value = { 'mountPoint': mount_point, 'isMounted': True } mount_share.return_value = True self.assertIsNone(self.drv._mount_volume(volume)) path = self.drv._get_volume_path(volume) payload = {'fields': 'mountPoint,isMounted'} get_filesystem.assert_called_with(path, payload) share = '%s:%s' % (self.drv.nas_host, mount_point) mount_share.assert_called_with(share)