Пример #1
0
def has_client_wwpns(vios_wraps, client_wwpn_pair):
    """Returns the vios wrapper and vfc map if the client WWPNs already exist.

    :param vios_wraps: The VIOS wrappers.  Should be queried with the
                       VIO_FMAP extended attribute.
    :param client_wwpn_pair: The pair (list or set) of the client WWPNs.
    :return vios_w: The VIOS wrapper containing the wwpn pair.  None if none
                    of the wrappers contain the pair.
    :return vfc_map: The mapping containing the client pair.  May be None.
    """
    client_wwpn_pair = set(
        [u.sanitize_wwpn_for_api(x) for x in client_wwpn_pair])

    for vios_wrap in vios_wraps:
        for vfc_map in vios_wrap.vfc_mappings:
            if vfc_map.client_adapter is None:
                continue

            pair = set([
                u.sanitize_wwpn_for_api(x)
                for x in vfc_map.client_adapter.wwpns
            ])
            if pair == client_wwpn_pair:
                return vios_wrap, vfc_map

    return None, None
Пример #2
0
def intersect_wwpns(wwpn_set1, wwpn_set2):
    """Will return the intersection of WWPNs between the two sets.

    :param wwpn_set1: A list of WWPNs.
    :param wwpn_set2: A list of WWPNs.
    :return: The intersection of the WWPNs.  Will maintain the WWPN format
             of wwpn_set1, but the comparison done will be agnostic of
             formats (ex. colons and/or upper/lower case).
    """
    wwpn_set2 = [u.sanitize_wwpn_for_api(x) for x in wwpn_set2]
    return [y for y in wwpn_set1 if u.sanitize_wwpn_for_api(y) in wwpn_set2]
Пример #3
0
def find_vios_for_vfc_wwpns(vios_wraps, vfc_wwpns):
    """Will find the VIOS that is hosting the vfc_wwpns.

    :param vios_wraps: A list or set of VIOS wrappers.
    :param vfc_wwpns: The list or set of virtual fibre channel WWPNs.
    :return: The VIOS wrapper that supports the vfc adapters.  If there is not
             one, then None will be returned.
    :return: The VFCMapping on the VIOS that supports the client adapters.
    """
    # Sanitize our input
    vfc_wwpns = {u.sanitize_wwpn_for_api(x) for x in vfc_wwpns}
    for vios_w in vios_wraps:
        for vfc_map in vios_w.vfc_mappings:
            # If the map has no client adapter...then move on
            if not vfc_map.client_adapter:
                continue

            # Maps without backing ports are effectively stale. We shouldn't
            # consider them.
            if vfc_map.backing_port is None:
                continue

            # If the WWPNs match, return it
            if vfc_wwpns == set(vfc_map.client_adapter.wwpns):
                return vios_w, vfc_map
    return None, None
Пример #4
0
def find_vios_for_wwpn(vios_wraps, p_port_wwpn):
    """Will find the VIOS that has a PhysFCPort for the p_port_wwpn.

    :param vios_wraps: A list or set of VIOS wrappers.
    :param p_port_wwpn: The physical port's WWPN.
    :return: The VIOS wrapper that contains a physical port with the WWPN.
             If there is not one, then None will be returned.
    :return: The port (which is a PhysFCPort wrapper) on the VIOS wrapper that
             represents the physical port.
    """
    # Sanitize our input
    s_p_port_wwpn = u.sanitize_wwpn_for_api(p_port_wwpn)
    for vios_w in vios_wraps:
        for port in vios_w.pfc_ports:
            # No need to sanitize the API WWPN, it comes from the API.
            if u.sanitize_wwpn_for_api(port.wwpn) == s_p_port_wwpn:
                return vios_w, port
    return None, None
