Create GCE Service outside Neutron service start path
Creating gce client inside Neutron service start causes neutron-server crash if service_key is not there at mentioned path. Neutron service should not crash at start if service key is not there. Change-Id: I8e0f8b150c60d55d71846face217d5213b5df9b7 Closes-Bug: #1707872
This commit is contained in:
parent
6c6d849778
commit
8d58fd2f16
@ -11,6 +11,7 @@ License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import uuid
|
||||
|
||||
@ -75,6 +76,10 @@ class GceResourceNotFound(e.NotFound):
|
||||
message = _("GCE Resource %(name)s %(identifier)s was not found")
|
||||
|
||||
|
||||
class GceServiceKeyNotFound(e.NotFound):
|
||||
message = _("GCE service key was not found at %(path)s location")
|
||||
|
||||
|
||||
def list_instances(compute, project, zone):
|
||||
"""Returns list of GCE instance resources for specified project
|
||||
|
||||
@ -151,6 +156,9 @@ def get_gce_service(service_key):
|
||||
:return: :class:`Resource <Resource>` object
|
||||
:rtype: googleapiclient.discovery.Resource
|
||||
"""
|
||||
if not os.path.exists(service_key):
|
||||
raise GceServiceKeyNotFound(path=service_key)
|
||||
|
||||
credentials = GoogleCredentials.from_stream(service_key)
|
||||
service = build('compute', 'v1', credentials=credentials)
|
||||
return service
|
||||
|
@ -48,13 +48,19 @@ class GceMechanismDriver(api.MechanismDriver):
|
||||
self.gce_region = gceconf.region
|
||||
self.gce_project = gceconf.project_id
|
||||
self.gce_svc_key = gceconf.service_key_path
|
||||
self._gce_svc = None
|
||||
|
||||
def initialize(self):
|
||||
self.gce_svc = gceutils.get_gce_service(self.gce_svc_key)
|
||||
LOG.info("GCE Mechanism driver init with %s project, %s region" %
|
||||
(self.gce_project, self.gce_region))
|
||||
self._subscribe_events()
|
||||
|
||||
@property
|
||||
def gce_svc(self):
|
||||
if self._gce_svc is None:
|
||||
self._gce_svc = gceutils.get_gce_service(self.gce_svc_key)
|
||||
return self._gce_svc
|
||||
|
||||
def _subscribe_events(self):
|
||||
registry.subscribe(self.secgroup_callback, resources.SECURITY_GROUP,
|
||||
events.BEFORE_DELETE)
|
||||
|
@ -75,10 +75,16 @@ class GceRouterPlugin(
|
||||
self.gce_region = gceconf.region
|
||||
self.gce_project = gceconf.project_id
|
||||
self.gce_svc_key = gceconf.service_key_path
|
||||
self.gce_svc = gceutils.get_gce_service(self.gce_svc_key)
|
||||
self._gce_svc = None
|
||||
LOG.info("GCE Router plugin init with %s project, %s region" %
|
||||
(self.gce_project, self.gce_region))
|
||||
|
||||
@property
|
||||
def gce_svc(self):
|
||||
if self._gce_svc is None:
|
||||
self._gce_svc = gceutils.get_gce_service(self.gce_svc_key)
|
||||
return self._gce_svc
|
||||
|
||||
def get_plugin_type(self):
|
||||
return plugin_type
|
||||
|
||||
|
@ -1,178 +1,181 @@
|
||||
"""
|
||||
Copyright (c) 2017 Platform9 Systems Inc.
|
||||
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 expressed or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
"""
|
||||
|
||||
import mock
|
||||
import os
|
||||
|
||||
from neutron.extensions import securitygroup as sg
|
||||
from neutron.manager import NeutronManager
|
||||
from neutron.plugins.ml2.drivers.gce.mech_gce import GceMechanismDriver
|
||||
from neutron.plugins.ml2.drivers.gce.mech_gce import SecurityGroupInvalidDirection # noqa
|
||||
from neutron.tests import base
|
||||
from neutron.tests.common.gce import gce_mock
|
||||
from neutron.tests.common.gce.gce_mock import FakeNeutronManager
|
||||
from neutron.tests.unit.extensions import test_securitygroup as test_sg
|
||||
from neutron_lib import constants as const
|
||||
|
||||
DATA_DIR = os.path.dirname(os.path.abspath("gce_mock.py")) + '/data'
|
||||
NETWORKS_LINK = "projects/omni-163105/global/networks"
|
||||
NETWORK_LINK = NETWORKS_LINK + "/net-03c4f178-670e-4805-a511-9470ca4a0b06"
|
||||
|
||||
if hasattr(NeutronManager, "get_plugin"):
|
||||
neutron_get_plugin = 'neutron.manager.NeutronManager.get_plugin'
|
||||
else:
|
||||
neutron_get_plugin = 'neutron_lib.plugins.directory.get_plugin'
|
||||
|
||||
|
||||
class GCENeutronTestCase(test_sg.SecurityGroupsTestCase, base.BaseTestCase):
|
||||
@mock.patch('neutron.common.gceutils.get_gce_service')
|
||||
def setUp(self, mock_service):
|
||||
mock_service.side_effect = gce_mock.get_gce_service
|
||||
super(GCENeutronTestCase, self).setUp()
|
||||
self._driver = GceMechanismDriver()
|
||||
self._driver.gce_zone = 'us-central1-c'
|
||||
self._driver.gce_region = 'us-central1'
|
||||
self._driver.gce_project = 'omni-163105'
|
||||
self._driver.gce_svc_key = "{0}/omni.json".format(DATA_DIR)
|
||||
self.context = self._create_fake_context()
|
||||
self._driver.initialize()
|
||||
|
||||
def _create_fake_context(self):
|
||||
context = mock.Mock()
|
||||
context.current = {}
|
||||
context.current['id'] = "fake_id_1234"
|
||||
context.current['cidr'] = "192.168.1.0/24"
|
||||
context.current['network_id'] = "fake_network_id_1234"
|
||||
return context
|
||||
|
||||
def get_fake_sg_rule(self, ethertype=const.IPv4, direction="ingress",
|
||||
protocol=const.PROTO_NAME_TCP):
|
||||
data = {
|
||||
'id': 'fake_rule_id',
|
||||
'security_group_id': '4cd70774-cc67-4a87-9b39-7d1db38eb087',
|
||||
'direction': direction,
|
||||
'protocol': protocol,
|
||||
'ethertype': ethertype,
|
||||
'tenant_id': 'fake_tenant_id',
|
||||
'port_range_min': '22',
|
||||
'port_range_max': '22',
|
||||
'remote_ip_prefix': None,
|
||||
'remote_group_id': None
|
||||
}
|
||||
return data
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.create_network')
|
||||
def test_create_network_postcommit(self, mock_create, mock_wait):
|
||||
mock_create.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.create_network_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.delete_network')
|
||||
def test_delete_network_postcommit(self, mock_delete, mock_wait):
|
||||
mock_delete.side_effect = gce_mock.delete_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.delete_network_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.create_subnet')
|
||||
@mock.patch('neutron.common.gceutils.get_network')
|
||||
def test_create_subnet_postcommit(self, mock_get, mock_create, mock_wait):
|
||||
mock_get.side_effect = gce_mock.get_network
|
||||
mock_create.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.create_subnet_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.delete_subnet')
|
||||
def test_delete_subnet_postcommit(self, mock_delete, mock_wait):
|
||||
mock_delete.side_effect = gce_mock.delete_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.delete_subnet_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
def test_convert_sg_to_gce_failure_with_wrong_ethertype(self):
|
||||
sg_rule = self.get_fake_sg_rule(ethertype=const.IPv6)
|
||||
self.assertRaises(sg.SecurityGroupRuleInvalidEtherType,
|
||||
self._driver._convert_secgrp_rule_to_gce,
|
||||
rule=sg_rule, network_link=NETWORK_LINK)
|
||||
|
||||
def test_convert_sg_to_gce_failure_with_wrong_direction(self):
|
||||
sg_rule = self.get_fake_sg_rule(direction="egress")
|
||||
self.assertRaises(SecurityGroupInvalidDirection,
|
||||
self._driver._convert_secgrp_rule_to_gce,
|
||||
rule=sg_rule, network_link=NETWORK_LINK)
|
||||
|
||||
def test_convert_sg_to_gce_failure_with_wrong_protocol(self):
|
||||
sg_rule = self.get_fake_sg_rule(protocol="fake_protocol")
|
||||
self.assertRaises(sg.SecurityGroupRuleInvalidProtocol,
|
||||
self._driver._convert_secgrp_rule_to_gce,
|
||||
rule=sg_rule, network_link=NETWORK_LINK)
|
||||
|
||||
def test_convert_sg_to_gce_success(self):
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
gce_rule = self._driver._convert_secgrp_rule_to_gce(
|
||||
sg_rule, NETWORK_LINK)
|
||||
self.assertTrue(isinstance(gce_rule, dict))
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.create_firewall_rule')
|
||||
def test_create_sg_rule(self, mock_create, mock_wait):
|
||||
mock_create.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
self.assertIsNone(
|
||||
self._driver._create_secgrp_rule(self.context, sg_rule,
|
||||
NETWORK_LINK))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch(neutron_get_plugin)
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.update_firewall_rule')
|
||||
@mock.patch('neutron.common.gceutils.get_firewall_rule')
|
||||
def test_update_sg_rule(self, mock_get, mock_update, mock_wait,
|
||||
mock_plugin):
|
||||
mock_get.side_effect = gce_mock.get_firewall_rule
|
||||
mock_update.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
mock_plugin.side_effect = FakeNeutronManager
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
self.assertIsNone(
|
||||
self._driver._update_secgrp_rule(self.context, sg_rule['id']))
|
||||
self.assertTrue(mock_update.called)
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.delete_firewall_rule')
|
||||
def test_delete_sg_rule(self, mock_delete, mock_wait):
|
||||
mock_delete.side_effect = gce_mock.delete_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
self.assertIsNone(
|
||||
self._driver._delete_secgrp_rule(self.context, sg_rule['id']))
|
||||
mock_delete.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
"secgrp-" + sg_rule['id'])
|
||||
"""
|
||||
Copyright (c) 2017 Platform9 Systems Inc.
|
||||
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 expressed or implied. See the
|
||||
License for the specific language governing permissions and limitations
|
||||
under the License.
|
||||
"""
|
||||
|
||||
import mock
|
||||
import os
|
||||
|
||||
from neutron.extensions import securitygroup as sg
|
||||
from neutron.manager import NeutronManager
|
||||
from neutron.plugins.ml2.drivers.gce.mech_gce import GceMechanismDriver
|
||||
from neutron.plugins.ml2.drivers.gce.mech_gce import SecurityGroupInvalidDirection # noqa
|
||||
from neutron.tests import base
|
||||
from neutron.tests.common.gce import gce_mock
|
||||
from neutron.tests.common.gce.gce_mock import FakeNeutronManager
|
||||
from neutron.tests.unit.extensions import test_securitygroup as test_sg
|
||||
from neutron_lib import constants as const
|
||||
|
||||
DATA_DIR = os.path.dirname(os.path.abspath("gce_mock.py")) + '/data'
|
||||
NETWORKS_LINK = "projects/omni-163105/global/networks"
|
||||
NETWORK_LINK = NETWORKS_LINK + "/net-03c4f178-670e-4805-a511-9470ca4a0b06"
|
||||
|
||||
if hasattr(NeutronManager, "get_plugin"):
|
||||
neutron_get_plugin = 'neutron.manager.NeutronManager.get_plugin'
|
||||
else:
|
||||
neutron_get_plugin = 'neutron_lib.plugins.directory.get_plugin'
|
||||
|
||||
|
||||
class GCENeutronTestCase(test_sg.SecurityGroupsTestCase, base.BaseTestCase):
|
||||
def setUp(self):
|
||||
super(GCENeutronTestCase, self).setUp()
|
||||
self.service_patcher = mock.patch(
|
||||
'neutron.common.gceutils.get_gce_service').start()
|
||||
mock_service = self.service_patcher.start()
|
||||
mock_service.side_effect = gce_mock.get_gce_service
|
||||
self.addCleanup(self.service_patcher.stop)
|
||||
self._driver = GceMechanismDriver()
|
||||
self._driver.gce_zone = 'us-central1-c'
|
||||
self._driver.gce_region = 'us-central1'
|
||||
self._driver.gce_project = 'omni-163105'
|
||||
self._driver.gce_svc_key = "{0}/omni.json".format(DATA_DIR)
|
||||
self.context = self._create_fake_context()
|
||||
self._driver.initialize()
|
||||
|
||||
def _create_fake_context(self):
|
||||
context = mock.Mock()
|
||||
context.current = {}
|
||||
context.current['id'] = "fake_id_1234"
|
||||
context.current['cidr'] = "192.168.1.0/24"
|
||||
context.current['network_id'] = "fake_network_id_1234"
|
||||
return context
|
||||
|
||||
def get_fake_sg_rule(self, ethertype=const.IPv4, direction="ingress",
|
||||
protocol=const.PROTO_NAME_TCP):
|
||||
data = {
|
||||
'id': 'fake_rule_id',
|
||||
'security_group_id': '4cd70774-cc67-4a87-9b39-7d1db38eb087',
|
||||
'direction': direction,
|
||||
'protocol': protocol,
|
||||
'ethertype': ethertype,
|
||||
'tenant_id': 'fake_tenant_id',
|
||||
'port_range_min': '22',
|
||||
'port_range_max': '22',
|
||||
'remote_ip_prefix': None,
|
||||
'remote_group_id': None
|
||||
}
|
||||
return data
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.create_network')
|
||||
def test_create_network_postcommit(self, mock_create, mock_wait):
|
||||
mock_create.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.create_network_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.delete_network')
|
||||
def test_delete_network_postcommit(self, mock_delete, mock_wait):
|
||||
mock_delete.side_effect = gce_mock.delete_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.delete_network_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.create_subnet')
|
||||
@mock.patch('neutron.common.gceutils.get_network')
|
||||
def test_create_subnet_postcommit(self, mock_get, mock_create, mock_wait):
|
||||
mock_get.side_effect = gce_mock.get_network
|
||||
mock_create.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.create_subnet_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.delete_subnet')
|
||||
def test_delete_subnet_postcommit(self, mock_delete, mock_wait):
|
||||
mock_delete.side_effect = gce_mock.delete_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
self.assertIsNone(self._driver.delete_subnet_postcommit(self.context))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
def test_convert_sg_to_gce_failure_with_wrong_ethertype(self):
|
||||
sg_rule = self.get_fake_sg_rule(ethertype=const.IPv6)
|
||||
self.assertRaises(sg.SecurityGroupRuleInvalidEtherType,
|
||||
self._driver._convert_secgrp_rule_to_gce,
|
||||
rule=sg_rule, network_link=NETWORK_LINK)
|
||||
|
||||
def test_convert_sg_to_gce_failure_with_wrong_direction(self):
|
||||
sg_rule = self.get_fake_sg_rule(direction="egress")
|
||||
self.assertRaises(SecurityGroupInvalidDirection,
|
||||
self._driver._convert_secgrp_rule_to_gce,
|
||||
rule=sg_rule, network_link=NETWORK_LINK)
|
||||
|
||||
def test_convert_sg_to_gce_failure_with_wrong_protocol(self):
|
||||
sg_rule = self.get_fake_sg_rule(protocol="fake_protocol")
|
||||
self.assertRaises(sg.SecurityGroupRuleInvalidProtocol,
|
||||
self._driver._convert_secgrp_rule_to_gce,
|
||||
rule=sg_rule, network_link=NETWORK_LINK)
|
||||
|
||||
def test_convert_sg_to_gce_success(self):
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
gce_rule = self._driver._convert_secgrp_rule_to_gce(
|
||||
sg_rule, NETWORK_LINK)
|
||||
self.assertTrue(isinstance(gce_rule, dict))
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.create_firewall_rule')
|
||||
def test_create_sg_rule(self, mock_create, mock_wait):
|
||||
mock_create.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
self.assertIsNone(
|
||||
self._driver._create_secgrp_rule(self.context, sg_rule,
|
||||
NETWORK_LINK))
|
||||
mock_wait.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
gce_mock.fake_operation())
|
||||
|
||||
@mock.patch(neutron_get_plugin)
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.update_firewall_rule')
|
||||
@mock.patch('neutron.common.gceutils.get_firewall_rule')
|
||||
def test_update_sg_rule(self, mock_get, mock_update, mock_wait,
|
||||
mock_plugin):
|
||||
mock_get.side_effect = gce_mock.get_firewall_rule
|
||||
mock_update.side_effect = gce_mock.create_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
mock_plugin.side_effect = FakeNeutronManager
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
self.assertIsNone(
|
||||
self._driver._update_secgrp_rule(self.context, sg_rule['id']))
|
||||
self.assertTrue(mock_update.called)
|
||||
|
||||
@mock.patch('neutron.common.gceutils.wait_for_operation')
|
||||
@mock.patch('neutron.common.gceutils.delete_firewall_rule')
|
||||
def test_delete_sg_rule(self, mock_delete, mock_wait):
|
||||
mock_delete.side_effect = gce_mock.delete_anything
|
||||
mock_wait.side_effect = gce_mock.wait_for_operation
|
||||
sg_rule = self.get_fake_sg_rule()
|
||||
self.assertIsNone(
|
||||
self._driver._delete_secgrp_rule(self.context, sg_rule['id']))
|
||||
mock_delete.assert_called_once_with(self._driver.gce_svc,
|
||||
self._driver.gce_project,
|
||||
"secgrp-" + sg_rule['id'])
|
||||
|
Loading…
Reference in New Issue
Block a user