From d83afeccf1c0c055f783c63f641ac9bbcacf6e90 Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Sun, 31 Jul 2011 23:21:11 -0700 Subject: [PATCH 1/7] bug802772 update exception handling in OVS plugin to use API exceptions. --- quantum/db/api.py | 97 +++++++++++----- quantum/plugins/SamplePlugin.py | 10 +- .../plugins/openvswitch/ovs_quantum_plugin.py | 109 ++++++++---------- 3 files changed, 121 insertions(+), 95 deletions(-) diff --git a/quantum/db/api.py b/quantum/db/api.py index 6813d2096ce..0c42bda3df9 100644 --- a/quantum/db/api.py +++ b/quantum/db/api.py @@ -20,6 +20,7 @@ from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, exc +from quantum.common import exceptions as q_exc from quantum.db import models _ENGINE = None @@ -105,8 +106,8 @@ def network_get(net_id): return session.query(models.Network).\ filter_by(uuid=net_id).\ one() - except exc.NoResultFound: - raise Exception("No net found with id = %s" % net_id) + except exc.NoResultFound, e: + raise q_exc.NetworkNotFound(net_id=net_id) def network_rename(net_id, tenant_id, new_name): @@ -115,6 +116,8 @@ def network_rename(net_id, tenant_id, new_name): res = session.query(models.Network).\ filter_by(tenant_id=tenant_id, name=new_name).\ one() + if not res: + raise exc.NetworkNotFound(net_id=net_id) except exc.NoResultFound: net = network_get(net_id) net.name = new_name @@ -134,10 +137,13 @@ def network_destroy(net_id): session.flush() return net except exc.NoResultFound: - raise Exception("No network found with id = %s" % net_id) + raise q_exc.NetworkNotFound(net_id=net_id) def port_create(net_id, state=None): + # confirm network exists + network_get(net_id) + session = get_session() with session.begin(): port = models.Port(net_id) @@ -154,63 +160,90 @@ def port_list(net_id): all() -def port_get(port_id): +def port_get(port_id, net_id): + # confirm network exists + network_get(net_id) session = get_session() try: return session.query(models.Port).\ filter_by(uuid=port_id).\ + filter_by(network_id=net_id).\ one() except exc.NoResultFound: - raise Exception("No port found with id = %s " % port_id) + raise q_exc.PortNotFound(net_id=net_id, port_id=port_id) -def port_set_state(port_id, new_state): - port = port_get(port_id) - if port: - session = get_session() - port.state = new_state - session.merge(port) - session.flush() - return port +def port_set_state(port_id, net_id, new_state): + if new_state not in ('ACTIVE', 'DOWN'): + raise q_exc.StateInvalid(port_state=new_state) + # confirm network exists + network_get(net_id) -def port_set_attachment(port_id, new_interface_id): + port = port_get(port_id, net_id) session = get_session() - ports = [] + port.state = new_state + session.merge(port) + session.flush() + return port + + +def port_set_attachment(port_id, net_id, new_interface_id): + # confirm network exists + network_get(net_id) + + session = get_session() + port = port_get(port_id, net_id) + if new_interface_id != "": + # We are setting, not clearing, the attachment-id + if port['interface_id']: + raise q_exc.PortInUse(net_id=net_id, port_id=port_id, + att_id=port['interface_id']) + try: - ports = session.query(models.Port).\ + port = session.query(models.Port).\ filter_by(interface_id=new_interface_id).\ - all() + one() + raise q_exc.AlreadyAttached(net_id=net_id, + port_id=port_id, + att_id=new_interface_id, + att_port_id=port['uuid']) except exc.NoResultFound: + # this is what should happen pass - if len(ports) == 0: - port = port_get(port_id) - port.interface_id = new_interface_id - session.merge(port) - session.flush() - return port - else: - raise Exception("Port with attachment \"%s\" already exists" - % (new_interface_id)) + port.interface_id = new_interface_id + session.merge(port) + session.flush() + return port -def port_unset_attachment(port_id): +def port_unset_attachment(port_id, net_id): + # confirm network exists + network_get(net_id) + session = get_session() - port = port_get(port_id) + port = port_get(port_id, net_id) port.interface_id = None session.merge(port) session.flush -def port_destroy(port_id): +def port_destroy(port_id, net_id): + # confirm network exists + network_get(net_id) + session = get_session() try: port = session.query(models.Port).\ - filter_by(uuid=port_id).\ - one() + filter_by(uuid=port_id).\ + filter_by(network_id=net_id).\ + one() + if port['interface_id']: + raise q_exc.PortInUse(net_id=net_id, port_id=port_id, + att_id=port['interface_id']) session.delete(port) session.flush() return port except exc.NoResultFound: - raise Exception("No port found with id = %s " % port_id) + raise q_exc.PortNotFound(port_id=port_id) diff --git a/quantum/plugins/SamplePlugin.py b/quantum/plugins/SamplePlugin.py index 34573d2fe5e..f4aefac0a08 100644 --- a/quantum/plugins/SamplePlugin.py +++ b/quantum/plugins/SamplePlugin.py @@ -240,7 +240,7 @@ class FakePlugin(object): def _get_port(self, tenant_id, network_id, port_id): net = self._get_network(tenant_id, network_id) try: - port = db.port_get(port_id) + port = db.port_get(port_id, network_id) except: raise exc.PortNotFound(net_id=network_id, port_id=port_id) # Port must exist and belong to the appropriate network. @@ -373,7 +373,7 @@ class FakePlugin(object): self._get_network(tenant_id, net_id) self._get_port(tenant_id, net_id, port_id) self._validate_port_state(new_state) - db.port_set_state(port_id, new_state) + db.port_set_state(port_id, net_id, new_state) port_item = {'port-id': port_id, 'port-state': new_state} return port_item @@ -392,7 +392,7 @@ class FakePlugin(object): raise exc.PortInUse(net_id=net_id, port_id=port_id, att_id=port['interface_id']) try: - port = db.port_destroy(port_id) + port = db.port_destroy(port_id, net_id) except Exception, e: raise Exception("Failed to delete port: %s" % str(e)) d = {} @@ -412,7 +412,7 @@ class FakePlugin(object): if port['interface_id']: raise exc.PortInUse(net_id=net_id, port_id=port_id, att_id=port['interface_id']) - db.port_set_attachment(port_id, remote_interface_id) + db.port_set_attachment(port_id, net_id, remote_interface_id) def unplug_interface(self, tenant_id, net_id, port_id): """ @@ -423,4 +423,4 @@ class FakePlugin(object): self._get_port(tenant_id, net_id, port_id) # TODO(salvatore-orlando): # Should unplug on port without attachment raise an Error? - db.port_unset_attachment(port_id) + db.port_unset_attachment(port_id, net_id) diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 2f23517ec75..3d49f62e8d9 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -19,12 +19,13 @@ import ConfigParser import logging as LOG +from optparse import OptionParser import os import sys import unittest +from quantum.common import exceptions as q_exc from quantum.quantum_plugin_base import QuantumPluginBase -from optparse import OptionParser import quantum.db.api as db import ovs_db @@ -111,101 +112,93 @@ class OVSQuantumPlugin(QuantumPluginBase): nets = [] for x in db.network_list(tenant_id): LOG.debug("Adding network: %s" % x.uuid) - d = {} - d["net-id"] = str(x.uuid) - d["net-name"] = x.name - nets.append(d) + nets.append(self._make_net_dict(str(x.uuid), x.name, None)) return nets + def _make_net_dict(self, net_id, net_name, ports): + res = {'net-id': net_id, + 'net-name': net_name} + if ports: + res['net-ports'] = ports + return res + def create_network(self, tenant_id, net_name): - d = {} - try: - res = db.network_create(tenant_id, net_name) - LOG.debug("Created newtork: %s" % res) - except Exception, e: - LOG.error("Error: %s" % str(e)) - return d - d["net-id"] = str(res.uuid) - d["net-name"] = res.name - vlan_id = self.vmap.acquire(str(res.uuid)) - ovs_db.add_vlan_binding(vlan_id, str(res.uuid)) - return d + net = db.network_create(tenant_id, net_name) + LOG.debug("Created network: %s" % net) + vlan_id = self.vmap.acquire(str(net.uuid)) + ovs_db.add_vlan_binding(vlan_id, str(net.uuid)) + return self._make_net_dict(str(net.uuid), net.name, []) def delete_network(self, tenant_id, net_id): + net = db.network_get(net_id) + + # Verify that no attachments are plugged into the network + for port in db.port_list(net_id): + if port['interface_id']: + raise q_exc.NetworkInUse(net_id=net_id) net = db.network_destroy(net_id) - d = {} - d["net-id"] = str(net.uuid) ovs_db.remove_vlan_binding(net_id) self.vmap.release(net_id) - return d + return self._make_net_dict(str(net.uuid), net.name, []) def get_network_details(self, tenant_id, net_id): - ports = db.port_list(net_id) - ifaces = [] - for p in ports: - ifaces.append(p.interface_id) - return ifaces + net = db.network_get(net_id) + ports = self.get_all_ports(tenant_id, net_id) + return self._make_net_dict(str(net.uuid), net.name, ports) def rename_network(self, tenant_id, net_id, new_name): - try: - net = db.network_rename(net_id, tenant_id, new_name) - except Exception, e: - raise Exception("Failed to rename network: %s" % str(e)) - d = {} - d["net-id"] = str(net.uuid) - d["net-name"] = net.name - return d + net = db.network_rename(net_id, tenant_id, new_name) + return self._make_net_dict(str(net.uuid), net.name, None) + + def _make_port_dict(self, port_id, port_state, net_id, attachment): + res = {'port-id': port_id, + 'port-state': port_state} + if net_id: + res['net-id'] = net_id + if attachment: + res['attachment-id'] = attachment + return res def get_all_ports(self, tenant_id, net_id): ids = [] ports = db.port_list(net_id) - for x in ports: - LOG.debug("Appending port: %s" % x.uuid) - d = {} - d["port-id"] = str(x.uuid) + for p in ports: + LOG.debug("Appending port: %s" % p.uuid) + d = self._make_port_dict(str(p.uuid), "ACTIVE", None, None) ids.append(d) return ids def create_port(self, tenant_id, net_id, port_state=None): LOG.debug("Creating port with network_id: %s" % net_id) port = db.port_create(net_id) - d = {} - d["port-id"] = str(port.uuid) - LOG.debug("-> %s" % (port.uuid)) - return d + return self._make_port_dict(str(port.uuid), "ACTIVE", None, None) def delete_port(self, tenant_id, net_id, port_id): - try: - port = db.port_destroy(port_id) - except Exception, e: - raise Exception("Failed to delete port: %s" % str(e)) - d = {} - d["port-id"] = str(port.uuid) - return d + port = db.port_destroy(port_id, net_id) + return self._make_port_dict(str(port.uuid), "ACTIVE", None, None) def update_port(self, tenant_id, net_id, port_id, port_state): """ Updates the state of a port on the specified Virtual Network. """ LOG.debug("update_port() called\n") - port = db.port_get(port_id) - port['port-state'] = port_state - return port + port = db.port_get(port_id, net_id) + db.port_set_state(port_id, net_id, port_state) + return self._make_port_dict(str(port.uuid), "ACTIVE", None, None) def get_port_details(self, tenant_id, net_id, port_id): - port = db.port_get(port_id) - rv = {"port-id": port.uuid, "attachment": port.interface_id, - "net-id": port.network_id, "port-state": "UP"} - return rv + port = db.port_get(port_id, net_id) + return self._make_port_dict(str(port.uuid), "ACTIVE", + port.network_id, port.interface_id) def plug_interface(self, tenant_id, net_id, port_id, remote_iface_id): - db.port_set_attachment(port_id, remote_iface_id) + db.port_set_attachment(port_id, net_id, remote_iface_id) def unplug_interface(self, tenant_id, net_id, port_id): - db.port_set_attachment(port_id, "") + db.port_set_attachment(port_id, net_id, "") def get_interface_details(self, tenant_id, net_id, port_id): - res = db.port_get(port_id) + res = db.port_get(port_id, net_id) return res.interface_id From 3df4e822a28a20861627b8ab78fb19b26dd3c9e7 Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Mon, 1 Aug 2011 00:14:18 -0700 Subject: [PATCH 2/7] make ovs plugin pay attention to port state --- .../openvswitch/agent/ovs_quantum_agent.py | 2 +- .../plugins/openvswitch/ovs_quantum_plugin.py | 12 ++++++------ tests/unit/test_api.py | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py index 5d2a66ca37a..404c801787f 100755 --- a/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py +++ b/quantum/plugins/openvswitch/agent/ovs_quantum_agent.py @@ -198,7 +198,7 @@ class OVSQuantumAgent: while True: cursor = conn.cursor() - cursor.execute("SELECT * FROM ports") + cursor.execute("SELECT * FROM ports where state = 'ACTIVE'") rows = cursor.fetchall() cursor.close() all_bindings = {} diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 3d49f62e8d9..0544f4d01d4 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -164,18 +164,18 @@ class OVSQuantumPlugin(QuantumPluginBase): ports = db.port_list(net_id) for p in ports: LOG.debug("Appending port: %s" % p.uuid) - d = self._make_port_dict(str(p.uuid), "ACTIVE", None, None) + d = self._make_port_dict(str(p.uuid), p.state, None, None) ids.append(d) return ids def create_port(self, tenant_id, net_id, port_state=None): LOG.debug("Creating port with network_id: %s" % net_id) - port = db.port_create(net_id) - return self._make_port_dict(str(port.uuid), "ACTIVE", None, None) + port = db.port_create(net_id,port_state) + return self._make_port_dict(str(port.uuid), port.state, None, None) def delete_port(self, tenant_id, net_id, port_id): port = db.port_destroy(port_id, net_id) - return self._make_port_dict(str(port.uuid), "ACTIVE", None, None) + return self._make_port_dict(str(port.uuid), port.state, None, None) def update_port(self, tenant_id, net_id, port_id, port_state): """ @@ -184,11 +184,11 @@ class OVSQuantumPlugin(QuantumPluginBase): LOG.debug("update_port() called\n") port = db.port_get(port_id, net_id) db.port_set_state(port_id, net_id, port_state) - return self._make_port_dict(str(port.uuid), "ACTIVE", None, None) + return self._make_port_dict(str(port.uuid), port.state, None, None) def get_port_details(self, tenant_id, net_id, port_id): port = db.port_get(port_id, net_id) - return self._make_port_dict(str(port.uuid), "ACTIVE", + return self._make_port_dict(str(port.uuid), port.state, port.network_id, port.interface_id) def plug_interface(self, tenant_id, net_id, port_id, remote_iface_id): diff --git a/tests/unit/test_api.py b/tests/unit/test_api.py index d17e6ed87fa..d0daf85489f 100644 --- a/tests/unit/test_api.py +++ b/tests/unit/test_api.py @@ -414,6 +414,23 @@ class APITest(unittest.TestCase): show_port_res.body, content_type) self.assertEqual({'id': port_id, 'state': new_port_state}, port_data['port']) + + # now set it back to the original value + update_port_req = testlib.update_port_request(self.tenant_id, + network_id, port_id, + port_state, + format) + update_port_res = update_port_req.get_response(self.api) + self.assertEqual(update_port_res.status_int, 200) + show_port_req = testlib.show_port_request(self.tenant_id, + network_id, port_id, + format) + show_port_res = show_port_req.get_response(self.api) + self.assertEqual(show_port_res.status_int, 200) + port_data = self._port_serializer.deserialize( + show_port_res.body, content_type) + self.assertEqual({'id': port_id, 'state': port_state}, + port_data['port']) LOG.debug("_test_set_port_state - format:%s - END", format) def _test_set_port_state_networknotfound(self, format): From b0691d4202dc7d4042f7b08a99c39836236b6a9f Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Mon, 1 Aug 2011 07:45:49 -0700 Subject: [PATCH 3/7] pep8 fix --- quantum/plugins/openvswitch/ovs_quantum_plugin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 0544f4d01d4..505468ce9f6 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -170,7 +170,7 @@ class OVSQuantumPlugin(QuantumPluginBase): def create_port(self, tenant_id, net_id, port_state=None): LOG.debug("Creating port with network_id: %s" % net_id) - port = db.port_create(net_id,port_state) + port = db.port_create(net_id, port_state) return self._make_port_dict(str(port.uuid), port.state, None, None) def delete_port(self, tenant_id, net_id, port_id): From 67af7c736ca6666ae9756e084d60b15f6f0f311e Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Mon, 1 Aug 2011 10:11:16 -0700 Subject: [PATCH 4/7] fix incorrect handling of duplicate network name, add exception for duplicate network name, and add unit test to confirm detection. --- quantum/api/faults.py | 16 +++++++++++ quantum/api/networks.py | 13 ++++++--- quantum/common/exceptions.py | 5 ++++ quantum/db/api.py | 47 ++++++++++++++++----------------- quantum/plugins/SamplePlugin.py | 5 +--- tests/unit/test_api.py | 19 +++++++++++++ 6 files changed, 73 insertions(+), 32 deletions(-) diff --git a/quantum/api/faults.py b/quantum/api/faults.py index ef4d50bc6b2..52b36109d7d 100644 --- a/quantum/api/faults.py +++ b/quantum/api/faults.py @@ -31,6 +31,7 @@ class Fault(webob.exc.HTTPException): 401: "unauthorized", 420: "networkNotFound", 421: "networkInUse", + 422: "networkNameExists", 430: "portNotFound", 431: "requestedStateInvalid", 432: "portInUse", @@ -90,6 +91,21 @@ class NetworkInUse(webob.exc.HTTPClientError): title = 'Network in Use' explanation = ('Unable to remove the network: attachments still plugged.') +class NetworkNameExists(webob.exc.HTTPClientError): + """ + subclass of :class:`~HTTPClientError` + + This indicates that the server could not set the network name to the + specified value because another network for the same tenant already has + that name. + + code: 422, title: Network Name Exists + """ + code = 422 + title = 'Network Name Exists' + explanation = ('Unable to set network name: tenant already has network' \ + ' with same name.') + class PortNotFound(webob.exc.HTTPClientError): """ diff --git a/quantum/api/networks.py b/quantum/api/networks.py index 9afc09c24e3..27709eb5941 100644 --- a/quantum/api/networks.py +++ b/quantum/api/networks.py @@ -107,12 +107,15 @@ class Controller(common.QuantumController): self._network_ops_param_list) except exc.HTTPError as e: return faults.Fault(e) - network = self._plugin.\ + try: + network = self._plugin.\ create_network(tenant_id, request_params['net-name']) - builder = networks_view.get_view_builder(request) - result = builder.build(network) - return dict(networks=result) + builder = networks_view.get_view_builder(request) + result = builder.build(network) + return dict(networks=result) + except exception.NetworkNameExists as e: + return faults.Fault(faults.NetworkNameExists(e)) def update(self, request, tenant_id, id): """ Updates the name for the network with the given id """ @@ -128,6 +131,8 @@ class Controller(common.QuantumController): return exc.HTTPAccepted() except exception.NetworkNotFound as e: return faults.Fault(faults.NetworkNotFound(e)) + except exception.NetworkNameExists as e: + return faults.Fault(faults.NetworkNameExists(e)) def delete(self, request, tenant_id, id): """ Destroys the network with the given id """ diff --git a/quantum/common/exceptions.py b/quantum/common/exceptions.py index 4daf31762b9..b9705fb75ac 100644 --- a/quantum/common/exceptions.py +++ b/quantum/common/exceptions.py @@ -107,6 +107,11 @@ class AlreadyAttached(QuantumException): "%(port_id)s for network %(net_id)s. The attachment is " \ "already plugged into port %(att_port_id)s") +class NetworkNameExists(QuantumException): + message = _("Unable to set network name to %(net_name). " \ + "Network with id %(net_id) already has this name for " \ + "tenant %(tenant_id)") + class Duplicate(Error): pass diff --git a/quantum/db/api.py b/quantum/db/api.py index 0c42bda3df9..5711a47ddeb 100644 --- a/quantum/db/api.py +++ b/quantum/db/api.py @@ -76,21 +76,28 @@ def unregister_models(): BASE.metadata.drop_all(_ENGINE) -def network_create(tenant_id, name): +def _check_duplicate_net_name(tenant_id, net_name): session = get_session() - net = None try: net = session.query(models.Network).\ - filter_by(tenant_id=tenant_id, name=name).\ + filter_by(tenant_id=tenant_id, name=net_name).\ one() - raise Exception("Network with name %(name)s already " \ - "exists for tenant %(tenant_id)s" % locals()) + raise q_exc.NetworkNameExists(tenant_id=tenant_id, + net_name=net_name, net_id=net.uuid) except exc.NoResultFound: - with session.begin(): - net = models.Network(tenant_id, name) - session.add(net) - session.flush() - return net + # this is the "normal" path, as API spec specifies + # that net-names are unique within a tenant + pass + +def network_create(tenant_id, name): + session = get_session() + + _check_duplicate_net_name(tenant_id, name) + with session.begin(): + net = models.Network(tenant_id, name) + session.add(net) + session.flush() + return net def network_list(tenant_id): @@ -112,20 +119,12 @@ def network_get(net_id): def network_rename(net_id, tenant_id, new_name): session = get_session() - try: - res = session.query(models.Network).\ - filter_by(tenant_id=tenant_id, name=new_name).\ - one() - if not res: - raise exc.NetworkNotFound(net_id=net_id) - except exc.NoResultFound: - net = network_get(net_id) - net.name = new_name - session.merge(net) - session.flush() - return net - raise Exception("A network with name \"%s\" already exists" % new_name) - + net = network_get(net_id) + _check_duplicate_net_name(tenant_id, new_name) + net.name = new_name + session.merge(net) + session.flush() + return net def network_destroy(net_id): session = get_session() diff --git a/quantum/plugins/SamplePlugin.py b/quantum/plugins/SamplePlugin.py index f4aefac0a08..9b155a2c148 100644 --- a/quantum/plugins/SamplePlugin.py +++ b/quantum/plugins/SamplePlugin.py @@ -322,10 +322,7 @@ class FakePlugin(object): Virtual Network. """ LOG.debug("FakePlugin.rename_network() called") - try: - db.network_rename(net_id, tenant_id, new_name) - except: - raise exc.NetworkNotFound(net_id=net_id) + db.network_rename(net_id, tenant_id, new_name) net = self._get_network(tenant_id, net_id) return net diff --git a/tests/unit/test_api.py b/tests/unit/test_api.py index d17e6ed87fa..c52f6cefa75 100644 --- a/tests/unit/test_api.py +++ b/tests/unit/test_api.py @@ -152,6 +152,19 @@ class APITest(unittest.TestCase): network_data['network']) LOG.debug("_test_rename_network - format:%s - END", format) + def _test_rename_network_duplicate(self, format): + LOG.debug("_test_rename_network_duplicate - format:%s - START", format) + content_type = "application/%s" % format + network_id1 = self._create_network(format, name="net1") + network_id2 = self._create_network(format, name="net2") + update_network_req = testlib.update_network_request(self.tenant_id, + network_id2, + "net1", + format) + update_network_res = update_network_req.get_response(self.api) + self.assertEqual(update_network_res.status_int, 422) + LOG.debug("_test_rename_network_duplicate - format:%s - END", format) + def _test_rename_network_badrequest(self, format): LOG.debug("_test_rename_network_badrequest - format:%s - START", format) @@ -693,6 +706,12 @@ class APITest(unittest.TestCase): def test_rename_network_xml(self): self._test_rename_network('xml') + def test_rename_network_duplicate_json(self): + self._test_rename_network_duplicate('json') + + def test_rename_network_duplicate_xml(self): + self._test_rename_network_duplicate('xml') + def test_rename_network_badrequest_json(self): self._test_rename_network_badrequest('json') From 32b5806ddf86b22f4d02cd8bf82753fedc2dd1c0 Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Tue, 2 Aug 2011 10:14:25 -0700 Subject: [PATCH 5/7] fix broken flush in db.network_destroy, pep8 fixes --- quantum/api/faults.py | 1 + quantum/common/exceptions.py | 1 + quantum/db/api.py | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/quantum/api/faults.py b/quantum/api/faults.py index 52b36109d7d..670ef9f8996 100644 --- a/quantum/api/faults.py +++ b/quantum/api/faults.py @@ -91,6 +91,7 @@ class NetworkInUse(webob.exc.HTTPClientError): title = 'Network in Use' explanation = ('Unable to remove the network: attachments still plugged.') + class NetworkNameExists(webob.exc.HTTPClientError): """ subclass of :class:`~HTTPClientError` diff --git a/quantum/common/exceptions.py b/quantum/common/exceptions.py index b9705fb75ac..23dc700a47b 100644 --- a/quantum/common/exceptions.py +++ b/quantum/common/exceptions.py @@ -107,6 +107,7 @@ class AlreadyAttached(QuantumException): "%(port_id)s for network %(net_id)s. The attachment is " \ "already plugged into port %(att_port_id)s") + class NetworkNameExists(QuantumException): message = _("Unable to set network name to %(net_name). " \ "Network with id %(net_id) already has this name for " \ diff --git a/quantum/db/api.py b/quantum/db/api.py index 5711a47ddeb..436df84152b 100644 --- a/quantum/db/api.py +++ b/quantum/db/api.py @@ -89,6 +89,7 @@ def _check_duplicate_net_name(tenant_id, net_name): # that net-names are unique within a tenant pass + def network_create(tenant_id, name): session = get_session() @@ -126,6 +127,7 @@ def network_rename(net_id, tenant_id, new_name): session.flush() return net + def network_destroy(net_id): session = get_session() try: @@ -225,7 +227,7 @@ def port_unset_attachment(port_id, net_id): port = port_get(port_id, net_id) port.interface_id = None session.merge(port) - session.flush + session.flush() def port_destroy(port_id, net_id): From 292f5683a6580f1cc5b25d67cf3567907e5a6da5 Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Fri, 5 Aug 2011 22:53:57 -0700 Subject: [PATCH 6/7] remove unneeded tests from ovs_quantum_plugin --- quantum/api/faults.py | 1 + quantum/common/exceptions.py | 4 + quantum/db/api.py | 1 + quantum/plugins.ini | 2 +- .../openvswitch/ovs_quantum_plugin.ini | 2 +- .../plugins/openvswitch/ovs_quantum_plugin.py | 105 ------------------ 6 files changed, 8 insertions(+), 107 deletions(-) diff --git a/quantum/api/faults.py b/quantum/api/faults.py index 52b36109d7d..670ef9f8996 100644 --- a/quantum/api/faults.py +++ b/quantum/api/faults.py @@ -91,6 +91,7 @@ class NetworkInUse(webob.exc.HTTPClientError): title = 'Network in Use' explanation = ('Unable to remove the network: attachments still plugged.') + class NetworkNameExists(webob.exc.HTTPClientError): """ subclass of :class:`~HTTPClientError` diff --git a/quantum/common/exceptions.py b/quantum/common/exceptions.py index b9705fb75ac..478ddd551bf 100644 --- a/quantum/common/exceptions.py +++ b/quantum/common/exceptions.py @@ -21,6 +21,9 @@ Quantum-type exceptions. SHOULD include dedicated exception logging. """ import logging +import gettext + +gettext.install('quantum', unicode=1) class QuantumException(Exception): @@ -107,6 +110,7 @@ class AlreadyAttached(QuantumException): "%(port_id)s for network %(net_id)s. The attachment is " \ "already plugged into port %(att_port_id)s") + class NetworkNameExists(QuantumException): message = _("Unable to set network name to %(net_name). " \ "Network with id %(net_id) already has this name for " \ diff --git a/quantum/db/api.py b/quantum/db/api.py index 5711a47ddeb..75f09e36d7e 100644 --- a/quantum/db/api.py +++ b/quantum/db/api.py @@ -89,6 +89,7 @@ def _check_duplicate_net_name(tenant_id, net_name): # that net-names are unique within a tenant pass + def network_create(tenant_id, name): session = get_session() diff --git a/quantum/plugins.ini b/quantum/plugins.ini index 307d2b48d2c..cb669f9e791 100644 --- a/quantum/plugins.ini +++ b/quantum/plugins.ini @@ -1,3 +1,3 @@ [PLUGIN] # Quantum plugin provider module -provider = quantum.plugins.SamplePlugin.FakePlugin +provider = quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPlugin diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.ini b/quantum/plugins/openvswitch/ovs_quantum_plugin.ini index 66095d85d1b..e6dc431e09e 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.ini +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.ini @@ -6,4 +6,4 @@ host = 127.0.0.1 port = 3306 [OVS] -integration-bridge = br100 +integration-bridge = br-int diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 505468ce9f6..1ca17b94096 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -35,7 +35,6 @@ CONF_FILE = "ovs_quantum_plugin.ini" LOG.basicConfig(level=LOG.WARN) LOG.getLogger("ovs_quantum_plugin") - def find_config(basepath): for root, dirs, files in os.walk(basepath): if CONF_FILE in files: @@ -220,108 +219,6 @@ class VlanMapTest(unittest.TestCase): self.assertTrue(self.vmap.get(vlan_id) == None) -# TODO(bgh): Make the tests use a sqlite database instead of mysql -class OVSPluginTest(unittest.TestCase): - - def setUp(self): - self.quantum = OVSQuantumPlugin() - self.tenant_id = "testtenant" - - def testCreateNetwork(self): - net1 = self.quantum.create_network(self.tenant_id, "plugin_test1") - self.assertTrue(net1["net-name"] == "plugin_test1") - - def testGetNetworks(self): - net1 = self.quantum.create_network(self.tenant_id, "plugin_test1") - net2 = self.quantum.create_network(self.tenant_id, "plugin_test2") - nets = self.quantum.get_all_networks(self.tenant_id) - count = 0 - for x in nets: - if "plugin_test" in x["net-name"]: - count += 1 - self.assertTrue(count == 2) - - def testDeleteNetwork(self): - net = self.quantum.create_network(self.tenant_id, "plugin_test1") - self.quantum.delete_network(self.tenant_id, net["net-id"]) - nets = self.quantum.get_all_networks(self.tenant_id) - count = 0 - for x in nets: - if "plugin_test" in x["net-name"]: - count += 1 - self.assertTrue(count == 0) - - def testRenameNetwork(self): - net = self.quantum.create_network(self.tenant_id, "plugin_test1") - net = self.quantum.rename_network(self.tenant_id, net["net-id"], - "plugin_test_renamed") - self.assertTrue(net["net-name"] == "plugin_test_renamed") - - def testCreatePort(self): - net1 = self.quantum.create_network(self.tenant_id, "plugin_test1") - port = self.quantum.create_port(self.tenant_id, net1["net-id"]) - ports = self.quantum.get_all_ports(self.tenant_id, net1["net-id"]) - count = 0 - for p in ports: - count += 1 - self.assertTrue(count == 1) - - def testDeletePort(self): - net1 = self.quantum.create_network(self.tenant_id, "plugin_test1") - port = self.quantum.create_port(self.tenant_id, net1["net-id"]) - ports = self.quantum.get_all_ports(self.tenant_id, net1["net-id"]) - count = 0 - for p in ports: - count += 1 - self.assertTrue(count == 1) - for p in ports: - self.quantum.delete_port(self.tenant_id, id, p["port-id"]) - ports = self.quantum.get_all_ports(self.tenant_id, net1["net-id"]) - count = 0 - for p in ports: - count += 1 - self.assertTrue(count == 0) - - def testGetPorts(self): - pass - - def testPlugInterface(self): - net1 = self.quantum.create_network(self.tenant_id, "plugin_test1") - port = self.quantum.create_port(self.tenant_id, net1["net-id"]) - self.quantum.plug_interface(self.tenant_id, net1["net-id"], - port["port-id"], "vif1.1") - port = self.quantum.get_port_details(self.tenant_id, net1["net-id"], - port["port-id"]) - self.assertTrue(port["attachment"] == "vif1.1") - - def testUnPlugInterface(self): - net1 = self.quantum.create_network(self.tenant_id, "plugin_test1") - port = self.quantum.create_port(self.tenant_id, net1["net-id"]) - self.quantum.plug_interface(self.tenant_id, net1["net-id"], - port["port-id"], "vif1.1") - port = self.quantum.get_port_details(self.tenant_id, net1["net-id"], - port["port-id"]) - self.assertTrue(port["attachment"] == "vif1.1") - self.quantum.unplug_interface(self.tenant_id, net1["net-id"], - port["port-id"]) - port = self.quantum.get_port_details(self.tenant_id, net1["net-id"], - port["port-id"]) - self.assertTrue(port["attachment"] == "") - - def tearDown(self): - networks = self.quantum.get_all_networks(self.tenant_id) - # Clean up any test networks lying around - for net in networks: - id = net["net-id"] - name = net["net-name"] - if "plugin_test" in name: - # Clean up any test ports lying around - ports = self.quantum.get_all_ports(self.tenant_id, id) - for p in ports: - self.quantum.delete_port(self.tenant_id, id, p["port-id"]) - self.quantum.delete_network(self.tenant_id, id) - - if __name__ == "__main__": usagestr = "Usage: %prog [OPTIONS] [args]" parser = OptionParser(usage=usagestr) @@ -338,7 +235,5 @@ if __name__ == "__main__": # Make sqlalchemy quieter LOG.getLogger('sqlalchemy.engine').setLevel(LOG.WARN) # Run the tests - suite = unittest.TestLoader().loadTestsFromTestCase(OVSPluginTest) - unittest.TextTestRunner(verbosity=2).run(suite) suite = unittest.TestLoader().loadTestsFromTestCase(VlanMapTest) unittest.TextTestRunner(verbosity=2).run(suite) From 132667244bb6b28815cf4efbabeaab32f38a7b35 Mon Sep 17 00:00:00 2001 From: Dan Wendlandt Date: Fri, 5 Aug 2011 23:06:20 -0700 Subject: [PATCH 7/7] pep8 cleanup, restore defaults --- quantum/db/api.py | 1 + quantum/plugins.ini | 2 +- quantum/plugins/openvswitch/ovs_quantum_plugin.py | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/quantum/db/api.py b/quantum/db/api.py index 75f09e36d7e..8eccb055082 100644 --- a/quantum/db/api.py +++ b/quantum/db/api.py @@ -127,6 +127,7 @@ def network_rename(net_id, tenant_id, new_name): session.flush() return net + def network_destroy(net_id): session = get_session() try: diff --git a/quantum/plugins.ini b/quantum/plugins.ini index cb669f9e791..307d2b48d2c 100644 --- a/quantum/plugins.ini +++ b/quantum/plugins.ini @@ -1,3 +1,3 @@ [PLUGIN] # Quantum plugin provider module -provider = quantum.plugins.openvswitch.ovs_quantum_plugin.OVSQuantumPlugin +provider = quantum.plugins.SamplePlugin.FakePlugin diff --git a/quantum/plugins/openvswitch/ovs_quantum_plugin.py b/quantum/plugins/openvswitch/ovs_quantum_plugin.py index 1ca17b94096..1b46fca7c10 100644 --- a/quantum/plugins/openvswitch/ovs_quantum_plugin.py +++ b/quantum/plugins/openvswitch/ovs_quantum_plugin.py @@ -35,6 +35,7 @@ CONF_FILE = "ovs_quantum_plugin.ini" LOG.basicConfig(level=LOG.WARN) LOG.getLogger("ovs_quantum_plugin") + def find_config(basepath): for root, dirs, files in os.walk(basepath): if CONF_FILE in files: