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