diff --git a/nova_powervm/tests/virt/powervm/__init__.py b/nova_powervm/tests/virt/powervm/__init__.py index 8e5e9ce9..cc08a7dc 100644 --- a/nova_powervm/tests/virt/powervm/__init__.py +++ b/nova_powervm/tests/virt/powervm/__init__.py @@ -13,6 +13,7 @@ # License for the specific language governing permissions and limitations # under the License. +from nova import objects from nova.objects import flavor import os import sys @@ -57,6 +58,16 @@ TEST_MIGRATION_SAME_HOST = { 'new_instance_type_id': 2, } +IMAGE1 = { + 'id': 1, + 'name': 'image1', + 'size': 300, + 'container_format': 'bare', + 'disk_format': 'raw' + +} +TEST_IMAGE1 = objects.ImageMeta.from_dict(IMAGE1) + # NOTE(mikal): All of this is because if dnspython is present in your # environment then eventlet monkeypatches socket.getaddrinfo() with an # implementation which doesn't work for IPv6. What we're checking here is diff --git a/nova_powervm/tests/virt/powervm/disk/test_driver.py b/nova_powervm/tests/virt/powervm/disk/test_driver.py index d79e98ef..e75d2190 100644 --- a/nova_powervm/tests/virt/powervm/disk/test_driver.py +++ b/nova_powervm/tests/virt/powervm/disk/test_driver.py @@ -18,6 +18,7 @@ import mock from nova import test +from nova_powervm.tests.virt import powervm from nova_powervm.tests.virt.powervm import fixtures as fx from nova_powervm.virt.powervm.disk import driver as disk_dvr @@ -40,8 +41,7 @@ class TestDiskAdapter(test.TestCase): def test_get_image_upload(self): # Test if there is an ID, that we get a file adapter back - img_meta = {'id': 'test_id'} - temp = self.st_adpt._get_image_upload(mock.Mock(), img_meta) + temp = self.st_adpt._get_image_upload(mock.Mock(), powervm.TEST_IMAGE1) self.assertIsInstance(temp, disk_dvr.IterableToFileAdapter) def test_get_info(self): diff --git a/nova_powervm/tests/virt/powervm/disk/test_localdisk.py b/nova_powervm/tests/virt/powervm/disk/test_localdisk.py index a393802d..44bf0b90 100644 --- a/nova_powervm/tests/virt/powervm/disk/test_localdisk.py +++ b/nova_powervm/tests/virt/powervm/disk/test_localdisk.py @@ -24,6 +24,7 @@ from pypowervm.tests.test_utils import pvmhttp from pypowervm.wrappers import storage as pvm_stor from pypowervm.wrappers import virtual_io_server as pvm_vios +from nova_powervm.tests.virt import powervm from nova_powervm.tests.virt.powervm import fixtures as fx from nova_powervm.virt.powervm.disk import driver as disk_dvr from nova_powervm.virt.powervm.disk import localdisk as ld @@ -75,16 +76,16 @@ class TestLocalDisk(test.TestCase): @mock.patch('nova.image.API') def test_create_disk_from_image(self, mock_img_api, mock_file_adpt, mock_upload_vdisk): - mock_img = {'id': 'fake_id', 'size': 50} mock_upload_vdisk.return_value = ('vdisk', None) inst = mock.Mock() inst.name = 'Inst Name' inst.uuid = 'd5065c2c-ac43-3fa6-af32-ea84a3960291' vdisk = self.get_ls(self.apt).create_disk_from_image( - None, inst, mock_img, 20) + None, inst, powervm.TEST_IMAGE1, 20) mock_upload_vdisk.assert_called_with(mock.ANY, mock.ANY, mock.ANY, - mock.ANY, 'b_Inst_Nam_d506', 50, + mock.ANY, 'b_Inst_Nam_d506', + powervm.TEST_IMAGE1.size, d_size=21474836480) self.assertEqual('vdisk', vdisk) diff --git a/nova_powervm/tests/virt/powervm/disk/test_ssp.py b/nova_powervm/tests/virt/powervm/disk/test_ssp.py index 22fa5bee..ca30b89a 100644 --- a/nova_powervm/tests/virt/powervm/disk/test_ssp.py +++ b/nova_powervm/tests/virt/powervm/disk/test_ssp.py @@ -28,6 +28,7 @@ from pypowervm.wrappers import cluster as pvm_clust from pypowervm.wrappers import storage as pvm_stg from pypowervm.wrappers import virtual_io_server as pvm_vios +from nova_powervm.tests.virt import powervm from nova_powervm.tests.virt.powervm import fixtures as fx from nova_powervm.virt.powervm.disk import driver as disk_dvr from nova_powervm.virt.powervm.disk import ssp @@ -304,17 +305,14 @@ class TestSSPDiskAdapter(test.TestCase): @mock.patch('nova.image.API') def test_create_disk_from_new_image(self, mock_img_api, mock_it2fadp, mock_upload_lu, mock_crt_lnk_cln): - b1G = 1024 * 1024 * 1024 - b2G = 2 * b1G ssp_stor = self._get_ssp_stor() - img = dict(name='image-name', id='image-id', size=b2G) def verify_upload_new_lu(vios_uuid, ssp1, stream, lu_name, f_size): self.assertIn(vios_uuid, ssp_stor.vios_uuids) self.assertEqual(ssp_stor._ssp_wrap, ssp1) - # 'image' + '_' + s/-/_/g(image['id']), per _get_image_name - self.assertEqual('image_image_name', lu_name) - self.assertEqual(b2G, f_size) + # 'image' + '_' + s/-/_/g(image.name), per _get_image_name + self.assertEqual('image_' + powervm.TEST_IMAGE1.name, lu_name) + self.assertEqual(powervm.TEST_IMAGE1.size, f_size) return 'image_lu', None def verify_create_lu_linked_clone(ssp1, clust1, imglu, lu_name, sz_gb): @@ -325,7 +323,8 @@ class TestSSPDiskAdapter(test.TestCase): mock_upload_lu.side_effect = verify_upload_new_lu mock_crt_lnk_cln.side_effect = verify_create_lu_linked_clone - lu = ssp_stor.create_disk_from_image(None, self.instance, img, 1) + lu = ssp_stor.create_disk_from_image(None, self.instance, + powervm.TEST_IMAGE1, 1) self.assertEqual('new_lu', lu) @mock.patch('pypowervm.tasks.storage.crt_lu_linked_clone') @@ -333,12 +332,9 @@ class TestSSPDiskAdapter(test.TestCase): @mock.patch('nova.image.API') def test_create_disk_from_existing_image(self, mock_img_api, mock_it2fadp, mock_crt_lnk_cln): - b1G = 1024 * 1024 * 1024 - b2G = 2 * b1G ssp_stor = self._get_ssp_stor() - img = dict(name='image-name', id='image-id', size=b2G) # Mock the 'existing' image LU - img_lu = pvm_stg.LU.bld(None, 'image_image_name', 123, + img_lu = pvm_stg.LU.bld(None, 'image_' + powervm.TEST_IMAGE1.name, 123, typ=pvm_stg.LUType.IMAGE) ssp_stor._ssp_wrap.logical_units.append(img_lu) @@ -353,7 +349,8 @@ class TestSSPDiskAdapter(test.TestCase): return ssp1, 'new_lu' mock_crt_lnk_cln.side_effect = verify_create_lu_linked_clone - lu = ssp_stor.create_disk_from_image(None, Instance(), img, 1) + lu = ssp_stor.create_disk_from_image( + None, Instance(), powervm.TEST_IMAGE1, 1) self.assertEqual('new_lu', lu) def test_find_lu(self): diff --git a/nova_powervm/tests/virt/powervm/test_driver.py b/nova_powervm/tests/virt/powervm/test_driver.py index c0f02a4a..2efeabde 100644 --- a/nova_powervm/tests/virt/powervm/test_driver.py +++ b/nova_powervm/tests/virt/powervm/test_driver.py @@ -1106,7 +1106,7 @@ class TestPowerVMDriver(test.TestCase): # Invoke the method. self.drv.rescue('context', inst, mock.MagicMock(), - mock.MagicMock(), 'rescue_psswd') + powervm.TEST_IMAGE1, 'rescue_psswd') self.assertTrue(mock_task_vm.power_off.called) self.assertTrue(self.drv.disk_dvr.create_disk_from_image.called) diff --git a/nova_powervm/virt/powervm/disk/driver.py b/nova_powervm/virt/powervm/disk/driver.py index 171b6e7c..c5b94916 100644 --- a/nova_powervm/virt/powervm/disk/driver.py +++ b/nova_powervm/virt/powervm/disk/driver.py @@ -238,10 +238,11 @@ class DiskAdapter(object): built for the invoker. :param context: User context - :param image_meta: The image metadata. + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :return: The stream to send to pypowervm. """ - chunks = self.image_api.download(context, image_meta['id']) + chunks = self.image_api.download(context, image_meta.id) return IterableToFileAdapter(chunks) @staticmethod @@ -265,7 +266,7 @@ class DiskAdapter(object): @staticmethod def _get_image_name(image_meta): """Generate a name for a virtual storage copy of an image.""" - return pvm_util.sanitize_file_name_for_api(image_meta['name'], + return pvm_util.sanitize_file_name_for_api(image_meta.name, prefix=DiskType.IMAGE + '_') @staticmethod @@ -320,7 +321,8 @@ class DiskAdapter(object): :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. - :param image_meta: dict identifying the image in glance + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :param disk_size: The size of the disk to create in GB. If smaller than the image, it will be ignored (as the disk must be at least as big as the image). Must be an diff --git a/nova_powervm/virt/powervm/disk/localdisk.py b/nova_powervm/virt/powervm/disk/localdisk.py index 63ed15de..2d09b474 100644 --- a/nova_powervm/virt/powervm/disk/localdisk.py +++ b/nova_powervm/virt/powervm/disk/localdisk.py @@ -166,13 +166,14 @@ class LocalStorage(disk_dvr.DiskAdapter): 'disk_name': disk_name, 'mp_uuid': self.mp_uuid, 'vios_name': vios_uuid}) - def create_disk_from_image(self, context, instance, image, disk_size, + def create_disk_from_image(self, context, instance, image_meta, disk_size, image_type=disk_dvr.DiskType.BOOT): """Creates a disk and copies the specified image to it. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. - :param image: image dict used to locate the image in glance + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :param disk_size: The size of the disk to create in GB. If smaller than the image, it will be ignored (as the disk must be at least as big as the image). Must be an @@ -183,11 +184,11 @@ class LocalStorage(disk_dvr.DiskAdapter): LOG.info(_LI('Create disk.')) # Transfer the image - stream = self._get_image_upload(context, image) + stream = self._get_image_upload(context, image_meta) vol_name = self._get_disk_name(image_type, instance, short=True) # Disk size to API is in bytes. Input from method is in Gb - disk_bytes = self._disk_gb_to_bytes(disk_size, floor=image['size']) + disk_bytes = self._disk_gb_to_bytes(disk_size, floor=image_meta.size) # This method will create a new disk at our specified size. It will # then put the image in the disk. If the disk is bigger, user can @@ -196,7 +197,7 @@ class LocalStorage(disk_dvr.DiskAdapter): # enough to support the image (up to 1 Gb boundary). vdisk, f_wrap = tsk_stg.upload_new_vdisk( self.adapter, self._vios_uuid, self.vg_uuid, stream, vol_name, - image['size'], d_size=disk_bytes) + image_meta.size, d_size=disk_bytes) return vdisk diff --git a/nova_powervm/virt/powervm/disk/ssp.py b/nova_powervm/virt/powervm/disk/ssp.py index fcf893ed..18ba9f9f 100644 --- a/nova_powervm/virt/powervm/disk/ssp.py +++ b/nova_powervm/virt/powervm/disk/ssp.py @@ -199,7 +199,8 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): """ tsk_stg.rm_ssp_storage(self._ssp, storage_elems) - def create_disk_from_image(self, context, instance, img_meta, disk_size_gb, + def create_disk_from_image(self, context, instance, image_meta, + disk_size_gb, image_type=disk_drv.DiskType.BOOT): """Creates a boot disk and links the specified image to it. @@ -209,9 +210,8 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. - :param img_meta: image metadata dict: - { 'id': reference used to locate the image in glance, - 'size': size in bytes of the image. } + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :param disk_size_gb: The size of the disk to create in GB. If smaller than the image, it will be ignored (as the disk must be at least as big as the image). Must be an @@ -221,7 +221,7 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): """ LOG.info(_LI('SSP: Create %(image_type)s disk from image %(image_id)s ' 'for instance %(instance_uuid)s.'), - dict(image_type=image_type, image_id=img_meta['id'], + dict(image_type=image_type, image_id=image_meta.id, instance_uuid=instance.uuid)) # TODO(IBM): There's an optimization to be had here if we can create @@ -229,7 +229,7 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): # This will require some nontrivial refactoring, though, as the LUs are # created down inside of upload_new_lu and crt_lu_linked_clone. - image_lu = self._get_or_upload_image_lu(context, img_meta) + image_lu = self._get_or_upload_image_lu(context, image_meta) boot_lu_name = self._get_disk_name(image_type, instance) LOG.info(_LI('SSP: Disk name is %s'), boot_lu_name) @@ -245,7 +245,7 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): if lu.lu_type == lu_type and lu.name == lu_name: return lu - def _get_or_upload_image_lu(self, context, img_meta): + def _get_or_upload_image_lu(self, context, image_meta): """Ensures our SSP has an LU containing the specified image. If an LU of type IMAGE corresponding to the input image metadata @@ -253,13 +253,12 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): with the image contents from glance, and return it. :param context: nova context used to retrieve image from glance - :param img_meta: image metadata dict: - { 'id': reference used to locate the image in glance, - 'size': size in bytes of the image. } + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :return: A pypowervm LU ElementWrapper representing the image. """ # Key off of the name to see whether we already have the image - luname = self._get_image_name(img_meta) + luname = self._get_image_name(image_meta) lu = self._find_lu(luname, pvm_stg.LUType.IMAGE) if lu: LOG.info(_LI('SSP: Using already-uploaded image LU %s.'), luname) @@ -267,10 +266,10 @@ class SSPDiskAdapter(disk_drv.DiskAdapter): # We don't have it yet. Create it and upload the glance image to it. # Make the image LU only as big as the image. - stream = self._get_image_upload(context, img_meta) + stream = self._get_image_upload(context, image_meta) LOG.info(_LI('SSP: Uploading new image LU %s.'), luname) lu, f_wrap = tsk_stg.upload_new_lu( - self._any_vios_uuid(), self._ssp, stream, luname, img_meta['size']) + self._any_vios_uuid(), self._ssp, stream, luname, image_meta.size) return lu def get_disk_ref(self, instance, disk_type): diff --git a/nova_powervm/virt/powervm/driver.py b/nova_powervm/virt/powervm/driver.py index d9237616..2896cf37 100644 --- a/nova_powervm/virt/powervm/driver.py +++ b/nova_powervm/virt/powervm/driver.py @@ -236,8 +236,8 @@ class PowerVMDriver(driver.ComputeDriver): :param instance: Instance object as returned by DB layer. This function should use the data there to guide the creation of the new instance. - :param image_meta: image object returned by nova.image.glance that - defines the image from which to boot this instance + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :param injected_files: User files to inject into instance. :param admin_password: Administrator password to set in instance. :param network_info: @@ -635,14 +635,18 @@ class PowerVMDriver(driver.ComputeDriver): rescue_password): """Rescue the specified instance. - :param instance: nova.objects.instance.Instance + :param nova.context.RequestContext context: + The context for the rescue. + :param nova.objects.instance.Instance instance: + The instance being rescued. + :param nova.network.model.NetworkInfo network_info: + Necessary network information for the resume. + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. + :param rescue_password: new root password to set for rescue. """ self._log_operation('rescue', instance) - # We need the image size, which isn't in the system meta data - # so get the all the info. - image_meta = self.image_api.get(context, image_meta['id']) - pvm_inst_uuid = vm.get_pvm_uuid(instance) # Define the flow flow = tf_lf.Flow("rescue") @@ -1006,9 +1010,8 @@ class PowerVMDriver(driver.ComputeDriver): :param disk_info: the newly transferred disk information :param network_info: :py:meth:`~nova.network.manager.NetworkManager.get_instance_nw_info` - :param image_meta: image object returned by nova.image.glance that - defines the image from which this instance - was created + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :param resize_instance: True if the instance disks are being resized, False otherwise :param block_device_info: instance volume block device info diff --git a/nova_powervm/virt/powervm/tasks/storage.py b/nova_powervm/virt/powervm/tasks/storage.py index d21577cc..e5f8a3fe 100644 --- a/nova_powervm/virt/powervm/tasks/storage.py +++ b/nova_powervm/virt/powervm/tasks/storage.py @@ -133,7 +133,8 @@ class CreateDiskForImg(task.Task): :param disk_dvr: The storage driver. :param context: The context passed into the driver method. :param instance: The nova instance. - :param image_meta: The image metadata. + :param nova.objects.ImageMeta image_meta: + The metadata of the image of the instance. :param disk_size: The size of disk to create. If the size is smaller than the image, the image size will be used. :param image_type: The image type. See disk/driver.py