From 3b42ff35f7241bf1d3e239c094fc9604af7fb0a1 Mon Sep 17 00:00:00 2001
From: armando-migliaccio <armamig@gmail.com>
Date: Mon, 20 Jul 2015 16:46:17 -0700
Subject: [PATCH] Register provider configuration with ServiceTypeManager

Instead of hard-coding advanced services, like vpnaas, with the ServiceTypeManager,
this change makes the registration explicit by leveraging the newly introduced API
add_provider_configuration.
Some unit testing refactoring was required to reduce code duplication and to deal
with the new way service providers are processed.

Related-bug: #1473110

Change-Id: I8924234aadf786801ffc100d7daa27acc145a195
---
 neutron_vpnaas/services/vpn/plugin.py         | 15 ++++++++++
 .../tests/unit/db/vpn/test_vpn_db.py          | 24 +++++++++++----
 .../vpn/service_drivers/test_cisco_ipsec.py   | 29 ++++++++++++++-----
 .../vpn/service_drivers/test_ipsec.py         | 24 +++++++++++----
 4 files changed, 74 insertions(+), 18 deletions(-)

diff --git a/neutron_vpnaas/services/vpn/plugin.py b/neutron_vpnaas/services/vpn/plugin.py
index bcf8191f6..b2d54fe54 100644
--- a/neutron_vpnaas/services/vpn/plugin.py
+++ b/neutron_vpnaas/services/vpn/plugin.py
@@ -14,8 +14,10 @@
 #    License for the specific language governing permissions and limitations
 #    under the License.
 
+from neutron.db import servicetype_db as st_db
 from neutron.i18n import _LI
 from neutron.plugins.common import constants
+from neutron.services import provider_configuration as pconf
 from neutron.services import service_base
 from oslo_log import log as logging
 
@@ -24,6 +26,17 @@ from neutron_vpnaas.db.vpn import vpn_db
 LOG = logging.getLogger(__name__)
 
 
+def add_provider_configuration(type_manager, service_type):
+    try:
+        type_manager.add_provider_configuration(
+            service_type,
+            pconf.ProviderConfiguration('neutron_vpnaas'))
+    except AttributeError:
+        # TODO(armax): remove this try catch once the API
+        # add_provider_configuration becomes available
+        LOG.debug('add_provider_configuration API is not available')
+
+
 class VPNPlugin(vpn_db.VPNPluginDb):
 
     """Implementation of the VPN Service Plugin.
@@ -41,6 +54,8 @@ class VPNDriverPlugin(VPNPlugin, vpn_db.VPNPluginRpcDbMixin):
     #TODO(nati) handle ikepolicy and ipsecpolicy update usecase
     def __init__(self):
         super(VPNDriverPlugin, self).__init__()
+        self.service_type_manager = st_db.ServiceTypeManager.get_instance()
+        add_provider_configuration(self.service_type_manager, constants.VPN)
         # Load the service driver from neutron.conf.
         drivers, default_provider = service_base.load_drivers(
             constants.VPN, self)
diff --git a/neutron_vpnaas/tests/unit/db/vpn/test_vpn_db.py b/neutron_vpnaas/tests/unit/db/vpn/test_vpn_db.py
index dbf8e141d..98dde8424 100644
--- a/neutron_vpnaas/tests/unit/db/vpn/test_vpn_db.py
+++ b/neutron_vpnaas/tests/unit/db/vpn/test_vpn_db.py
@@ -422,13 +422,27 @@ class VPNPluginDbTestCase(VPNTestMixin,
                 constants.VPN +
                 ':vpnaas:neutron_vpnaas.services.vpn.'
                 'service_drivers.ipsec.IPsecVPNDriver:default')
-
-        cfg.CONF.set_override('service_provider',
-                              [vpnaas_provider],
-                              'service_providers')
+        # TODO(armax): remove this if branch as soon as the ServiceTypeManager
+        # API for adding provider configurations becomes available
+        if not hasattr(sdb.ServiceTypeManager, 'add_provider_configuration'):
+            cfg.CONF.set_override(
+                'service_provider', [vpnaas_provider], 'service_providers')
+        else:
+            bits = vpnaas_provider.split(':')
+            vpnaas_provider = {
+                'service_type': bits[0],
+                'name': bits[1],
+                'driver': bits[2]
+            }
+            if len(bits) == 4:
+                vpnaas_provider['default'] = True
+            # override the default service provider
+            self.service_providers = (
+                mock.patch.object(sdb.ServiceTypeManager,
+                                  'get_service_providers').start())
+            self.service_providers.return_value = [vpnaas_provider]
         # force service type manager to reload configuration:
         sdb.ServiceTypeManager._instance = None
-
         service_plugins = {'vpnaas_plugin': vpnaas_plugin}
         plugin_str = ('neutron_vpnaas.tests.unit.db.vpn.'
                       'test_vpn_db.TestVpnCorePlugin')
diff --git a/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_cisco_ipsec.py b/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_cisco_ipsec.py
index 4c6a28be1..aa0a470d1 100644
--- a/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_cisco_ipsec.py
+++ b/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_cisco_ipsec.py
@@ -58,14 +58,27 @@ class TestCiscoValidatorSelection(base.BaseTestCase):
 
     def setUp(self):
         super(TestCiscoValidatorSelection, self).setUp()
-        vpnaas_provider = (constants.VPN + ':vpnaas:' +
-                           CISCO_IPSEC_SERVICE_DRIVER + ':default')
-        cfg.CONF.set_override('service_provider',
-                              [vpnaas_provider],
-                              'service_providers')
-        stm = st_db.ServiceTypeManager()
-        mock.patch('neutron.db.servicetype_db.ServiceTypeManager.get_instance',
-                   return_value=stm).start()
+        # TODO(armax): remove this if branch as soon as the ServiceTypeManager
+        # API for adding provider configurations becomes available
+        if not hasattr(st_db.ServiceTypeManager, 'add_provider_configuration'):
+            vpnaas_provider = (constants.VPN +
+                               ':vpnaas:' +
+                               CISCO_IPSEC_SERVICE_DRIVER + ':default')
+            cfg.CONF.set_override(
+                'service_provider', [vpnaas_provider], 'service_providers')
+        else:
+            vpnaas_provider = [{
+                'service_type': constants.VPN,
+                'name': 'vpnaas',
+                'driver': CISCO_IPSEC_SERVICE_DRIVER,
+                'default': True
+            }]
+            # override the default service provider
+            self.service_providers = (
+                mock.patch.object(st_db.ServiceTypeManager,
+                                  'get_service_providers').start())
+            self.service_providers.return_value = vpnaas_provider
+        st_db.ServiceTypeManager._instance = None
         mock.patch('neutron.common.rpc.create_connection').start()
         self.vpn_plugin = vpn_plugin.VPNDriverPlugin()
 
diff --git a/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_ipsec.py b/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_ipsec.py
index 7c51f3e11..7c285affa 100644
--- a/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_ipsec.py
+++ b/neutron_vpnaas/tests/unit/services/vpn/service_drivers/test_ipsec.py
@@ -54,11 +54,25 @@ class TestValidatorSelection(base.BaseTestCase):
 
     def setUp(self):
         super(TestValidatorSelection, self).setUp()
-        vpnaas_provider = (constants.VPN + ':vpnaas:' +
-                           IPSEC_SERVICE_DRIVER + ':default')
-        cfg.CONF.set_override('service_provider',
-                              [vpnaas_provider],
-                              'service_providers')
+        # TODO(armax): remove this if branch as soon as the ServiceTypeManager
+        # API for adding provider configurations becomes available
+        if not hasattr(st_db.ServiceTypeManager, 'add_provider_configuration'):
+            vpnaas_provider = (constants.VPN + ':vpnaas:' +
+                               IPSEC_SERVICE_DRIVER + ':default')
+            cfg.CONF.set_override(
+                'service_provider', [vpnaas_provider], 'service_providers')
+        else:
+            vpnaas_provider = [{
+                'service_type': constants.VPN,
+                'name': 'vpnaas',
+                'driver': IPSEC_SERVICE_DRIVER,
+                'default': True
+            }]
+            # override the default service provider
+            self.service_providers = (
+                mock.patch.object(st_db.ServiceTypeManager,
+                                  'get_service_providers').start())
+            self.service_providers.return_value = vpnaas_provider
         mock.patch('neutron.common.rpc.create_connection').start()
         stm = st_db.ServiceTypeManager()
         mock.patch('neutron.db.servicetype_db.ServiceTypeManager.get_instance',