def test_upload_new_vdisk_failure(self, mock_create_file): """Tests the failure path for uploading of the virtual disks.""" # First need to load in the various test responses. vg_orig = tju.load_file(UPLOAD_VOL_GRP_ORIG, self.adpt) vg_post_crt = tju.load_file(UPLOAD_VOL_GRP_NEW_VDISK, self.adpt) self.adpt.read.return_value = vg_orig self.adpt.update_by_path.return_value = vg_post_crt mock_create_file.return_value = self._fake_meta() self.assertRaises(exc.Error, ts.upload_new_vdisk, self.adpt, self.v_uuid, self.vg_uuid, None, 'test3', 50) # Test cleanup failure self.adpt.delete.side_effect = exc.Error('Something bad') f_wrap = ts.upload_new_vdisk(self.adpt, self.v_uuid, self.vg_uuid, None, 'test2', 50, sha_chksum='abc123') self.adpt.delete.assert_called_once_with( 'File', service='web', root_id='6233b070-31cc-4b57-99bd-37f80e845de9') self.assertIsNotNone(f_wrap)
def setUp(self): super(TestSCSIMapper, self).setUp() # Common Adapter self.adpt = self.useFixture(fx.AdapterFx()).adpt # Don't really sleep self.useFixture(fx.SleepFx()) # Fake URI mock_crt_href_p = mock.patch('pypowervm.wrappers.virtual_io_server.' 'VSCSIMapping.crt_related_href') self.mock_crt_href = mock_crt_href_p.start() self.addCleanup(mock_crt_href_p.stop) href = ('https://9.1.2.3:12443/rest/api/uom/ManagedSystem/' 'c5d782c7-44e4-3086-ad15-b16fb039d63b/LogicalPartition/' + LPAR_UUID) self.mock_crt_href.return_value = href # Mock the delay function, by overriding the sleep mock_delay_p = mock.patch('time.sleep') self.mock_delay = mock_delay_p.start() self.addCleanup(mock_delay_p.stop) self.v1resp = tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) self.v1wrap = pvm_vios.VIOS.wrap(self.v1resp) self.v2resp = tju.load_file(VIO_MULTI_MAP_FILE2, self.adpt) self.v2wrap = pvm_vios.VIOS.wrap(self.v2resp)
def test_upload_new_vdisk_coordinated(self, mock_create_file): """Tests the uploads of a virtual disk using the coordinated path.""" # Override adapter's traits to use the coordinated local API self.adptfx.set_traits(fx.LocalPVMTraits) # First need to load in the various test responses. vg_orig = tju.load_file(UPLOAD_VOL_GRP_ORIG, self.adpt) vg_post_crt = tju.load_file(UPLOAD_VOL_GRP_NEW_VDISK, self.adpt) self.adpt.read.return_value = vg_orig self.adpt.update_by_path.return_value = vg_post_crt mock_create_file.return_value = self._fake_meta() n_vdisk, f_wrap = ts.upload_new_vdisk( self.adpt, self.v_uuid, self.vg_uuid, None, 'test2', 50, d_size=25, sha_chksum='abc123') # Ensure the create file was called mock_create_file.assert_called_once_with( self.adpt, 'test2', vf.FileType.DISK_IMAGE_COORDINATED, self.v_uuid, f_size=50, tdev_udid='0300f8d6de00004b000000014a54555cd9.3', sha_chksum='abc123') # Ensure cleanup was called after the upload self.adpt.delete.assert_called_once_with( 'File', service='web', root_id='6233b070-31cc-4b57-99bd-37f80e845de9') self.assertIsNone(f_wrap) self.assertIsNotNone(n_vdisk) self.assertIsInstance(n_vdisk, stor.VDisk)
def setUp(self): super(TestPartition, self).setUp() self.adpt = self.useFixture( fx.AdapterFx(traits=fx.RemotePVMTraits)).adpt self.mgmt_vio = tju.load_file(VIO_FEED_WITH_MGMT, self.adpt) self.mgmt_lpar = tju.load_file(LPAR_FEED_WITH_MGMT, self.adpt) self.nomgmt_vio = tju.load_file(VIO_FEED_NO_MGMT, self.adpt) self.nomgmt_lpar = tju.load_file(LPAR_FEED_NO_MGMT, self.adpt)
def setUp(self, traits_type): super(TestIBMi, self).setUp() self.traits = traits_type self.apt = self.useFixture(pvm_fx.AdapterFx(traits=self.traits)).adpt self.vio_feed = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FEED, self.apt)) self.vioslist = [self.vio_feed[0], self.vio_feed[1]] self.cna_feed = pvm_net.CNA.wrap(tju.load_file(CNA_FEED, self.apt)) self.cnalist = [self.cna_feed[0], self.cna_feed[1]]
def setUp(self, traits_type): super(TestIBMi, self).setUp() self.traits = traits_type self.apt = self.useFixture(pvm_fx.AdapterFx( traits=self.traits)).adpt self.vio_feed = pvm_vios.VIOS.wrap( tju.load_file(VIOS_FEED, self.apt)) self.vioslist = [self.vio_feed[0], self.vio_feed[1]] self.cna_feed = pvm_net.CNA.wrap( tju.load_file(CNA_FEED, self.apt)) self.cnalist = [self.cna_feed[0], self.cna_feed[1]]
def setUp(self): super(TestScrub3, self).setUp() self.adpt = self.useFixture(fx.AdapterFx()).adpt self.vio_feed = [vios.VIOS.wrap(tju.load_file(VIOS_ENTRY2, self.adpt))] self.txfx = self.useFixture(fx.FeedTaskFx(self.vio_feed)) self.logfx = self.useFixture(fx.LoggingFx()) self.ftsk = tx.FeedTask('scrub', self.vio_feed)
def setUp(self): super(TestRMSTorage, self).setUp() self.adptfx = self.useFixture(fx.AdapterFx(traits=fx.RemotePVMTraits)) self.adpt = self.adptfx.adpt self.v_uuid = '14B854F7-42CE-4FF0-BD57-1D117054E701' self.vg_uuid = 'b6bdbf1f-eddf-3c81-8801-9859eb6fedcb' self.vg_resp = tju.load_file(UPLOAD_VOL_GRP_NEW_VDISK, self.adpt)
def test_ensure_ltm_monitors_non_default(self): """Verifies that the LTM monitors with different default inputs""" resp = tju.load_file('pcm_pref.txt') self.adpt.read_by_href.return_value = resp # Create a side effect that can validate the input to the update def validate_of_update(*kargs, **kwargs): element = kargs[0] etag = kargs[1] self.assertIsNotNone(element) # Wrap the element so we can validate it. pref = pvm_mon.PcmPref.wrap(pvm_e.Entry({'etag': etag}, element, self.adpt)) self.assertTrue(pref.compute_ltm_enabled) self.assertTrue(pref.ltm_enabled) self.assertFalse(pref.stm_enabled) self.assertTrue(pref.aggregation_enabled) return element self.adpt.update.side_effect = validate_of_update # This will invoke the validate_of_update pvm_t_mon.ensure_ltm_monitors(self.adpt, 'host_uuid', compute_ltm=True, override_to_default=True) # Make sure the update was in fact invoked though self.assertEqual(1, self.adpt.update.call_count)
def test_pre_live_migration_on_source(self, mock_fabric_names, mock_get_fabric_meta, mock_find_vios_for_vfc_wwpns): mock_fabric_names.return_value = ['A', 'B'] mock_get_fabric_meta.side_effect = [[('11', 'AA BB'), ('22', 'CC DD')], [('33', 'EE FF')]] vios_wraps = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FEED)) vios1_w = vios_wraps[0] def mock_client_adpt(slot): return mock.Mock(client_adapter=mock.Mock(lpar_slot_num=slot)) mock_find_vios_for_vfc_wwpns.side_effect = [ (vios1_w, mock_client_adpt(1)), (vios1_w, mock_client_adpt(2)), (vios1_w, mock_client_adpt(3)) ] # Execute the test mig_data = {} self.vol_drv.pre_live_migration_on_source(mig_data) self.assertEqual('[1, 2]', mig_data.get('src_npiv_fabric_slots_A')) self.assertEqual('[3]', mig_data.get('src_npiv_fabric_slots_B')) vios_peer_slots = jsonutils.loads(mig_data.get('src_vios_peer_slots')) self.assertItemsEqual([[1, 2, 3]], vios_peer_slots) # Ensure only string data is placed in the dict. for key in mig_data: self.assertEqual(str, type(mig_data[key]))
def test_derive_npiv_map_existing_no_preserve(self): # Use sample vios data with mappings. vios_file = 'fake_vios_mappings.txt' vios_w = pvm_vios.VIOS.wrap(tju.load_file(vios_file).entry) vios_wraps = [vios_w] # Subset the WWPNs on that VIOS p_wwpns = ['10000090FA1B6898', '10000090FA1B6899'] v_port_wwpns = ['c05076065a7c02e4', 'c05076065a7c02e5'] candidates = vfc_mapper._find_ports_on_vio(vios_w, p_wwpns) for p_port in candidates: if p_port.wwpn == p_wwpns[1]: # Artificially inflate the free ports so that it would get # chosen for a newly created mapping. p_port.set_parm_value('AvailablePorts', '64') # Run the derivation now resp = vfc_mapper.derive_npiv_map(vios_wraps, p_wwpns, v_port_wwpns, preserve=False) self.assertIsNotNone(resp) self.assertEqual(1, len(resp)) # Make sure we only got one phys port key back and it should *not* # match the existing mapping of 'preserve' testcase. unique_keys = set([i[0] for i in resp]) self.assertEqual({'10000090FA1B6899'}, unique_keys)
def test_crt_cna_no_vnet_crt(self, mock_vnet_find): """Tests the creation of Client Network Adapters. The virtual network creation shouldn't be done in this flow. """ # First need to load in the various test responses. vs = tju.load_file(VSWITCH_FILE) self.adpt.read.return_value = vs # PVMish Traits self.adptfx.set_traits(fx.LocalPVMTraits) # Create a side effect that can validate the input into the create # call. def validate_of_create(*kargs, **kwargs): self.assertIsNotNone(kargs[0]) self.assertEqual('LogicalPartition', kargs[1]) self.assertEqual('fake_lpar', kwargs.get('root_id')) self.assertEqual('ClientNetworkAdapter', kwargs.get('child_type')) return pvm_net.CNA.bld(self.adpt, 1, 'href').entry self.adpt.create.side_effect = validate_of_create n_cna = cna.crt_cna(self.adpt, 'fake_host', 'fake_lpar', 5) self.assertIsNotNone(n_cna) self.assertIsInstance(n_cna, pvm_net.CNA) self.assertEqual(0, mock_vnet_find.call_count)
def test_crt_cluster_ssp(self, mock_adp, mock_status, mock_monitor_job, mock_del_job): # Load up GET Cluster/do/Create (job template) mock_adp.read.return_value = tju.load_file(CREATE_CLUSTER, mock_adp) # We'll pretend the job ran and completed successfully mock_monitor_job.return_value = False mock_status.__get__ = mock.Mock( return_value=jwrap.JobStatus.COMPLETED_OK) # Mock Job.create_job to check job parameter values def create_job(job_el, entry_type, *args, **kwargs): self.assertEqual(entry_type, clust.Cluster.schema_type) job = jwrap.Job.wrap(ent.Entry({}, job_el, None)) param_vals = job._get_vals(u.xpath( 'JobParameters', 'JobParameter', 'ParameterValue')) self.assertEqual( param_vals[0], '<uom:Cluster xmlns:uom="http://www.ibm.com/xmlns/systems/powe' 'r/firmware/uom/mc/2012_10/" schemaVersion="V1_0"><uom:Metadat' 'a><uom:Atom/></uom:Metadata><uom:ClusterName>clust_name</uom:' 'ClusterName><uom:RepositoryDisk schemaVersion="V1_0"><uom:Phy' 'sicalVolume schemaVersion="V1_0"><uom:Metadata><uom:Atom/></u' 'om:Metadata><uom:VolumeName>repos_pv_name</uom:VolumeName></u' 'om:PhysicalVolume></uom:RepositoryDisk><uom:Node schemaVersio' 'n="V1_0"><uom:Node schemaVersion="V1_0"><uom:Metadata><uom:At' 'om/></uom:Metadata><uom:HostName>vios1</uom:HostName><uom:Par' 'titionID>5</uom:PartitionID><uom:MachineTypeModelAndSerialNum' 'ber schemaVersion="V1_0"><uom:Metadata><uom:Atom/></uom:Metad' 'ata><uom:MachineType>XXXX</uom:MachineType><uom:Model>YYY</uo' 'm:Model><uom:SerialNumber>ZZZZZZZ</uom:SerialNumber></uom:Mac' 'hineTypeModelAndSerialNumber><uom:VirtualIOServer href="https' '://a.example.com:12443/rest/api/uom/VirtualIOServer/12345678-' '1234-1234-1234-123456789012" rel="related"/></uom:Node></uom:' 'Node></uom:Cluster>') self.assertEqual( param_vals[1], '<uom:SharedStoragePool xmlns:uom="http://www.ibm.com/xmlns/sy' 'stems/power/firmware/uom/mc/2012_10/" schemaVersion="V1_0"><u' 'om:Metadata><uom:Atom/></uom:Metadata><uom:PhysicalVolumes sc' 'hemaVersion="V1_0"><uom:PhysicalVolume schemaVersion="V1_0"><' 'uom:Metadata><uom:Atom/></uom:Metadata><uom:VolumeName>hdisk1' '</uom:VolumeName></uom:PhysicalVolume><uom:PhysicalVolume sch' 'emaVersion="V1_0"><uom:Metadata><uom:Atom/></uom:Metadata><uo' 'm:VolumeName>hdisk2</uom:VolumeName></uom:PhysicalVolume><uom' ':PhysicalVolume schemaVersion="V1_0"><uom:Metadata><uom:Atom/' '></uom:Metadata><uom:VolumeName>hdisk3</uom:VolumeName></uom:' 'PhysicalVolume></uom:PhysicalVolumes><uom:StoragePoolName>ssp' '_name</uom:StoragePoolName></uom:SharedStoragePool>') return mock.MagicMock() mock_adp.create_job.side_effect = create_job node = clust.Node.bld( mock_adp, hostname='vios1', lpar_id=5, mtms='XXXX-YYY*ZZZZZZZ', vios_uri='https://a.example.com:12443/rest/api/uom/VirtualIOServe' 'r/12345678-1234-1234-1234-123456789012') repos = stor.PV.bld(mock_adp, name='repos_pv_name') data = [stor.PV.bld(mock_adp, name=n) for n in ( 'hdisk1', 'hdisk2', 'hdisk3')] cs.crt_cluster_ssp('clust_name', 'ssp_name', repos, node, data) # run_job() should run delete_job() at the end self.assertEqual(mock_del_job.call_count, 1)
def test_add_map(self): """Tests the add_map method.""" vio_resp = tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) vio_w = pvm_vios.VIOS.wrap(vio_resp) pv = pvm_stor.PV.bld(self.adpt, 'pv_name', 'pv_udid') scsi_map = scsi_mapper.build_vscsi_mapping('host_uuid', vio_w, LPAR_UUID, pv) # Get the original count orig_mappings = len(vio_w.scsi_mappings) # Add the actual mapping resp1 = scsi_mapper.add_map(vio_w, scsi_map) self.assertIsNotNone(resp1) self.assertIsInstance(resp1, pvm_vios.VSCSIMapping) # The mapping should return as None, as it is already there. resp2 = scsi_mapper.add_map(vio_w, scsi_map) self.assertIsNone(resp2) # Make sure only one was added. self.assertEqual(orig_mappings + 1, len(vio_w.scsi_mappings)) # Now make sure the mapping added can be found found = scsi_mapper.find_maps(vio_w.scsi_mappings, LPAR_UUID, stg_elem=pv) self.assertEqual(1, len(found)) self.assertEqual(scsi_map, found[0])
def test_find_map_port(self): vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) # Happy path, should find the first port on the VIOS p1 = vfc_mapper._find_map_port(vios_w.pfc_ports, []) self.assertIsNotNone(p1) # Lets add a mapping where P1 is used. Should not get that result # back. p2 = vfc_mapper._find_map_port(vios_w.pfc_ports, [(p1.wwpn, '')]) self.assertIsNotNone(p2) self.assertNotEqual(p1, p2) # Now add a third and fourth port. Same assertions. p3 = vfc_mapper._find_map_port(vios_w.pfc_ports, [(p1.wwpn, ''), (p2.wwpn, '')]) self.assertIsNotNone(p3) self.assertNotIn(p3, [p1, p2]) p4 = vfc_mapper._find_map_port(vios_w.pfc_ports, [(p1.wwpn, ''), (p2.wwpn, ''), (p3.wwpn, '')]) self.assertIsNotNone(p4) self.assertNotIn(p4, [p1, p2, p3]) # Artificially inflate the use of other ports. port_use = [(p1.wwpn, ''), (p2.wwpn, ''), (p3.wwpn, ''), (p4.wwpn, ''), (p1.wwpn, ''), (p2.wwpn, ''), (p4.wwpn, '')] p_temp = vfc_mapper._find_map_port(vios_w.pfc_ports, port_use) self.assertIsNotNone(p_temp) self.assertNotIn(p_temp, [p1, p2, p4])
def test_mapping_new_mapping(self): # Mock Data self.adpt.read.return_value = tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) # Validate that the mapping was added to existing def validate_update(*kargs, **kwargs): vios_w = kargs[0] self.assertEqual(6, len(vios_w.scsi_mappings)) # Make sure that the adapters do not match self.assertNotEqual(vios_w.scsi_mappings[0].client_adapter, vios_w.scsi_mappings[5].client_adapter) self.assertNotEqual(vios_w.scsi_mappings[0].server_adapter, vios_w.scsi_mappings[5].server_adapter) return vios_w.entry self.adpt.update_by_path.side_effect = validate_update # Create the new storage dev pv = pvm_stor.PV.bld(self.adpt, 'pv_name', 'pv_udid') # Run the code scsi_mapper.add_vscsi_mapping('host_uuid', 'vios_uuid', LPAR_UUID, pv, fuse_limit=5) # Make sure that our validation code above was invoked self.assertEqual(1, self.adpt.update_by_path.call_count)
def test_crt_cna_new_vswitch(self, mock_vnet_find): """Validates the create will also create the vSwitch.""" # First need to load in the various test responses. vs = tju.load_file(VSWITCH_FILE) self.adpt.read.return_value = vs # Create a side effect that can validate the input into the create # call. def validate_of_create(*kargs, **kwargs): self.assertIsNotNone(kargs[0]) if 'LogicalPartition' == kargs[1]: self.assertEqual('LogicalPartition', kargs[1]) self.assertEqual('fake_lpar', kwargs.get('root_id')) self.assertEqual('ClientNetworkAdapter', kwargs.get('child_type')) return pvm_net.CNA.bld(self.adpt, 1, 'href').entry else: # Is the vSwitch create self.assertEqual('ManagedSystem', kargs[1]) self.assertEqual('VirtualSwitch', kwargs.get('child_type')) # Return a previously created vSwitch... return pvm_net.VSwitch.wrap(vs)[0].entry self.adpt.create.side_effect = validate_of_create n_cna = cna.crt_cna(self.adpt, 'fake_host', 'fake_lpar', 5, vswitch='Temp', crt_vswitch=True) self.assertIsNotNone(n_cna)
def test_build_migration_mappings(self): vios_wraps = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FEED)) fabric_data = { 'A': { 'slots': [3, 4], 'p_port_wwpns': ["10000090FA5371F1", "10000090FA53720A"] }, 'B': { 'slots': [5, 6], 'p_port_wwpns': ["10000090FA5371F2", "10000090FA537209"] } } slot_peers = [[3, 5], [4, 6]] resp = vfc_mapper.build_migration_mappings(vios_wraps, fabric_data, slot_peers) self.assertEqual(4, len(resp)) self.assertEqual( set(resp), { '4/nimbus-ch03-p2-vios1/1//fcs1', '6/nimbus-ch03-p2-vios1/1//fcs0', '3/nimbus-ch03-p2-vios2/2//fcs0', '5/nimbus-ch03-p2-vios2/2//fcs1' }) fabric_data = { 'A': { 'slots': [3], 'p_port_wwpns': ["10000090FA5371F1"] }, 'B': { 'slots': [5, 6], 'p_port_wwpns': ["10000090FA5371F2", "10000090FA537209"] } } slot_peers = [[3, 5], [6]] resp = vfc_mapper.build_migration_mappings(vios_wraps, fabric_data, slot_peers) self.assertEqual(3, len(resp)) self.assertEqual( set(resp), { '5/nimbus-ch03-p2-vios2/2//fcs1', '3/nimbus-ch03-p2-vios2/2//fcs0', '6/nimbus-ch03-p2-vios1/1//fcs0' }) # Use invalid ports fabric_data = { 'A': { 'slots': [3], 'p_port_wwpns': ["10000090FA5371F1"] }, 'B': { 'slots': [5], 'p_port_wwpns': ["10000090FA537209"] } } slot_peers = [[3, 5]] self.assertRaises(e.UnableToFindFCPortMap, vfc_mapper.build_migration_mappings, vios_wraps, fabric_data, slot_peers)
def test_remove_hdisk_classic(self, mock_adapter, mock_run_job): mock_adapter.read.return_value = ( tju.load_file(VIOS_FEED).feed.entries[0]) fc._remove_hdisk_classic(mock_adapter, 'host_name', 'dev_name', 'vios_uuid') # Validate method invocations self.assertEqual(2, mock_adapter.read.call_count) self.assertEqual(1, mock_run_job.call_count)
def test_derive_npiv_map_existing_no_bp(self, mock_bp): vios_file = 'fake_vios_mappings.txt' vios_w = pvm_vios.VIOS.wrap(tju.load_file(vios_file).entry) # Subset the WWPNs on that VIOS p_wwpns = ['10000090FA1B6898', '10000090FA1B6899'] v_port_wwpns = ['c05076065a7c02e4', 'c05076065a7c02e5'] resp = vfc_mapper.derive_npiv_map([vios_w], p_wwpns, v_port_wwpns) # We shouldn't have returned the existing mapping that didn't have # a backing port. self.assertEqual([], resp)
def test_remove_storage_vopt_retry(self): """Tests removing the storage vOpt with multiple retries.""" # Mock Data. The retry will call this three times. They have to # be indepdent loads, otherwise the data gets re-used and the remove # will not be properly invoked. self.adpt.read.side_effect = [ tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) ] global attempt_count attempt_count = 0 # Validate that the mapping was removed from existing. First few # loops, force a retry def validate_update(*kargs, **kwargs): global attempt_count attempt_count += 1 if attempt_count == 3: vios_w = kargs[0] self.assertEqual(4, len(vios_w.scsi_mappings)) return vios_w.entry else: tju.raiseRetryException() self.adpt.update_by_path.side_effect = validate_update # Run the code media_name = 'bldr1_dfe05349_kyleh_config.iso' remel = scsi_mapper.remove_vopt_mapping(self.adpt, 'fake_vios_uuid', 2, media_name=media_name)[1] # Make sure that our validation code above was invoked self.assertEqual(3, self.adpt.update_by_path.call_count) self.assertEqual(3, attempt_count) self.assertEqual(1, len(remel)) self.assertIsInstance(remel[0], pvm_stor.VOptMedia)
def test_upload_new_vdisk_coordinated(self, mock_create_file): """Tests the uploads of a virtual disk using the coordinated path.""" # Override adapter's traits to use the coordinated local API self.adptfx.set_traits(fx.LocalPVMTraits) # First need to load in the various test responses. vg_orig = tju.load_file(UPLOAD_VOL_GRP_ORIG, self.adpt) vg_post_crt = tju.load_file(UPLOAD_VOL_GRP_NEW_VDISK, self.adpt) self.adpt.read.return_value = vg_orig self.adpt.update_by_path.return_value = vg_post_crt mock_create_file.return_value = self._fake_meta() n_vdisk, f_wrap = ts.upload_new_vdisk(self.adpt, self.v_uuid, self.vg_uuid, None, 'test2', 50, d_size=25, sha_chksum='abc123') # Ensure the create file was called mock_create_file.assert_called_once_with( self.adpt, 'test2', vf.FileType.DISK_IMAGE_COORDINATED, self.v_uuid, f_size=50, tdev_udid='0300f8d6de00004b000000014a54555cd9.3', sha_chksum='abc123') # Ensure cleanup was called after the upload self.adpt.delete.assert_called_once_with( 'File', service='web', root_id='6233b070-31cc-4b57-99bd-37f80e845de9') self.assertIsNone(f_wrap) self.assertIsNotNone(n_vdisk) self.assertIsInstance(n_vdisk, stor.VDisk)
def test_build_migration_mappings_for_fabric_invalid_physical_port(self): vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) vios_wraps = [vios_w] # Invalid WWPNs should raise an error. p_wwpns = ['10000090FA45477B'] client_slots = ['1', '2'] # Build migration mappings success case self.assertRaises(e.UnableToFindFCPortMap, vfc_mapper.build_migration_mappings_for_fabric, vios_wraps, p_wwpns, client_slots)
def setUp(self): super(TestISCSIAdapter, self).setUp() self.adpt = self.useFixture(pvm_fx.AdapterFx()).adpt self.vios_feed_resp = load_file(VIOS_FEED) self.feed = pvm_vios.VIOS.wrap(self.vios_feed_resp) self.ft_fx = pvm_fx.FeedTaskFx(self.feed) self.useFixture(self.ft_fx) self.adpt.read.return_value = self.vios_feed_resp @mock.patch('pypowervm.wrappers.virtual_io_server.VIOS', autospec=True) @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid') @mock.patch('pypowervm.tasks.partition.get_mgmt_partition', autospec=True) @mock.patch('pypowervm.tasks.hdisk.discover_iscsi_initiator', autospec=True) def init_vol_adpt(mock_initiator, mock_mgmt_part, mock_pvm_uuid, mock_vios): self.trans_type = 'iscsi' self.iqn = 'iqn.2016-08.bar.foo:target' self.lun = '1' self.host_ip = '10.0.0.1' self.user = '******' self.password = '******' self.serial = 'f042c68a-c5a5-476a-ba34-2f6d43f4226c' con_info = { 'serial': self.serial, 'driver_volume_type': self.trans_type, 'data': { 'target_iqn': self.iqn, 'target_lun': self.lun, 'target_portal': self.host_ip, 'auth_username': self.user, 'auth_password': self.password }, } mock_inst = mock.MagicMock() mock_pvm_uuid.return_value = '1234' mock_initiator.return_value = 'initiatior iqn' # The getter can just return the VIOS values (to remove a read # that would otherwise need to be mocked). mock_vios.getter.return_value = self.feed return iscsi.IscsiVolumeAdapter(self.adpt, 'host_uuid', mock_inst, con_info) self.vol_drv = init_vol_adpt() # setup system_metadata tests self.devname = "/dev/fake" self.slot_mgr = mock.Mock() self.slot_mgr.build_map.get_vscsi_slot.return_value = 62, 'the_lua'
def test_separate_mappings(self): vios_wrap = pvm_vios.VIOS.wrap(tju.load_file(VIO_MULTI_MAP_FILE2, self.adpt)) client_href = ('https://9.1.2.3:12443/rest/api/uom/ManagedSystem/' '726e9cb3-6576-3df5-ab60-40893d51d074/LogicalPartition/' '0C0A6EBE-7BF4-4707-8780-A140F349E42E') sep = scsi_mapper._separate_mappings(vios_wrap, client_href) self.assertEqual(2, len(sep)) self.assertEqual( {'1eU8246.L2C.0604C7A-V1-C13', '1eU8246.L2C.0604C7A-V1-C25'}, set(sep.keys())) self.assertEqual(sep['1eU8246.L2C.0604C7A-V1-C13'][0], vios_wrap.scsi_mappings[-1])
def test_query_ltm_feed(self): self.adpt.read_by_path.return_value = tju.load_file(LTM_FEED) feed = pvm_t_mon.query_ltm_feed(self.adpt, 'host_uuid') # Make sure the feed is correct. Our sample data has 130 elements # in the feed. self.assertEqual(130, len(feed)) # Make sure each element is a LTMMetric for mon in feed: self.assertIsInstance(mon, pvm_mon.LTMMetrics) self.assertEqual(1, self.adpt.read_by_path.call_count)
def test_remove_storage_vopt_retry(self): """Tests removing the storage vOpt with multiple retries.""" # Mock Data. The retry will call this three times. They have to # be indepdent loads, otherwise the data gets re-used and the remove # will not be properly invoked. self.adpt.read.side_effect = [ tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt)] global attempt_count attempt_count = 0 # Validate that the mapping was removed from existing. First few # loops, force a retry def validate_update(*kargs, **kwargs): global attempt_count attempt_count += 1 if attempt_count == 3: vios_w = kargs[0] self.assertEqual(4, len(vios_w.scsi_mappings)) return vios_w.entry else: tju.raiseRetryException() self.adpt.update_by_path.side_effect = validate_update # Run the code media_name = 'bldr1_dfe05349_kyleh_config.iso' vios, remel = scsi_mapper.remove_vopt_mapping( self.adpt, 'fake_vios_uuid', 2, media_name=media_name) # Make sure that our validation code above was invoked self.assertEqual(3, self.adpt.update_by_path.call_count) self.assertEqual(3, attempt_count) self.assertEqual(1, len(remel)) self.assertIsInstance(remel[0], pvm_stor.VOptMedia)
def test_crt_lu_linked_clone(self, mock_run_job): clust1 = clust.Cluster.wrap(tju.load_file(CLUSTER, self.adpt)) self.adpt.read.return_value = tju.load_file(LU_LINKED_CLONE_JOB, self.adpt) def verify_run_job(uuid, job_parms): self.assertEqual(clust1.uuid, uuid) self.assertEqual( '<web:JobParameter xmlns:web="http://www.ibm.com/xmlns/systems' '/power/firmware/web/mc/2012_10/" schemaVersion="V1_0"><web:Pa' 'rameterName>SourceUDID</web:ParameterName><web:ParameterValue' '>xxabc1231</web:ParameterValue></web:JobParameter>'.encode( 'utf-8'), job_parms[0].toxmlstring()) self.assertEqual( '<web:JobParameter xmlns:web="http://www.ibm.com/xmlns/systems' '/power/firmware/web/mc/2012_10/" schemaVersion="V1_0"><web:Pa' 'rameterName>DestinationUDID</web:ParameterName><web:Parameter' 'Value>udid_linked_lu</web:ParameterValue></web:JobParameter>'. encode('utf-8'), job_parms[1].toxmlstring()) mock_run_job.side_effect = verify_run_job ts.crt_lu_linked_clone(self.ssp, clust1, self.ssp.logical_units[0], 'linked_lu')
def test_mapping_retry(self): """Tests that a mapping function will be retried.""" # Mock Data. Need to load this once per retry, or else the mappings # get appended with each other. self.adpt.read.side_effect = [ tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) ] global attempt_count attempt_count = 0 # Validate that the mapping was added to existing. First few times # through loop, force a retry exception def validate_update(*kargs, **kwargs): global attempt_count attempt_count += 1 if attempt_count == 3: vios_w = kargs[0] self.assertEqual(6, len(vios_w.scsi_mappings)) return vios_w.entry else: tju.raiseRetryException() self.adpt.update_by_path.side_effect = validate_update # Create the new storage dev pv = pvm_stor.PV.bld(self.adpt, 'pv_name', 'pv_udid') # Run the code scsi_mapper.add_vscsi_mapping('host_uuid', 'vios_uuid', LPAR_UUID, pv) # Make sure that our validation code above was invoked self.assertEqual(3, self.adpt.update_by_path.call_count) self.assertEqual(3, attempt_count)
def test_remove_storage_vopt(self): # Mock Data self.adpt.read.return_value = tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) # Validate that the mapping was removed from existing def validate_update(*kargs, **kwargs): vios_w = kargs[0] self.assertEqual(4, len(vios_w.scsi_mappings)) return vios_w.entry self.adpt.update_by_path.side_effect = validate_update # Run the code media_name = 'bldr1_dfe05349_kyleh_config.iso' vios, remel = scsi_mapper.remove_vopt_mapping( self.adpt, 'fake_vios_uuid', 2, media_name=media_name) # Make sure that our validation code above was invoked self.assertEqual(1, self.adpt.update_by_path.call_count) self.assertEqual(1, len(remel)) self.assertIsInstance(remel[0], pvm_stor.VOptMedia) # And the VIOS was "looked up" self.assertEqual(1, self.adpt.read.call_count) # Now do it again, but passing the vios wrapper and the client UUID vios_wrap = pvm_vios.VIOS.wrap( tju.load_file(VIO_MULTI_MAP_FILE, self.adpt)) self.adpt.update_by_path.reset_mock() self.adpt.read.reset_mock() vios, remel = scsi_mapper.remove_vopt_mapping( self.adpt, vios_wrap, LPAR_UUID, media_name=media_name) self.assertEqual(1, self.adpt.update_by_path.call_count) self.assertEqual(1, len(remel)) self.assertIsInstance(remel[0], pvm_stor.VOptMedia) # But the VIOS was not "looked up" self.assertEqual(0, self.adpt.read.call_count)
def test_mapping_retry(self): """Tests that a mapping function will be retried.""" # Mock Data. Need to load this once per retry, or else the mappings # get appended with each other. self.adpt.read.side_effect = [ tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt), tju.load_file(VIO_MULTI_MAP_FILE, self.adpt)] global attempt_count attempt_count = 0 # Validate that the mapping was added to existing. First few times # through loop, force a retry exception def validate_update(*kargs, **kwargs): global attempt_count attempt_count += 1 if attempt_count == 3: vios_w = kargs[0] self.assertEqual(6, len(vios_w.scsi_mappings)) return vios_w.entry else: tju.raiseRetryException() self.adpt.update_by_path.side_effect = validate_update # Create the new storage dev pv = pvm_stor.PV.bld(self.adpt, 'pv_name', 'pv_udid') # Run the code scsi_mapper.add_vscsi_mapping('host_uuid', 'vios_uuid', LPAR_UUID, pv) # Make sure that our validation code above was invoked self.assertEqual(3, self.adpt.update_by_path.call_count) self.assertEqual(3, attempt_count)
def test_derive_npiv_map_failure(self): """Make sure we get a failure in the event of no candidates.""" vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) vios_wraps = [vios_w] # Subset the WWPNs on that VIOS. These WWPNs don't actually exist, # so the VIOSes passed in won't have these as candidate ports. p_wwpns = ['10000090FA45473bA', '10:00:00:90:fa:45:17:58A'] # Virtual WWPNs can be faked, and simplified. v_port_wwpns = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] # Run the derivation now self.assertRaises(e.UnableToFindFCPortMap, vfc_mapper.derive_npiv_map, vios_wraps, p_wwpns, v_port_wwpns)
def test_crt_lu_linked_clone(self, mock_run_job): clust1 = clust.Cluster.wrap(tju.load_file(CLUSTER, self.adpt)) self.adpt.read.return_value = tju.load_file(LU_LINKED_CLONE_JOB, self.adpt) def verify_run_job(uuid, job_parms): self.assertEqual(clust1.uuid, uuid) self.assertEqual( '<web:JobParameter xmlns:web="http://www.ibm.com/xmlns/systems' '/power/firmware/web/mc/2012_10/" schemaVersion="V1_0"><web:Pa' 'rameterName>SourceUDID</web:ParameterName><web:ParameterValue' '>xxabc1231</web:ParameterValue></web:JobParameter>'. encode('utf-8'), job_parms[0].toxmlstring()) self.assertEqual( '<web:JobParameter xmlns:web="http://www.ibm.com/xmlns/systems' '/power/firmware/web/mc/2012_10/" schemaVersion="V1_0"><web:Pa' 'rameterName>DestinationUDID</web:ParameterName><web:Parameter' 'Value>udid_linked_lu</web:ParameterValue></web:JobParameter>'. encode('utf-8'), job_parms[1].toxmlstring()) mock_run_job.side_effect = verify_run_job ts.crt_lu_linked_clone(self.ssp, clust1, self.ssp.logical_units[0], 'linked_lu')
def test_derive_npiv_map_multi_vio(self): vios_wraps = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FEED)) # Subset the WWPNs on that VIOS p_wwpns = ['10000090FA5371F2', '10000090FA53720A'] # Virtual WWPNs can be faked, and simplified. v_port_wwpns = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] # Run the derivation now resp = vfc_mapper.derive_npiv_map(vios_wraps, p_wwpns, v_port_wwpns) self.assertIsNotNone(resp) self.assertEqual(5, len(resp)) # Make sure we only get two unique keys back. unique_keys = set([i[0] for i in resp]) self.assertEqual(set(p_wwpns), unique_keys)
def test_index_mappings(self): vwrap = pvm_vios.VIOS.wrap(tju.load_file(VIO_MULTI_MAP_FILE2, self.adpt)) idx = scsi_mapper.index_mappings(vwrap.scsi_mappings) self.assertEqual({ 'by-lpar-id', 'by-lpar-uuid', 'by-storage-udid'}, set(idx.keys())) exp_lpar_ids = ('2', '5', '6', '7', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '27', '28', '29', '33', '35', '36', '39', '40') self.assertEqual(set(exp_lpar_ids), set(idx['by-lpar-id'].keys())) # Each mapping has a different LPAR ID, so each LPAR ID only has one # mapping for lpar_id in exp_lpar_ids: maplist = idx['by-lpar-id'][lpar_id] self.assertEqual(1, len(maplist)) self.assertIsInstance(maplist[0], pvm_vios.VSCSIMapping) self.assertEqual(lpar_id, str(maplist[0].server_adapter.lpar_id)) # Not all mappings have client_lpar_href, so this list is shorter. exp_lpar_uuids = ('0C0A6EBE-7BF4-4707-8780-A140F349E42E', '0FB69DD7-4B93-4C09-8916-8BC9821ABAAC', '263EE77B-AD6E-4920-981A-4B7D245B8571', '292ACAF5-C96B-447A-8C7E-7503D80AA33E', '32AA6AA5-CCE6-4523-860C-0852455036BE', '3CE30EC6-C98A-4A58-A764-09DAC7C324BC', '615C9134-243D-4A11-93EB-C0556664B761', '7CFDD55B-E0D7-4B8C-8254-9305E31BB1DC') self.assertEqual(set(exp_lpar_uuids), set(idx['by-lpar-uuid'].keys())) # Of ten mappings with client_lpar_href, three have the same UUID. for lpar_uuid in exp_lpar_uuids: maplist = idx['by-lpar-uuid'][lpar_uuid] for smap in maplist: self.assertIsInstance(smap, pvm_vios.VSCSIMapping) self.assertTrue(smap.client_lpar_href.endswith(lpar_uuid)) if lpar_uuid == '0C0A6EBE-7BF4-4707-8780-A140F349E42E': self.assertEqual(3, len(maplist)) else: self.assertEqual(1, len(maplist)) # Only five mappings have storage, and all are different self.assertEqual(5, len(idx['by-storage-udid'].keys())) for sudid in idx['by-storage-udid']: self.assertEqual(1, len(idx['by-storage-udid'][sudid]))
def test_derive_npiv_map(self): vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) vios_wraps = [vios_w] # Subset the WWPNs on that VIOS p_wwpns = ['10000090FA45473B', '10:00:00:90:fa:45:17:58'] # Virtual WWPNs can be faked, and simplified. v_port_wwpns = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] # Run the derivation now resp = vfc_mapper.derive_npiv_map(vios_wraps, p_wwpns, v_port_wwpns) self.assertIsNotNone(resp) self.assertEqual(5, len(resp)) # Make sure we only get two unique keys back. unique_keys = set([i[0] for i in resp]) self.assertEqual({'10000090FA45473B', '10000090FA451758'}, unique_keys)
def test_build_migration_mappings_for_fabric(self, mock_derive): vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) vios_wraps = [vios_w] # Subset the WWPNs on that VIOS p_wwpns = ['10000090FA45473B', '10:00:00:90:fa:45:17:58'] client_slots = ['1', '2'] # The derive is non-deterministic. That makes testing odd. Force # a deterministic result. mock_derive.return_value = [('10000090FA451758', 'A A'), ('10000090FA45473B', 'B B')] # Build migration mappings success case resp = vfc_mapper.build_migration_mappings_for_fabric( vios_wraps, p_wwpns, client_slots) self.assertEqual(2, len(resp)) self.assertEqual({'1/IO Server/1//fcs2', '2/IO Server/1//fcs1'}, set(resp))
def test_derive_base_npiv_map(self): vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) vios_wraps = [vios_w] # Subset the WWPNs on that VIOS p_wwpns = ['10000090FA45473B', '10:00:00:90:fa:45:17:58'] # Run the derivation now resp = vfc_mapper.derive_base_npiv_map(vios_wraps, p_wwpns, 5) self.assertIsNotNone(resp) self.assertEqual(5, len(resp)) # Make sure we only get two unique keys back. unique_keys = set([i[0] for i in resp]) self.assertEqual({'10000090FA45473B', '10000090FA451758'}, unique_keys) # Make sure we get the 'marker' back for the values. Should now be # fused. values = set(i[1] for i in resp) self.assertEqual({vfc_mapper._FUSED_ANY_WWPN}, values)
def test_find_vios_for_wwpn(self): vios_w = pvm_vios.VIOS.wrap(tju.load_file(VIOS_FILE).entry) vios_feed_w = [vios_w] # Basic test vio_resp, p_resp = vfc_mapper.find_vios_for_wwpn( vios_feed_w, '10000090FA45473B') self.assertEqual(vios_w, vio_resp) self.assertIsNotNone(p_resp) # Validates the sanitized input vio_resp, p_resp = vfc_mapper.find_vios_for_wwpn( vios_feed_w, '10:00:00:90:fa:45:47:3b') self.assertEqual(vios_w, vio_resp) self.assertIsNotNone(p_resp) # Make sure a bad WWPN returns no result vio_resp, p_resp = vfc_mapper.find_vios_for_wwpn( vios_feed_w, '10:00:00:90:fa:45:47:3f') self.assertIsNone(vio_resp) self.assertIsNone(p_resp)
def test_remove_pv_mapping(self): # Mock Data self.adpt.read.return_value = tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) # Validate that the mapping was removed to existing def validate_update(*kargs, **kwargs): vios_w = kargs[0] self.assertEqual(4, len(vios_w.scsi_mappings)) return vios_w.entry self.adpt.update_by_path.side_effect = validate_update # Run the code vios, remel = scsi_mapper.remove_pv_mapping( self.adpt, 'fake_vios_uuid', 2, 'hdisk10') # Make sure that our validation code above was invoked self.assertEqual(1, self.adpt.update_by_path.call_count) self.assertEqual(1, len(remel)) self.assertIsInstance(remel[0], pvm_stor.PV)
def test_mapping(self): # Mock Data vio_resp = tju.load_file(VIO_MULTI_MAP_FILE, self.adpt) self.adpt.read.return_value = vio_resp # Validate that the mapping was added to existing def validate_update(*kargs, **kwargs): vios_w = kargs[0] self.assertEqual(6, len(vios_w.scsi_mappings)) self.assertEqual(vios_w.scsi_mappings[0].client_adapter, vios_w.scsi_mappings[4].client_adapter) self.assertEqual(vios_w.scsi_mappings[0].server_adapter, vios_w.scsi_mappings[4].server_adapter) return vios_w.entry self.adpt.update_by_path.side_effect = validate_update # Create the new storage dev pv = pvm_stor.PV.bld(self.adpt, 'pv_name', 'pv_udid') # Run the code scsi_mapper.add_vscsi_mapping('host_uuid', 'vios_uuid', LPAR_UUID, pv) # Make sure that our validation code above was invoked self.assertEqual(1, self.adpt.update_by_path.call_count) # And the VIOS was "looked up" self.assertEqual(1, self.adpt.read.call_count) # Now do it again, but passing the vios wrapper vios_wrap = pvm_vios.VIOS.wrap(vio_resp) self.adpt.update_by_path.reset_mock() self.adpt.read.reset_mock() scsi_mapper.add_vscsi_mapping('host_uuid', vios_wrap, LPAR_UUID, pv) # Since the mapping already existed, our update mock was not called self.assertEqual(0, self.adpt.update_by_path.call_count) # And the VIOS was not "looked up" self.assertEqual(0, self.adpt.read.call_count)
def test_find_stale_lpars(self): self.adpt.read.return_value = tju.load_file(LPAR_FEED, adapter=self.adpt) vwrap = vios.VIOS.wrap(tju.load_file(VIOS_ENTRY, adapter=self.adpt)) self.assertEqual({55, 21}, set(ts.find_stale_lpars(vwrap)))
def _fake_meta(self): """Returns a fake meta class for the _create_file mock.""" resp = tju.load_file(UPLOADED_FILE, self.adpt) return vf.File.wrap(resp)