Esempio n. 1
0
def find_mapping_net_assn(context, network_id, host_id):
    """
    Takes in a network id and the host id to return an SEA that creates that
    mapping. If there's no association found, a None is returned

    :context: The context used to call the dom API
    :network_id: The neutron network id.
    :host_id: The Host id of the host, for which we want the
    association.
    :returns: The associated Network Association.  May be None
    """
    return dom_api.network_association_find(context, host_id, network_id)
Esempio n. 2
0
    def _find_default_adapter(self, host_dom, candidate_seas, net_id, vlan,
                              context, session):
        """
        Will return the adapter from 'candiate_seas' that is the appropriate
        default adapter.

        :param host_dom: The DOM for the Host
        :param candidate_seas: All of the candidate SEA DOM objects.
        :param net_id: The neutron network id (optional).
        :param vlan: The VLAN for the query.  Optional.
        :param context: The context for all queries
        :param session: The database session

        :return: The sea from the candidate_seas list that is the default.  If
                 None is returned, then 'do-not-use' is the default.
        """
        LOG.debug('_find_default_adapter starting..')
        # First check to see is if a network association exists already,
        # and if so, return that.
        if net_id:
            net_assn = dom_api.network_association_find(context,
                                                        host_dom.host_name,
                                                        net_id, session)
            if net_assn:
                # If the network association has 'none' set for the SEA, then
                # return None
                if net_assn.sea is None:
                    LOG.debug('returning None')
                    return None
                else:
                    # Find the corresponding SEA from our query and return that
                    for sea in candidate_seas:
                        if sea.name == net_assn.sea.name and\
                            sea.vio_server.lpar_id == \
                                net_assn.sea.vio_server.lpar_id:
                            LOG.debug('returning %s' % sea)
                            return sea

        # Next up, check to see if there is a peer!
        # A peer network is one that shares the same VLAN id as this one.
        # NOTE: This isn't a true peer as we're disregarding vswitch here.  We
        # just know by this point that no SEA was associated with the passed
        # in net_id, so we are free to pick any vswitch that fits the bill.
        peer_sea = self._find_peer_network_sea(context, host_dom.host_name,
                                               vlan, session)
        if peer_sea:
            # Find the corresponding SEA from our candidate list.
            for sea in candidate_seas:
                if sea.name == peer_sea.name and\
                        sea.vio_server.lpar_id == peer_sea.vio_server.lpar_id:
                    LOG.debug('returning %s' % sea)
                    return sea

        # Next up is to check the SEAs to see if any contains the VLAN passed
        # in.
        if vlan:
            for sea in candidate_seas:
                if sea.pvid == vlan or vlan in sea.additional_vlans():
                    LOG.debug('returning %s' % sea)
                    return sea

        # Lastly, we just have to return the lowest adapter...
        return self._find_default_with_no_vlan(candidate_seas)
