Exemplo n.º 1
0
    def test_obj_load_attr(self, mock_va_get_all_by_vol, mock_vt_get_by_id, mock_admin_metadata_get, mock_metadata_get):
        volume = objects.Volume._from_db_object(self.context, objects.Volume(), fake_volume.fake_db_volume())

        # Test metadata lazy-loaded field
        metadata = {"foo": "bar"}
        mock_metadata_get.return_value = metadata
        self.assertEqual(metadata, volume.metadata)
        mock_metadata_get.assert_called_once_with(self.context, volume.id)

        # Test volume_type lazy-loaded field
        volume_type = objects.VolumeType(context=self.context, id=5)
        mock_vt_get_by_id.return_value = volume_type
        self.assertEqual(volume_type, volume.volume_type)
        mock_vt_get_by_id.assert_called_once_with(self.context, volume.volume_type_id)

        # Test volume_attachment lazy-loaded field
        va_objs = [objects.VolumeAttachment(context=self.context, id=i) for i in [3, 4, 5]]
        va_list = objects.VolumeAttachmentList(context=self.context, objects=va_objs)
        mock_va_get_all_by_vol.return_value = va_list
        self.assertEqual(va_list, volume.volume_attachment)
        mock_va_get_all_by_vol.assert_called_once_with(self.context, volume.id)

        # Test admin_metadata lazy-loaded field - user context
        adm_metadata = {"bar": "foo"}
        mock_admin_metadata_get.return_value = adm_metadata
        self.assertEqual({}, volume.admin_metadata)
        self.assertFalse(mock_admin_metadata_get.called)

        # Test admin_metadata lazy-loaded field - admin context
        adm_context = self.context.elevated()
        volume = objects.Volume._from_db_object(adm_context, objects.Volume(), fake_volume.fake_db_volume())
        adm_metadata = {"bar": "foo"}
        mock_admin_metadata_get.return_value = adm_metadata
        self.assertEqual(adm_metadata, volume.admin_metadata)
        mock_admin_metadata_get.assert_called_once_with(adm_context, volume.id)
Exemplo n.º 2
0
    def test_finish_volume_migration(self, volume_update, metadata_update):
        src_volume_db = fake_volume.fake_db_volume(**{'id': fake.volume_id})
        dest_volume_db = fake_volume.fake_db_volume(**{'id': fake.volume2_id})
        src_volume = objects.Volume._from_db_object(
            self.context, objects.Volume(), src_volume_db,
            expected_attrs=['metadata', 'glance_metadata'])
        dest_volume = objects.Volume._from_db_object(
            self.context, objects.Volume(), dest_volume_db,
            expected_attrs=['metadata', 'glance_metadata'])
        updated_dest_volume = src_volume.finish_volume_migration(
            dest_volume)
        self.assertEqual('deleting', updated_dest_volume.migration_status)
        self.assertEqual('migration src for ' + src_volume.id,
                         updated_dest_volume.display_description)
        self.assertEqual(src_volume.id, updated_dest_volume._name_id)
        self.assertTrue(volume_update.called)

        # Ignore these attributes, since they were updated by
        # finish_volume_migration
        ignore_keys = ('id', 'provider_location', '_name_id',
                       'migration_status', 'display_description', 'status')
        dest_vol_filtered = {k: v for k, v in updated_dest_volume.iteritems()
                             if k not in ignore_keys}
        src_vol_filtered = {k: v for k, v in src_volume.iteritems()
                            if k not in ignore_keys}
        self.assertEqual(src_vol_filtered, dest_vol_filtered)
Exemplo n.º 3
0
    def test_get_by_project_with_sort_key(self, sort_keys):
        fake_volume.fake_db_volume()

        self.assertRaises(exception.InvalidInput,
                          objects.VolumeList.get_all_by_project,
                          self.context,
                          self.context.project_id,
                          sort_keys=sort_keys)
Exemplo n.º 4
0
    def test_restore_backup(self, arg1):
        """Test restore_backup."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc_vol = self.driver.create_volume(volume)
        volume['provider_location'] = rc_vol['provider_location']

        volume_backup = fake_volume.fake_db_volume(**self._VOLUME_BACKUP)
        self.driver.restore_backup(None, volume_backup, volume, None)
        arg1.assert_called_with(None, volume_backup, volume, None)
Exemplo n.º 5
0
    def test_create_cloned_volume_error_on_non_existing_volume(self):
        """Test create_cloned_volume is error on non existing volume."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        volume['provider_location'] = '1'
        volume2 = fake_volume.fake_db_volume(**self._VOLUME2)

        self.assertRaises(exception.VolumeBackendAPIException,
                          self.driver.create_cloned_volume,
                          volume2, volume)
Exemplo n.º 6
0
    def test_create_volume_error_on_no_available_ldev(self):
        """Test create_volume is error on no available ldev."""
        for i in range(1, 1024):
            volume = fake_volume.fake_db_volume(**self._VOLUME)
            rc = self.driver.create_volume(volume)
            self.assertEqual(str(i), rc['provider_location'])

        volume = fake_volume.fake_db_volume(**self._VOLUME)
        self.assertRaises(exception.VolumeBackendAPIException,
                          self.driver.create_volume, volume)
Exemplo n.º 7
0
    def test_restore_backup_error(self, arg1):
        """Test restore_backup is error."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        volume['provider_location'] = '1'

        volume_backup = fake_volume.fake_db_volume(**self._VOLUME_BACKUP)

        self.assertRaises(exception.CinderException,
                          self.driver.restore_backup,
                          None, volume_backup, volume, None)
        arg1.assert_called_with(None, volume_backup, volume, None)
Exemplo n.º 8
0
    def test_create_cloned_volume_error_on_diff_size(self):
        """Test create_cloned_volume is error on different size."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc_vol = self.driver.create_volume(volume)
        volume['provider_location'] = rc_vol['provider_location']

        volume3 = fake_volume.fake_db_volume(**self._VOLUME3)

        self.assertRaises(exception.VolumeBackendAPIException,
                          self.driver.create_cloned_volume,
                          volume3, volume)