Пример #5
0
def add_map(vios_w, host_uuid, lpar_uuid, port_map, error_if_invalid=True):
    """Adds a vFC mapping to a given VIOS wrapper.

    These changes are not flushed back to the REST server.  The wrapper itself
    is simply modified.

    :param vios_w: VIOS EntryWrapper representing the Virtual I/O Server whose
                   VFC mappings are to be updated.
    :param host_uuid: The pypowervm UUID of the host.
    :param lpar_uuid: The pypowervm UUID of the client LPAR to attach to.
    :param port_map: The port mapping (as defined by the derive_npiv_map
                     method).
    :param error_if_invalid: (Optional, Default: True) If the port mapping
                             physical port can not be found, raise an error.
    :return: The VFCMapping that was added.  If the mapping already existed
             then None is returned.
    """
    # This is meant to find the physical port.  Can run against a single
    # element.  We assume invoker has passed correct VIOS.
    new_vios_w, p_port = find_vios_for_wwpn([vios_w], port_map[0])
    if new_vios_w is None:
        if error_if_invalid:
            # Log the payload in the response.
            LOG.warn(_("Unable to find appropriate VIOS.  The payload "
                       "provided was likely insufficient.  The payload data "
                       "is:\n %s)"), vios_w.toxmlstring())
            raise e.UnableToDerivePhysicalPortForNPIV(wwpn=port_map[0],
                                                      vio_uri=vios_w.href)
        else:
            return None

    v_wwpns = None
    if port_map[1] != _FUSED_ANY_WWPN:
        v_wwpns = [u.sanitize_wwpn_for_api(x) for x in port_map[1].split()]

    if v_wwpns is not None:
        for vfc_map in vios_w.vfc_mappings:
            if (vfc_map.client_adapter is None or
                    vfc_map.client_adapter.wwpns is None):
                continue
            if set(vfc_map.client_adapter.wwpns) != set(v_wwpns):
                continue

            # If we reach this point, we know that we have a matching map.  So
            # the attach of this volume, for this vFC mapping is complete.
            # Nothing else needs to be done, exit the method.
            return None

    # However, if we hit here, then we need to create a new mapping and
    # attach it to the VIOS mapping
    vfc_map = pvm_vios.VFCMapping.bld(vios_w.adapter, host_uuid, lpar_uuid,
                                      p_port.name, client_wwpns=v_wwpns)
    vios_w.vfc_mappings.append(vfc_map)
    return vfc_map
Пример #6
0
def _find_ports_on_vio(vio_w, p_port_wwpns):
    """Will return a list of Physical FC Ports on the vio_w.

    :param vio_w: The VIOS wrapper.
    :param p_port_wwpns: The list of all physical ports.  May exceed the
                         ports on the VIOS.
    :return: List of the physical FC Port wrappers that are on the VIOS
             for the WWPNs that exist on this system.
    """
    return [port for port in vio_w.pfc_ports
            if u.sanitize_wwpn_for_api(port.wwpn) in p_port_wwpns]
Пример #7
0
def has_client_wwpns(vios_wraps, client_wwpn_pair):
    """Returns the vios wrapper and vfc map if the client WWPNs already exist.

    :param vios_wraps: The VIOS wrappers.  Should be queried with the
                       FC_MAPPING extended attribute.
    :param client_wwpn_pair: The pair (list or set) of the client WWPNs.
    :return vios_w: The VIOS wrapper containing the wwpn pair.  None if none
                    of the wrappers contain the pair.
    :return vfc_map: The mapping containing the client pair.  May be None.
    """
    client_wwpn_pair = set([u.sanitize_wwpn_for_api(x)
                            for x in client_wwpn_pair])

    for vios_wrap in vios_wraps:
        for vfc_map in vios_wrap.vfc_mappings:
            if vfc_map.client_adapter is None:
                continue

            pair = set([u.sanitize_wwpn_for_api(x)
                        for x in vfc_map.client_adapter.wwpns])
            if pair == client_wwpn_pair:
                return vios_wrap, vfc_map

    return None, None
Пример #8
0
def find_vios_for_vfc_wwpns(vios_wraps, vfc_wwpns):
    """Will find the VIOS that is hosting the vfc_wwpns.

    :param vios_wraps: A list or set of VIOS wrappers.
    :param vfc_wwpns: The list or set of virtual fibre channel WWPNs.
    :return: The VIOS wrapper that supports the vfc adapters.  If there is not
             one, then None will be returned.
    :return: The VFCMapping on the VIOS that supports the client adapters.
    """
    # Sanitize our input
    vfc_wwpns = {u.sanitize_wwpn_for_api(x) for x in vfc_wwpns}
    for vios_w in vios_wraps:
        for vfc_map in vios_w.vfc_mappings:
            # If the map has no client adapter...then move on
            if not vfc_map.client_adapter:
                continue

            # If the WWPNs match, return it
            if vfc_wwpns == set(vfc_map.client_adapter.wwpns):
                return vios_w, vfc_map
    return None, None
Пример #9
0
def c_wwpn_to_vfc_mapping(vios_w, c_wwpn):
    """Finds the vFC mapping (if any) for a given client WWPN.

    This is a helper method that will parse through a given VIOS wrapper
    (retrieved with pypowervm.const.XAG.VIO_FMAP) and will find the client vFC
    mapping for that WWPN.

    :param vios_w: The Virtual I/O Server wrapper.  Should have
                   pypowervm.const.XAG.VIO_FMAP associated with it.
    :param c_wwpn: One of the client's WWPNs.
    :return: The vFC mapping (or None)
    """
    wwpn = util.sanitize_wwpn_for_api(c_wwpn)
    for vfc_map in vios_w.vfc_mappings:
        # If there is not a client adapter, it isn't properly attached.
        if not vfc_map.client_adapter:
            continue

        if wwpn in vfc_map.client_adapter.wwpns:
            return vfc_map

    return None
Пример #10
0
def find_maps(mapping_list, client_lpar_id, client_adpt=None, port_map=None):
    """Filter a list of VFC mappings by LPAR ID.

    This is based on scsi_mapper.find_maps, but does not yet provide all the
    same functionality.

    :param mapping_list: The mappings to filter.  Iterable of VFCMapping.
    :param client_lpar_id: Integer short ID or string UUID of the LPAR on the
                           client side of the mapping.  Note that the UUID form
                           relies on the presence of the client_lpar_href
                           field.  Some mappings lack this field, and would
                           therefore be ignored.
    :param client_adpt: (Optional, Default=None) If set, will only include the
                        mapping if the client adapter's WWPNs match as well.
    :param port_map: (Optional, Default=None) If set, will look for a matching
                     mapping based off the client WWPNs as specified by the
                     port mapping.  The format of this is defined by the
                     derive_npiv_map method.
    :return: A list comprising the subset of the input mapping_list whose
             client LPAR IDs match client_lpar_id.
    """
    is_uuid, client_id = uuid.id_or_uuid(client_lpar_id)
    matching_maps = []

    if port_map:
        v_wwpns = [u.sanitize_wwpn_for_api(x) for x in port_map[1].split()]

    for vfc_map in mapping_list:
        # If to a different VM, continue on.
        href = vfc_map.client_lpar_href
        if is_uuid and (not href or client_id != u.get_req_path_uuid(
                href, preserve_case=True)):
            continue
        elif (not is_uuid and
                # Use the server adapter in case this is an orphan.
                vfc_map.server_adapter.lpar_id != client_id):
            continue

        # If there is a client adapter, and it is not a 'ANY WWPN', then
        # check to see if the mappings match.
        if client_adpt and client_adpt.wwpns != {_ANY_WWPN}:
            # If they passed in a client adapter, but the map doesn't have
            # one, then we have to ignore
            if not vfc_map.client_adapter:
                continue

            # Check to make sure the WWPNs between the two match.  This should
            # be an order independence check (as this query shouldn't care...
            # but the API itself does care about order).
            if set(client_adpt.wwpns) != set(vfc_map.client_adapter.wwpns):
                continue

        # If the user had a port map, do the virtual WWPNs from that port
        # map match the client adapter wwpn map.
        if port_map:
            if vfc_map.client_adapter is None:
                continue

            # If it is a new mapping with generated WWPNs, then the client
            # adapter can't have WWPNs.
            if v_wwpns == [_ANY_WWPN, _ANY_WWPN]:
                if vfc_map.client_adapter.wwpns != []:
                    continue
            elif set(vfc_map.client_adapter.wwpns) != set(v_wwpns):
                continue

        # Found a match!
        matching_maps.append(vfc_map)

    return matching_maps
