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)
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)
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 }