Lazy Load Services
When the Manila share service starts, it instantiates the Neutron network helper, which makes a call to the Neutron service. If the service is started and the Neutron service is unaccessible, the share service will fail to even start. This patch lazy loads those parameters so that they are only loaded when needed (and presumably when the Neutron service is up). Change-Id: I1857c0cb6fc41afd0d01916addc1fd216070ffd7 Closes-Bug: #1481331
This commit is contained in:
parent
74f09b7379
commit
4f861423a0
@ -22,6 +22,7 @@ from manila import exception
|
||||
from manila import network
|
||||
from manila.network.neutron import api as neutron_api
|
||||
from manila.network.neutron import constants as neutron_constants
|
||||
from manila import utils
|
||||
|
||||
neutron_single_network_plugin_opts = [
|
||||
cfg.StrOpt(
|
||||
@ -50,7 +51,17 @@ class NeutronNetworkPlugin(network.NetworkBaseAPI):
|
||||
def __init__(self, *args, **kwargs):
|
||||
db_driver = kwargs.pop('db_driver', None)
|
||||
super(NeutronNetworkPlugin, self).__init__(db_driver=db_driver)
|
||||
self.neutron_api = neutron_api.API(*args, **kwargs)
|
||||
self._neutron_api = None
|
||||
self._neutron_api_args = args
|
||||
self._neutron_api_kwargs = kwargs
|
||||
|
||||
@property
|
||||
@utils.synchronized("instantiate_neutron_api")
|
||||
def neutron_api(self):
|
||||
if not self._neutron_api:
|
||||
self._neutron_api = neutron_api.API(*self._neutron_api_args,
|
||||
**self._neutron_api_kwargs)
|
||||
return self._neutron_api
|
||||
|
||||
def allocate_network(self, context, share_server, share_network, **kwargs):
|
||||
"""Allocate network resources using given network information.
|
||||
|
@ -216,8 +216,15 @@ class ServiceInstanceManager(object):
|
||||
if self.get_config_option("driver_handles_share_servers"):
|
||||
self.path_to_public_key = self.get_config_option(
|
||||
"path_to_public_key")
|
||||
self.network_helper = self._get_network_helper()
|
||||
self.network_helper.setup_connectivity_with_service_instances()
|
||||
self._network_helper = None
|
||||
|
||||
@property
|
||||
@utils.synchronized("instantiate_network_helper")
|
||||
def network_helper(self):
|
||||
if not self._network_helper:
|
||||
self._network_helper = self._get_network_helper()
|
||||
self._network_helper.setup_connectivity_with_service_instances()
|
||||
return self._network_helper
|
||||
|
||||
def get_common_server(self):
|
||||
data = {
|
||||
@ -630,14 +637,14 @@ class NeutronNetworkHelper(BaseNetworkhelper):
|
||||
self.get_config_option("interface_driver"))()
|
||||
|
||||
if service_instance_manager.driver_config:
|
||||
network_config_group = (
|
||||
self._network_config_group = (
|
||||
service_instance_manager.driver_config.network_config_group or
|
||||
service_instance_manager.driver_config.config_group)
|
||||
else:
|
||||
network_config_group = None
|
||||
self._network_config_group = None
|
||||
|
||||
self.neutron_api = neutron.API(config_group_name=network_config_group)
|
||||
self.service_network_id = self.get_service_network_id()
|
||||
self._neutron_api = None
|
||||
self._service_network_id = None
|
||||
self.connect_share_server_to_tenant_network = (
|
||||
self.get_config_option('connect_share_server_to_tenant_network'))
|
||||
|
||||
@ -649,13 +656,28 @@ class NeutronNetworkHelper(BaseNetworkhelper):
|
||||
def admin_project_id(self):
|
||||
return self.neutron_api.admin_project_id
|
||||
|
||||
@property
|
||||
@utils.synchronized("instantiate_neutron_api_neutron_net_helper")
|
||||
def neutron_api(self):
|
||||
if not self._neutron_api:
|
||||
self._neutron_api = neutron.API(
|
||||
config_group_name=self._network_config_group)
|
||||
return self._neutron_api
|
||||
|
||||
@property
|
||||
@utils.synchronized("service_network_id_neutron_net_helper")
|
||||
def service_network_id(self):
|
||||
if not self._service_network_id:
|
||||
self._service_network_id = self._get_service_network_id()
|
||||
return self._service_network_id
|
||||
|
||||
def get_network_name(self, network_info):
|
||||
"""Returns name of network for service instance."""
|
||||
net = self.neutron_api.get_network(network_info['neutron_net_id'])
|
||||
return net['name']
|
||||
|
||||
@utils.synchronized("service_instance_get_service_network", external=True)
|
||||
def get_service_network_id(self):
|
||||
def _get_service_network_id(self):
|
||||
"""Finds existing or creates new service network."""
|
||||
service_network_name = self.get_config_option("service_network_name")
|
||||
networks = []
|
||||
|
@ -200,6 +200,20 @@ class TestCase(base_test.BaseTestCase):
|
||||
self.addCleanup(patcher.stop)
|
||||
return new_attr
|
||||
|
||||
def mock_class(self, class_name, new_val=None, **kwargs):
|
||||
"""Use python mock to mock a class
|
||||
|
||||
Mocks the specified objects attribute with the given value.
|
||||
Automatically performs 'addCleanup' for the mock.
|
||||
|
||||
"""
|
||||
if not new_val:
|
||||
new_val = mock.Mock()
|
||||
patcher = mock.patch(class_name, new_val, **kwargs)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
return new_val
|
||||
|
||||
# Useful assertions
|
||||
def assertDictMatch(self, d1, d2, approx_equal=False, tolerance=0.001):
|
||||
"""Assert two dicts are equivalent.
|
||||
|
@ -163,6 +163,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
||||
service_instance_network_helper_type=service_instance.NOVA_NAME))
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self._manager = service_instance.ServiceInstanceManager()
|
||||
self._manager.network_helper
|
||||
service_instance.NovaNetworkHelper.assert_called_once_with(
|
||||
self._manager)
|
||||
self.assertFalse(service_instance.NeutronNetworkHelper.called)
|
||||
@ -178,6 +179,7 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
||||
)
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self._manager = service_instance.ServiceInstanceManager()
|
||||
self._manager.network_helper
|
||||
service_instance.NeutronNetworkHelper.assert_called_once_with(
|
||||
self._manager)
|
||||
self.assertFalse(service_instance.NovaNetworkHelper.called)
|
||||
@ -196,9 +198,9 @@ class ServiceInstanceManagerTestCase(test.TestCase):
|
||||
driver_handles_share_servers=True,
|
||||
service_instance_network_helper_type=value))
|
||||
with test_utils.create_temp_config_with_opts(config_data):
|
||||
self.assertRaises(
|
||||
exception.ManilaException,
|
||||
service_instance.ServiceInstanceManager)
|
||||
manager = service_instance.ServiceInstanceManager()
|
||||
self.assertRaises(exception.ManilaException,
|
||||
lambda: manager.network_helper)
|
||||
self.assertFalse(service_instance.NeutronNetworkHelper.called)
|
||||
self.assertFalse(service_instance.NovaNetworkHelper.called)
|
||||
|
||||
@ -1266,7 +1268,7 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
|
||||
def _init_neutron_network_plugin(self):
|
||||
self.mock_object(
|
||||
service_instance.NeutronNetworkHelper, 'get_service_network_id',
|
||||
service_instance.NeutronNetworkHelper, '_get_service_network_id',
|
||||
mock.Mock(return_value='fake_service_network_id'))
|
||||
return service_instance.NeutronNetworkHelper(self.fake_manager)
|
||||
|
||||
@ -1278,7 +1280,7 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
'connect_share_server_to_tenant_network', 'get_config_option']
|
||||
for attr in attrs:
|
||||
self.assertTrue(hasattr(instance, attr), "No attr '%s'" % attr)
|
||||
service_instance.NeutronNetworkHelper.get_service_network_id.\
|
||||
service_instance.NeutronNetworkHelper._get_service_network_id.\
|
||||
assert_called_once_with()
|
||||
self.assertEqual('DEFAULT', instance.neutron_api.config_group_name)
|
||||
|
||||
@ -1304,7 +1306,7 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
def test_admin_project_id(self):
|
||||
instance = self._init_neutron_network_plugin()
|
||||
admin_project_id = 'fake_admin_project_id'
|
||||
instance.neutron_api = mock.Mock()
|
||||
self.mock_class('manila.network.neutron.api.API', mock.Mock())
|
||||
instance.neutron_api.admin_project_id = admin_project_id
|
||||
self.assertEqual(admin_project_id, instance.admin_project_id)
|
||||
|
||||
@ -1337,13 +1339,12 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
mock.Mock(return_value=network))
|
||||
instance = service_instance.NeutronNetworkHelper(self.fake_manager)
|
||||
|
||||
result = instance.get_service_network_id()
|
||||
result = instance._get_service_network_id()
|
||||
|
||||
self.assertEqual(network['id'], result)
|
||||
service_instance.neutron.API.get_all_admin_project_networks.\
|
||||
assert_has_calls([mock.call(), mock.call()])
|
||||
self.assertTrue(service_instance.neutron.API.
|
||||
get_all_admin_project_networks.called)
|
||||
service_instance.neutron.API.network_create.assert_has_calls([
|
||||
mock.call(instance.admin_project_id, service_network_name),
|
||||
mock.call(instance.admin_project_id, service_network_name)])
|
||||
|
||||
def test_get_service_network_id_one_exist(self):
|
||||
@ -1358,11 +1359,11 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
mock.Mock(return_value=admin_project_id))
|
||||
instance = service_instance.NeutronNetworkHelper(self.fake_manager)
|
||||
|
||||
result = instance.get_service_network_id()
|
||||
result = instance._get_service_network_id()
|
||||
|
||||
self.assertEqual(network['id'], result)
|
||||
service_instance.neutron.API.get_all_admin_project_networks.\
|
||||
assert_has_calls([mock.call(), mock.call()])
|
||||
self.assertTrue(service_instance.neutron.API.
|
||||
get_all_admin_project_networks.called)
|
||||
|
||||
def test_get_service_network_id_two_exist(self):
|
||||
service_network_name = fake_get_config_option('service_network_name')
|
||||
@ -1371,9 +1372,9 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
service_instance.neutron.API, 'get_all_admin_project_networks',
|
||||
mock.Mock(return_value=[network, network]))
|
||||
|
||||
self.assertRaises(
|
||||
exception.ServiceInstanceException,
|
||||
service_instance.NeutronNetworkHelper, self.fake_manager)
|
||||
helper = service_instance.NeutronNetworkHelper(self.fake_manager)
|
||||
self.assertRaises(exception.ManilaException,
|
||||
lambda: helper.service_network_id)
|
||||
|
||||
service_instance.neutron.API.get_all_admin_project_networks.\
|
||||
assert_has_calls([mock.call()])
|
||||
@ -1599,7 +1600,8 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
service_subnet = dict(id='fake_service_subnet')
|
||||
instance = self._init_neutron_network_plugin()
|
||||
instance.connect_share_server_to_tenant_network = True
|
||||
instance.service_network_id = 'fake_service_network_id'
|
||||
self.mock_object(instance, '_get_service_network_id',
|
||||
mock.Mock(return_value='fake_service_network_id'))
|
||||
self.mock_object(
|
||||
service_instance.neutron.API, 'admin_project_id',
|
||||
mock.Mock(return_value=admin_project_id))
|
||||
@ -1647,7 +1649,8 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
service_subnet = dict(id='fake_service_subnet')
|
||||
instance = self._init_neutron_network_plugin()
|
||||
instance.connect_share_server_to_tenant_network = False
|
||||
instance.service_network_id = 'fake_service_network_id'
|
||||
self.mock_object(instance, '_get_service_network_id',
|
||||
mock.Mock(return_value='fake_service_network_id'))
|
||||
router = dict(id='fake_router_id')
|
||||
self.mock_object(
|
||||
service_instance.neutron.API, 'admin_project_id',
|
||||
@ -1695,7 +1698,8 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
service_subnet = dict(id='fake_service_subnet')
|
||||
instance = self._init_neutron_network_plugin()
|
||||
instance.connect_share_server_to_tenant_network = False
|
||||
instance.service_network_id = 'fake_service_network_id'
|
||||
self.mock_object(instance, '_get_service_network_id',
|
||||
mock.Mock(return_value='fake_service_network_id'))
|
||||
router = dict(id='fake_router_id')
|
||||
self.mock_object(
|
||||
instance, '_get_private_router', mock.Mock(return_value=router))
|
||||
@ -1728,7 +1732,8 @@ class NeutronNetworkHelperTestCase(test.TestCase):
|
||||
service_subnet = dict(id='fake_service_subnet')
|
||||
instance = self._init_neutron_network_plugin()
|
||||
instance.connect_share_server_to_tenant_network = False
|
||||
instance.service_network_id = 'fake_service_network_id'
|
||||
self.mock_object(instance, '_get_service_network_id',
|
||||
mock.Mock(return_value='fake_service_network_id'))
|
||||
router = dict(id='fake_router_id')
|
||||
self.mock_object(
|
||||
service_instance.neutron.API, 'admin_project_id',
|
||||
|
Loading…
x
Reference in New Issue
Block a user