Exemplo n.º 9
0
    def test_finish_volume_migration(self, volume_update, metadata_update,
                                     src_vol_type_id, dest_vol_type_id,
                                     src_vol_status=None):
        src_volume_db = fake_volume.fake_db_volume(
            **{'id': fake.VOLUME_ID, 'volume_type_id': src_vol_type_id})
        if src_vol_type_id:
            src_volume_db['volume_type'] = fake_volume.fake_db_volume_type(
                id=src_vol_type_id)
        if src_vol_status:
            src_volume_db['status'] = src_vol_status

        dest_volume_db = fake_volume.fake_db_volume(
            **{'id': fake.VOLUME2_ID, 'volume_type_id': dest_vol_type_id})
        if dest_vol_type_id:
            dest_volume_db['volume_type'] = fake_volume.fake_db_volume_type(
                id=dest_vol_type_id)
        expected_attrs = objects.Volume._get_expected_attrs(self.context)
        src_volume = objects.Volume._from_db_object(
            self.context, objects.Volume(), src_volume_db,
            expected_attrs=expected_attrs)
        dest_volume = objects.Volume._from_db_object(
            self.context, objects.Volume(), dest_volume_db,
            expected_attrs=expected_attrs)
        updated_dest_volume = src_volume.finish_volume_migration(
            dest_volume)
        self.assertEqual('deleting', updated_dest_volume.migration_status)
        self.assertEqual('migration src for ' + src_volume.id,
                         updated_dest_volume.display_description)
        self.assertEqual(src_volume.id, updated_dest_volume._name_id)
        self.assertTrue(volume_update.called)
        volume_update.assert_has_calls([
            mock.call(self.context, src_volume.id, mock.ANY),
            mock.call(self.context, dest_volume.id, mock.ANY)])
        ctxt, vol_id, updates = volume_update.call_args[0]

        if src_vol_status and src_vol_status == 'retyping':
            self.assertIn('volume_type', updates)
        else:
            self.assertNotIn('volume_type', updates)

        # Ensure that the destination volume type has not been overwritten
        self.assertEqual(dest_vol_type_id,
                         getattr(updated_dest_volume, 'volume_type_id'))
        # Ignore these attributes, since they were updated by
        # finish_volume_migration
        ignore_keys = ('id', 'provider_location', '_name_id',
                       'migration_status', 'display_description', 'status',
                       'volume_glance_metadata', 'volume_type')

        dest_vol_dict = {k: updated_dest_volume[k] for k in
                         updated_dest_volume.keys() if k not in ignore_keys}
        src_vol_dict = {k: src_volume[k] for k in src_volume.keys()
                        if k not in ignore_keys}
        self.assertEqual(src_vol_dict, dest_vol_dict)
Exemplo n.º 10
0
    def test_copy_volume_data(self, arg1):
        """Test copy_volume_data."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc_vol = self.driver.create_volume(volume)
        volume['provider_location'] = rc_vol['provider_location']

        volume2 = fake_volume.fake_db_volume(**self._VOLUME2)
        rc_vol2 = self.driver.create_volume(volume2)
        volume2['provider_location'] = rc_vol2['provider_location']

        self.driver.copy_volume_data(None, volume, volume2, None)

        arg1.assert_called_with(None, volume, volume2, None)
Exemplo n.º 11
0
    def test_create_cloned_volume(self):
        """Test create_cloned_volume."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc_vol = self.driver.create_volume(volume)
        volume['provider_location'] = rc_vol['provider_location']

        volume2 = fake_volume.fake_db_volume(**self._VOLUME2)
        rc = self.driver.create_cloned_volume(volume2, volume)

        volume2['provider_location'] = rc['provider_location']

        has_volume = self.driver.common.volume_exists(volume2)
        self.assertTrue(has_volume)
Exemplo n.º 12
0
    def test_create_volume_from_snapshot_error_on_diff_size(self):
        """Test create_volume_from_snapshot is error on different size."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        self.driver.create_volume(volume)

        snapshot = fake_snapshot.fake_db_snapshot(**self._TEST_SNAPSHOT)
        rc_snap = self.driver.create_snapshot(snapshot)
        snapshot['provider_location'] = rc_snap['provider_location']

        volume3 = fake_volume.fake_db_volume(**self._VOLUME3)

        self.assertRaises(exception.VolumeBackendAPIException,
                          self.driver.create_volume_from_snapshot,
                          volume3, snapshot)
Exemplo n.º 13
0
    def test_copy_volume_data_error(self, arg1):
        """Test copy_volume_data is error."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc_vol = self.driver.create_volume(volume)
        volume['provider_location'] = rc_vol['provider_location']

        volume2 = fake_volume.fake_db_volume(**self._VOLUME2)
        volume2['provider_location'] = '2'

        self.assertRaises(exception.CinderException,
                          self.driver.copy_volume_data,
                          None, volume, volume2, None)

        arg1.assert_called_with(None, volume, volume2, None)
Exemplo n.º 14
0
    def test_create_volume_from_snapshot(self):
        """Test create_volume_from_snapshot."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        self.driver.create_volume(volume)

        snapshot = fake_snapshot.fake_db_snapshot(**self._TEST_SNAPSHOT)
        rc_snap = self.driver.create_snapshot(snapshot)
        snapshot['provider_location'] = rc_snap['provider_location']

        volume2 = fake_volume.fake_db_volume(**self._VOLUME2)
        rc = self.driver.create_volume_from_snapshot(volume2, snapshot)
        volume2['provider_location'] = rc['provider_location']

        has_volume = self.driver.common.volume_exists(volume2)
        self.assertTrue(has_volume)
Exemplo n.º 15
0
    def test_extend_volume_error_on_non_existing_volume(self):
        """Test extend_volume is error on non existing volume."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        volume['provider_location'] = '1'

        self.assertRaises(exception.VolumeBackendAPIException,
                          self.driver.extend_volume, volume, 256)
Exemplo n.º 16
0
    def test_obj_load_attr_group_not_exist(self, mock_group_get_by_id):
        fake_db_volume = fake_volume.fake_db_volume(group_id=None)
        volume = objects.Volume._from_db_object(
            self.context, objects.Volume(), fake_db_volume)

        self.assertIsNone(volume.group)
        mock_group_get_by_id.assert_not_called()
Exemplo n.º 17
0
    def test_manage_existing_with_none_sourceid(self):
        """Test manage_existing is error with no source-id."""
        existing_ref = {'source-id': None}
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc = self.driver.manage_existing(volume, existing_ref)

        self.assertIsNone(rc['provider_location'])
