コード例 #1
0
    def _get_gbp_details(self, context, request, host):
        with context.session.begin(subtransactions=True):
            device = request.get('device')

            core_plugin = self._core_plugin
            port_id = core_plugin._device_to_port_id(context, device)
            port_context = core_plugin.get_bound_port_context(
                context, port_id, host)
            if not port_context:
                LOG.warning(
                    _LW("Device %(device)s requested by agent "
                        "%(agent_id)s not found in database"), {
                            'device': port_id,
                            'agent_id': request.get('agent_id')
                        })
                return {'device': request.get('device')}
            port = port_context.current

            # NOTE(ivar): removed the PROXY_PORT_PREFIX hack.
            # This was needed to support network services without hotplug.

            epg = self._get_port_epg(context, port)

            details = {
                'device':
                request.get('device'),
                'enable_dhcp_optimization':
                self._is_dhcp_optimized(context, port),
                'enable_metadata_optimization':
                (self._is_metadata_optimized(context, port)),
                'port_id':
                port_id,
                'mac_address':
                port['mac_address'],
                'app_profile_name':
                epg.app_profile_name,
                'tenant_id':
                port['tenant_id'],
                'host':
                host,
                # TODO(ivar): scope names, possibly through AIM or the
                # name mapper
                'ptg_tenant':
                epg.tenant_name,
                'endpoint_group_name':
                epg.name,
                'promiscuous_mode':
                self._is_port_promiscuous(context, port),
                'extra_ips': [],
                'floating_ip': [],
                'ip_mapping': [],
                # Put per mac-address extra info
                'extra_details': {}
            }

            # Set VM name if needed.
            if port['device_owner'].startswith(
                    'compute:') and port['device_id']:
                vm = nclient.NovaClient().get_server(port['device_id'])
                details['vm-name'] = vm.name if vm else port['device_id']
            mtu = self._get_port_mtu(context, port)
            if mtu:
                details['interface_mtu'] = mtu

            # NOTE(ivar): having these methods cleanly separated actually makes
            # things less efficient by requiring lots of calls duplication.
            # we could alleviate this by passing down a cache that stores
            # commonly requested objects (like EPGs). 'details' itself could
            # be used for such caching.
            details['_cache'] = {}
            vrf = self._get_port_vrf(context, port, details)
            details['l3_policy_id'] = '%s %s' % (vrf.tenant_name, vrf.name)
            self._add_subnet_details(context, port, details)
            self._add_allowed_address_pairs_details(context, port, details)
            self._add_vrf_details(context, details['l3_policy_id'], details)
            self._add_nat_details(context, port, host, details)
            self._add_extra_details(context, port, details)
            self._add_segmentation_label_details(context, port, details)
            self._set_dhcp_lease_time(details)
            details.pop('_cache', None)

        LOG.debug("Details for port %s : %s", port['id'], details)
        return details
コード例 #2
0
    def bind_port(self, context):
        """Get port binding per host.

           This is similar to the one defined in the
           AgentMechanismDriverBase class, but is modified
           to support multiple L2 agent types (DVS and OpFlex).
        """
        port = context.current
        LOG.debug("Attempting to bind port %(port)s on "
                  "network %(network)s", {
                      'port': port['id'],
                      'network': context.network.current['id']
                  })
        vnic_type = port.get(portbindings.VNIC_TYPE, portbindings.VNIC_NORMAL)
        if vnic_type not in [portbindings.VNIC_NORMAL]:
            LOG.debug("Refusing to bind due to unsupported vnic_type: %s",
                      vnic_type)
            return

        if port['device_owner'].startswith('compute:'):
            # enforce the allowed_vm_names rules if possible
            if (port['device_id'] and self.apic_allowed_vm_name_driver):
                ptg, pt = self.apic_gbp._port_id_to_ptg(
                    context._plugin_context, port['id'])
                if ptg is None:
                    LOG.warning(_LW("PTG for port %s does not exist"),
                                port['id'])
                    return
                l2p = self.apic_gbp._get_l2_policy(context._plugin_context,
                                                   ptg['l2_policy_id'])
                l3p = self.apic_gbp.gbp_plugin.get_l3_policy(
                    context._plugin_context, l2p['l3_policy_id'])

                ok_to_bind = True
                if l3p.get('allowed_vm_names'):
                    ok_to_bind = False
                    vm = nclient.NovaClient().get_server(port['device_id'])
                    for allowed_vm_name in l3p['allowed_vm_names']:
                        match = re.search(allowed_vm_name, vm.name)
                        if match:
                            ok_to_bind = True
                            break
                if not ok_to_bind:
                    LOG.warning(
                        _LW("Failed to bind the port due to "
                            "allowed_vm_names rules %(rules)s "
                            "for VM: %(vm)s"), {
                                'rules': l3p['allowed_vm_names'],
                                'vm': vm.name
                            })
                    return

            # Attempt to bind ports for DVS agents for nova-compute daemons
            # first. This allows having network agents (dhcp, metadata)
            # that typically run on a network node using an OpFlex agent to
            # co-exist with nova-compute daemons for ESX, which host DVS
            # agents.
            agent_list = context.host_agents(AGENT_TYPE_DVS)
            if self._agent_bind_port(context, agent_list, self._bind_dvs_port):
                return

        # It either wasn't a DVS binding, or there wasn't a DVS
        # agent on the binding host (could be the case in a hybrid
        # environment supporting KVM and ESX compute). Go try for
        # OpFlex agents.
        agent_list = context.host_agents(ofcst.AGENT_TYPE_OPFLEX_OVS)
        self._agent_bind_port(context, agent_list, self._bind_opflex_port)