def test_crt_cfg_drv_vopt(self, mock_ccdi, mock_upl, mock_getsize, mock_attach, mock_ntf, mock_name): # Mock Returns cfg_dr_builder = m.ConfigDrivePowerVM(self.apt) cfg_dr_builder.vios_uuid = 'vios_uuid' mock_instance = mock.MagicMock() mock_instance.uuid = uuidsentinel.inst_id mock_upl.return_value = 'vopt', 'f_uuid' fh = mock_ntf.return_value.__enter__.return_value fh.name = 'iso_path' mock_name.return_value = 'fake-name' # Run cfg_dr_builder.create_cfg_drv_vopt(mock_instance, 'files', 'netinfo', 'fake_lpar', admin_pass='******') mock_ntf.assert_called_once_with(mode='rb') mock_ccdi.assert_called_once_with(cfg_dr_builder, mock_instance, 'files', 'netinfo', 'iso_path', admin_pass='******') mock_getsize.assert_called_once_with('iso_path') mock_upl.assert_called_once_with(self.apt, 'vios_uuid', fh, 'fake-name', mock_getsize.return_value) mock_attach.assert_called_once_with(mock_instance, 'fake_lpar', 'vopt', None)
def check_source(self, context, block_device_info, vol_drvs): """Check the source host Here we check the source host to see if it's capable of migrating the instance to the destination host. There may be conditions that can only be checked on the source side. Also, get the instance ready for the migration by removing any virtual optical devices attached to the LPAR. :param context: security context :param block_device_info: result of _get_instance_block_device_info :param vol_drvs: volume drivers for the attached volumes :returns: a dict containing migration info """ lpar_w = vm.get_instance_wrapper(self.drvr.adapter, self.instance, self.drvr.host_uuid) self.lpar_w = lpar_w LOG.debug('Dest Migration data: %s' % self.dest_data) # Only 'migrate_data' is sent to the destination on prelive call. mig_data = {'public_key': mgmt_task.get_public_key(self.drvr.adapter)} self.src_data['migrate_data'] = mig_data LOG.debug('Src Migration data: %s' % self.src_data) # Check proc compatability modes if (lpar_w.proc_compat_mode and lpar_w.proc_compat_mode not in self.dest_data['dest_proc_compat'].split(',')): raise LiveMigrationProcCompat( name=self.instance.name, mode=lpar_w.proc_compat_mode, modes=', '.join(self.dest_data['dest_proc_compat'].split(','))) # Check if VM is ready for migration self._check_migration_ready(lpar_w, self.drvr.host_wrapper) if lpar_w.migration_state != 'Not_Migrating': raise LiveMigrationInvalidState(name=self.instance.name, state=lpar_w.migration_state) # Check the number of migrations for capacity _verify_migration_capacity(self.drvr.host_wrapper, self.instance) # Get the 'source' pre-migration data for the volume drivers. Should # automatically update the mig_data dictionary as needed. for vol_drv in vol_drvs: vol_drv.pre_live_migration_on_source(mig_data) # Remove the VOpt devices LOG.debug('Removing VOpt.', instance=self.instance) media.ConfigDrivePowerVM(self.drvr.adapter, self.drvr.host_uuid).dlt_vopt(lpar_w.uuid) LOG.debug('Removing VOpt finished.', instance=self.instance) # Ensure the vterm is non-active vterm.close_vterm(self.drvr.adapter, lpar_w.uuid) return self.src_data
def test_crt_cfg_dr_iso(self, mock_mkdrv, mock_meta): """Validates that the image creation method works.""" cfg_dr_builder = m.ConfigDrivePowerVM(self.apt) mock_instance = mock.MagicMock() mock_instance.name = 'fake-instance' mock_instance.uuid = '1e46bbfd-73b6-3c2a-aeab-a1d3f065e92f' mock_files = mock.MagicMock() mock_net = mock.MagicMock() iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso( mock_instance, mock_files, mock_net) self.assertEqual('cfg_fake_instance.iso', file_name) self.assertEqual('/tmp/cfgdrv/cfg_fake_instance.iso', iso_path) # Make sure the length is limited properly mock_instance.name = 'fake-instance-with-name-that-is-too-long' iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso( mock_instance, mock_files, mock_net) self.assertEqual('cfg_fake_instance_with_name_that_.iso', file_name) self.assertEqual('/tmp/cfgdrv/cfg_fake_instance_with_name_that_.iso', iso_path) self.assertTrue(self.validate_vopt.called) # Test retry vopt create mock_mkdrv.reset_mock() mock_mkdrv.side_effect = [OSError, mock_mkdrv] mock_instance.name = 'fake-instance-2' iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso( mock_instance, mock_files, mock_net) self.assertEqual('cfg_fake_instance_2.iso', file_name) self.assertEqual('/tmp/cfgdrv/cfg_fake_instance_2.iso', iso_path) self.assertTrue(self.validate_vopt.called) self.assertEqual(mock_mkdrv.call_count, 2)
def test_validate_opt_vg(self): self.apt.read.side_effect = [self.vio_feed, self.vol_grp_resp] vg_update = self.vol_grp_resp.feed.entries[0] self.apt.update_by_path.return_value = vg_update cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host') self.assertEqual('1e46bbfd-73b6-3c2a-aeab-a1d3f065e92f', cfg_dr_builder.vg_uuid)
def test_dlt_vopt_no_map(self, mock_vop_valid, mock_vm_id, rm_vg_stor): feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)] ft_fx = pvm_fx.FeedTaskFx(feed) self.useFixture(ft_fx) # Set up the mock data. self.apt.read.side_effect = [self.vio_to_vg, self.vg_to_vio] mock_vm_id.return_value = '2' def validate_remove_stor(vg_w, vopts=None): vopts = {} if vopts is None else vopts self.assertIsInstance(vg_w, pvm_stor.VG) self.assertEqual(1, len(vopts)) self.assertIsInstance(vopts[0], pvm_stor.VOptMedia) rm_vg_stor.side_effect = validate_remove_stor # Count the number of SCSI mappings beforehand num_maps_before = len(feed[0].scsi_mappings) # Invoke the operation cfg_dr = m.ConfigDrivePowerVM(self.apt, 'fake_host') cfg_dr.vios_uuid = feed[0].uuid cfg_dr.dlt_vopt('2', remove_mappings=False) # The storage should have been removed self.assertTrue(rm_vg_stor.called) # The mappings should have changed self.assertTrue(ft_fx.patchers['update'].mock.called) # But the number should be the same (the vopt mapping was replaced) self.assertEqual(num_maps_before, len(feed[0].scsi_mappings))
def test_attach_vopt(self, mock_validate, mock_build_map, mock_add_map): # to act as the feed for FeedTaskFx and FeedTask. feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)] ft_fx = pvm_fx.FeedTaskFx(feed) self.useFixture(ft_fx) mock_instance = mock.MagicMock(name='fake-instance') cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host') cfg_dr_builder.vios_uuid = feed[0].uuid vopt = mock.Mock() self.apt.read.return_value = self.vio_to_vg def validate_build(host_uuid, vios_w, lpar_uuid, vopt_elem): self.assertEqual('fake_host', host_uuid) self.assertIsInstance(vios_w, pvm_vios.VIOS) self.assertEqual('lpar_uuid', lpar_uuid) self.assertEqual(vopt, vopt_elem) return 'map' mock_build_map.side_effect = validate_build def validate_add(vios_w, mapping): self.assertIsInstance(vios_w, pvm_vios.VIOS) self.assertEqual(mapping, 'map') return 'added' mock_add_map.side_effect = validate_add cfg_dr_builder._attach_vopt(mock_instance, 'lpar_uuid', vopt) # Make sure they were called and validated self.assertEqual(1, mock_build_map.call_count) self.assertEqual(1, mock_add_map.call_count) self.assertEqual(1, ft_fx.patchers['update'].mock.call_count)
def execute(self, lpar_wrap, mgmt_cna): LOG.info(_LI('Creating Config Drive for instance: %s'), self.instance.name) self.mb = media.ConfigDrivePowerVM(self.adapter, self.host_uuid) self.mb.create_cfg_drv_vopt(self.instance, self.injected_files, self.network_info, lpar_wrap.uuid, admin_pass=self.ad_pass, mgmt_cna=mgmt_cna, stg_ftsk=self.stg_ftsk)
def test_sanitize_network_info(self): network_info = [{'type': 'lbr'}, {'type': 'pvm_sea'}, {'type': 'ovs'}] cfg_dr_builder = m.ConfigDrivePowerVM(self.apt) resp = cfg_dr_builder._sanitize_network_info(network_info) expected_ret = [{'type': 'vif'}, {'type': 'vif'}, {'type': 'ovs'}] self.assertEqual(resp, expected_ret)
def execute(self, lpar_wrap, mgmt_cna): self.mb = media.ConfigDrivePowerVM(self.adapter) self.mb.create_cfg_drv_vopt(self.instance, self.injected_files, self.network_info, lpar_wrap.uuid, admin_pass=self.ad_pass, mgmt_cna=mgmt_cna, stg_ftsk=self.stg_ftsk)
def test_get_cfg_drv_name(self): cfg_dr_builder = m.ConfigDrivePowerVM(self.apt) mock_instance = mock.MagicMock() mock_instance.uuid = uuidsentinel.inst_id # calculate expected file name expected_file_name = 'cfg_' + mock_instance.uuid.replace('-', '') allowed_len = pvm_const.MaxLen.VOPT_NAME - 4 # '.iso' is 4 chars expected_file_name = expected_file_name[:allowed_len] + '.iso' name = cfg_dr_builder.get_cfg_drv_name(mock_instance) self.assertEqual(name, expected_file_name)
def test_dlt_vopt_no_map(self, mock_execute, mock_class_feed_task, mock_add_dlt_vopt_tasks, mock_find_maps): # Init objects to test with mock_feed_task = mock.MagicMock() mock_class_feed_task.return_value = mock_feed_task mock_find_maps.return_value = [] # Invoke the operation cfg_dr = m.ConfigDrivePowerVM(self.apt) cfg_dr.dlt_vopt('2', remove_mappings=False) # Verify expected methods were called mock_add_dlt_vopt_tasks.assert_not_called() self.assertTrue(mock_feed_task.execute.called)
def test_crt_cfg_drv_vopt(self, mock_attach, mock_upld, mock_rm, mock_size, mock_validate, mock_cfg_iso): # Mock Returns mock_cfg_iso.return_value = '/tmp/cfgdrv/fake.iso', 'fake.iso' mock_size.return_value = 10000 mock_upld.return_value = (mock.Mock(), None) # Run cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host') cfg_dr_builder.create_cfg_drv_vopt(mock.MagicMock(), mock.MagicMock(), mock.MagicMock(), 'fake_lpar') self.assertTrue(mock_upld.called) self.assertTrue(mock_attach.called) mock_attach.assert_called_with(mock.ANY, 'fake_lpar', mock.ANY, None)
def test_mgmt_cna_to_vif(self, mock_validate): mock_cna = mock.MagicMock() mock_cna.mac = "FAD4433ED120" # Run cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'fake_host') vif = cfg_dr_builder._mgmt_cna_to_vif(mock_cna) # Validate self.assertEqual(vif.get('address'), "fa:d4:43:3e:d1:20") self.assertEqual(vif.get('id'), 'mgmt_vif') self.assertIsNotNone(vif.get('network')) self.assertEqual(1, len(vif.get('network').get('subnets'))) subnet = vif.get('network').get('subnets')[0] self.assertEqual(6, subnet.get('version')) self.assertEqual('fe80::/64', subnet.get('cidr')) ip = subnet.get('ips')[0] self.assertEqual('fe80::f8d4:43ff:fe3e:d120', ip.get('address'))
def test_crt_cfg_dr_iso(self, mock_mkdrv, mock_meta, mock_vopt_valid): """Validates that the image creation method works.""" cfg_dr_builder = m.ConfigDrivePowerVM(self.apt, 'host_uuid') mock_instance = mock.MagicMock() mock_instance.name = 'fake-instance' mock_instance.uuid = '1e46bbfd-73b6-3c2a-aeab-a1d3f065e92f' mock_files = mock.MagicMock() mock_net = mock.MagicMock() iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso( mock_instance, mock_files, mock_net) self.assertEqual('cfg_fake_instance.iso', file_name) self.assertEqual('/tmp/cfgdrv/cfg_fake_instance.iso', iso_path) # Make sure the length is limited properly mock_instance.name = 'fake-instance-with-name-that-is-too-long' iso_path, file_name = cfg_dr_builder._create_cfg_dr_iso( mock_instance, mock_files, mock_net) self.assertEqual('cfg_fake_instance_with_name_that_.iso', file_name) self.assertEqual('/tmp/cfgdrv/cfg_fake_instance_with_name_that_.iso', iso_path)
def test_attach_vopt(self, mock_class_wrapper_task, mock_build_map, mock_add_map): # Create objects to test with mock_instance = mock.MagicMock(name='fake-instance') cfg_dr_builder = m.ConfigDrivePowerVM(self.apt) vopt = mock.Mock() mock_vios = mock.Mock(spec=pvm_vios.VIOS) mock_vios.configure_mock(name='vios name') # Mock methods not currently under test mock_wrapper_task = mock.MagicMock() mock_class_wrapper_task.return_value = mock_wrapper_task def call_param(param): param(mock_vios) mock_wrapper_task.add_functor_subtask.side_effect = call_param def validate_build(host_uuid, vios_w, lpar_uuid, vopt_elem): self.assertEqual(None, host_uuid) self.assertIsInstance(vios_w, pvm_vios.VIOS) self.assertEqual('lpar_uuid', lpar_uuid) self.assertEqual(vopt, vopt_elem) return 'map' mock_build_map.side_effect = validate_build def validate_add(vios_w, mapping): self.assertIsInstance(vios_w, pvm_vios.VIOS) self.assertEqual(mapping, 'map') return 'added' mock_add_map.side_effect = validate_add # Run the actual test cfg_dr_builder._attach_vopt(mock_instance, 'lpar_uuid', vopt) # Make sure they were called and validated self.assertTrue(mock_wrapper_task.execute.called) self.assertEqual(1, mock_build_map.call_count) self.assertEqual(1, mock_add_map.call_count) self.assertTrue(self.validate_vopt.called)
def test_add_dlt_vopt_tasks(self, mock_find_maps, mock_gen_match_func): # Init objects to test with cfg_dr = m.ConfigDrivePowerVM(self.apt) stg_ftsk = mock.MagicMock() cfg_dr.vios_uuid = 'vios_uuid' lpar_uuid = 'lpar_uuid' mock_find_maps.return_value = [mock.Mock(backing_storage='stor')] # Run cfg_dr.add_dlt_vopt_tasks(lpar_uuid, stg_ftsk) # Validate mock_gen_match_func.assert_called_with(pvm_stg.VOptMedia) mock_find_maps.assert_called_with( stg_ftsk.get_wrapper().scsi_mappings, client_lpar_id='2', match_func=mock_gen_match_func.return_value) self.assertTrue(stg_ftsk.add_post_execute.called) self.assertTrue( stg_ftsk.wrapper_tasks['vios_uuid'].add_functor_subtask.called)
def test_crt_cfg_dr_iso(self, mock_pvm_uuid, mock_mkdrv, mock_meta): """Validates that the image creation method works.""" cfg_dr_builder = m.ConfigDrivePowerVM(self.apt) self.assertTrue(self.validate_vopt.called) mock_instance = mock.MagicMock() mock_instance.uuid = '1e46bbfd-73b6-3c2a-aeab-a1d3f065e92f' mock_files = mock.MagicMock() mock_net = mock.MagicMock() iso_path = '/tmp/cfgdrv.iso' cfg_dr_builder._create_cfg_dr_iso(mock_instance, mock_files, mock_net, iso_path) self.assertTrue(mock_pvm_uuid.called) self.assertEqual(mock_mkdrv.call_count, 1) # Test retry iso create mock_mkdrv.reset_mock() mock_mkdrv.side_effect = [OSError, mock_mkdrv] cfg_dr_builder._create_cfg_dr_iso(mock_instance, mock_files, mock_net, iso_path) self.assertEqual(mock_mkdrv.call_count, 2)
def test_dlt_vopt(self, mock_vop_valid, mock_vm_id, rm_vg_stor): feed = [pvm_vios.VIOS.wrap(self.vio_to_vg)] ft_fx = pvm_fx.FeedTaskFx(feed) self.useFixture(ft_fx) # Set up the mock data. self.apt.read.side_effect = [self.vio_to_vg, self.vg_to_vio] mock_vm_id.return_value = '2' # Make sure that the first update is a VIO and doesn't have the vopt # mapping def validate_update(*kargs, **kwargs): vol_grp = kargs[0] # This is the VG update. Make sure there are no optical medias # anymore. self.assertEqual(0, len(vol_grp.vmedia_repos[0].optical_media)) return vol_grp.entry self.apt.update_by_path.side_effect = validate_update def validate_remove_stor(vg_w, vopts=None): vopts = {} if vopts is None else vopts self.assertIsInstance(vg_w, pvm_stor.VG) self.assertEqual(1, len(vopts)) self.assertIsInstance(vopts[0], pvm_stor.VOptMedia) rm_vg_stor.side_effect = validate_remove_stor # Count the number of SCSI mappings beforehand num_maps_before = len(feed[0].scsi_mappings) # Invoke the operation cfg_dr = m.ConfigDrivePowerVM(self.apt, 'fake_host') cfg_dr.vios_uuid = feed[0].uuid cfg_dr.dlt_vopt('2') self.assertEqual(num_maps_before - 1, len(feed[0].scsi_mappings)) self.assertTrue(ft_fx.patchers['update'].mock.called) self.assertTrue(rm_vg_stor.called)
def check_source(self, context, block_device_info, vol_drvs): """Check the source host Here we check the source host to see if it's capable of migrating the instance to the destination host. There may be conditions that can only be checked on the source side. Also, get the instance ready for the migration by removing any virtual optical devices attached to the LPAR. :param context: security context :param block_device_info: result of _get_instance_block_device_info :param vol_drvs: volume drivers for the attached volumes :returns: a PowerVMLiveMigrateData object """ lpar_w = vm.get_instance_wrapper(self.drvr.adapter, self.instance) self.lpar_w = lpar_w LOG.debug('Dest Migration data: %s', self.mig_data, instance=self.instance) # Check proc compatibility modes if (lpar_w.proc_compat_mode and lpar_w.proc_compat_mode not in self.mig_data.dest_proc_compat.split(',')): msg = (_("Cannot migrate %(name)s because its " "processor compatibility mode %(mode)s " "is not in the list of modes \"%(modes)s\" " "supported by the target host.") % dict(name=self.instance.name, mode=lpar_w.proc_compat_mode, modes=', '.join( self.mig_data.dest_proc_compat.split(',')))) raise exception.MigrationPreCheckError(reason=msg) # Check if VM is ready for migration self._check_migration_ready(lpar_w, self.drvr.host_wrapper) if lpar_w.migration_state != 'Not_Migrating': msg = (_("Live migration of instance '%(name)s' failed because " "the migration state is: %(state)s") % dict(name=self.instance.name, state=lpar_w.migration_state)) raise exception.MigrationPreCheckError(reason=msg) # Check the number of migrations for capacity _verify_migration_capacity(self.drvr.host_wrapper, self.instance) self.mig_data.public_key = mgmt_task.get_public_key(self.drvr.adapter) # Get the 'source' pre-migration data for the volume drivers. vol_data = {} for vol_drv in vol_drvs: vol_drv.pre_live_migration_on_source(vol_data) self.mig_data.vol_data = vol_data LOG.debug('Source migration data: %s', self.mig_data, instance=self.instance) # Create a FeedTask to scrub any orphaned mappings/storage associated # with this LPAR. (Don't run it yet - we want to do the VOpt removal # within the same FeedTask.) stg_ftsk = stor_task.ScrubOrphanStorageForLpar(self.drvr.adapter, lpar_w.id) # Add subtasks to remove the VOpt devices under the same FeedTask. media.ConfigDrivePowerVM(self.drvr.adapter).dlt_vopt( lpar_w.uuid, stg_ftsk=stg_ftsk, remove_mappings=False) # Now execute the FeedTask, performing both scrub and VOpt removal. stg_ftsk.execute() # Ensure the vterm is non-active vterm.close_vterm(self.drvr.adapter, lpar_w.uuid) return self.mig_data
def execute(self): media_builder = media.ConfigDrivePowerVM(self.adapter, self.host_uuid) media_builder.dlt_vopt(self.lpar_uuid, stg_ftsk=self.stg_ftsk)
def execute(self): media_builder = media.ConfigDrivePowerVM(self.adapter) media_builder.dlt_vopt(vm.get_pvm_uuid(self.instance), stg_ftsk=self.stg_ftsk)