Exemplo n.º 18
0
    def test_manage_existing_snapshot(self, mock_can_send_version):
        volume_update = {'host': 'fake_host'}
        snpshot = {
            'id': fake.snapshot_id,
            'volume_id': fake.volume_id,
            'status': "creating",
            'progress': '0%',
            'volume_size': 0,
            'display_name': 'fake_name',
            'display_description': 'fake_description',
            'volume': fake_volume.fake_db_volume(**volume_update),
            'expected_attrs': ['volume'], }
        my_fake_snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context,
                                                               **snpshot)
        self._test_volume_api('manage_existing_snapshot',
                              rpc_method='cast',
                              snapshot=my_fake_snapshot_obj,
                              ref='foo',
                              host='fake_host',
                              version='2.0')

        mock_can_send_version.return_value = False
        self._test_volume_api('manage_existing_snapshot',
                              rpc_method='cast',
                              snapshot=my_fake_snapshot_obj,
                              ref='foo',
                              host='fake_host',
                              version='1.28')
Exemplo n.º 19
0
 def test_manage_existing_get_size(self):
     """Test manage_existing_get_size."""
     existing_ref = {'source-id': '101'}
     volume = fake_volume.fake_db_volume(**self._VOLUME)
     return_size = self.driver.manage_existing_get_size(
         volume, existing_ref)
     self.assertEqual(EXISTING_POOL_REF['101']['size'], return_size)
Exemplo n.º 20
0
 def test_destroy(self, volume_destroy):
     db_volume = fake_volume.fake_db_volume()
     volume = objects.Volume._from_db_object(self.context, objects.Volume(), db_volume)
     volume.destroy()
     self.assertTrue(volume_destroy.called)
     admin_context = volume_destroy.call_args[0][0]
     self.assertTrue(admin_context.is_admin)
Exemplo n.º 21
0
 def test_manage_existing_get_size_with_none_sourceid(self):
     """Test manage_existing_get_size is error with no source-id."""
     existing_ref = {'source-id': None}
     volume = fake_volume.fake_db_volume(**self._VOLUME)
     self.assertRaises(exception.ManageExistingInvalidReference,
                       self.driver.manage_existing_get_size,
                       volume, existing_ref)
Exemplo n.º 22
0
 def test_save_with_glance_metadata(self):
     db_volume = fake_volume.fake_db_volume()
     volume = objects.Volume._from_db_object(self.context,
                                             objects.Volume(), db_volume)
     volume.display_name = 'foobar'
     volume.glance_metadata = {'key1': 'value1'}
     self.assertRaises(exception.ObjectActionError, volume.save)
Exemplo n.º 23
0
 def test_save_with_consistencygroup(self):
     db_volume = fake_volume.fake_db_volume()
     volume = objects.Volume._from_db_object(self.context,
                                             objects.Volume(), db_volume)
     volume.display_name = 'foobar'
     volume.consistencygroup = objects.ConsistencyGroup()
     self.assertRaises(exception.ObjectActionError, volume.save)
Exemplo n.º 24
0
 def test_save_with_snapshots(self):
     db_volume = fake_volume.fake_db_volume()
     volume = objects.Volume._from_db_object(self.context,
                                             objects.Volume(), db_volume)
     volume.display_name = 'foobar'
     volume.snapshots = objects.SnapshotList()
     self.assertRaises(exception.ObjectActionError, volume.save)
Exemplo n.º 25
0
    def test_migrate_volume_generic_for_clone(self, volume_get,
                                              migrate_volume_completion,
                                              nova_api, create_volume, save):
        def fake_create_volume(*args, **kwargs):
            context, volume, request_spec, filter_properties = args
            fake_db = mock.Mock()
            task = create_volume_manager.ExtractVolumeSpecTask(fake_db)
            specs = task.execute(context, volume, {})
            self.assertEqual('raw', specs['type'])

        def fake_copy_volume_data_with_chk_param(*args, **kwargs):
            context, src, dest = args
            self.assertEqual(src['source_volid'], dest['source_volid'])

        fake_db_new_volume = {'status': 'available', 'id': fake.VOLUME_ID}
        fake_new_volume = fake_volume.fake_db_volume(**fake_db_new_volume)
        host_obj = {'host': 'newhost', 'capabilities': {}}
        volume_get.return_value = fake_new_volume

        clone = tests_utils.create_volume(self.context, size=1,
                                          host=CONF.host)
        clone['source_volid'] = fake.VOLUME2_ID
        create_volume.side_effect = fake_create_volume

        with mock.patch.object(self.volume, '_copy_volume_data') as \
                mock_copy_volume:
            mock_copy_volume.side_effect = fake_copy_volume_data_with_chk_param
            self.volume._migrate_volume_generic(self.context, clone,
                                                host_obj, None)
Exemplo n.º 26
0
    def test_manage_existing(self):
        """Test manage_existing."""
        existing_ref = {'source-id': '101'}
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc = self.driver.manage_existing(volume, existing_ref)

        self.assertEqual('101', rc['provider_location'])
Exemplo n.º 27
0
    def test_get_by_group(self, get_all_by_group):
        db_volume = fake_volume.fake_db_volume()
        get_all_by_group.return_value = [db_volume]

        volumes = objects.VolumeList.get_all_by_group(self.context, "fake-host")
        self.assertEqual(1, len(volumes))
        TestVolume._compare(self, db_volume, volumes[0])
