def allocate_for_instance(self, context, instance, **kwargs):
        """Allocate network resources for the instance.

        :param context: The request context.
        :param instance: nova.objects.instance.Instance object.
        :param requested_networks: optional value containing
            network_id, fixed_ip, and port_id
        :param security_groups: security groups to allocate for instance
        :param macs: None or a set of MAC addresses that the instance
            should use. macs is supplied by the hypervisor driver (contrast
            with requested_networks which is user supplied).
            NB: NeutronV2 currently assigns hypervisor supplied MAC addresses
            to arbitrary networks, which requires openflow switches to
            function correctly if more than one network is being used with
            the bare metal hypervisor (which is the only one known to limit
            MAC addresses).
        :param dhcp_options: None or a set of key/value pairs that should
            determine the DHCP BOOTP response, eg. for PXE booting an instance
            configured with the baremetal hypervisor. It is expected that these
            are already formatted for the neutron v2 api.
            See nova/virt/driver.py:dhcp_options_for_instance for an example.
        :param bind_host_id: the host ID to attach to the ports being created.
        """
        hypervisor_macs = kwargs.get('macs', None)

        # The neutron client and port_client (either the admin context or
        # tenant context) are read here. The reason for this is that there are
        # a number of different calls for the instance allocation.
        # We do not want to create a new neutron session for each of these
        # calls.
        neutron = get_client(context)
        # Requires admin creds to set port bindings
        port_client = (neutron if not
                       self._has_port_binding_extension(context,
                           refresh_cache=True, neutron=neutron) else
                       get_client(context, admin=True))
        # Store the admin client - this is used later
        admin_client = port_client if neutron != port_client else None
        LOG.debug('allocate_for_instance()', instance=instance)
        if not instance.project_id:
            msg = _('empty project id for instance %s')
            raise exception.InvalidInput(
                reason=msg % instance.uuid)
        requested_networks = kwargs.get('requested_networks')
        dhcp_opts = kwargs.get('dhcp_options', None)
        bind_host_id = kwargs.get('bind_host_id')
        ports, net_ids, ordered_networks, available_macs = (
            self._process_requested_networks(context,
                instance, neutron, requested_networks, hypervisor_macs))

        nets = self._get_available_networks(context, instance.project_id,
                                            net_ids, neutron=neutron)
        if not nets:
            # NOTE(chaochin): If user specifies a network id and the network
            # can not be found, raise NetworkNotFound error.
            if requested_networks:
                for request in requested_networks:
                    if not request.port_id and request.network_id:
                        raise exception.NetworkNotFound(
                            network_id=request.network_id)
            else:
                LOG.debug("No network configured", instance=instance)
                return network_model.NetworkInfo([])

        # if this function is directly called without a requested_network param
        # or if it is indirectly called through allocate_port_for_instance()
        # with None params=(network_id=None, requested_ip=None, port_id=None,
        # pci_request_id=None):
        if (not requested_networks
            or requested_networks.is_single_unspecified):
            # If no networks were requested and none are available, consider
            # it a bad request.
            if not nets:
                raise exception.InterfaceAttachFailedNoNetwork(
                    project_id=instance.project_id)
            # bug/1267723 - if no network is requested and more
            # than one is available then raise NetworkAmbiguous Exception
            if len(nets) > 1:
                msg = _("Multiple possible networks found, use a Network "
                         "ID to be more specific.")
                raise exception.NetworkAmbiguous(msg)
            ordered_networks.append(
                objects.NetworkRequest(network_id=nets[0]['id']))

        # NOTE(melwitt): check external net attach permission after the
        #                check for ambiguity, there could be another
        #                available net which is permitted bug/1364344
        self._check_external_network_attach(context, nets)

        security_groups = kwargs.get('security_groups', [])
        security_group_ids = self._process_security_groups(
                                    instance, neutron, security_groups)

        preexisting_port_ids = []
        created_port_ids = []
        ports_in_requested_order = []
        nets_in_requested_order = []
        for request in ordered_networks:
            # Network lookup for available network_id
            network = None
            for net in nets:
                if net['id'] == request.network_id:
                    network = net
                    break
            # if network_id did not pass validate_networks() and not available
            # here then skip it safely not continuing with a None Network
            else:
                continue

            nets_in_requested_order.append(network)
            # If security groups are requested on an instance then the
            # network must has a subnet associated with it. Some plugins
            # implement the port-security extension which requires
            # 'port_security_enabled' to be True for security groups.
            # That is why True is returned if 'port_security_enabled'
            # is not found.
            if (security_groups and not (
                    network['subnets']
                    and network.get('port_security_enabled', True))):

                raise exception.SecurityGroupCannotBeApplied()
            zone = 'compute:%s' % instance.availability_zone
            port_req_body = {'port': {'device_id': instance.uuid,
                                      'device_owner': zone}}
            try:
                self._populate_neutron_extension_values(
                    context, instance, request.pci_request_id, port_req_body,
                    network=network, neutron=neutron,
                    bind_host_id=bind_host_id)
                self._populate_mac_address(instance, request.pci_request_id,
                                           port_req_body)
                if request.port_id:
                    port = ports[request.port_id]
                    port_client.update_port(port['id'], port_req_body)
                    preexisting_port_ids.append(port['id'])
                    ports_in_requested_order.append(port['id'])
                else:
                    created_port = self._create_port(
                            port_client, instance, request.network_id,
                            port_req_body, request.address,
                            security_group_ids, available_macs, dhcp_opts)
                    created_port_ids.append(created_port)
                    ports_in_requested_order.append(created_port)
                self._update_port_dns_name(context, instance, network,
                                           ports_in_requested_order[-1],
                                           neutron)
            except Exception:
                with excutils.save_and_reraise_exception():
                    self._unbind_ports(context,
                                       preexisting_port_ids,
                                       neutron, port_client)
                    self._delete_ports(neutron, instance, created_port_ids)
        nw_info = self.get_instance_nw_info(
            context, instance, networks=nets_in_requested_order,
            port_ids=ports_in_requested_order,
            admin_client=admin_client,
            preexisting_port_ids=preexisting_port_ids,
            update_cells=True)
        # NOTE(danms): Only return info about ports we created in this run.
        # In the initial allocation case, this will be everything we created,
        # and in later runs will only be what was created that time. Thus,
        # this only affects the attach case, not the original use for this
        # method.
        return network_model.NetworkInfo([vif for vif in nw_info
                                          if vif['id'] in created_port_ids +
                                          preexisting_port_ids])
dataset/ETHPy150Open BU-NU-CLOUD-SP16/Trusted-Platform-Module-nova/nova/network/neutronv2/api.py/API.allocate_for_instance/original