Esempio n. 3
0
    def _get_specific_host_seas(self, context, host, vswitch=None, vlan=None,
                                net_id=None, session=None, ports=None):
        """
        This method will return the SEA candidates for a given host, and only
        that host.

        The format of the response will be:
        {
         "host_name": "host2",
         "adapters": [
            {
             "default": true,
             "sea_name": "ent5",
             "vswitch": "ETHERNET0",
             "lpar_id": 1,
             "ha_lpar_id": null,
             "ha_mode": "disabled",
             "pvid": 1,
             "state": "Available",
             "ha_state": null,
             "lpar_name": "15-34B9Z",
             "ha_lpar_name": null,
             "ha_sea": null
            }
         ]
        }

        :param context: The context for the request.
        :param host: The host name (as a string)
        :param vswitch: The vswitch that should be used to help identify the
                        default adapter.  If set to None all of the vSwitches
                        will be utilized.
        :param vlan: The vlan that should be used to help identify the default
                     adapter.  If set to None (the default value), a VLAN ID of
                     1 will be used.
        :param net_id: The network UUID of a neutron Network. This is optional
        :param ports: An optional list of ports for the specified network.
        """
        # Build basic data to determine targets
        vio_servers = dom_api.vio_server_find_all(context, host, session)
        host_dom = dom_model.Host(host, vio_servers)
        vswitches = self._get_vswitches(host_dom.find_all_primary_seas())

        # If the network id was set, then we should always use that networks
        # vlan id instead of the passed in value.
        vlan = self._determine_vlan(vlan, net_id, host, context)

        # We need to determine if this network has any VMs on the host.  If so,
        # then we can't be set to Do not Use.  We also can't allow them to
        # change vSwitches.
        allow_do_not_use_option = False
        if net_id:
            # We only allow the do not use option if the VM count for this
            # network is 0.  Otherwise a VM is using it, and we can't flip
            # to do not use until all the VMs are done.
            vm_list = dom_api.instances_find(context, host, net_id, ports)
            allow_do_not_use_option = (len(vm_list) == 0)

            # As noted above...if the network association has VMs, then we
            # can't let the user change the vSwitch that the networks are on.
            # Therefore, set the specific_vswitch so that the candidate_sea
            # loop won't take any other vSwitches into account.
            if len(vm_list) > 0:
                net_assn = dom_api.network_association_find(context,
                                                            host_dom.host_name,
                                                            net_id, session)

                # If there is a network association, just override the vSwitch
                # list with the network associations vSwitch.  This limits it
                # to a single vSwitch search scope.
                if net_assn and net_assn.sea:
                    vswitches = [net_assn.sea.primary_vea.vswitch_name]
        else:
            # If there was not a network id, then we assume that this is a
            # new network and therefore do not use should always be returned.
            allow_do_not_use_option = True

        # Variable to store all candidate SEAs
        candidate_seas = []

        # Walk through the vswitches on this host and determine the valid
        # candidates (broken into pools defined by the vswitches).
        for vswitch_name in vswitches:
            # If the user passed in a vswitch, and we don't match, continue
            if vswitch is not None and vswitch != vswitch_name:
                continue

            # Extend the candidates
            candidate_seas.extend(self._get_candidate_seas_for_vswitch(
                host_dom, vswitch_name, vlan))

        # Now we need to find the default adapter...may be None, which
        # indicates that it is a do not use.
        default_sea = self._find_default_adapter(host_dom, candidate_seas,
                                                 net_id, vlan, context,
                                                 session)
        # If the default sea is not selected, and there's only one vswitch
        # we need to determine a default adapter for this VLAN and create
        # that relationship.
        if(default_sea is None and not allow_do_not_use_option and net_id):
            vswitch_with_vlan = []
            for vswitch in vswitches:
                sea = host_dom.find_sea_for_vlan_vswitch(vlan, vswitch)
                if sea:
                    vswitch_with_vlan.append(sea)
            # We would like to set this as the default since in this
            # present call to host-seas - we need to report a default
            if len(vswitch_with_vlan) == 1:
                default_sea = vswitch_with_vlan[0]
                dom_api.network_association_put_sea(context, host, net_id,
                                                    vswitch_with_vlan[0],
                                                    session)

        # Now, build the adapter list to return
        adapter_list = []
        if allow_do_not_use_option or len(vswitches) > 1:
            adapter_list.append(self._format_sea_to_dict_response
                                (host_dom,
                                 None,
                                 default_sea is None))
        if default_sea and default_sea not in candidate_seas:
            candidate_seas.append(default_sea)
        for sea in candidate_seas:
            adapter_list.append(self._format_sea_to_dict_response
                                (host_dom, sea,
                                 default_sea == sea))

        msg = (ras.vif_get_msg('info', 'HOST_SEAS_RETURN') %
               {'vlan': vlan,
                'host_name': host,
                'list': adapter_list})
        ras.function_tracepoint(
            LOG, __name__, ras.TRACE_INFO, msg)
        return {
            'host_name': host_dom.host_name,
            'adapters': adapter_list
        }