Exemplo n.º 28
0
    def test_from_db_object_with_all_expected_attributes(self):
        expected_attrs = ['metadata', 'admin_metadata', 'glance_metadata',
                          'volume_type', 'volume_attachment',
                          'consistencygroup']

        db_metadata = [{'key': 'foo', 'value': 'bar'}]
        db_admin_metadata = [{'key': 'admin_foo', 'value': 'admin_bar'}]
        db_glance_metadata = [{'key': 'glance_foo', 'value': 'glance_bar'}]
        db_volume_type = fake_volume.fake_db_volume_type()
        db_volume_attachments = fake_volume.fake_db_volume_attachment()
        db_consistencygroup = fake_consistencygroup.fake_db_consistencygroup()
        db_snapshots = fake_snapshot.fake_db_snapshot()

        db_volume = fake_volume.fake_db_volume(
            volume_metadata=db_metadata,
            volume_admin_metadata=db_admin_metadata,
            volume_glance_metadata=db_glance_metadata,
            volume_type=db_volume_type,
            volume_attachment=[db_volume_attachments],
            consistencygroup=db_consistencygroup,
            snapshots=[db_snapshots],
        )
        volume = objects.Volume._from_db_object(self.context, objects.Volume(),
                                                db_volume, expected_attrs)

        self.assertEqual({'foo': 'bar'}, volume.metadata)
        self.assertEqual({'admin_foo': 'admin_bar'}, volume.admin_metadata)
        self.assertEqual({'glance_foo': 'glance_bar'}, volume.glance_metadata)
        self._compare(self, db_volume_type, volume.volume_type)
        self._compare(self, db_volume_attachments, volume.volume_attachment)
        self._compare(self, db_consistencygroup, volume.consistencygroup)
        self._compare(self, db_snapshots, volume.snapshots)
Exemplo n.º 29
0
    def test_delete_volume_on_non_existing_volume(self):
        """Test delete_volume on non existing volume."""
        volume = fake_volume.fake_db_volume(**self._VOLUME)
        volume['provider_location'] = '1'
        has_volume = self.driver.common.volume_exists(volume)
        self.assertFalse(has_volume)

        self.driver.delete_volume(volume)
Exemplo n.º 30
0
 def test_save(self, volume_update):
     db_volume = fake_volume.fake_db_volume()
     volume = objects.Volume._from_db_object(self.context,
                                             objects.Volume(), db_volume)
     volume.display_name = 'foobar'
     volume.save()
     volume_update.assert_called_once_with(self.context, volume.id,
                                           {'display_name': 'foobar'})
Exemplo n.º 31
0
 def test_create_snapshot(self, volume_get):
     with mock.patch.object(self.driver, "_rpc_call",
                            self.jsonrpcclient.call):
         db_volume = fake_volume.fake_db_volume()
         db_volume['name'] = "lvs_test/lvol0"
         ctxt = context.get_admin_context()
         db_volume = objects.Volume._from_db_object(ctxt, objects.Volume(),
                                                    db_volume)
         volume_get.return_value = db_volume
         snapshot = {}
         snapshot['volume_id'] = db_volume['id']
         snapshot['name'] = "snapshot0"
         snapshot['volume'] = db_volume
         for bdev in self.jsonrpcclient.bdevs:
             if bdev['aliases'][-1] == "lvs_test/lvol0":
                 bdev['aliases'].append(db_volume.name)
         self.driver.create_snapshot(snapshot)
         bdev = self.driver._get_spdk_volume_name("lvs_test/snapshot0")
         self.assertEqual("58b17014-d4a1-4f85-9761-093643ed18f2", bdev)
Exemplo n.º 32
0
    def test_initialize_connection(self):
        """Test initialize_connection."""
        connector = {
            'wwpns': ['12345678912345aa', '12345678912345bb'],
            'ip': '127.0.0.1'
        }

        volume = fake_volume.fake_db_volume(**self._VOLUME)
        rc_vol = self.driver.create_volume(volume)
        volume['provider_location'] = rc_vol['provider_location']
        conn_info = self.driver.initialize_connection(volume, connector)
        self.assertIn('data', conn_info)
        self.assertIn('initiator_target_map', conn_info['data'])

        is_attached = self.driver.common.is_volume_attached(volume, connector)
        self.assertTrue(is_attached)

        self.driver.terminate_connection(volume, connector)
        self.driver.delete_volume(volume)
Exemplo n.º 33
0
    def test_save_with_admin_metadata(self, volume_update,
                                      admin_metadata_update):
        # Test with no admin context
        db_volume = fake_volume.fake_db_volume()
        volume = objects.Volume._from_db_object(self.context,
                                                objects.Volume(), db_volume)
        volume.admin_metadata = {'key1': 'value1'}
        volume.save()
        self.assertFalse(admin_metadata_update.called)

        # Test with admin context
        admin_context = context.RequestContext(self.user_id, self.project_id,
                                               is_admin=True)
        volume = objects.Volume._from_db_object(admin_context,
                                                objects.Volume(), db_volume)
        volume.admin_metadata = {'key1': 'value1'}
        volume.save()
        admin_metadata_update.assert_called_once_with(
            admin_context, volume.id, {'key1': 'value1'}, True)
Exemplo n.º 34
0
 def test_volume_attached(self, volume_attached):
     attachment = fake_volume.volume_attachment_ovo(self.context)
     updated_values = {
         'mountpoint': '/dev/sda',
         'attach_status': fields.VolumeAttachStatus.ATTACHED,
         'instance_uuid': fake.INSTANCE_ID
     }
     volume_attached.return_value = (fake_volume.fake_db_volume(),
                                     updated_values)
     volume = attachment.finish_attach(fake.INSTANCE_ID, 'fake_host',
                                       '/dev/sda', 'rw')
     self.assertIsInstance(volume, objects.Volume)
     volume_attached.assert_called_once_with(mock.ANY, attachment.id,
                                             fake.INSTANCE_ID, 'fake_host',
                                             '/dev/sda', 'rw', True)
     self.assertEqual('/dev/sda', attachment.mountpoint)
     self.assertEqual(fake.INSTANCE_ID, attachment.instance_uuid)
     self.assertEqual(fields.VolumeAttachStatus.ATTACHED,
                      attachment.attach_status)
Exemplo n.º 35
0
    def test_create_from_image_no_internal_context(
            self, mock_get_internal_context, mock_create_from_img_dl,
            mock_create_from_src, mock_handle_bootable, mock_fetch_img):
        self.mock_driver.clone_image.return_value = (None, False)
        mock_get_internal_context.return_value = None
        volume = fake_volume.fake_db_volume()

        image_location = 'someImageLocationStr'
        image_id = 'c7a8b8d4-e519-46c7-a0df-ddf1b9b9fff2'
        image_meta = {'properties': {'virtual_size': '2147483648'}}

        manager = create_volume_manager.CreateVolumeFromSpecTask(
            self.mock_volume_manager,
            self.mock_db,
            self.mock_driver,
            image_volume_cache=self.mock_cache)

        manager._create_from_image(self.ctxt, volume, image_location, image_id,
                                   image_meta, self.mock_image_service)

        # Make sure clone_image is always called
        self.assertTrue(self.mock_driver.clone_image.called)

        # Create from source shouldn't happen if cache cannot be used.
        self.assertFalse(mock_create_from_src.called)

        # The image download should happen if clone fails and we can't use the
        # image-volume cache due to not having an internal context available.
        mock_create_from_img_dl.assert_called_once_with(
            self.ctxt, volume, image_location, image_id,
            self.mock_image_service)

        # This should not attempt to use a minimal size volume
        self.assertFalse(self.mock_db.volume_update.called)

        # Make sure we didn't try and create a cache entry
        self.assertFalse(self.mock_cache.ensure_space.called)
        self.assertFalse(self.mock_cache.create_cache_entry.called)

        mock_handle_bootable.assert_called_once_with(self.ctxt,
                                                     volume['id'],
                                                     image_id=image_id,
                                                     image_meta=image_meta)
Exemplo n.º 36
0
    def test_create_from_snapshot(self, snapshot_get_by_id, handle_bootable):
        fake_db = mock.MagicMock()
        fake_driver = mock.MagicMock()
        fake_volume_manager = mock.MagicMock()
        fake_manager = create_volume_manager.CreateVolumeFromSpecTask(
            fake_volume_manager, fake_db, fake_driver)
        volume = fake_volume.fake_db_volume()
        orig_volume_db = mock.MagicMock(id=10, bootable=True)
        snapshot_obj = fake_snapshot.fake_snapshot_obj(self.ctxt)
        snapshot_get_by_id.return_value = snapshot_obj
        fake_db.volume_get.return_value = orig_volume_db

        fake_manager._create_from_snapshot(self.ctxt, volume,
                                           snapshot_obj.id)
        fake_driver.create_volume_from_snapshot.assert_called_once_with(
            volume, snapshot_obj)
        fake_db.volume_get.assert_called_once_with(self.ctxt,
                                                   snapshot_obj.volume_id)
        handle_bootable.assert_called_once_with(self.ctxt, volume['id'],
                                                snapshot_id=snapshot_obj.id)
Exemplo n.º 37
0
 def test_manage_existing_snapshot(self):
     volume_update = {'host': 'fake_host'}
     snpshot = {
         'id': fake.SNAPSHOT_ID,
         'volume_id': fake.VOLUME_ID,
         'status': fields.SnapshotStatus.CREATING,
         'progress': '0%',
         'volume_size': 0,
         'display_name': 'fake_name',
         'display_description': 'fake_description',
         'volume': fake_volume.fake_db_volume(**volume_update),
         'expected_attrs': ['volume'], }
     my_fake_snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context,
                                                            **snpshot)
     self._test_volume_api('manage_existing_snapshot',
                           rpc_method='cast',
                           snapshot=my_fake_snapshot_obj,
                           ref='foo',
                           host='fake_host',
                           version='3.0')
Exemplo n.º 38
0
 def test_manage_existing_snapshot(self):
     volume_update = {'host': 'fake_host'}
     snpshot = {
         'id': 1,
         'volume_id': 'fake_id',
         'status': "creating",
         'progress': '0%',
         'volume_size': 0,
         'display_name': 'fake_name',
         'display_description': 'fake_description',
         'volume': fake_volume.fake_db_volume(**volume_update),
         'expected_attrs': ['volume'], }
     my_fake_snapshot_obj = fake_snapshot.fake_snapshot_obj(self.context,
                                                            **snpshot)
     self._test_volume_api('manage_existing_snapshot',
                           rpc_method='cast',
                           snapshot=my_fake_snapshot_obj,
                           ref='foo',
                           host='fake_host',
                           version='1.28')
    def test_refresh(self, volume_get, volume_metadata_get):
        db_volume1 = fake_volume.fake_db_volume()
        db_volume2 = db_volume1.copy()
        db_volume2['display_name'] = 'foobar'

        # On the second volume_get, return the volume with an updated
        # display_name
        volume_get.side_effect = [db_volume1, db_volume2]
        volume = objects.Volume.get_by_id(self.context, '1')
        self._compare(self, db_volume1, volume)

        # display_name was updated, so a volume refresh should have a new value
        # for that field
        volume.refresh()
        self._compare(self, db_volume2, volume)
        volume_get.assert_has_calls([
            mock.call(self.context, '1'),
            mock.call.__nonzero__(),
            mock.call(self.context, '1')
        ])
Exemplo n.º 40
0
    def test_get_volume_format_spec(self, volume_versioned_object,
                                    volume_meta_contains_fmt,
                                    volume_type_contains_fmt):
        fake_vol_meta_fmt = 'vhd'
        fake_vol_type_fmt = 'vhdx'

        volume_metadata = {}
        volume_type_extra_specs = {}

        fake_vol_dict = fake_volume.fake_db_volume()
        del fake_vol_dict['name']

        if volume_meta_contains_fmt:
            volume_metadata['volume_format'] = fake_vol_meta_fmt
        elif volume_type_contains_fmt:
            volume_type_extra_specs['smbfs:volume_format'] = fake_vol_type_fmt

        ctxt = context.get_admin_context()
        volume_type = db.volume_type_create(
            ctxt, {'extra_specs': volume_type_extra_specs,
                   'name': 'fake_vol_type'})
        fake_vol_dict.update(metadata=volume_metadata,
                             volume_type_id=volume_type.id)
        # We want to get a 'real' SqlA model object, not just a dict.
        volume = db.volume_create(ctxt, fake_vol_dict)
        volume = db.volume_get(ctxt, volume.id)

        if volume_versioned_object:
            volume = objects.Volume._from_db_object(ctxt, objects.Volume(),
                                                    volume)

        resulted_fmt = self._smbfs_driver._get_volume_format_spec(volume)

        if volume_meta_contains_fmt:
            expected_fmt = fake_vol_meta_fmt
        elif volume_type_contains_fmt:
            expected_fmt = fake_vol_type_fmt
        else:
            expected_fmt = None

        self.assertEqual(expected_fmt, resulted_fmt)
