Example #1
0
    def update_port(self, context, port_id, port):
        """Update values of a port.

        :param context: neutron api request context
        :param id: UUID representing the port to update.
        :param port: dictionary with keys indicating fields to update.

        :returns: a mapping sequence with the following signature:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": sets admin state of port. if down, port
                               does not forward packets.
            "status": dicates whether port is currently operational
                       (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID's and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.StateInvalid
        :raises: exceptions.PortNotFound
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: update_port() called"))

        self._warn_on_state_status(port["port"])

        # Validate Args
        orig_port = super(NeutronRestProxyV2, self).get_port(context, port_id)
        with context.session.begin(subtransactions=True):
            # Update DB
            new_port = super(NeutronRestProxyV2, self).update_port(context, port_id, port)
            self._update_extra_dhcp_opts_on_port(context, port_id, port, new_port)
            if portbindings.HOST_ID in port["port"] and "id" in new_port:
                host_id = port["port"][portbindings.HOST_ID]
                porttracker_db.put_port_hostid(context, new_port["id"], host_id)
            new_port = self._extend_port_dict_binding(context, new_port)

            # update on networl ctrl
            mapped_port = self._map_state_and_status(new_port)
            self.servers.rest_update_port(orig_port["tenant_id"], orig_port["network_id"], mapped_port, port_id)

        if new_port.get("device_id") != orig_port.get("device_id") and orig_port.get("device_id"):
            try:
                self.servers.rest_unplug_interface(orig_port["tenant_id"], orig_port["network_id"], orig_port["id"])
                device_id = new_port.get("device_id")
                if device_id:
                    self.rest_plug_interface(new_port["tenant_id"], new_port["network_id"], new_port, device_id)

            except RemoteRestError:
                with excutils.save_and_reraise_exception():
                    port_update = {"port": {"status": "ERROR"}}
                    super(NeutronRestProxyV2, self).update_port(context, new_port["id"], port_update)

        # return new_port
        return new_port
Example #2
0
    def create_port(self, context, port):
        """Create a port, which is a connection point of a device
        (e.g., a VM NIC) to attach to a L2 Neutron network.
        :param context: neutron api request context
        :param port: dictionary describing the port

        :returns:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": Sets admin state of port. if down, port
                              does not forward packets.
            "status": dicates whether port is currently operational
                      (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID"s and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.NetworkNotFound
        :raises: exceptions.StateInvalid
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: create_port() called"))

        # Update DB in new session so exceptions rollback changes
        with context.session.begin(subtransactions=True):
            self._ensure_default_security_group_on_port(context, port)
            sgids = self._get_security_groups_on_port(context, port)
            # set port status to pending. updated after rest call completes
            port['port']['status'] = const.PORT_STATUS_BUILD
            dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])
            new_port = super(NeutronRestProxyV2,
                             self).create_port(context, port)
            self._process_port_create_security_group(context, new_port, sgids)
        if (portbindings.HOST_ID in port['port'] and 'id' in new_port):
            host_id = port['port'][portbindings.HOST_ID]
            porttracker_db.put_port_hostid(context, new_port['id'], host_id)
        new_port[addr_pair.ADDRESS_PAIRS] = (
            self._process_create_allowed_address_pairs(
                context, new_port, port['port'].get(addr_pair.ADDRESS_PAIRS)))
        self._process_port_create_extra_dhcp_opts(context, new_port, dhcp_opts)
        new_port = self._extend_port_dict_binding(context, new_port)
        net = super(NeutronRestProxyV2,
                    self).get_network(context, new_port["network_id"])
        if self.add_meta_server_route:
            if new_port['device_owner'] == const.DEVICE_OWNER_DHCP:
                destination = METADATA_SERVER_IP + '/32'
                self._add_host_route(context, destination, new_port)

        # create on network ctrl
        mapped_port = self._map_state_and_status(new_port)
        self.evpool.spawn_n(self.async_port_create, net["tenant_id"],
                            new_port["network_id"], mapped_port)
        self.notify_security_groups_member_updated(context, new_port)
        return new_port
