Added support of multi-region environment
Octavia does not support keystone regions and can choose an incorrect endpoint url when multiple regions provides same services. Change-Id: I5ea9de380419592920555a2c2fe7ac6f6935e700 Closes-Bug: #1487359
This commit is contained in:
parent
cdd03b28eb
commit
0ab265ff41
|
@ -11,8 +11,10 @@
|
||||||
#
|
#
|
||||||
# octavia_plugins = hot_plug_plugin
|
# octavia_plugins = hot_plug_plugin
|
||||||
|
|
||||||
# nova_region_name =
|
# Region in Identity service catalog to use for communication with the OpenStack services.
|
||||||
#
|
#
|
||||||
|
# os_region_name =
|
||||||
|
|
||||||
# Hostname to be used by the host machine for services running on it.
|
# Hostname to be used by the host machine for services running on it.
|
||||||
# The default value is the hostname of the host machine.
|
# The default value is the hostname of the host machine.
|
||||||
# host =
|
# host =
|
||||||
|
@ -143,4 +145,4 @@
|
||||||
# Cleanup interval for Deleted amphora
|
# Cleanup interval for Deleted amphora
|
||||||
# cleanup_interval = 30
|
# cleanup_interval = 30
|
||||||
# Amphora expiry age in seconds. Default is 1 week
|
# Amphora expiry age in seconds. Default is 1 week
|
||||||
# amphora_expiry_age = 604800
|
# amphora_expiry_age = 604800
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
from neutronclient.neutron import client as neutron_client
|
||||||
|
from novaclient import client as nova_client
|
||||||
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import excutils
|
||||||
|
|
||||||
|
from octavia.common import keystone
|
||||||
|
from octavia.i18n import _LE
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
NEUTRON_VERSION = '2.0'
|
||||||
|
NOVA_VERSION = '2'
|
||||||
|
|
||||||
|
|
||||||
|
class NovaAuth(object):
|
||||||
|
nova_client = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_nova_client(cls, region):
|
||||||
|
"""Create nova client object.
|
||||||
|
|
||||||
|
:param region: The region of the service
|
||||||
|
:return: a Nova Client object.
|
||||||
|
:raises Exception: if the client cannot be created
|
||||||
|
"""
|
||||||
|
if not cls.nova_client:
|
||||||
|
try:
|
||||||
|
cls.nova_client = nova_client.Client(
|
||||||
|
NOVA_VERSION, session=keystone.get_session(),
|
||||||
|
region_name=region
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.exception(_LE("Error creating Nova client."))
|
||||||
|
return cls.nova_client
|
||||||
|
|
||||||
|
|
||||||
|
class NeutronAuth(object):
|
||||||
|
neutron_client = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_neutron_client(cls, region):
|
||||||
|
"""Create neutron client object.
|
||||||
|
|
||||||
|
:param region: The region of the service
|
||||||
|
:return: a Neutron Client object.
|
||||||
|
:raises Exception: if the client cannot be created
|
||||||
|
"""
|
||||||
|
if not cls.neutron_client:
|
||||||
|
try:
|
||||||
|
cls.neutron_client = neutron_client.Client(
|
||||||
|
NEUTRON_VERSION, session=keystone.get_session(),
|
||||||
|
region_name=region
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
with excutils.save_and_reraise_exception():
|
||||||
|
LOG.exception(_LE("Error creating Neutron client."))
|
||||||
|
return cls.neutron_client
|
|
@ -72,9 +72,9 @@ core_opts = [
|
||||||
help=_('CA file for novaclient to verify server certificates')),
|
help=_('CA file for novaclient to verify server certificates')),
|
||||||
cfg.BoolOpt('nova_api_insecure', default=False,
|
cfg.BoolOpt('nova_api_insecure', default=False,
|
||||||
help=_("If True, ignore any SSL validation issues")),
|
help=_("If True, ignore any SSL validation issues")),
|
||||||
cfg.StrOpt('nova_region_name',
|
cfg.StrOpt('os_region_name',
|
||||||
help=_('Name of nova region to use. Useful if keystone manages'
|
help=_('Region in Identity service catalog to use for '
|
||||||
' more than one region.')),
|
'communication with the OpenStack services.')),
|
||||||
cfg.StrOpt('octavia_plugins',
|
cfg.StrOpt('octavia_plugins',
|
||||||
default='hot_plug_plugin',
|
default='hot_plug_plugin',
|
||||||
help=_('Name of the controller plugin to use'))
|
help=_('Name of the controller plugin to use'))
|
||||||
|
|
|
@ -12,15 +12,13 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from novaclient import client as nova_client
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import excutils
|
|
||||||
|
|
||||||
|
from octavia.common import clients
|
||||||
from octavia.common import constants
|
from octavia.common import constants
|
||||||
from octavia.common import data_models as models
|
from octavia.common import data_models as models
|
||||||
from octavia.common import exceptions
|
from octavia.common import exceptions
|
||||||
from octavia.common import keystone
|
|
||||||
from octavia.compute import compute_base
|
from octavia.compute import compute_base
|
||||||
from octavia.i18n import _LE
|
from octavia.i18n import _LE
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||||
def __init__(self, region=None):
|
def __init__(self, region=None):
|
||||||
super(VirtualMachineManager, self).__init__()
|
super(VirtualMachineManager, self).__init__()
|
||||||
# Must initialize nova api
|
# Must initialize nova api
|
||||||
self._nova_client = NovaAuth.get_nova_client(region)
|
self._nova_client = clients.NovaAuth.get_nova_client(region)
|
||||||
self.manager = self._nova_client.servers
|
self.manager = self._nova_client.servers
|
||||||
|
|
||||||
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
def build(self, name="amphora_name", amphora_flavor=None, image_id=None,
|
||||||
|
@ -144,26 +142,3 @@ class VirtualMachineManager(compute_base.ComputeBase):
|
||||||
lb_network_ip=lb_network_ip
|
lb_network_ip=lb_network_ip
|
||||||
)
|
)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class NovaAuth(object):
|
|
||||||
_nova_client = None
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_nova_client(cls, region):
|
|
||||||
"""Create nova client object.
|
|
||||||
|
|
||||||
:param region: The region of the service
|
|
||||||
:return: a Nova Client object.
|
|
||||||
:raises Exception: if the client cannot be created
|
|
||||||
"""
|
|
||||||
if not cls._nova_client:
|
|
||||||
try:
|
|
||||||
cls._nova_client = nova_client.Client(
|
|
||||||
constants.NOVA_2, session=keystone.get_session(),
|
|
||||||
region_name=region
|
|
||||||
)
|
|
||||||
except Exception:
|
|
||||||
with excutils.save_and_reraise_exception():
|
|
||||||
LOG.exception(_LE("Error creating Nova client."))
|
|
||||||
return cls._nova_client
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class BaseComputeTask(task.Task):
|
||||||
namespace='octavia.compute.drivers',
|
namespace='octavia.compute.drivers',
|
||||||
name=CONF.controller_worker.compute_driver,
|
name=CONF.controller_worker.compute_driver,
|
||||||
invoke_on_load=True,
|
invoke_on_load=True,
|
||||||
invoke_kwds={'region': CONF.nova_region_name}
|
invoke_kwds={'region': CONF.os_region_name}
|
||||||
).driver
|
).driver
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,8 @@ class BaseNetworkTask(task.Task):
|
||||||
self.network_driver = stevedore_driver.DriverManager(
|
self.network_driver = stevedore_driver.DriverManager(
|
||||||
namespace='octavia.network.drivers',
|
namespace='octavia.network.drivers',
|
||||||
name=CONF.controller_worker.network_driver,
|
name=CONF.controller_worker.network_driver,
|
||||||
invoke_on_load=True
|
invoke_on_load=True,
|
||||||
|
invoke_kwds={'region': CONF.os_region_name}
|
||||||
).driver
|
).driver
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,4 +342,4 @@ class GetAmphoraeNetworkConfigs(BaseNetworkTask):
|
||||||
ha_subnet=ha_subnet,
|
ha_subnet=ha_subnet,
|
||||||
ha_port=ha_port
|
ha_port=ha_port
|
||||||
)
|
)
|
||||||
return amp_net_configs
|
return amp_net_configs
|
||||||
|
|
|
@ -13,11 +13,10 @@
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from neutronclient.common import exceptions as neutron_client_exceptions
|
from neutronclient.common import exceptions as neutron_client_exceptions
|
||||||
from neutronclient.neutron import client as neutron_client
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from octavia.common import clients
|
||||||
from octavia.common import data_models
|
from octavia.common import data_models
|
||||||
from octavia.common import keystone
|
|
||||||
from octavia.i18n import _LE, _LI
|
from octavia.i18n import _LE, _LI
|
||||||
from octavia.network import base
|
from octavia.network import base
|
||||||
from octavia.network import data_models as network_models
|
from octavia.network import data_models as network_models
|
||||||
|
@ -25,16 +24,14 @@ from octavia.network.drivers.neutron import utils
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
NEUTRON_VERSION = '2.0'
|
|
||||||
SEC_GRP_EXT_ALIAS = 'security-group'
|
SEC_GRP_EXT_ALIAS = 'security-group'
|
||||||
|
|
||||||
|
|
||||||
class BaseNeutronDriver(base.AbstractNetworkDriver):
|
class BaseNeutronDriver(base.AbstractNetworkDriver):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, region=None):
|
||||||
self.sec_grp_enabled = True
|
self.sec_grp_enabled = True
|
||||||
self.neutron_client = neutron_client.Client(
|
self.neutron_client = clients.NeutronAuth.get_neutron_client(region)
|
||||||
NEUTRON_VERSION, session=keystone.get_session())
|
|
||||||
extensions = self.neutron_client.list_extensions()
|
extensions = self.neutron_client.list_extensions()
|
||||||
self._extensions = extensions.get('extensions')
|
self._extensions = extensions.get('extensions')
|
||||||
self._check_sec_grps()
|
self._check_sec_grps()
|
||||||
|
@ -172,4 +169,4 @@ class BaseNeutronDriver(base.AbstractNetworkDriver):
|
||||||
'(port id: {port_id}.').format(
|
'(port id: {port_id}.').format(
|
||||||
port_id=port_id)
|
port_id=port_id)
|
||||||
LOG.exception(message)
|
LOG.exception(message)
|
||||||
raise base.NetworkException(message)
|
raise base.NetworkException(message)
|
||||||
|
|
|
@ -94,7 +94,7 @@ class NoopManager(object):
|
||||||
|
|
||||||
|
|
||||||
class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
||||||
def __init__(self):
|
def __init__(self, region=None):
|
||||||
super(NoopNetworkDriver, self).__init__()
|
super(NoopNetworkDriver, self).__init__()
|
||||||
self.driver = NoopManager()
|
self.driver = NoopManager()
|
||||||
|
|
||||||
|
@ -130,4 +130,4 @@ class NoopNetworkDriver(driver_base.AbstractNetworkDriver):
|
||||||
self.driver.get_subnet(subnet_id)
|
self.driver.get_subnet(subnet_id)
|
||||||
|
|
||||||
def get_port(self, port_id):
|
def get_port(self, port_id):
|
||||||
self.driver.get_port(port_id)
|
self.driver.get_port(port_id)
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import mock
|
import mock
|
||||||
import testtools
|
import testtools
|
||||||
|
|
||||||
from octavia.compute.drivers import nova_driver
|
from octavia.common import clients
|
||||||
|
|
||||||
|
|
||||||
class TestCase(testtools.TestCase):
|
class TestCase(testtools.TestCase):
|
||||||
|
@ -26,4 +26,5 @@ class TestCase(testtools.TestCase):
|
||||||
self.addCleanup(self.clean_caches)
|
self.addCleanup(self.clean_caches)
|
||||||
|
|
||||||
def clean_caches(self):
|
def clean_caches(self):
|
||||||
nova_driver.NovaAuth._nova_client = None
|
clients.NovaAuth.nova_client = None
|
||||||
|
clients.NeutronAuth.neutron_client = None
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import neutronclient.v2_0
|
||||||
|
import novaclient.v2
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from octavia.common import clients
|
||||||
|
from octavia.common import keystone
|
||||||
|
from octavia.tests.unit import base
|
||||||
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
|
class TestNovaAuth(base.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
CONF.set_override(group='keystone_authtoken', name='auth_version',
|
||||||
|
override='2')
|
||||||
|
# Reset the session and client
|
||||||
|
clients.NovaAuth.nova_client = None
|
||||||
|
keystone._SESSION = None
|
||||||
|
|
||||||
|
super(TestNovaAuth, self).setUp()
|
||||||
|
|
||||||
|
def test_get_nova_client(self):
|
||||||
|
# There should be no existing client
|
||||||
|
self.assertIsNone(
|
||||||
|
clients.NovaAuth.nova_client
|
||||||
|
)
|
||||||
|
|
||||||
|
# Mock out the keystone session and get the client
|
||||||
|
keystone._SESSION = mock.MagicMock()
|
||||||
|
bc1 = clients.NovaAuth.get_nova_client(region=None)
|
||||||
|
|
||||||
|
# Our returned client should also be the saved client
|
||||||
|
self.assertIsInstance(
|
||||||
|
clients.NovaAuth.nova_client,
|
||||||
|
novaclient.v2.client.Client
|
||||||
|
)
|
||||||
|
self.assertIs(
|
||||||
|
clients.NovaAuth.nova_client,
|
||||||
|
bc1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Getting the session again should return the same object
|
||||||
|
bc2 = clients.NovaAuth.get_nova_client(
|
||||||
|
region="test-region")
|
||||||
|
self.assertIs(bc1, bc2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestNeutronAuth(base.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
CONF.set_override(group='keystone_authtoken', name='auth_version',
|
||||||
|
override='2')
|
||||||
|
# Reset the session and client
|
||||||
|
clients.NeutronAuth.neutron_client = None
|
||||||
|
keystone._SESSION = None
|
||||||
|
|
||||||
|
super(TestNeutronAuth, self).setUp()
|
||||||
|
|
||||||
|
def test_get_neutron_client(self):
|
||||||
|
# There should be no existing client
|
||||||
|
self.assertIsNone(
|
||||||
|
clients.NeutronAuth.neutron_client
|
||||||
|
)
|
||||||
|
|
||||||
|
# Mock out the keystone session and get the client
|
||||||
|
keystone._SESSION = mock.MagicMock()
|
||||||
|
bc1 = clients.NeutronAuth.get_neutron_client(region=None)
|
||||||
|
|
||||||
|
# Our returned client should also be the saved client
|
||||||
|
self.assertIsInstance(
|
||||||
|
clients.NeutronAuth.neutron_client,
|
||||||
|
neutronclient.v2_0.client.Client
|
||||||
|
)
|
||||||
|
self.assertIs(
|
||||||
|
clients.NeutronAuth.neutron_client,
|
||||||
|
bc1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Getting the session again should return the same object
|
||||||
|
bc2 = clients.NeutronAuth.get_neutron_client(
|
||||||
|
region="test-region")
|
||||||
|
self.assertIs(bc1, bc2)
|
|
@ -12,8 +12,6 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from keystoneclient import session
|
|
||||||
import novaclient.v2
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_utils import uuidutils
|
from oslo_utils import uuidutils
|
||||||
import six
|
import six
|
||||||
|
@ -21,7 +19,6 @@ import six
|
||||||
from octavia.common import constants
|
from octavia.common import constants
|
||||||
from octavia.common import data_models as models
|
from octavia.common import data_models as models
|
||||||
from octavia.common import exceptions
|
from octavia.common import exceptions
|
||||||
from octavia.common import keystone
|
|
||||||
import octavia.compute.drivers.nova_driver as nova_common
|
import octavia.compute.drivers.nova_driver as nova_common
|
||||||
import octavia.tests.unit.base as base
|
import octavia.tests.unit.base as base
|
||||||
|
|
||||||
|
@ -123,55 +120,3 @@ class TestNovaClient(base.TestCase):
|
||||||
self.manager.manager.get.side_effect = Exception
|
self.manager.manager.get.side_effect = Exception
|
||||||
self.assertRaises(exceptions.ComputeGetException,
|
self.assertRaises(exceptions.ComputeGetException,
|
||||||
self.manager.get_amphora, self.amphora.id)
|
self.manager.get_amphora, self.amphora.id)
|
||||||
|
|
||||||
|
|
||||||
class TestNovaAuth(base.TestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
CONF.set_override(group='keystone_authtoken', name='auth_version',
|
|
||||||
override='2')
|
|
||||||
# Reset the session and client
|
|
||||||
nova_common.NovaAuth._nova_client = None
|
|
||||||
keystone._SESSION = None
|
|
||||||
|
|
||||||
super(TestNovaAuth, self).setUp()
|
|
||||||
|
|
||||||
def test_get_keystone_client(self):
|
|
||||||
# There should be no existing session
|
|
||||||
self.assertIsNone(keystone._SESSION)
|
|
||||||
|
|
||||||
# Get us a session
|
|
||||||
ks1 = keystone.get_session()
|
|
||||||
|
|
||||||
# Our returned session should also be the saved session
|
|
||||||
self.assertIsInstance(keystone._SESSION, session.Session)
|
|
||||||
self.assertIs(keystone._SESSION, ks1)
|
|
||||||
|
|
||||||
# Getting the session again should return the same object
|
|
||||||
ks2 = keystone.get_session()
|
|
||||||
self.assertIs(ks1, ks2)
|
|
||||||
|
|
||||||
def test_get_nova_client(self):
|
|
||||||
# There should be no existing client
|
|
||||||
self.assertIsNone(
|
|
||||||
nova_common.NovaAuth._nova_client
|
|
||||||
)
|
|
||||||
|
|
||||||
# Mock out the keystone session and get the client
|
|
||||||
keystone._SESSION = mock.MagicMock()
|
|
||||||
bc1 = nova_common.NovaAuth.get_nova_client(region=None)
|
|
||||||
|
|
||||||
# Our returned client should also be the saved client
|
|
||||||
self.assertIsInstance(
|
|
||||||
nova_common.NovaAuth._nova_client,
|
|
||||||
novaclient.v2.client.Client
|
|
||||||
)
|
|
||||||
self.assertIs(
|
|
||||||
nova_common.NovaAuth._nova_client,
|
|
||||||
bc1
|
|
||||||
)
|
|
||||||
|
|
||||||
# Getting the session again should return the same object
|
|
||||||
bc2 = nova_common.NovaAuth.get_nova_client(
|
|
||||||
region="test-region")
|
|
||||||
self.assertIs(bc1, bc2)
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import mock
|
||||||
from neutronclient.common import exceptions as neutron_exceptions
|
from neutronclient.common import exceptions as neutron_exceptions
|
||||||
from novaclient.client import exceptions as nova_exceptions
|
from novaclient.client import exceptions as nova_exceptions
|
||||||
|
|
||||||
|
from octavia.common import clients
|
||||||
from octavia.common import constants
|
from octavia.common import constants
|
||||||
from octavia.common import data_models
|
from octavia.common import data_models
|
||||||
from octavia.network import base as network_base
|
from octavia.network import base as network_base
|
||||||
|
@ -35,10 +36,11 @@ class TestAllowedAddressPairsDriver(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestAllowedAddressPairsDriver, self).setUp()
|
super(TestAllowedAddressPairsDriver, self).setUp()
|
||||||
with mock.patch('neutronclient.neutron.client.Client',
|
with mock.patch('octavia.common.clients.neutron_client.Client',
|
||||||
autospec=True) as neutron_client:
|
autospec=True) as neutron_client:
|
||||||
with mock.patch('novaclient.client.Client', autospec=True):
|
with mock.patch('octavia.common.clients.nova_client.Client',
|
||||||
client = neutron_client(neutron_base.NEUTRON_VERSION)
|
autospec=True):
|
||||||
|
client = neutron_client(clients.NEUTRON_VERSION)
|
||||||
client.list_extensions.return_value = {
|
client.list_extensions.return_value = {
|
||||||
'extensions': [
|
'extensions': [
|
||||||
{'alias': allowed_address_pairs.AAP_EXT_ALIAS},
|
{'alias': allowed_address_pairs.AAP_EXT_ALIAS},
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from octavia.common import clients
|
||||||
from octavia.common import data_models
|
from octavia.common import data_models
|
||||||
from octavia.network import data_models as network_models
|
from octavia.network import data_models as network_models
|
||||||
from octavia.network.drivers.neutron import base as neutron_base
|
from octavia.network.drivers.neutron import base as neutron_base
|
||||||
|
@ -37,9 +38,9 @@ class TestBaseNeutronNetworkDriver(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestBaseNeutronNetworkDriver, self).setUp()
|
super(TestBaseNeutronNetworkDriver, self).setUp()
|
||||||
with mock.patch('neutronclient.neutron.client.Client',
|
with mock.patch('octavia.common.clients.neutron_client.Client',
|
||||||
autospec=True) as neutron_client:
|
autospec=True) as neutron_client:
|
||||||
client = neutron_client(neutron_base.NEUTRON_VERSION)
|
client = neutron_client(clients.NEUTRON_VERSION)
|
||||||
client.list_extensions.return_value = {
|
client.list_extensions.return_value = {
|
||||||
'extensions': [
|
'extensions': [
|
||||||
{'alias': neutron_base.SEC_GRP_EXT_ALIAS}
|
{'alias': neutron_base.SEC_GRP_EXT_ALIAS}
|
||||||
|
|
Loading…
Reference in New Issue