From c4f0c4ba967af71d31629beff72a0f1f748202cb Mon Sep 17 00:00:00 2001 From: Mohammad Banikazemi Date: Tue, 22 Apr 2014 12:32:33 -0400 Subject: [PATCH] Fixes bugs for requests sent to SDN-VE controller This patchset fixes a couple of bugs wrt processing requests before sending them to the backend controller and adjusts the requests based on the controller requirements. It also corrects typos, add quotas and changes the default for a configuration parameter. Change-Id: I4b64c2b49ff4854949afc1e54cba1057f376b058 Closes-Bug: #1311260 DocImpact: The default tenant type is chganged from OF to OVERLAY --- .../plugins/ibm/sdnve_neutron_plugin.ini | 9 +++-- neutron/plugins/ibm/common/config.py | 4 +- neutron/plugins/ibm/sdnve_api.py | 5 ++- neutron/plugins/ibm/sdnve_neutron_plugin.py | 37 +++++++++++++++---- neutron/tests/unit/ibm/test_sdnve_api.py | 8 ++++ 5 files changed, 47 insertions(+), 16 deletions(-) diff --git a/etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini b/etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini index 8cb32ea1dc..0fab50706d 100644 --- a/etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini +++ b/etc/neutron/plugins/ibm/sdnve_neutron_plugin.ini @@ -1,6 +1,6 @@ [sdnve] # (ListOpt) The IP address of one (or more) SDN-VE controllers -# Default value is : controller_ips = 127.0.0.1 +# Default value is: controller_ips = 127.0.0.1 # Example: controller_ips = 127.0.0.1,127.0.0.2 # (StrOpt) The integration bridge for OF based implementation # The default value for integration_bridge is None @@ -17,7 +17,7 @@ # Example: out_of_band = False # # (BoolOpt) The fake controller for testing purposes -# Default value is : use_fake_controller = False +# Default value is: use_fake_controller = False # (StrOpt) The port number for use with controller # The default value for the port is 8443 # Example: port = 8443 @@ -29,8 +29,9 @@ # Example: password = sdnve_password # # (StrOpt) The default type of tenants (and associated resources) -# Default value for OF is: default_tenant = OF -# Example: default_tenant = OVERLAY +# Available choices are: OVERLAY or OF +# The default value for tenant type is OVERLAY +# Example: default_tenant_type = OVERLAY # (StrOpt) The string in tenant description that indicates # Default value for OF tenants: of_signature = SDNVE-OF # (StrOpt) The string in tenant description that indicates diff --git a/neutron/plugins/ibm/common/config.py b/neutron/plugins/ibm/common/config.py index b32c7b630d..fe67bc7df1 100644 --- a/neutron/plugins/ibm/common/config.py +++ b/neutron/plugins/ibm/common/config.py @@ -49,8 +49,8 @@ sdnve_opts = [ cfg.ListOpt('interface_mappings', default=DEFAULT_INTERFACE_MAPPINGS, help=_("List of :")), - cfg.StrOpt('default_tenant_type', default='OF', - help=_("Tenant type: OF (default) and OVERLAY")), + cfg.StrOpt('default_tenant_type', default='OVERLAY', + help=_("Tenant type: OVERLAY (default) or OF")), cfg.StrOpt('overlay_signature', default='SDNVE-OVERLAY', help=_("The string in tenant description that indicates " "the tenant is a OVERLAY tenant")), diff --git a/neutron/plugins/ibm/sdnve_api.py b/neutron/plugins/ibm/sdnve_api.py index 43ba132da2..a0f1f0b9bb 100644 --- a/neutron/plugins/ibm/sdnve_api.py +++ b/neutron/plugins/ibm/sdnve_api.py @@ -226,6 +226,7 @@ class Client(RequestHandler): body = dict( (k.replace(':', '_'), v) for k, v in body.items() if attributes.is_attr_set(v)) + return body def sdnve_list(self, resource, **params): '''Fetches a list of resources.''' @@ -255,7 +256,7 @@ class Client(RequestHandler): LOG.info(_("Bad resource for forming a create request")) return 0, '' - self.process_request(body) + body = self.process_request(body) status, data = self.post(res, body=body) return (status, data) @@ -267,7 +268,7 @@ class Client(RequestHandler): LOG.info(_("Bad resource for forming a update request")) return 0, '' - self.process_request(body) + body = self.process_request(body) return self.put(res + specific, body=body) def sdnve_delete(self, resource, specific): diff --git a/neutron/plugins/ibm/sdnve_neutron_plugin.py b/neutron/plugins/ibm/sdnve_neutron_plugin.py index fda586eb7e..b88b04d24b 100644 --- a/neutron/plugins/ibm/sdnve_neutron_plugin.py +++ b/neutron/plugins/ibm/sdnve_neutron_plugin.py @@ -21,15 +21,16 @@ import functools from oslo.config import cfg -from neutron.common import constants as q_const +from neutron.common import constants as n_const from neutron.common import exceptions as n_exc -from neutron.common import rpc as q_rpc +from neutron.common import rpc as n_rpc from neutron.common import topics from neutron.db import agents_db from neutron.db import db_base_plugin_v2 from neutron.db import external_net_db from neutron.db import l3_gwmode_db from neutron.db import portbindings_db +from neutron.db import quota_db # noqa from neutron.extensions import portbindings from neutron.openstack.common import excutils from neutron.openstack.common import log as logging @@ -54,7 +55,7 @@ class SdnveRpcCallbacks(): If a manager would like to set an rpc API version, or support more than one class as the target of rpc messages, override this method. ''' - return q_rpc.PluginRpcDispatcher([self, + return n_rpc.PluginRpcDispatcher([self, agents_db.AgentExtRpcCallback()]) def sdnve_info(self, rpc_context, **kwargs): @@ -119,7 +120,7 @@ class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2, __native_sorting_support = False supported_extension_aliases = ["binding", "router", "external-net", - "agent"] + "agent", "quotas"] def __init__(self, configfile=None): self.base_binding_dict = { @@ -266,7 +267,7 @@ class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2, session = context.session # Set port status as 'ACTIVE' to avoid needing the agent - port['port']['status'] = q_const.PORT_STATUS_ACTIVE + port['port']['status'] = n_const.PORT_STATUS_ACTIVE port_data = port['port'] with session.begin(subtransactions=True): @@ -480,6 +481,11 @@ class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2, context, id, router) if processed_request['router']: + egw = processed_request['router'].get('external_gateway_info') + # Check for existing empty set (different from None) in request + if egw == {}: + processed_request['router'][ + 'external_gateway_info'] = {'network_id': 'null'} (res, data) = self.sdnve_client.sdnve_update( 'router', id, processed_request['router']) if res not in constants.HTTP_ACCEPTABLE: @@ -555,11 +561,11 @@ class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2, {'router_id': router_id, 'interface_info': interface_info}) subnet_id = interface_info.get('subnet_id') + port_id = interface_info.get('port_id') if not subnet_id: - portid = interface_info.get('port_id') - if not portid: + if not port_id: raise sdnve_exc.BadInputException(msg=_('No port ID')) - myport = super(SdnvePluginV2, self).get_port(context, portid) + myport = super(SdnvePluginV2, self).get_port(context, port_id) LOG.debug(_("SdnvePluginV2.remove_router_interface port: %s"), myport) myfixed_ips = myport.get('fixed_ips') @@ -571,6 +577,21 @@ class SdnvePluginV2(db_base_plugin_v2.NeutronDbPluginV2, LOG.debug( _("SdnvePluginV2.remove_router_interface subnet_id: %s"), subnet_id) + else: + if not port_id: + # The backend requires port id info in the request + subnet = super(SdnvePluginV2, self).get_subnet(context, + subnet_id) + df = {'device_id': [router_id], + 'device_owner': [n_const.DEVICE_OWNER_ROUTER_INTF], + 'network_id': [subnet['network_id']]} + ports = self.get_ports(context, filters=df) + if ports: + pid = ports[0]['id'] + interface_info['port_id'] = pid + msg = ("SdnvePluginV2.remove_router_interface " + "subnet_id: %(sid)s port_id: %(pid)s") + LOG.debug(msg, {'sid': subnet_id, 'pid': pid}) (res, data) = self.sdnve_client.sdnve_update( 'router', router_id + '/remove_router_interface', interface_info) diff --git a/neutron/tests/unit/ibm/test_sdnve_api.py b/neutron/tests/unit/ibm/test_sdnve_api.py index ff54078de4..f1f8d60b8b 100644 --- a/neutron/tests/unit/ibm/test_sdnve_api.py +++ b/neutron/tests/unit/ibm/test_sdnve_api.py @@ -135,3 +135,11 @@ class TestSdnveApi(base.BaseTestCase): result = self.api.sdnve_check_and_create_tenant( id, constants.TENANT_TYPE_OF) self.assertIsNone(result) + + def test_process_request(self): + my_request = {'key_1': 'value_1', 'router:external': 'True', + 'key_2': 'value_2'} + expected = {'key_1': 'value_1', 'router_external': 'True', + 'key_2': 'value_2'} + result = self.api.process_request(my_request) + self.assertEqual(expected, result)