Example #3
0
    def create_port(self, context, port):
        """Create a port, which is a connection point of a device
        (e.g., a VM NIC) to attach to a L2 Neutron network.
        :param context: neutron api request context
        :param port: dictionary describing the port

        :returns:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": Sets admin state of port. if down, port
                              does not forward packets.
            "status": dicates whether port is currently operational
                      (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID"s and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.NetworkNotFound
        :raises: exceptions.StateInvalid
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: create_port() called"))

        # Update DB in new session so exceptions rollback changes
        with context.session.begin(subtransactions=True):
            self._ensure_default_security_group_on_port(context, port)
            sgids = self._get_security_groups_on_port(context, port)
            # set port status to pending. updated after rest call completes
            port['port']['status'] = const.PORT_STATUS_BUILD
            dhcp_opts = port['port'].get(edo_ext.EXTRADHCPOPTS, [])
            new_port = super(NeutronRestProxyV2, self).create_port(context,
                                                                   port)
            self._process_port_create_security_group(context, new_port, sgids)
        if (portbindings.HOST_ID in port['port']
            and 'id' in new_port):
            host_id = port['port'][portbindings.HOST_ID]
            porttracker_db.put_port_hostid(context, new_port['id'],
                                           host_id)
        self._process_port_create_extra_dhcp_opts(context, new_port,
                                                  dhcp_opts)
        new_port = self._extend_port_dict_binding(context, new_port)
        net = super(NeutronRestProxyV2,
                    self).get_network(context, new_port["network_id"])
        if self.add_meta_server_route:
            if new_port['device_owner'] == 'network:dhcp':
                destination = METADATA_SERVER_IP + '/32'
                self._add_host_route(context, destination, new_port)

        # create on network ctrl
        mapped_port = self._map_state_and_status(new_port)
        self.evpool.spawn_n(self.async_port_create, net["tenant_id"],
                            new_port["network_id"], mapped_port)
        self.notify_security_groups_member_updated(context, new_port)
        return new_port
Example #4
0
 def _prepare_port_for_controller(self, context):
     port = context.current
     net = context.network.current
     port["network"] = net
     port["binding_host"] = context._binding.host
     actx = ctx.get_admin_context()
     if portbindings.HOST_ID in port and "id" in port:
         host_id = port[portbindings.HOST_ID]
         porttracker_db.put_port_hostid(actx, port["id"], host_id)
     else:
         host_id = ""
     prepped_port = self._extend_port_dict_binding(actx, port)
     prepped_port = self._map_state_and_status(prepped_port)
     if portbindings.HOST_ID not in prepped_port or prepped_port[portbindings.HOST_ID] == "":
         # in ML2, controller doesn't care about ports without
         # the host_id set
         return False
     return prepped_port
Example #5
0
 def _prepare_port_for_controller(self, context):
     port = context.current
     net = context.network.current
     port['network'] = net
     port['binding_host'] = context._binding.host
     actx = ctx.get_admin_context()
     if (portbindings.HOST_ID in port and 'id' in port):
         host_id = port[portbindings.HOST_ID]
         porttracker_db.put_port_hostid(actx, port['id'], host_id)
     else:
         host_id = ''
     prepped_port = self._extend_port_dict_binding(actx, port)
     prepped_port = self._map_state_and_status(prepped_port)
     if (portbindings.HOST_ID not in prepped_port or
         prepped_port[portbindings.HOST_ID] == ''):
         # in ML2, controller doesn't care about ports without
         # the host_id set
         return False
     return prepped_port
Example #6
0
 def _prepare_port_for_controller(self, context):
     port = context.current
     net = context.network.current
     port['network'] = net
     port['binding_host'] = context._binding.host
     actx = ctx.get_admin_context()
     if (portbindings.HOST_ID in port and 'id' in port):
         host_id = port[portbindings.HOST_ID]
         porttracker_db.put_port_hostid(actx, port['id'], host_id)
     else:
         host_id = ''
     prepped_port = self._extend_port_dict_binding(actx, port)
     prepped_port = self._map_state_and_status(prepped_port)
     if (portbindings.HOST_ID not in prepped_port or
         prepped_port[portbindings.HOST_ID] == ''):
         LOG.warning(_("Ignoring port notification to controller because "
                       "of missing host ID."))
         # in ML2, controller doesn't care about ports without
         # the host_id set
         return False
     return prepped_port
Example #7
0
    def update_port(self, context, port_id, port):
        """Update values of a port.

        :param context: neutron api request context
        :param id: UUID representing the port to update.
        :param port: dictionary with keys indicating fields to update.

        :returns: a mapping sequence with the following signature:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": sets admin state of port. if down, port
                               does not forward packets.
            "status": dicates whether port is currently operational
                       (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID's and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.StateInvalid
        :raises: exceptions.PortNotFound
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: update_port() called"))

        self._warn_on_state_status(port['port'])

        # Validate Args
        orig_port = super(NeutronRestProxyV2, self).get_port(context, port_id)
        with context.session.begin(subtransactions=True):
            # Update DB
            new_port = super(NeutronRestProxyV2,
                             self).update_port(context, port_id, port)
            ctrl_update_required = False
            if addr_pair.ADDRESS_PAIRS in port['port']:
                ctrl_update_required |= (
                    self.update_address_pairs_on_port(context, port_id, port,
                                                      orig_port, new_port))
            if 'fixed_ips' in port['port']:
                self._check_fixed_ips_and_address_pairs_no_overlap(
                    context, new_port)
            self._update_extra_dhcp_opts_on_port(context, port_id, port,
                                                 new_port)
            old_host_id = porttracker_db.get_port_hostid(context,
                                                         orig_port['id'])
            if (portbindings.HOST_ID in port['port']
                and 'id' in new_port):
                host_id = port['port'][portbindings.HOST_ID]
                porttracker_db.put_port_hostid(context, new_port['id'],
                                               host_id)
                if old_host_id != host_id:
                    ctrl_update_required = True

            if (new_port.get("device_id") != orig_port.get("device_id") and
                orig_port.get("device_id")):
                ctrl_update_required = True

            if ctrl_update_required:
                # tenant_id must come from network in case network is shared
                net_tenant_id = self._get_port_net_tenantid(context, new_port)
                new_port = self._extend_port_dict_binding(context, new_port)
                mapped_port = self._map_state_and_status(new_port)
                self.servers.rest_update_port(net_tenant_id,
                                              new_port["network_id"],
                                              mapped_port)
            agent_update_required = self.update_security_group_on_port(
                context, port_id, port, orig_port, new_port)
        agent_update_required |= self.is_security_group_member_updated(
            context, orig_port, new_port)

        # return new_port
        return new_port
Example #8
0
    def update_port(self, context, port_id, port):
        """Update values of a port.

        :param context: neutron api request context
        :param id: UUID representing the port to update.
        :param port: dictionary with keys indicating fields to update.

        :returns: a mapping sequence with the following signature:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": sets admin state of port. if down, port
                               does not forward packets.
            "status": dicates whether port is currently operational
                       (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID's and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.StateInvalid
        :raises: exceptions.PortNotFound
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: update_port() called"))

        self._warn_on_state_status(port['port'])

        # Validate Args
        orig_port = super(NeutronRestProxyV2, self).get_port(context, port_id)
        with context.session.begin(subtransactions=True):
            # Update DB
            new_port = super(NeutronRestProxyV2,
                             self).update_port(context, port_id, port)
            self._update_extra_dhcp_opts_on_port(context, port_id, port,
                                                 new_port)
            ctrl_update_required = False
            old_host_id = porttracker_db.get_port_hostid(
                context, orig_port['id'])
            if (portbindings.HOST_ID in port['port'] and 'id' in new_port):
                host_id = port['port'][portbindings.HOST_ID]
                porttracker_db.put_port_hostid(context, new_port['id'],
                                               host_id)
                if old_host_id != host_id:
                    ctrl_update_required = True

            if (new_port.get("device_id") != orig_port.get("device_id")
                    and orig_port.get("device_id")):
                ctrl_update_required = True

            if ctrl_update_required:
                # tenant_id must come from network in case network is shared
                net_tenant_id = self._get_port_net_tenantid(context, new_port)
                new_port = self._extend_port_dict_binding(context, new_port)
                mapped_port = self._map_state_and_status(new_port)
                self.servers.rest_update_port(net_tenant_id,
                                              new_port["network_id"],
                                              mapped_port)
            agent_update_required = self.update_security_group_on_port(
                context, port_id, port, orig_port, new_port)
        agent_update_required |= self.is_security_group_member_updated(
            context, orig_port, new_port)

        # return new_port
        return new_port
    def update_port(self, context, port_id, port):
        """Update values of a port.

        :param context: neutron api request context
        :param id: UUID representing the port to update.
        :param port: dictionary with keys indicating fields to update.

        :returns: a mapping sequence with the following signature:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": sets admin state of port. if down, port
                               does not forward packets.
            "status": dicates whether port is currently operational
                       (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID's and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.StateInvalid
        :raises: exceptions.PortNotFound
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: update_port() called"))

        self._warn_on_state_status(port["port"])

        # Validate Args
        orig_port = super(NeutronRestProxyV2, self).get_port(context, port_id)

        # Update DB
        new_port = super(NeutronRestProxyV2, self).update_port(context, port_id, port)
        if portbindings.HOST_ID in port["port"] and "device_id" in port["port"]:
            porttracker_db.put_port_hostid(context, port["port"]["device_id"], port["port"][portbindings.HOST_ID])
        # update on networl ctrl
        try:
            resource = PORTS_PATH % (orig_port["tenant_id"], orig_port["network_id"], port_id)
            mapped_port = self._map_state_and_status(new_port)
            data = {"port": mapped_port}
            ret = self.servers.put(resource, data)
            if not self.servers.action_success(ret):
                raise RemoteRestError(ret[2])

            if new_port.get("device_id") != orig_port.get("device_id"):
                if orig_port.get("device_id"):
                    self._unplug_interface(context, orig_port["tenant_id"], orig_port["network_id"], orig_port["id"])
                device_id = new_port.get("device_id")
                if device_id:
                    self._plug_interface(
                        context, new_port["tenant_id"], new_port["network_id"], new_port["id"], device_id
                    )

        except RemoteRestError as e:
            LOG.error(_("NeutronRestProxyV2: Unable to create remote port: " "%s"), e.message)
            # reset port to original state
            super(NeutronRestProxyV2, self).update_port(context, port_id, orig_port)
            raise

        # return new_port
        return self._extend_port_dict_binding(context, new_port)
    def create_port(self, context, port):
        """Create a port, which is a connection point of a device
        (e.g., a VM NIC) to attach to a L2 Neutron network.
        :param context: neutron api request context
        :param port: dictionary describing the port

        :returns:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": Sets admin state of port. if down, port
                              does not forward packets.
            "status": dicates whether port is currently operational
                      (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID"s and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.NetworkNotFound
        :raises: exceptions.StateInvalid
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: create_port() called"))

        # Update DB
        port["port"]["admin_state_up"] = False
        if portbindings.HOST_ID in port["port"] and "device_id" in port["port"]:
            porttracker_db.put_port_hostid(context, port["port"]["device_id"], port["port"][portbindings.HOST_ID])
        new_port = super(NeutronRestProxyV2, self).create_port(context, port)
        net = super(NeutronRestProxyV2, self).get_network(context, new_port["network_id"])

        if self.add_meta_server_route:
            if new_port["device_owner"] == "network:dhcp":
                destination = METADATA_SERVER_IP + "/32"
                self._add_host_route(context, destination, new_port)

        # create on networl ctrl
        try:
            resource = PORT_RESOURCE_PATH % (net["tenant_id"], net["id"])
            mapped_port = self._map_state_and_status(new_port)
            data = {"port": mapped_port}
            ret = self.servers.post(resource, data)
            if not self.servers.action_success(ret):
                raise RemoteRestError(ret[2])

            # connect device to network, if present
            device_id = port["port"].get("device_id")
            if device_id:
                self._plug_interface(context, net["tenant_id"], net["id"], new_port["id"], device_id)
        except RemoteRestError as e:
            LOG.error(_("NeutronRestProxyV2: Unable to create remote port: " "%s"), e.message)
            super(NeutronRestProxyV2, self).delete_port(context, new_port["id"])
            raise

        # Set port state up and return that port
        port_update = {"port": {"admin_state_up": True}}
        new_port = super(NeutronRestProxyV2, self).update_port(context, new_port["id"], port_update)
        return self._extend_port_dict_binding(context, new_port)
Example #11
0
    def create_port(self, context, port):
        """Create a port, which is a connection point of a device
        (e.g., a VM NIC) to attach to a L2 Neutron network.
        :param context: neutron api request context
        :param port: dictionary describing the port

        :returns:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": Sets admin state of port. if down, port
                              does not forward packets.
            "status": dicates whether port is currently operational
                      (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID"s and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.NetworkNotFound
        :raises: exceptions.StateInvalid
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: create_port() called"))

        # Update DB in new session so exceptions rollback changes
        with context.session.begin(subtransactions=True):
            port["port"]["admin_state_up"] = False
            dhcp_opts = port["port"].get(edo_ext.EXTRADHCPOPTS, [])
            new_port = super(NeutronRestProxyV2, self).create_port(context, port)
            if portbindings.HOST_ID in port["port"] and "id" in new_port:
                host_id = port["port"][portbindings.HOST_ID]
                porttracker_db.put_port_hostid(context, new_port["id"], host_id)
            self._process_port_create_extra_dhcp_opts(context, new_port, dhcp_opts)
            new_port = self._extend_port_dict_binding(context, new_port)
            net = super(NeutronRestProxyV2, self).get_network(context, new_port["network_id"])

            if self.add_meta_server_route:
                if new_port["device_owner"] == "network:dhcp":
                    destination = METADATA_SERVER_IP + "/32"
                    self._add_host_route(context, destination, new_port)

            # create on network ctrl
            mapped_port = self._map_state_and_status(new_port)
            self.servers.rest_create_port(net, mapped_port)

        # connect device to network, if present
        device_id = port["port"].get("device_id")
        if device_id:
            try:
                self.servers.rest_plug_interface(net["tenant_id"], net["id"], new_port, device_id)
            except RemoteRestError:
                with excutils.save_and_reraise_exception():
                    port_update = {"port": {"status": "ERROR"}}
                    super(NeutronRestProxyV2, self).update_port(context, new_port["id"], port_update)
        # Set port state up and return that port
        port_update = {"port": {"admin_state_up": True}}
        new_port = super(NeutronRestProxyV2, self).update_port(context, new_port["id"], port_update)
        return self._extend_port_dict_binding(context, new_port)
Example #12
0
    def create_port(self, context, port):
        """Create a port, which is a connection point of a device
        (e.g., a VM NIC) to attach to a L2 Neutron network.
        :param context: neutron api request context
        :param port: dictionary describing the port

        :returns:
        {
            "id": uuid represeting the port.
            "network_id": uuid of network.
            "tenant_id": tenant_id
            "mac_address": mac address to use on this port.
            "admin_state_up": Sets admin state of port. if down, port
                              does not forward packets.
            "status": dicates whether port is currently operational
                      (limit values to "ACTIVE", "DOWN", "BUILD", and "ERROR")
            "fixed_ips": list of subnet ID"s and IP addresses to be used on
                         this port
            "device_id": identifies the device (e.g., virtual server) using
                         this port.
        }

        :raises: exceptions.NetworkNotFound
        :raises: exceptions.StateInvalid
        :raises: RemoteRestError
        """
        LOG.debug(_("NeutronRestProxyV2: create_port() called"))

        # Update DB in new session so exceptions rollback changes
        with context.session.begin(subtransactions=True):
            self._ensure_default_security_group_on_port(context, port)
            sgids = self._get_security_groups_on_port(context, port)
            # non-router port status is set to pending. it is then updated
            # after the async rest call completes. router ports are synchronous
            if port["port"]["device_owner"] == l3_db.DEVICE_OWNER_ROUTER_INTF:
                port["port"]["status"] = const.PORT_STATUS_ACTIVE
            else:
                port["port"]["status"] = const.PORT_STATUS_BUILD
            dhcp_opts = port["port"].get(edo_ext.EXTRADHCPOPTS, [])
            new_port = super(NeutronRestProxyV2, self).create_port(context, port)
            self._process_port_create_security_group(context, new_port, sgids)
        if portbindings.HOST_ID in port["port"] and "id" in new_port:
            host_id = port["port"][portbindings.HOST_ID]
            porttracker_db.put_port_hostid(context, new_port["id"], host_id)
        new_port[addr_pair.ADDRESS_PAIRS] = self._process_create_allowed_address_pairs(
            context, new_port, port["port"].get(addr_pair.ADDRESS_PAIRS)
        )
        self._process_port_create_extra_dhcp_opts(context, new_port, dhcp_opts)
        new_port = self._extend_port_dict_binding(context, new_port)
        net = super(NeutronRestProxyV2, self).get_network(context, new_port["network_id"])
        if self.add_meta_server_route:
            if new_port["device_owner"] == const.DEVICE_OWNER_DHCP:
                destination = METADATA_SERVER_IP + "/32"
                self._add_host_route(context, destination, new_port)

        # create on network ctrl
        mapped_port = self._map_state_and_status(new_port)
        # ports have to be created synchronously when creating a router
        # port since adding router interfaces is a multi-call process
        if mapped_port["device_owner"] == l3_db.DEVICE_OWNER_ROUTER_INTF:
            self.servers.rest_create_port(net["tenant_id"], new_port["network_id"], mapped_port)
        else:
            self.evpool.spawn_n(self.async_port_create, net["tenant_id"], new_port["network_id"], mapped_port)
        self.notify_security_groups_member_updated(context, new_port)
        return new_port