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_resources() as port: # 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( 'connect.return_value.edit_config.side_effect', AttributeError): self._delete('ports', port['port']['id'], wexc.HTTPInternalServerError.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_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_resources() as port: # 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( 'connect.return_value.edit_config.side_effect', AttributeError): self._delete('ports', port['port']['id'], wexc.HTTPInternalServerError.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 _manage_port(self, vlan_name, vlan_id, host, instance): """Called during create and update port events. Create a VLAN in the appropriate switch/port and configure the appropriate interfaces for this VLAN. """ # 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 excep.NexusComputeHostNotConfigured(host=host) # 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 excep.NexusPortBindingNotFound: # Check for vlan/switch binding try: nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) except excep.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port LOG.debug(_("Nexus: create & trunk vlan %s"), vlan_name) self.driver.create_and_trunk_vlan(switch_ip, vlan_id, vlan_name, port_id) vlan_created = True vlan_trunked = True else: # Only trunk vlan on the port LOG.debug(_("Nexus: trunk vlan %s"), vlan_name) self.driver.enable_vlan_on_trunk_int(switch_ip, vlan_id, port_id) vlan_trunked = 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 and vlan_trunked: LOG.debug(_("Nexus: delete & untrunk vlan %s"), vlan_name) self.driver.delete_and_untrunk_vlan(switch_ip, vlan_id, port_id) elif vlan_created: LOG.debug(_("Nexus: delete vlan %s"), vlan_name) self.driver.delete_vlan(switch_ip, vlan_id) elif vlan_trunked: LOG.debug(_("Nexus: untrunk vlan %s"), vlan_name) self.driver.disable_vlan_on_trunk_int(switch_ip, vlan_id, port_id)
def _manage_port(self, vlan_name, vlan_id, host, instance): """Called during create and update port events. Create a VLAN in the appropriate switch/port and configure the appropriate interfaces for this VLAN. """ # 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 excep.NexusComputeHostNotConfigured(host=host) # 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 excep.NexusPortBindingNotFound: # Check for vlan/switch binding try: nxos_db.get_nexusvlan_binding(vlan_id, switch_ip) except excep.NexusPortBindingNotFound: # Create vlan and trunk vlan on the port LOG.debug(_("Nexus: create & trunk vlan %s"), vlan_name) self.driver.create_and_trunk_vlan(switch_ip, vlan_id, vlan_name, port_id) vlan_created = True vlan_trunked = True else: # Only trunk vlan on the port LOG.debug(_("Nexus: trunk vlan %s"), vlan_name) self.driver.enable_vlan_on_trunk_int(switch_ip, vlan_id, port_id) vlan_trunked = 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 and vlan_trunked: LOG.debug(_("Nexus: delete & untrunk vlan %s"), vlan_name) self.driver.delete_and_untrunk_vlan( switch_ip, vlan_id, port_id) elif vlan_created: LOG.debug(_("Nexus: delete vlan %s"), vlan_name) self.driver.delete_vlan(switch_ip, vlan_id) elif vlan_trunked: LOG.debug(_("Nexus: untrunk vlan %s"), vlan_name) self.driver.disable_vlan_on_trunk_int( switch_ip, vlan_id, port_id)
def delete_port_precommit(self, context): """Delete port pre-database commit event. Delete port bindings from the database and scan whether the network is still required on the interfaces trunked. """ if not self._is_deviceowner_compute(context.current): return port = context.current device_id = port['device_id'] vlan_id = self._get_vlanid(context) if not vlan_id or not device_id: return # Delete DB row for this port try: row = nxos_db.get_nexusvm_binding(vlan_id, device_id) except excep.NexusPortBindingNotFound: return switch_ip = row.switch_ip nexus_port = None if row.port_id != 'router': nexus_port = row.port_id 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 excep.NexusPortBindingNotFound: try: # Delete this vlan from this switch if nexus_port: self.driver.disable_vlan_on_trunk_int(switch_ip, row.vlan_id, nexus_port) self.driver.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)
def delete_port_precommit(self, context): """Delete port pre-database commit event. Delete port bindings from the database and scan whether the network is still required on the interfaces trunked. """ if not self._is_deviceowner_compute(context.current): return port = context.current device_id = port['device_id'] vlan_id = self._get_vlanid(context) if not vlan_id or not device_id: return # Delete DB row for this port try: row = nxos_db.get_nexusvm_binding(vlan_id, device_id) except excep.NexusPortBindingNotFound: return switch_ip = row.switch_ip nexus_port = None if row.port_id != 'router': nexus_port = row.port_id 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 excep.NexusPortBindingNotFound: try: # Delete this vlan from this switch if nexus_port: self.driver.disable_vlan_on_trunk_int( switch_ip, row.vlan_id, nexus_port) self.driver.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)
def test_nexusvlanbinding_get(self): """Test get of port bindings based on vlan and switch.""" npb11 = self._npb_test_obj(10, 100) npb21 = self._npb_test_obj(20, 100) npb22 = self._npb_test_obj(20, 200) self._add_bindings_to_db([npb11, npb21, npb22]) npb_all_v100 = self._get_nexusvlan_binding(npb11) self.assertEqual(len(npb_all_v100), 2) npb_v200 = self._get_nexusvlan_binding(npb22) self.assertEqual(len(npb_v200), 1) self._assert_bindings_match(npb_v200[0], npb22) with testtools.ExpectedException(exceptions.NexusPortBindingNotFound): nexus_db_v2.get_nexusvlan_binding(npb21.vlan, "dummySwitch")
def test_nexusbinding_update(self): """Tests update of vlan IDs for port bindings.""" 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_bindings_to_db([npb11, npb21]) npb_all_v100 = nexus_db_v2.get_nexusvlan_binding(100, '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 = nexus_db_v2.update_nexusport_binding(npb21.port, 200) self._assert_bindings_match(npb, npb22) npb_all_v100 = nexus_db_v2.get_nexusvlan_binding(100, '1.1.1.1') self.assertEqual(len(npb_all_v100), 1) self._assert_bindings_match(npb_all_v100[0], npb11) npb = nexus_db_v2.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(exceptions.NexusPortBindingNotFound): nexus_db_v2.update_nexusport_binding(npb33.port, 200)
def _get_nexusvlan_binding(self, npb): """Gets port bindings based on vlan and switch.""" return nexus_db_v2.get_nexusvlan_binding(npb.vlan, npb.switch)