Exemplo n.º 41
0
    def test_create_backup_no_service(self, mock_volume_update,
                                      mock_volume_get, mock_host, mock_error):
        volume = fake_volume.fake_db_volume()
        volume['status'] = 'backing-up'
        volume['previous_status'] = 'available'
        mock_volume_get.return_value = volume
        mock_host.side_effect = exception.ServiceNotFound(
            service_id='cinder-volume')
        backup = fake_backup.fake_backup_obj(self.context)

        self.manager.create_backup(self.context, backup=backup)

        mock_host.assert_called_once_with(volume)
        mock_volume_get.assert_called_once_with(self.context, backup.volume_id)
        mock_volume_update.assert_called_once_with(
            self.context, backup.volume_id, {
                'status': 'available',
                'previous_status': 'backing-up'
            })
        mock_error.assert_called_once_with(
            backup, 'Service not found for creating backup.')
Exemplo n.º 42
0
 def test_save(self, test_cg, ovo, expected, volume_update):
     use_quota = ovo.pop('use_quota', None)
     db_volume = fake_volume.fake_db_volume(**ovo)
     # TODO: (Y release) remove expected_attrs
     if 'volume_admin_metadata' in ovo:
         expected_attrs = ['admin_metadata']
     else:
         expected_attrs = []
     volume = objects.Volume._from_db_object(self.context,
                                             objects.Volume(), db_volume,
                                             expected_attrs=expected_attrs)
     volume.display_name = 'foobar'
     if test_cg:
         volume.consistencygroup = None
     # TODO: (Y release) remove next 2 lines
     if use_quota is not None:
         volume.use_quota = use_quota
     volume.save()
     # TODO: (Y release) remove use_quota
     volume_update.assert_called_once_with(self.context, volume.id,
                                           {'display_name': 'foobar',
                                            'use_quota': expected})
Exemplo n.º 43
0
 def test_migrate_volume_generic(self, volume_get,
                                 migrate_volume_completion,
                                 nova_api):
     fake_db_new_volume = {'status': 'available', 'id': fake.VOLUME_ID}
     fake_new_volume = fake_volume.fake_db_volume(**fake_db_new_volume)
     new_volume_obj = fake_volume.fake_volume_obj(self.context,
                                                  **fake_new_volume)
     host_obj = {'host': 'newhost', 'capabilities': {}}
     volume_get.return_value = fake_new_volume
     update_server_volume = nova_api.return_value.update_server_volume
     volume = tests_utils.create_volume(self.context, size=1,
                                        host=CONF.host)
     with mock.patch.object(self.volume, '_copy_volume_data') as \
             mock_copy_volume:
         self.volume._migrate_volume_generic(self.context, volume,
                                             host_obj, None)
         mock_copy_volume.assert_called_with(self.context, volume,
                                             new_volume_obj,
                                             remote='dest')
         migrate_volume_completion.assert_called_with(
             self.context, volume, new_volume_obj, error=False)
         self.assertFalse(update_server_volume.called)
Exemplo n.º 44
0
    def test_create_from_image_cache_miss_error_size_invalid(
            self, mock_qemu_info, mock_get_internal_context,
            mock_create_from_img_dl, mock_create_from_src,
            mock_handle_bootable, mock_fetch_img):
        mock_fetch_img.return_value = mock.MagicMock()
        image_info = imageutils.QemuImgInfo()
        image_info.virtual_size = '2147483648'
        mock_qemu_info.return_value = image_info
        self.mock_driver.clone_image.return_value = (None, False)
        self.mock_cache.get_entry.return_value = None

        volume = fake_volume.fake_volume_obj(self.ctxt,
                                             size=1,
                                             host='foo@bar#pool')
        image_volume = fake_volume.fake_db_volume(size=2)
        self.mock_db.volume_create.return_value = image_volume

        image_location = 'someImageLocationStr'
        image_id = 'c7a8b8d4-e519-46c7-a0df-ddf1b9b9fff2'
        image_meta = mock.MagicMock()

        manager = create_volume_manager.CreateVolumeFromSpecTask(
            self.mock_volume_manager,
            self.mock_db,
            self.mock_driver,
            image_volume_cache=self.mock_cache)

        self.assertRaises(exception.ImageUnacceptable,
                          manager._create_from_image, self.ctxt, volume,
                          image_location, image_id, image_meta,
                          self.mock_image_service)

        # The volume size should NOT be changed when in this case
        self.assertFalse(self.mock_db.volume_update.called)

        # Make sure we didn't try and create a cache entry
        self.assertFalse(self.mock_cache.ensure_space.called)
        self.assertFalse(self.mock_cache.create_cache_entry.called)
Exemplo n.º 45
0
 def test_migrate_volume_generic_attached_volume(self, volume_get,
                                                 migrate_volume_completion,
                                                 nova_api):
     attached_host = 'some-host'
     fake_volume_id = fake.VOLUME_ID
     fake_db_new_volume = {'status': 'available', 'id': fake_volume_id}
     fake_new_volume = fake_volume.fake_db_volume(**fake_db_new_volume)
     host_obj = {'host': 'newhost', 'capabilities': {}}
     fake_uuid = fakes.get_fake_uuid()
     update_server_volume = nova_api.return_value.update_server_volume
     volume_get.return_value = fake_new_volume
     volume = tests_utils.create_volume(self.context, size=1,
                                        host=CONF.host)
     volume_attach = tests_utils.attach_volume(
         self.context, volume['id'], fake_uuid, attached_host, '/dev/vda')
     self.assertIsNotNone(volume_attach['volume_attachment'][0]['id'])
     self.assertEqual(
         fake_uuid, volume_attach['volume_attachment'][0]['instance_uuid'])
     self.assertEqual('in-use', volume_attach['status'])
     self.volume._migrate_volume_generic(self.context, volume,
                                         host_obj, None)
     self.assertFalse(migrate_volume_completion.called)
     update_server_volume.assert_called_with(self.context, fake_uuid,
                                             volume['id'], fake_volume_id)
Exemplo n.º 46
0
    def test_copy_volume_to_image_volume_vhd(self, mock_copy_volume_to_image,
                                             mock_update, mock_get,
                                             mock_create,
                                             mock_get_volume_image_metadata):
        """Test create image from volume with vhd_disk_format"""

        db_volume = fake_volume.fake_db_volume()
        volume_obj = objects.Volume._from_db_object(self.context,
                                                    objects.Volume(),
                                                    db_volume)

        mock_create.side_effect = self.fake_vhd_image_service_create
        mock_get.return_value = volume_obj
        mock_copy_volume_to_image.side_effect = (
            self.fake_rpc_copy_volume_to_image)

        req = fakes.HTTPRequest.blank('/v2/tenant1/volumes/%s/action' % id)
        body = self._get_os_volume_upload_image()

        res_dict = self.controller._volume_upload_image(req, id, body)
        expected_res = {
            'os-volume_upload_image': {
                'id': fake.volume_id,
                'updated_at': None,
                'status': 'uploading',
                'display_description': None,
                'size': 1,
                'volume_type': None,
                'image_id': 1,
                'container_format': u'bare',
                'disk_format': u'vhd',
                'image_name': u'image_name'
            }
        }

        self.assertDictMatch(expected_res, res_dict)
Exemplo n.º 47
0
 def test_create(self, volume_create):
     db_volume = fake_volume.fake_db_volume()
     volume_create.return_value = db_volume
     volume = objects.Volume(context=self.context)
     volume.create()
     self.assertEqual(db_volume['id'], volume.id)
Exemplo n.º 48
0
 def test_get_by_id(self, volume_get):
     db_volume = fake_volume.fake_db_volume()
     volume_get.return_value = db_volume
     volume = objects.Volume.get_by_id(self.context, fake.volume_id)
     volume_get.assert_called_once_with(self.context, fake.volume_id)
     self._compare(self, db_volume, volume)
Exemplo n.º 49
0
    def test_obj_load_attr(self, mock_sl_get_all_for_volume, mock_cg_get_by_id,
                           mock_va_get_all_by_vol, mock_vt_get_by_id,
                           mock_admin_metadata_get, mock_glance_metadata_get,
                           mock_metadata_get):
        volume = objects.Volume._from_db_object(self.context, objects.Volume(),
                                                fake_volume.fake_db_volume())

        # Test metadata lazy-loaded field
        metadata = {'foo': 'bar'}
        mock_metadata_get.return_value = metadata
        self.assertEqual(metadata, volume.metadata)
        mock_metadata_get.assert_called_once_with(self.context, volume.id)

        # Test glance_metadata lazy-loaded field
        glance_metadata = [{'key': 'foo', 'value': 'bar'}]
        mock_glance_metadata_get.return_value = glance_metadata
        self.assertEqual({'foo': 'bar'}, volume.glance_metadata)
        mock_glance_metadata_get.assert_called_once_with(
            self.context, volume.id)

        # Test volume_type lazy-loaded field
        # Case1. volume.volume_type_id = None
        self.assertIsNone(volume.volume_type)

        # Case2. volume2.volume_type_id = 1
        fake2 = fake_volume.fake_db_volume()
        fake2.update({'volume_type_id': fake.volume_id})
        volume2 = objects.Volume._from_db_object(self.context,
                                                 objects.Volume(), fake2)
        volume_type = objects.VolumeType(context=self.context,
                                         id=fake.volume_type_id)
        mock_vt_get_by_id.return_value = volume_type
        self.assertEqual(volume_type, volume2.volume_type)
        mock_vt_get_by_id.assert_called_once_with(self.context,
                                                  volume2.volume_type_id)

        # Test consistencygroup lazy-loaded field
        consistencygroup = objects.ConsistencyGroup(
            context=self.context, id=fake.consistency_group_id)
        mock_cg_get_by_id.return_value = consistencygroup
        self.assertEqual(consistencygroup, volume.consistencygroup)
        mock_cg_get_by_id.assert_called_once_with(self.context,
                                                  volume.consistencygroup_id)

        # Test snapshots lazy-loaded field
        snapshots = objects.SnapshotList(context=self.context,
                                         id=fake.snapshot_id)
        mock_sl_get_all_for_volume.return_value = snapshots
        self.assertEqual(snapshots, volume.snapshots)
        mock_sl_get_all_for_volume.assert_called_once_with(
            self.context, volume.id)

        # Test volume_attachment lazy-loaded field
        va_objs = [
            objects.VolumeAttachment(context=self.context, id=i)
            for i in [fake.object_id, fake.object2_id, fake.object3_id]
        ]
        va_list = objects.VolumeAttachmentList(context=self.context,
                                               objects=va_objs)
        mock_va_get_all_by_vol.return_value = va_list
        self.assertEqual(va_list, volume.volume_attachment)
        mock_va_get_all_by_vol.assert_called_once_with(self.context, volume.id)

        # Test admin_metadata lazy-loaded field - user context
        adm_metadata = {'bar': 'foo'}
        mock_admin_metadata_get.return_value = adm_metadata
        self.assertEqual({}, volume.admin_metadata)
        self.assertFalse(mock_admin_metadata_get.called)

        # Test admin_metadata lazy-loaded field - admin context
        adm_context = self.context.elevated()
        volume = objects.Volume._from_db_object(adm_context, objects.Volume(),
                                                fake_volume.fake_db_volume())
        adm_metadata = {'bar': 'foo'}
        mock_admin_metadata_get.return_value = adm_metadata
        self.assertEqual(adm_metadata, volume.admin_metadata)
        mock_admin_metadata_get.assert_called_once_with(adm_context, volume.id)
Exemplo n.º 50
0
 def test_get_by_id(self, volume_get, volume_glance_metadata_get):
     db_volume = fake_volume.fake_db_volume()
     volume_get.return_value = db_volume
     volume = objects.Volume.get_by_id(self.context, 1)
     self._compare(self, db_volume, volume)
Exemplo n.º 51
0
 def test_destroy(self, volume_destroy):
     db_volume = fake_volume.fake_db_volume()
     volume = objects.Volume._from_db_object(self.context, objects.Volume(),
                                             db_volume)
     volume.destroy()
     volume_destroy.assert_called_once_with(self.context, '1')
Exemplo n.º 52
0
def _stub_volume(*args, **kwargs):
    updates = {'provider_location': 'hyperscale-sv:/hyperscale'}
    return fake_volume.fake_db_volume(**updates)
Exemplo n.º 53
0
    def test_create_from_image_cache_miss_error_downloading(
            self, mock_qemu_info, mock_get_internal_context,
            mock_create_from_img_dl, mock_create_from_src,
            mock_handle_bootable, mock_fetch_img):
        mock_fetch_img.return_value = mock.MagicMock()
        image_info = imageutils.QemuImgInfo()
        image_info.virtual_size = '2147483648'
        mock_qemu_info.return_value = image_info
        self.mock_driver.clone_image.return_value = (None, False)
        self.mock_cache.get_entry.return_value = None

        volume = fake_volume.fake_volume_obj(self.ctxt, size=10,
                                             host='foo@bar#pool')
        image_volume = fake_volume.fake_db_volume(size=2)
        self.mock_db.volume_create.return_value = image_volume

        mock_create_from_img_dl.side_effect = exception.CinderException()

        def update_volume(ctxt, id, updates):
            volume.update(updates)
            return volume
        self.mock_db.volume_update.side_effect = update_volume

        image_location = 'someImageLocationStr'
        image_id = 'c7a8b8d4-e519-46c7-a0df-ddf1b9b9fff2'
        image_meta = mock.MagicMock()

        manager = create_volume_manager.CreateVolumeFromSpecTask(
            self.mock_volume_manager,
            self.mock_db,
            self.mock_driver,
            image_volume_cache=self.mock_cache
        )

        self.assertRaises(
            exception.CinderException,
            manager._create_from_image,
            self.ctxt,
            volume,
            image_location,
            image_id,
            image_meta,
            self.mock_image_service
        )

        # Make sure clone_image is always called
        self.assertTrue(self.mock_driver.clone_image.called)

        # The image download should happen if clone fails and
        # we get a cache miss
        mock_create_from_img_dl.assert_called_once_with(
            self.ctxt,
            mock.ANY,
            image_location,
            image_id,
            self.mock_image_service
        )

        # The volume size should be reduced to virtual_size and then put back,
        # especially if there is an exception while creating the volume.
        self.assertEqual(2, self.mock_db.volume_update.call_count)
        self.mock_db.volume_update.assert_any_call(self.ctxt,
                                                   volume['id'],
                                                   {'size': 2})
        self.mock_db.volume_update.assert_any_call(self.ctxt,
                                                   volume['id'],
                                                   {'size': 10})

        # Make sure we didn't try and create a cache entry
        self.assertFalse(self.mock_cache.ensure_space.called)
        self.assertFalse(self.mock_cache.create_cache_entry.called)
Exemplo n.º 54
0
    'status': fields.BackupStatus.CREATING,
    'size': 1,
    'display_name': 'fake_name',
    'display_description': 'fake_description',
    'user_id': fake.USER_ID,
    'project_id': fake.PROJECT_ID,
    'temp_volume_id': None,
    'temp_snapshot_id': None,
    'snapshot_id': None,
    'data_timestamp': None,
    'restore_volume_id': None,
    'backup_metadata': {},
}

vol_props = {'status': 'available', 'size': 1}
fake_vol = fake_volume.fake_db_volume(**vol_props)
snap_props = {
    'status': fields.BackupStatus.AVAILABLE,
    'volume_id': fake_vol['id'],
    'expected_attrs': ['metadata']
}
fake_snap = fake_snapshot.fake_db_snapshot(**snap_props)


class TestBackup(test_objects.BaseObjectsTestCase):
    @mock.patch('cinder.db.get_by_id', return_value=fake_backup)
    def test_get_by_id(self, backup_get):
        backup = objects.Backup.get_by_id(self.context, fake.USER_ID)
        self._compare(self, fake_backup, backup)
        backup_get.assert_called_once_with(self.context, models.Backup,
                                           fake.USER_ID)
Exemplo n.º 55
0
    def test_finish_volume_migration(self,
                                     volume_update,
                                     metadata_update,
                                     src_vol_type_id,
                                     dest_vol_type_id,
                                     src_vol_status=None):
        src_volume_db = fake_volume.fake_db_volume(
            **{
                'id': fake.VOLUME_ID,
                'volume_type_id': src_vol_type_id
            })
        if src_vol_type_id:
            src_volume_db['volume_type'] = fake_volume.fake_db_volume_type(
                id=src_vol_type_id)
        if src_vol_status:
            src_volume_db['status'] = src_vol_status

        dest_volume_db = fake_volume.fake_db_volume(
            **{
                'id': fake.VOLUME2_ID,
                'volume_type_id': dest_vol_type_id
            })
        if dest_vol_type_id:
            dest_volume_db['volume_type'] = fake_volume.fake_db_volume_type(
                id=dest_vol_type_id)
        expected_attrs = objects.Volume._get_expected_attrs(self.context)
        src_volume = objects.Volume._from_db_object(
            self.context,
            objects.Volume(),
            src_volume_db,
            expected_attrs=expected_attrs)
        dest_volume = objects.Volume._from_db_object(
            self.context,
            objects.Volume(),
            dest_volume_db,
            expected_attrs=expected_attrs)
        updated_dest_volume = src_volume.finish_volume_migration(dest_volume)
        self.assertEqual('deleting', updated_dest_volume.migration_status)
        self.assertEqual('migration src for ' + src_volume.id,
                         updated_dest_volume.display_description)
        self.assertEqual(src_volume.id, updated_dest_volume._name_id)
        self.assertTrue(volume_update.called)
        volume_update.assert_has_calls([
            mock.call(self.context, src_volume.id, mock.ANY),
            mock.call(self.context, dest_volume.id, mock.ANY)
        ])
        ctxt, vol_id, updates = volume_update.call_args[0]

        if src_vol_status and src_vol_status == 'retyping':
            self.assertIn('volume_type', updates)
        else:
            self.assertNotIn('volume_type', updates)

        # Ensure that the destination volume type has not been overwritten
        self.assertEqual(dest_vol_type_id,
                         getattr(updated_dest_volume, 'volume_type_id'))
        # Ignore these attributes, since they were updated by
        # finish_volume_migration
        ignore_keys = ('id', 'provider_location', '_name_id',
                       'migration_status', 'display_description', 'status',
                       'volume_glance_metadata', 'volume_type')

        dest_vol_dict = {
            k: updated_dest_volume[k]
            for k in updated_dest_volume.keys() if k not in ignore_keys
        }
        src_vol_dict = {
            k: src_volume[k]
            for k in src_volume.keys() if k not in ignore_keys
        }
        self.assertEqual(src_vol_dict, dest_vol_dict)