def create_network(self, network, attachment):
        """Create or update a network when an attachment is changed.

        This method is not invoked at the usual plugin create_network() time.
        Instead, it is invoked on create/update port.

        :param network: Network on which the port operation is happening
        :param attachment: Details about the owner of the port

        Create a VLAN in the appropriate switch/port, and configure the
        appropriate interfaces for this VLAN.
        """
        LOG.debug(_("NexusPlugin:create_network() called"))
        # Grab the switch IP and port for this host
        host = str(attachment[const.HOST_NAME])
        switch_ip, port_id = self._client.get_switch_and_port_id(host)
        if not switch_ip and not port_id:
            raise cisco_exc.NexusComputeHostNotConfigured(host=host)

        vlan_id = network[const.NET_VLAN_ID]
        vlan_name = network[const.NET_VLAN_NAME]
        auto_create = True
        auto_trunk = True
        if cdb.is_provider_vlan(vlan_id):
            vlan_name = ''.join(
                [conf.CISCO.provider_vlan_name_prefix,
                 str(vlan_id)])
            auto_create = conf.CISCO.provider_vlan_auto_create
            auto_trunk = conf.CISCO.provider_vlan_auto_trunk

        # Check if this network is already in the DB
        vlan_created = False
        vlan_trunked = False

        try:
            nxos_db.get_port_vlan_switch_binding(port_id, vlan_id, switch_ip)
        except cisco_exc.NexusPortBindingNotFound:
            # Check for vlan/switch binding
            try:
                nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
            except cisco_exc.NexusPortBindingNotFound:
                if auto_create and auto_trunk:
                    # Create vlan and trunk vlan on the port
                    LOG.debug("Nexus: create & trunk vlan %s" % vlan_name)
                    self._client.create_and_trunk_vlan(switch_ip, vlan_id,
                                                       vlan_name, port_id)
                    vlan_created = True
                    vlan_trunked = True
                elif auto_create:
                    # Create vlan but do not trunk it on the port
                    LOG.debug("Nexus: create vlan %s" % vlan_name)
                    self._client.create_vlan(switch_ip, vlan_id, vlan_name)
                    vlan_created = True
            else:
                if auto_trunk:
                    # Only trunk vlan on the port
                    LOG.debug("Nexus: trunk vlan %s" % vlan_name)
                    self._client.enable_vlan_on_trunk_int(
                        switch_ip, vlan_id, port_id)
                    vlan_trunked = True

        try:
            instance = attachment[const.INSTANCE_ID]
            nxos_db.add_nexusport_binding(port_id, str(vlan_id), switch_ip,
                                          instance)
        except Exception:
            with excutils.save_and_reraise_exception():
                # Add binding failed, roll back any vlan creation/enabling
                if vlan_created and vlan_trunked:
                    LOG.debug("Nexus: delete & untrunk vlan %s" % vlan_name)
                    self._client.delete_and_untrunk_vlan(
                        switch_ip, vlan_id, port_id)
                elif vlan_created:
                    LOG.debug("Nexus: delete vlan %s" % vlan_name)
                    self._client.delete_vlan(switch_ip, vlan_id)
                elif vlan_trunked:
                    LOG.debug("Nexus: untrunk vlan %s" % vlan_name)
                    self._client.disable_vlan_on_trunk_int(
                        switch_ip, vlan_id, port_id)

        net_id = network[const.NET_ID]
        new_net_dict = {
            const.NET_ID: net_id,
            const.NET_NAME: network[const.NET_NAME],
            const.NET_PORTS: {},
            const.NET_VLAN_NAME: vlan_name,
            const.NET_VLAN_ID: vlan_id
        }
        self._networks[net_id] = new_net_dict
        return new_net_dict
    def create_network(self, network, attachment):
        """Create or update a network when an attachment is changed.

        This method is not invoked at the usual plugin create_network() time.
        Instead, it is invoked on create/update port.

        :param network: Network on which the port operation is happening
        :param attachment: Details about the owner of the port

        Create a VLAN in the appropriate switch/port, and configure the
        appropriate interfaces for this VLAN.
        """
        LOG.debug(_("NexusPlugin:create_network() called"))
        # Grab the switch IPs and ports for this host
        host_connections = []
        host = attachment['host_name']
        for switch_type, switch_ip, attr in self._nexus_switches:
            if str(attr) == str(host):
                port = self._nexus_switches[switch_type, switch_ip, attr]
                # Get ether type for port, assume an ethernet type
                # if none specified.
                if ':' in port:
                    etype, port_id = port.split(':')
                else:
                    etype, port_id = 'ethernet', port
                host_connections.append((switch_ip, etype, port_id))
        if not host_connections:
            raise cisco_exc.NexusComputeHostNotConfigured(host=host)

        vlan_id = network[const.NET_VLAN_ID]
        vlan_name = network[const.NET_VLAN_NAME]
        auto_create = True
        auto_trunk = True
        if cdb.is_provider_vlan(vlan_id):
            vlan_name = ''.join([conf.CISCO.provider_vlan_name_prefix,
                                 str(vlan_id)])
            auto_create = conf.CISCO.provider_vlan_auto_create
            auto_trunk = conf.CISCO.provider_vlan_auto_trunk

        # Check if this network is already in the DB
        for switch_ip, etype, port_id in host_connections:
            vlan_created = False
            vlan_trunked = False
            eport_id = '%s:%s' % (etype, port_id)
            # Check for switch vlan bindings
            try:
                # This vlan has already been created on this switch
                # via another operation, like SVI bindings.
                nxos_db.get_nexusvlan_binding(vlan_id, switch_ip)
                vlan_created = True
                auto_create = False
            except cisco_exc.NexusPortBindingNotFound:
                # No changes, proceed as normal
                pass

            try:
                nxos_db.get_port_vlan_switch_binding(eport_id, vlan_id,
                                                     switch_ip)
            except cisco_exc.NexusPortBindingNotFound:
                if auto_create and auto_trunk:
                    # Create vlan and trunk vlan on the port
                    LOG.debug(_("Nexus: create & trunk vlan %s"), vlan_name)
                    self._client.create_and_trunk_vlan(
                        switch_ip, vlan_id, vlan_name, etype, port_id)
                    vlan_created = True
                    vlan_trunked = True
                elif auto_create:
                    # Create vlan but do not trunk it on the port
                    LOG.debug(_("Nexus: create vlan %s"), vlan_name)
                    self._client.create_vlan(switch_ip, vlan_id, vlan_name)
                    vlan_created = True
                elif auto_trunk:
                    # Only trunk vlan on the port
                    LOG.debug(_("Nexus: trunk vlan %s"), vlan_name)
                    self._client.enable_vlan_on_trunk_int(
                        switch_ip, vlan_id, etype, port_id)
                    vlan_trunked = True

            try:
                instance = attachment[const.INSTANCE_ID]
                nxos_db.add_nexusport_binding(eport_id, str(vlan_id),
                                              switch_ip, instance)
            except Exception:
                with excutils.save_and_reraise_exception():
                    # Add binding failed, roll back any vlan creation/enabling
                    if vlan_created and vlan_trunked:
                        LOG.debug(_("Nexus: delete & untrunk vlan %s"),
                                  vlan_name)
                        self._client.delete_and_untrunk_vlan(switch_ip,
                                                             vlan_id,
                                                             etype, port_id)
                    elif vlan_created:
                        LOG.debug(_("Nexus: delete vlan %s"), vlan_name)
                        self._client.delete_vlan(switch_ip, vlan_id)
                    elif vlan_trunked:
                        LOG.debug(_("Nexus: untrunk vlan %s"), vlan_name)
                        self._client.disable_vlan_on_trunk_int(switch_ip,
                                                               vlan_id,
                                                               etype,
                                                               port_id)

        net_id = network[const.NET_ID]
        new_net_dict = {const.NET_ID: net_id,
                        const.NET_NAME: network[const.NET_NAME],
                        const.NET_PORTS: {},
                        const.NET_VLAN_NAME: vlan_name,
                        const.NET_VLAN_ID: vlan_id}
        self._networks[net_id] = new_net_dict
        return new_net_dict