def _create_disk_from_image(self, context, instance, image_meta, image_type=disk_drv.DiskType.BOOT): """Creates a disk and copies the specified image to it. If the specified image has not already been uploaded, an Image LU is created for it. A Disk LU is then created for the instance and linked to the Image LU. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. :param nova.objects.ImageMeta image_meta: The metadata of the image of the instance. :param image_type: The image type. See disk_drv.DiskType. :return: The backing pypowervm LU storage object that was created. """ LOG.info('SSP: Create %(image_type)s disk from image %(image_id)s.', dict(image_type=image_type, image_id=image_meta.id), instance=instance) image_lu = tsk_cs.get_or_upload_image_lu( self._tier, self._get_image_name(image_meta), self._any_vios_uuid(), disk_drv.IterableToFileAdapter( IMAGE_API.download(context, image_meta.id)), image_meta.size, upload_type=tsk_stg.UploadType.IO_STREAM) boot_lu_name = self._get_disk_name(image_type, instance) LOG.info('SSP: Disk name is %s', boot_lu_name, instance=instance) return tsk_stg.crt_lu( self._tier, boot_lu_name, instance.flavor.root_gb, typ=pvm_stg.LUType.DISK, clone=image_lu)[1]
def test_conflict_I_lose(self): """We both bid at the same time; and I lose.""" self.setup_crt_lu_mock(self.fail, conflicting_mkr_lu=self.confl_mkr_lu_win) self.assertEqual( self.img_lu, cs.get_or_upload_image_lu(self.tier, self.img_lu.name, self.vios_uuid, self.mock_stream_func, self.b_size)) # I tried creating mine because his wasn't there at the start self.assertEqual(1, self.mock_crt_lu.call_count) # I "slept", waiting for the other guy to finish self.assertEqual(1, self.mock_sleep.call_count) # I didn't upload self.mock_upload_lu.assert_not_called() # I did remove my marker from the SSP self.mkr_lu.delete.assert_called_once_with() # I didn't remove the image LU (because I didn't create it) self.img_lu.delete.assert_not_called() # I searched the first time through, once in _upload_conflict, and once # after the sleep self.assertEqual(3, self.mock_luent_srch.call_count) # Right number of LUs self.assertEqual(self.exp_num_lus, len(self.entries))
def test_conflict_I_win(self): """We both bid at the same time; and I win.""" self.setup_crt_lu_mock(self.crt_img_lu, conflicting_mkr_lu=self.confl_mkr_lu_lose) self.assertEqual( self.img_lu, cs.get_or_upload_image_lu(self.tier, self.img_lu.name, self.vios_uuid, self.mock_stream_func, self.b_size)) # I tried creating mine because his wasn't there at the start; and I # also created the image LU. self.assertEqual(2, self.mock_crt_lu.call_count) # Since I won, I did the upload self.assertEqual(1, self.mock_upload_lu.call_count) # I did remove my marker from the SSP self.mkr_lu.delete.assert_called_once_with() # I didn't remove the image LU (because I won) self.img_lu.delete.assert_not_called() # I never slept self.mock_sleep.assert_not_called() # I searched the first time through, and in _upload_conflict self.assertEqual(2, self.mock_luent_srch.call_count) # IRL, the other guy will have removed his marker LU at some point. # Here, we can expect it to remain, so there's one "extra". self.assertEqual(self.exp_num_lus + 1, len(self.entries))
def test_already_exists(self): """The image LU is already there.""" self.entries.append(self.img_lu) self.assertEqual( self.img_lu, cs.get_or_upload_image_lu(self.tier, self.img_lu.name, self.vios_uuid, self.mock_stream_func, self.b_size)) # We only searched once self.assertEqual(1, self.mock_luent_srch.call_count) # We didn't create anything self.mock_crt_lu.assert_not_called() # We didn't upload anything self.mock_upload_lu.assert_not_called() # We didn't delete anything self.mkr_lu.delete.assert_not_called() self.img_lu.delete.assert_not_called() # We didn't sleep self.mock_sleep.assert_not_called() # Stream func not invoked self.mock_stream_func.assert_not_called() # Right number of LUs self.assertEqual(self.exp_num_lus, len(self.entries))
def create_disk_from_image(self, context, instance, image_meta): """Creates a boot disk and links the specified image to it. If the specified image has not already been uploaded, an Image LU is created for it. A Disk LU is then created for the instance and linked to the Image LU. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. :param nova.objects.ImageMeta image_meta: The metadata of the image of the instance. :return: The backing pypowervm LU storage object that was created. """ LOG.info('SSP: Create boot disk from image %s.', image_meta.id, instance=instance) image_lu = tsk_cs.get_or_upload_image_lu( self._tier, pvm_u.sanitize_file_name_for_api( image_meta.name, prefix=DiskType.IMAGE + '_', suffix='_' + image_meta.checksum), random.choice(self._vios_uuids), IterableToFileAdapter( IMAGE_API.download(context, image_meta.id)), image_meta.size, upload_type=tsk_stg.UploadType.IO_STREAM) boot_lu_name = pvm_u.sanitize_file_name_for_api( instance.name, prefix=DiskType.BOOT + '_') LOG.info('SSP: Disk name is %s', boot_lu_name, instance=instance) return tsk_stg.crt_lu( self._tier, boot_lu_name, instance.flavor.root_gb, typ=pvm_stg.LUType.DISK, clone=image_lu)[1]
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. If the specified image has not already been uploaded, an Image LU is created for it. A Disk LU is then created for the instance and linked to the Image LU. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. :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 int. :param image_type: The image type. See disk_drv.DiskType. :return: The backing pypowervm LU storage object that was created. """ 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=image_meta.id, instance_uuid=instance.uuid)) def upload(path): IMAGE_API.download(context, image_meta.id, dest_path=path) image_lu = tsk_cs.get_or_upload_image_lu( self._tier, self._get_image_name(image_meta), self._any_vios_uuid(), upload, image_meta.size, upload_type=tsk_stg.UploadType.FUNC) boot_lu_name = self._get_disk_name(image_type, instance) LOG.info(_LI('SSP: Disk name is %s'), boot_lu_name) return tsk_stg.crt_lu(self._tier, boot_lu_name, disk_size_gb, typ=pvm_stg.LUType.DISK, clone=image_lu)[1]
def test_upload_no_conflict(self): """Upload a new LU - no conflict.""" self.setup_crt_lu_mock(self.crt_img_lu) self.assertEqual( self.img_lu, cs.get_or_upload_image_lu(self.tier, self.img_lu.name, self.vios_uuid, self.mock_stream_func, self.b_size)) # Uploaded content self.assertEqual(1, self.mock_upload_lu.call_count) # Removed marker LU self.mkr_lu.delete.assert_called_once_with() # Did not delete image LU self.img_lu.delete.assert_not_called() # I pulled the feed the first time through, and for _upload_conflict self.assertEqual(2, self.mock_luent_srch.call_count) # Right number of LUs self.assertEqual(self.exp_num_lus, len(self.entries))
def test_conflict_started(self): """Another upload is in progress when we get there.""" self.entries.append(self.confl_mkr_lu_lose) self.entries.append(self.img_lu) self.assertEqual( self.img_lu, cs.get_or_upload_image_lu(self.tier, self.img_lu.name, self.vios_uuid, self.mock_stream_func, self.b_size)) # I "waited" for the other guy to complete self.assertEqual(1, self.mock_sleep.call_count) # I did not create, upload, or remove anything self.mock_crt_lu.assert_not_called() self.mock_upload_lu.assert_not_called() self.mkr_lu.delete.assert_not_called() self.img_lu.delete.assert_not_called() # I searched the first time through, and once after the sleep self.assertEqual(2, self.mock_luent_srch.call_count) # Right number of LUs self.assertEqual(self.exp_num_lus, len(self.entries))
def create_disk_from_image(self, context, instance, image_meta): """Creates a boot disk and links the specified image to it. If the specified image has not already been uploaded, an Image LU is created for it. A Disk LU is then created for the instance and linked to the Image LU. :param context: nova context used to retrieve image from glance :param instance: instance to create the disk for. :param nova.objects.ImageMeta image_meta: The metadata of the image of the instance. :return: The backing pypowervm LU storage object that was created. """ LOG.info('SSP: Create boot disk from image %s.', image_meta.id, instance=instance) image_lu = tsk_cs.get_or_upload_image_lu( self._tier, pvm_u.sanitize_file_name_for_api(image_meta.name, prefix=disk_drv.DiskType.IMAGE + '_', suffix='_' + image_meta.checksum), random.choice(self._vios_uuids), disk_drv.IterableToFileAdapter( IMAGE_API.download(context, image_meta.id)), image_meta.size, upload_type=tsk_stg.UploadType.IO_STREAM) boot_lu_name = pvm_u.sanitize_file_name_for_api( instance.name, prefix=disk_drv.DiskType.BOOT + '_') LOG.info('SSP: Disk name is %s', boot_lu_name, instance=instance) return tsk_stg.crt_lu(self._tier, boot_lu_name, instance.flavor.root_gb, typ=pvm_stg.LUType.DISK, clone=image_lu)[1]
def test_conflict_not_started(self): """Another upload is about to start when we get there.""" # Note that the conflicting process wins, even though its marker LU # name would lose to ours - because we don't get around to creating # ours. self.entries.append(self.confl_mkr_lu_lose) self.assertEqual( self.img_lu, cs.get_or_upload_image_lu(self.tier, self.img_lu.name, self.vios_uuid, self.mock_stream_func, self.b_size)) # I "waited" for the other guy to complete self.assertEqual(1, self.mock_sleep.call_count) # I did not create, upload, or remove anything self.mock_crt_lu.assert_not_called() self.mock_upload_lu.assert_not_called() self.mkr_lu.delete.assert_not_called() self.img_lu.delete.assert_not_called() # I pulled the feed the first time through, and once after the sleep self.assertEqual(2, self.mock_luent_srch.call_count) # Right number of LUs self.assertEqual(self.exp_num_lus, len(self.entries))