diff --git a/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py b/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py index 24722fdf26d..061059d7084 100644 --- a/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py +++ b/cinder/tests/unit/volume/drivers/vmware/test_vmware_vmdk.py @@ -1681,13 +1681,67 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): vops.get_dc.assert_called_once_with(rp) get_volume_group_folder.assert_called_once_with(dc, vol['project_id']) + @mock.patch.object(VMDK_DRIVER, 'volumeops') + def _test_get_connection_info(self, vops, vmdk_connector=False): + volume = self._create_volume_obj() + backing = mock.Mock(value='ref-1') + if vmdk_connector: + vmdk_path = mock.sentinel.vmdk_path + vops.get_vmdk_path.return_value = vmdk_path + + datastore = mock.Mock(value='ds-1') + vops.get_datastore.return_value = datastore + + datacenter = mock.Mock(value='dc-1') + vops.get_dc.return_value = datacenter + + connector = {'platform': mock.sentinel.platform, + 'os_type': mock.sentinel.os_type} + else: + connector = {'instance': 'vm-1'} + ret = self._driver._get_connection_info(volume, backing, connector) + + self.assertEqual('vmdk', ret['driver_volume_type']) + self.assertEqual('ref-1', ret['data']['volume']) + self.assertEqual(volume.id, ret['data']['volume_id']) + self.assertEqual(volume.name, ret['data']['name']) + + if vmdk_connector: + self.assertEqual(volume.size * units.Gi, ret['data']['vmdk_size']) + self.assertEqual(vmdk_path, ret['data']['vmdk_path']) + self.assertEqual('ds-1', ret['data']['datastore']) + self.assertEqual('dc-1', ret['data']['datacenter']) + + config = self._driver.configuration + exp_config = { + 'vmware_host_ip': config.vmware_host_ip, + 'vmware_host_port': config.vmware_host_port, + 'vmware_host_username': config.vmware_host_username, + 'vmware_host_password': config.vmware_host_password, + 'vmware_api_retry_count': config.vmware_api_retry_count, + 'vmware_task_poll_interval': config.vmware_task_poll_interval, + 'vmware_ca_file': config.vmware_ca_file, + 'vmware_insecure': config.vmware_insecure, + 'vmware_tmp_dir': config.vmware_tmp_dir, + 'vmware_image_transfer_timeout_secs': + config.vmware_image_transfer_timeout_secs, + } + self.assertEqual(exp_config, ret['data']['config']) + + def test_get_connection_info(self): + self._test_get_connection_info() + + def test_get_connection_info_vmdk_connector(self): + self._test_get_connection_info(vmdk_connector=True) + @mock.patch.object(VMDK_DRIVER, 'volumeops') @mock.patch('oslo_vmware.vim_util.get_moref') @mock.patch.object(VMDK_DRIVER, '_create_backing') @mock.patch.object(VMDK_DRIVER, '_relocate_backing') + @mock.patch.object(VMDK_DRIVER, '_get_connection_info') def _test_initialize_connection( - self, relocate_backing, create_backing, get_moref, vops, - backing_exists=True, instance_exists=True): + self, get_connection_info, relocate_backing, create_backing, + get_moref, vops, backing_exists=True, instance_exists=True): backing_val = mock.sentinel.backing_val backing = mock.Mock(value=backing_val) @@ -1709,14 +1763,13 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): else: connector = {} + conn_info = mock.sentinel.conn_info + get_connection_info.return_value = conn_info + volume = self._create_volume_obj() - conn_info = self._driver.initialize_connection(volume, connector) - - self.assertEqual('vmdk', conn_info['driver_volume_type']) - self.assertEqual(backing_val, conn_info['data']['volume']) - self.assertEqual(volume.id, conn_info['data']['volume_id']) - self.assertEqual(volume.name, conn_info['data']['name']) + ret = self._driver.initialize_connection(volume, connector) + self.assertEqual(conn_info, ret) if instance_exists: vops.get_host.assert_called_once_with(instance_moref) if backing_exists: @@ -1731,6 +1784,7 @@ class VMwareVcVmdkDriverTestCase(test.TestCase): else: create_backing.assert_not_called() relocate_backing.assert_not_called() + get_connection_info.assert_called_once_with(volume, backing, connector) def test_initialize_connection_with_instance_and_backing(self): self._test_initialize_connection() diff --git a/cinder/volume/drivers/vmware/vmdk.py b/cinder/volume/drivers/vmware/vmdk.py index ceb4c7d3873..7b7ed359731 100644 --- a/cinder/volume/drivers/vmware/vmdk.py +++ b/cinder/volume/drivers/vmware/vmdk.py @@ -502,6 +502,51 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): return (host_ref, resource_pool, folder, summary) + def _get_connection_info(self, volume, backing, connector): + connection_info = {'driver_volume_type': 'vmdk'} + connection_info['data'] = { + 'volume': backing.value, + 'volume_id': volume.id, + 'name': volume.name, + } + + # vmdk connector in os-brick needs additional connection info. + if 'platform' in connector and 'os_type' in connector: + connection_info['data']['vmdk_size'] = volume['size'] * units.Gi + + vmdk_path = self.volumeops.get_vmdk_path(backing) + connection_info['data']['vmdk_path'] = vmdk_path + + datastore = self.volumeops.get_datastore(backing) + connection_info['data']['datastore'] = datastore.value + + datacenter = self.volumeops.get_dc(backing) + connection_info['data']['datacenter'] = datacenter.value + + config = self.configuration + vmdk_connector_config = { + 'vmware_host_ip': config.vmware_host_ip, + 'vmware_host_port': config.vmware_host_port, + 'vmware_host_username': config.vmware_host_username, + 'vmware_host_password': config.vmware_host_password, + 'vmware_api_retry_count': config.vmware_api_retry_count, + 'vmware_task_poll_interval': config.vmware_task_poll_interval, + 'vmware_ca_file': config.vmware_ca_file, + 'vmware_insecure': config.vmware_insecure, + 'vmware_tmp_dir': config.vmware_tmp_dir, + 'vmware_image_transfer_timeout_secs': + config.vmware_image_transfer_timeout_secs, + } + connection_info['data']['config'] = vmdk_connector_config + + LOG.debug("Returning connection_info (volume: '%(volume)s', volume_id:" + " '%(volume_id)s') for connector: %(connector)s.", + {'volume': connection_info['data']['volume'], + 'volume_id': volume.id, + 'connector': connector}) + + return connection_info + def _initialize_connection(self, volume, connector): """Get information of volume's backing. @@ -511,8 +556,6 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): :param connector: Connector information :return: Return connection information """ - connection_info = {'driver_volume_type': 'vmdk'} - backing = self.volumeops.get_backing(volume.name) if 'instance' in connector: # The instance exists @@ -543,18 +586,7 @@ class VMwareVcVmdkDriver(driver.VolumeDriver): # Create backing backing = self._create_backing(volume) - # Set volume ID and backing moref value and name. - connection_info['data'] = {'volume': backing.value, - 'volume_id': volume.id, - 'name': volume.name} - - LOG.info(_LI("Returning connection_info: %(info)s for volume: " - "%(volume)s with connector: %(connector)s."), - {'info': connection_info, - 'volume': volume.name, - 'connector': connector}) - - return connection_info + return self._get_connection_info(volume, backing, connector) def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info. diff --git a/releasenotes/notes/vmdk_backup_restore-41f807b7bc8e0ae8.yaml b/releasenotes/notes/vmdk_backup_restore-41f807b7bc8e0ae8.yaml new file mode 100644 index 00000000000..05ae0c92f04 --- /dev/null +++ b/releasenotes/notes/vmdk_backup_restore-41f807b7bc8e0ae8.yaml @@ -0,0 +1,4 @@ +--- +fixes: + - Fixed backup and restore of volumes in VMware VMDK driver. +