Пример #11
0
def add_map(vios_w, host_uuid, lpar_uuid, port_map, error_if_invalid=True,
            lpar_slot_num=None):
    """Adds a vFC mapping to a given VIOS wrapper.

    These changes are not flushed back to the REST server.  The wrapper itself
    is simply modified.

    :param vios_w: VIOS EntryWrapper representing the Virtual I/O Server whose
                   VFC mappings are to be updated.
    :param host_uuid: The pypowervm UUID of the host.
    :param lpar_uuid: The pypowervm UUID of the client LPAR to attach to.
    :param port_map: The port mapping (as defined by the derive_npiv_map
                     method).
    :param error_if_invalid: (Optional, Default: True) If the port mapping
                             physical port can not be found, raise an error.
    :param lpar_slot_num: (Optional, Default: None) The client adapter
                          VirtualSlotNumber to be set. If None the next
                          available slot would be used.
    :return: The VFCMapping that was added or updated with a missing backing
             port.  If the mapping already existed then None is returned.
    """
    # This is meant to find the physical port.  Can run against a single
    # element.  We assume invoker has passed correct VIOS.
    new_vios_w, p_port = find_vios_for_wwpn([vios_w], port_map[0])
    if new_vios_w is None:
        if error_if_invalid:
            # Log the payload in the response.
            LOG.warning(_("Unable to find appropriate VIOS.  The payload "
                          "provided was likely insufficient.  The payload "
                          "data is:\n %s)"), vios_w.toxmlstring(pretty=True))
            raise e.UnableToDerivePhysicalPortForNPIV(wwpn=port_map[0],
                                                      vio_uri=vios_w.href)
        else:
            return None

    v_wwpns = None
    if port_map[1] != _FUSED_ANY_WWPN:
        v_wwpns = [u.sanitize_wwpn_for_api(x) for x in port_map[1].split()]

    if v_wwpns is not None:
        for vfc_map in vios_w.vfc_mappings:
            if (vfc_map.client_adapter is None or
                    vfc_map.client_adapter.wwpns is None):
                continue
            if set(vfc_map.client_adapter.wwpns) != set(v_wwpns):
                continue

            # If we reach this point, we know that we have a matching map.
            # Check that the physical port is set in the mapping.
            if vfc_map.backing_port:
                LOG.debug("Matching existing vfc map found with backing port:"
                          " %s", vfc_map.backing_port.wwpn)
                # The attach of this volume, for this vFC mapping is complete.
                # Nothing else needs to be done, exit the method.
                return None
            else:
                LOG.info(_("The matched VFC port map has no backing port set."
                           " Adding %(port)s to mapping for client wwpns: "
                           "%(wwpns)s"),
                         {'port': p_port.name, 'wwpns': v_wwpns})
                # Build the backing_port and add it to the vfc_map.
                vfc_map.backing_port = bp.PhysFCPort.bld_ref(
                    vios_w.adapter, p_port.name, ref_tag='Port')
                return vfc_map

    # However, if we hit here, then we need to create a new mapping and
    # attach it to the VIOS mapping
    vfc_map = pvm_vios.VFCMapping.bld(vios_w.adapter, host_uuid, lpar_uuid,
                                      p_port.name, client_wwpns=v_wwpns,
                                      lpar_slot_num=lpar_slot_num)
    vios_w.vfc_mappings.append(vfc_map)
    return vfc_map