def add_router_interface(self, vlan_name, vlan_id, subnet_id, gateway_ip, router_id): """Create VLAN SVI on the Nexus switch.""" # Find a switch to create the SVI on switch_ip = self._find_switch_for_svi() if not switch_ip: raise cisco_exc.NoNexusSviSwitch() # Check if this vlan exists on the switch already try: nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) except cisco_exc.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port self._client.create_and_trunk_vlan(switch_ip, vlan_id, vlan_name, nexus_port=None) # Check if a router interface has already been created try: nxos_db.get_nexusvm_binding(vlan_id, router_id) raise cisco_exc.SubnetInterfacePresent(subnet_id=subnet_id, router_id=router_id) except cisco_exc.NexusPortBindingNotFound: self._client.create_vlan_svi(switch_ip, vlan_id, gateway_ip) nxos_db.add_nexusport_binding('router', str(vlan_id), switch_ip, router_id) return True
def test_nexus_delete_port_rollback(self): """Test for proper rollback for nexus plugin delete port failure. Test for rollback (i.e. restoration) of a VLAN entry in the nexus database whenever the nexus plugin fails to reconfigure the nexus switch during a delete_port operation. """ with self._create_port_res() as res: port = self.deserialize(self.fmt, res) # Check that there is only one binding in the nexus database # for this VLAN/nexus switch. start_rows = nexus_db_v2.get_nexusvlan_binding( self.vlan_start, self.switch_ip) self.assertEqual(len(start_rows), 1) # Simulate a Nexus switch configuration error during # port deletion. with self._patch_ncclient( 'manager.connect.return_value.edit_config.side_effect', AttributeError): self._delete('ports', port['port']['id'], base.FAULT_MAP[c_exc.NexusConfigFailed].code) # Confirm that the binding has been restored (rolled back). end_rows = nexus_db_v2.get_nexusvlan_binding( self.vlan_start, self.switch_ip) self.assertEqual(start_rows, end_rows)
def add_router_interface(self, vlan_name, vlan_id, subnet_id, gateway_ip, router_id): """Create VLAN SVI on the Nexus switch.""" # Find a switch to create the SVI on switch_ip = self._find_switch_for_svi() if not switch_ip: raise cisco_exc.NoNexusSviSwitch() # Check if this vlan exists on the switch already try: nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) except cisco_exc.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port self._client.create_and_trunk_vlan( switch_ip, vlan_id, vlan_name, etype=None, nexus_port=None) # Check if a router interface has already been created try: nxos_db.get_nexusvm_bindings(vlan_id, router_id) raise cisco_exc.SubnetInterfacePresent(subnet_id=subnet_id, router_id=router_id) except cisco_exc.NexusPortBindingNotFound: self._client.create_vlan_svi(switch_ip, vlan_id, gateway_ip) nxos_db.add_nexusport_binding('router', str(vlan_id), switch_ip, router_id) return True
def test_model_delete_port_rollback(self): """Test for proper rollback for OVS plugin delete port failure. Test that the nexus port configuration is rolled back (restored) by the Cisco model plugin when there is a failure in the OVS plugin for a delete port operation. """ with self._create_port_res() as res: # After port is created, we should have one binding for this # vlan/nexus switch. port = self.deserialize(self.fmt, res) start_rows = nexus_db_v2.get_nexusvlan_binding(VLAN_START, NEXUS_IP_ADDR) self.assertEqual(len(start_rows), 1) # Inject an exception in the OVS plugin delete_port # processing, and attempt a port deletion. inserted_exc = q_exc.Conflict expected_http = base.FAULT_MAP[inserted_exc].code with mock.patch.object(l3_db.L3_NAT_db_mixin, "disassociate_floatingips", side_effect=inserted_exc): self._delete("ports", port["port"]["id"], expected_code=expected_http) # Confirm that the Cisco model plugin has restored # the nexus configuration for this port after deletion failure. end_rows = nexus_db_v2.get_nexusvlan_binding(VLAN_START, NEXUS_IP_ADDR) self.assertEqual(start_rows, end_rows)
def test_nexus_delete_port_rollback(self): """Test for proper rollback for nexus plugin delete port failure. Test for rollback (i.e. restoration) of a VLAN entry in the nexus database whenever the nexus plugin fails to reconfigure the nexus switch during a delete_port operation. """ with self._create_port_res() as res: port = self.deserialize(self.fmt, res) # Check that there is only one binding in the nexus database # for this VLAN/nexus switch. start_rows = nexus_db_v2.get_nexusvlan_binding(VLAN_START, NEXUS_IP_ADDR) self.assertEqual(len(start_rows), 1) # Simulate a Nexus switch configuration error during # port deletion. with self._patch_ncclient("manager.connect.return_value.edit_config.side_effect", AttributeError): self._delete("ports", port["port"]["id"], base.FAULT_MAP[c_exc.NexusConfigFailed].code) # Confirm that the binding has been restored (rolled back). end_rows = nexus_db_v2.get_nexusvlan_binding(VLAN_START, NEXUS_IP_ADDR) self.assertEqual(start_rows, end_rows)
def test_model_delete_port_rollback(self): """Test for proper rollback for OVS plugin delete port failure. Test that the nexus port configuration is rolled back (restored) by the Cisco model plugin when there is a failure in the OVS plugin for a delete port operation. """ with self._create_port_res() as res: # After port is created, we should have one binding for this # vlan/nexus switch. port = self.deserialize(self.fmt, res) start_rows = nexus_db_v2.get_nexusvlan_binding( self.vlan_start, self.switch_ip) self.assertEqual(len(start_rows), 1) # Inject an exception in the OVS plugin delete_port # processing, and attempt a port deletion. inserted_exc = q_exc.Conflict expected_http = base.FAULT_MAP[inserted_exc].code with mock.patch.object(l3_db.L3_NAT_db_mixin, 'disassociate_floatingips', side_effect=inserted_exc): self._delete('ports', port['port']['id'], expected_code=expected_http) # Confirm that the Cisco model plugin has restored # the nexus configuration for this port after deletion failure. end_rows = nexus_db_v2.get_nexusvlan_binding( self.vlan_start, self.switch_ip) self.assertEqual(start_rows, end_rows)
def delete_port(self, device_id, vlan_id): """Delete port. Delete port bindings from the database and scan whether the network is still required on the interfaces trunked. """ LOG.debug(_("NexusPlugin:delete_port() called")) # Delete DB row(s) for this port try: rows = nxos_db.get_nexusvm_bindings(vlan_id, device_id) except cisco_exc.NexusPortBindingNotFound: return auto_delete = True auto_untrunk = True if cdb.is_provider_vlan(vlan_id): auto_delete = conf.CISCO.provider_vlan_auto_create auto_untrunk = conf.CISCO.provider_vlan_auto_trunk LOG.debug(_("delete_network(): provider vlan %s"), vlan_id) instance_id = False for row in rows: instance_id = row["instance_id"] switch_ip = row.switch_ip etype, nexus_port = "", "" if row["port_id"] == "router": etype, nexus_port = "vlan", row["port_id"] auto_untrunk = False else: etype, nexus_port = row["port_id"].split(":") nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id, row.switch_ip, row.instance_id) # Check whether there are any remaining instances using this # vlan on this Nexus port. try: nxos_db.get_port_vlan_switch_binding(row.port_id, row.vlan_id, row.switch_ip) except cisco_exc.NexusPortBindingNotFound: try: if nexus_port and auto_untrunk: # Untrunk the vlan from this Nexus interface self._client.disable_vlan_on_trunk_int(switch_ip, row.vlan_id, etype, nexus_port) # Check whether there are any remaining instances # using this vlan on the Nexus switch. if auto_delete: try: nxos_db.get_nexusvlan_binding(row.vlan_id, row.switch_ip) except cisco_exc.NexusPortBindingNotFound: # Delete this vlan from this switch self._client.delete_vlan(switch_ip, row.vlan_id) except Exception: # The delete vlan operation on the Nexus failed, # so this delete_port request has failed. For # consistency, roll back the Nexus database to what # it was before this request. with excutils.save_and_reraise_exception(): nxos_db.add_nexusport_binding(row.port_id, row.vlan_id, row.switch_ip, row.instance_id) return instance_id
def delete_port(self, device_id, vlan_id): """Delete port. Delete port bindings from the database and scan whether the network is still required on the interfaces trunked. """ LOG.debug(_("NexusPlugin:delete_port() called")) # Delete DB row(s) for this port try: rows = nxos_db.get_nexusvm_bindings(vlan_id, device_id) except cisco_exc.NexusPortBindingNotFound: return auto_delete = True auto_untrunk = True if cdb.is_provider_vlan(vlan_id): auto_delete = conf.CISCO.provider_vlan_auto_create auto_untrunk = conf.CISCO.provider_vlan_auto_trunk LOG.debug("delete_network(): provider vlan %s" % vlan_id) instance_id = False for row in rows: instance_id = row['instance_id'] switch_ip = row.switch_ip etype, nexus_port = '', '' if row['port_id'] == 'router': etype, nexus_port = 'vlan', row['port_id'] else: etype, nexus_port = row['port_id'].split(':') nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id, row.switch_ip, row.instance_id) # Check for any other bindings with the same vlan_id and switch_ip try: nxos_db.get_nexusvlan_binding(row.vlan_id, row.switch_ip) except cisco_exc.NexusPortBindingNotFound: try: # Delete this vlan from this switch if nexus_port and auto_untrunk: self._client.disable_vlan_on_trunk_int( switch_ip, row.vlan_id, etype, nexus_port) if auto_delete: self._client.delete_vlan(switch_ip, row.vlan_id) except Exception: # The delete vlan operation on the Nexus failed, # so this delete_port request has failed. For # consistency, roll back the Nexus database to what # it was before this request. with excutils.save_and_reraise_exception(): nxos_db.add_nexusport_binding(row.port_id, row.vlan_id, row.switch_ip, row.instance_id) return instance_id
def delete_port(self, device_id, vlan_id): """Delete port. Delete port bindings from the database and scan whether the network is still required on the interfaces trunked. """ LOG.debug(_("NexusPlugin:delete_port() called")) # Delete DB row(s) for this port try: rows = nxos_db.get_nexusvm_bindings(vlan_id, device_id) except cisco_exc.NexusPortBindingNotFound: return auto_delete = True auto_untrunk = True if cdb.is_provider_vlan(vlan_id): auto_delete = conf.CISCO.provider_vlan_auto_create auto_untrunk = conf.CISCO.provider_vlan_auto_trunk LOG.debug(_("delete_network(): provider vlan %s"), vlan_id) instance_id = False for row in rows: instance_id = row['instance_id'] switch_ip = row.switch_ip etype, nexus_port = '', '' if row['port_id'] == 'router': etype, nexus_port = 'vlan', row['port_id'] auto_untrunk = False else: etype, nexus_port = row['port_id'].split(':') nxos_db.remove_nexusport_binding(row.port_id, row.vlan_id, row.switch_ip, row.instance_id) # Check for any other bindings with the same vlan_id and switch_ip try: nxos_db.get_nexusvlan_binding(row.vlan_id, row.switch_ip) except cisco_exc.NexusPortBindingNotFound: try: # Delete this vlan from this switch if nexus_port and auto_untrunk: self._client.disable_vlan_on_trunk_int( switch_ip, row.vlan_id, etype, nexus_port) if auto_delete: self._client.delete_vlan(switch_ip, row.vlan_id) except Exception: # The delete vlan operation on the Nexus failed, # so this delete_port request has failed. For # consistency, roll back the Nexus database to what # it was before this request. with excutils.save_and_reraise_exception(): nxos_db.add_nexusport_binding(row.port_id, row.vlan_id, row.switch_ip, row.instance_id) return instance_id
def test_nexusvlanbinding_get(self): npb11 = self._npb_test_obj(10, 100) npb21 = self._npb_test_obj(20, 100) npb22 = self._npb_test_obj(20, 200) self._add_to_db([npb11, npb21, npb22]) npb_all_v100 = nxdb.get_nexusvlan_binding(npb11.vlan, npb11.switch) self.assertEqual(len(npb_all_v100), 2) npb_v200 = nxdb.get_nexusvlan_binding(npb22.vlan, npb22.switch) self.assertEqual(len(npb_v200), 1) self._assert_equal(npb_v200[0], npb22) with testtools.ExpectedException(c_exc.NexusPortBindingNotFound): nxdb.get_nexusvlan_binding(npb21.vlan, "dummySwitch")
def test_nexusvlanbinding_get(self): npb11 = self._npb_test_obj(10, 100) npb21 = self._npb_test_obj(20, 100) npb22 = self._npb_test_obj(20, 200) self._add_to_db([npb11, npb21, npb22]) npb_all_v100 = nxdb.get_nexusvlan_binding(npb11.vlan, npb11.switch) self.assertEqual(len(npb_all_v100), 2) npb_v200 = nxdb.get_nexusvlan_binding(npb22.vlan, npb22.switch) self.assertEqual(len(npb_v200), 1) self._assert_equal(npb_v200[0], npb22) with testtools.ExpectedException(c_exc.NexusPortBindingNotFound): nxdb.get_nexusvlan_binding(npb21.vlan, "dummySwitch")
def delete_port(self, device_id, vlan_id): """Delete port. Delete port bindings from the database and scan whether the network is still required on the interfaces trunked. """ LOG.debug(_("NexusPlugin:delete_port() called")) # Delete DB row for this port try: row = nxos_db.get_nexusvm_binding(vlan_id, device_id) except cisco_exc.NexusPortBindingNotFound: return nxos_db.remove_nexusport_binding(row['port_id'], row['vlan_id'], row['switch_ip'], row['instance_id']) # Check for any other bindings with the same vlan_id and switch_ip try: nxos_db.get_nexusvlan_binding(row['vlan_id'], row['switch_ip']) except cisco_exc.NexusPortBindingNotFound: try: # Delete this vlan from this switch _nexus_ip = row['switch_ip'] _nexus_ports = () if row['port_id'] != 'router': _nexus_ports = (row['port_id'],) _nexus_ssh_port = (self._nexus_switches[_nexus_ip, 'ssh_port']) _nexus_creds = self.get_credential(_nexus_ip) _nexus_username = _nexus_creds['username'] _nexus_password = _nexus_creds['password'] self._client.delete_vlan( str(row['vlan_id']), _nexus_ip, _nexus_username, _nexus_password, _nexus_ports, _nexus_ssh_port) except Exception: # The delete vlan operation on the Nexus failed, # so this delete_port request has failed. For # consistency, roll back the Nexus database to what # it was before this request. with excutils.save_and_reraise_exception(): nxos_db.add_nexusport_binding(row['port_id'], row['vlan_id'], row['switch_ip'], row['instance_id']) return row['instance_id']
def test_nexusbinding_update(self): npb11 = self._npb_test_obj(10, 100, switch="1.1.1.1", instance="test") npb21 = self._npb_test_obj(20, 100, switch="1.1.1.1", instance="test") self._add_to_db([npb11, npb21]) npb_all_v100 = nxdb.get_nexusvlan_binding(npb11.vlan, "1.1.1.1") self.assertEqual(len(npb_all_v100), 2) npb22 = self._npb_test_obj(20, 200, switch="1.1.1.1", instance="test") npb = nxdb.update_nexusport_binding(npb21.port, 200) self._assert_equal(npb, npb22) npb_all_v100 = nxdb.get_nexusvlan_binding(npb11.vlan, "1.1.1.1") self.assertEqual(len(npb_all_v100), 1) self._assert_equal(npb_all_v100[0], npb11) npb = nxdb.update_nexusport_binding(npb21.port, 0) self.assertIsNone(npb) npb33 = self._npb_test_obj(30, 300, switch="1.1.1.1", instance="test") with testtools.ExpectedException(c_exc.NexusPortBindingNotFound): nxdb.update_nexusport_binding(npb33.port, 200)
def test_nexusbinding_update(self): npb11 = self._npb_test_obj(10, 100, switch='1.1.1.1', instance='test') npb21 = self._npb_test_obj(20, 100, switch='1.1.1.1', instance='test') self._add_to_db([npb11, npb21]) npb_all_v100 = nxdb.get_nexusvlan_binding(npb11.vlan, '1.1.1.1') self.assertEqual(len(npb_all_v100), 2) npb22 = self._npb_test_obj(20, 200, switch='1.1.1.1', instance='test') npb = nxdb.update_nexusport_binding(npb21.port, 200) self._assert_equal(npb, npb22) npb_all_v100 = nxdb.get_nexusvlan_binding(npb11.vlan, '1.1.1.1') self.assertEqual(len(npb_all_v100), 1) self._assert_equal(npb_all_v100[0], npb11) npb = nxdb.update_nexusport_binding(npb21.port, 0) self.assertIsNone(npb) npb33 = self._npb_test_obj(30, 300, switch='1.1.1.1', instance='test') with testtools.ExpectedException(c_exc.NexusPortBindingNotFound): nxdb.update_nexusport_binding(npb33.port, 200)
def add_router_interface(self, vlan_name, vlan_id, subnet_id, gateway_ip, router_id): """Create VLAN SVI on the Nexus switch.""" # Find a switch to create the SVI on switch_ip = self._find_switch_for_svi() if not switch_ip: raise cisco_exc.NoNexusSwitch() _nexus_ip = switch_ip _nexus_ssh_port = self._nexus_switches[switch_ip, 'ssh_port'] _nexus_creds = self.get_credential(_nexus_ip) _nexus_username = _nexus_creds['username'] _nexus_password = _nexus_creds['password'] # Check if this vlan exists on the switch already try: nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) except cisco_exc.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port self._client.create_vlan( vlan_name, str(vlan_id), _nexus_ip, _nexus_username, _nexus_password, [], _nexus_ssh_port, vlan_id) # Check if a router interface has already been created try: nxos_db.get_nexusvm_binding(vlan_id, router_id) raise cisco_exc.SubnetInterfacePresent(subnet_id=subnet_id, router_id=router_id) except cisco_exc.NexusPortBindingNotFound: self._client.create_vlan_svi(vlan_id, _nexus_ip, _nexus_username, _nexus_password, _nexus_ssh_port, gateway_ip) nxos_db.add_nexusport_binding('router', str(vlan_id), switch_ip, router_id) return True
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
def create_network(self, tenant_id, net_name, net_id, vlan_name, vlan_id, host, instance): """Create network. 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 for switch_ip, attr in self._nexus_switches: if str(attr) == str(host): port_id = self._nexus_switches[switch_ip, attr] break else: raise cisco_exc.NexusComputeHostNotConfigured(host=host) # Check if this network is already in the DB vlan_created = False vlan_enabled = False try: nxos_db.get_port_vlan_switch_binding(port_id, vlan_id, switch_ip) except cisco_exc.NexusPortBindingNotFound: _nexus_ip = switch_ip _nexus_ports = (port_id,) _nexus_ssh_port = \ self._nexus_switches[switch_ip, 'ssh_port'] _nexus_creds = self.get_credential(_nexus_ip) _nexus_username = _nexus_creds['username'] _nexus_password = _nexus_creds['password'] # Check for vlan/switch binding try: nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) except cisco_exc.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port self._client.create_vlan( vlan_name, str(vlan_id), _nexus_ip, _nexus_username, _nexus_password, _nexus_ports, _nexus_ssh_port, vlan_id) vlan_created = True else: # Only trunk vlan on the port man = self._client.nxos_connect(_nexus_ip, int(_nexus_ssh_port), _nexus_username, _nexus_password) self._client.enable_vlan_on_trunk_int(man, _nexus_ip, port_id, vlan_id) vlan_enabled = True try: 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: self._client.delete_vlan( str(vlan_id), _nexus_ip, _nexus_username, _nexus_password, _nexus_ports, _nexus_ssh_port) if vlan_enabled: self._client.disable_vlan_on_trunk_int(man, port_id, vlan_id) new_net_dict = {const.NET_ID: net_id, const.NET_NAME: 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
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 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