def _ensure_phys_ports_for_system(self, npiv_port_maps, vios_wraps, fabric): """Ensures that the npiv_port_map is correct for the system. Rare scenarios can occur where the physical port on the NPIV port map does not match the actual port. This is generally caused when the last volume is removed from the VM, the VM is migrated to another host, and then a new volume is attached. Stale metadata would be there (as it can't be cleaned out) on the attach. This method clears that up. :param npiv_port_maps: The existing port maps. :param vios_wraps: The Virtual I/O Server wraps. :param fabric: The name of the fabric :return: The npiv_port_maps. May be unchanged. """ # Check that all physical ports in the mappings belong to 'this' # set of VIOSs. if all( pvm_vfcm.find_vios_for_wwpn(vios_wraps, pm[0])[0] for pm in npiv_port_maps): LOG.debug( "All physical ports were found on the given Virtual I/O " "Server(s).", instance=self.instance) return npiv_port_maps # If ANY of the VIOS ports were not there, rebuild the port maps LOG.debug("Rebuild existing_npiv_port_maps=%s. Reset fabric state.", npiv_port_maps, instance=self.instance) v_wwpns = [] for port_map in npiv_port_maps: v_wwpns.extend(port_map[1].split()) self._set_fabric_state(fabric, FS_UNMAPPED) # Derive new maps and don't preserve existing maps npiv_port_maps = pvm_vfcm.derive_npiv_map(vios_wraps, self._fabric_ports(fabric), v_wwpns, preserve=False) LOG.debug("Rebuilt port maps: %s", npiv_port_maps, instance=self.instance) self._set_fabric_meta(fabric, npiv_port_maps) LOG.warning( "Had to update the system metadata for the WWPNs due to " "incorrect physical WWPNs on fabric %(fabric)s", {'fabric': fabric}, instance=self.instance) return npiv_port_maps
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 _ensure_phys_ports_for_system(self, npiv_port_maps, vios_wraps, fabric): """Ensures that the npiv_port_map is correct for the system. Rare scenarios can occur where the physical port on the NPIV port map does not match the actual port. This is generally caused when the last volume is removed from the VM, the VM is migrated to another host, and then a new volume is attached. Stale metadata would be there (as it can't be cleaned out) on the attach. This method clears that up. :param npiv_port_maps: The existing port maps. :param vios_wraps: The Virtual I/O Server wraps. :param fabric: The name of the fabric :return: The npiv_port_maps. May be unchanged. """ # Check that all physical ports in the mappings belong to 'this' # set of VIOSs. if all(pvm_vfcm.find_vios_for_wwpn(vios_wraps, pm[0])[0] for pm in npiv_port_maps): LOG.debug("Physical ports check out - just return maps.") return npiv_port_maps # If ANY of the VIOS ports were not there, rebuild the port maps LOG.debug("Rebuild existing_npiv_port_maps=%s. Reset fabric state." % npiv_port_maps) v_wwpns = [] for port_map in npiv_port_maps: v_wwpns.extend(port_map[1].split()) self._set_fabric_state(fabric, FS_UNMAPPED) # Derive new maps and don't preserve existing maps npiv_port_maps = pvm_vfcm.derive_npiv_map( vios_wraps, self._fabric_ports(fabric), v_wwpns, preserve=False) LOG.debug("Rebuilt port maps: %s" % npiv_port_maps) self._set_fabric_meta(fabric, npiv_port_maps) LOG.warning(_LW("Had to update the system metadata for the WWPNs " "due to incorrect physical WWPNs on fabric " "%(fabric)s"), {'fabric': fabric}, instance=self.instance) return npiv_port_maps