Detect neutron endpoint on-the-fly
This change does the following: - reverts commit04de60093b
- reimplements Resource.is_using_neutron to check for neutron by attempting to create a neutron client - fix mocking in tests for changes which landed after04de600
If there is no 'network' entry in the service catalog then keystoneclient will raise an EndpointNotFound. The context will already have a keystone client cached which has a full service catalog locally, so calling is_using_neutron should have no particular overhead. This fixes a tripleo regression where the autodetection is triggered before keystone is ready, so that heat-engine fails to start. This race does not affect devstack as keystone is fully configured before heat services are started. Not adding config option networking_service will also prevent extra work required by downstream installation tools. Change-Id: I45a6154fa560f672d8d1942bf57f39601110bfc6 Closes-Bug: #1362812
This commit is contained in:
parent
99a11f8633
commit
d70da16894
@ -46,31 +46,12 @@ gettextutils.install('heat', lazy=True)
|
|||||||
|
|
||||||
LOG = logging.getLogger('heat.engine')
|
LOG = logging.getLogger('heat.engine')
|
||||||
|
|
||||||
|
|
||||||
def discover_networking_service():
|
|
||||||
from heat.common import heat_keystoneclient as hkc
|
|
||||||
|
|
||||||
# create empty context
|
|
||||||
ctxt = hkc.context.RequestContext()
|
|
||||||
# create admin client
|
|
||||||
admin_client = hkc.KeystoneClient(ctxt).admin_client
|
|
||||||
services = admin_client.services.list()
|
|
||||||
|
|
||||||
if 'network' in [s.type for s in services]:
|
|
||||||
cfg.CONF.set_override('networking_service', 'neutron')
|
|
||||||
else:
|
|
||||||
cfg.CONF.set_override('networking_service', 'nova')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
cfg.CONF(project='heat', prog='heat-engine')
|
cfg.CONF(project='heat', prog='heat-engine')
|
||||||
logging.setup('heat')
|
logging.setup('heat')
|
||||||
messaging.setup()
|
messaging.setup()
|
||||||
|
|
||||||
if not cfg.CONF.networking_service:
|
|
||||||
discover_networking_service()
|
|
||||||
|
|
||||||
from heat.engine import service as engine
|
from heat.engine import service as engine
|
||||||
|
|
||||||
srv = engine.EngineService(cfg.CONF.host, rpc_api.ENGINE_TOPIC)
|
srv = engine.EngineService(cfg.CONF.host, rpc_api.ENGINE_TOPIC)
|
||||||
|
@ -73,10 +73,6 @@
|
|||||||
# Deprecated. (string value)
|
# Deprecated. (string value)
|
||||||
#onready=<None>
|
#onready=<None>
|
||||||
|
|
||||||
# Select OpenStack component responsible for networking - nova
|
|
||||||
# or neutron. (string value)
|
|
||||||
#networking_service=<None>
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Options defined in heat.common.config
|
# Options defined in heat.common.config
|
||||||
|
@ -138,11 +138,7 @@ engine_opts = [
|
|||||||
help=_('RPC timeout for the engine liveness check that is used'
|
help=_('RPC timeout for the engine liveness check that is used'
|
||||||
' for stack locking.')),
|
' for stack locking.')),
|
||||||
cfg.StrOpt('onready',
|
cfg.StrOpt('onready',
|
||||||
help=_('Deprecated.')),
|
help=_('Deprecated.'))]
|
||||||
cfg.StrOpt('networking_service',
|
|
||||||
choices=['nova', 'neutron'],
|
|
||||||
help=_('Select OpenStack component '
|
|
||||||
'responsible for networking - nova or neutron.'))]
|
|
||||||
|
|
||||||
rpc_opts = [
|
rpc_opts = [
|
||||||
cfg.StrOpt('host',
|
cfg.StrOpt('host',
|
||||||
|
@ -28,12 +28,14 @@ class NeutronClientPlugin(client_plugin.ClientPlugin):
|
|||||||
con = self.context
|
con = self.context
|
||||||
|
|
||||||
endpoint_type = self._get_client_option('neutron', 'endpoint_type')
|
endpoint_type = self._get_client_option('neutron', 'endpoint_type')
|
||||||
|
endpoint = self.url_for(service_type='network',
|
||||||
|
endpoint_type=endpoint_type)
|
||||||
|
|
||||||
args = {
|
args = {
|
||||||
'auth_url': con.auth_url,
|
'auth_url': con.auth_url,
|
||||||
'service_type': 'network',
|
'service_type': 'network',
|
||||||
'token': self.auth_token,
|
'token': self.auth_token,
|
||||||
'endpoint_url': self.url_for(service_type='network',
|
'endpoint_url': endpoint,
|
||||||
endpoint_type=endpoint_type),
|
|
||||||
'endpoint_type': endpoint_type,
|
'endpoint_type': endpoint_type,
|
||||||
'ca_cert': self._get_client_option('neutron', 'ca_file'),
|
'ca_cert': self._get_client_option('neutron', 'ca_file'),
|
||||||
'insecure': self._get_client_option('neutron', 'insecure')
|
'insecure': self._get_client_option('neutron', 'insecure')
|
||||||
|
@ -1116,6 +1116,10 @@ class Resource(object):
|
|||||||
self._data = None
|
self._data = None
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
def is_using_neutron(self):
|
||||||
def is_using_neutron():
|
try:
|
||||||
return cfg.CONF.networking_service == 'neutron'
|
self.client('neutron')
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
@ -1002,9 +1002,17 @@ class ResourceTest(HeatTestCase):
|
|||||||
snippet = rsrc_defn.ResourceDefinition('aresource',
|
snippet = rsrc_defn.ResourceDefinition('aresource',
|
||||||
'GenericResourceType')
|
'GenericResourceType')
|
||||||
res = resource.Resource('aresource', snippet, self.stack)
|
res = resource.Resource('aresource', snippet, self.stack)
|
||||||
cfg.CONF.set_override('networking_service', 'neutron')
|
self.patch(
|
||||||
|
'heat.engine.clients.os.neutron.NeutronClientPlugin._create')
|
||||||
self.assertTrue(res.is_using_neutron())
|
self.assertTrue(res.is_using_neutron())
|
||||||
cfg.CONF.set_override('networking_service', 'nova')
|
|
||||||
|
def test_is_not_using_neutron(self):
|
||||||
|
snippet = rsrc_defn.ResourceDefinition('aresource',
|
||||||
|
'GenericResourceType')
|
||||||
|
res = resource.Resource('aresource', snippet, self.stack)
|
||||||
|
mock_create = self.patch(
|
||||||
|
'heat.engine.clients.os.neutron.NeutronClientPlugin._create')
|
||||||
|
mock_create.side_effect = Exception()
|
||||||
self.assertFalse(res.is_using_neutron())
|
self.assertFalse(res.is_using_neutron())
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
|
from keystoneclient import exceptions as keystone_exc
|
||||||
from neutronclient.common.exceptions import NeutronClientException
|
from neutronclient.common.exceptions import NeutronClientException
|
||||||
from neutronclient.v2_0 import client as neutronclient
|
from neutronclient.v2_0 import client as neutronclient
|
||||||
from novaclient.v1_1 import security_group_rules as nova_sgr
|
from novaclient.v1_1 import security_group_rules as nova_sgr
|
||||||
from novaclient.v1_1 import security_groups as nova_sg
|
from novaclient.v1_1 import security_groups as nova_sg
|
||||||
from oslo.config import cfg
|
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
@ -145,6 +145,11 @@ Resources:
|
|||||||
neutronclient.Client, 'delete_security_group_rule')
|
neutronclient.Client, 'delete_security_group_rule')
|
||||||
self.m.StubOutWithMock(neutronclient.Client, 'delete_security_group')
|
self.m.StubOutWithMock(neutronclient.Client, 'delete_security_group')
|
||||||
|
|
||||||
|
def mock_no_neutron(self):
|
||||||
|
mock_create = self.patch(
|
||||||
|
'heat.engine.clients.os.neutron.NeutronClientPlugin._create')
|
||||||
|
mock_create.side_effect = keystone_exc.EndpointNotFound()
|
||||||
|
|
||||||
def create_stack(self, templ):
|
def create_stack(self, templ):
|
||||||
self.stack = self.parse_stack(template_format.parse(templ))
|
self.stack = self.parse_stack(template_format.parse(templ))
|
||||||
self.assertIsNone(self.stack.create())
|
self.assertIsNone(self.stack.create())
|
||||||
@ -166,6 +171,7 @@ Resources:
|
|||||||
|
|
||||||
def test_security_group_nova(self):
|
def test_security_group_nova(self):
|
||||||
#create script
|
#create script
|
||||||
|
self.mock_no_neutron()
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
|
nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
|
||||||
id=1,
|
id=1,
|
||||||
@ -258,6 +264,7 @@ Resources:
|
|||||||
|
|
||||||
def test_security_group_nova_bad_source_group(self):
|
def test_security_group_nova_bad_source_group(self):
|
||||||
#create script
|
#create script
|
||||||
|
self.mock_no_neutron()
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
|
nova_sg.SecurityGroupManager.list().AndReturn([NovaSG(
|
||||||
id=1,
|
id=1,
|
||||||
@ -322,6 +329,7 @@ Resources:
|
|||||||
|
|
||||||
def test_security_group_client_exception(self):
|
def test_security_group_client_exception(self):
|
||||||
#create script
|
#create script
|
||||||
|
self.mock_no_neutron()
|
||||||
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
nova.NovaClientPlugin._create().AndReturn(self.fc)
|
||||||
sg_name = utils.PhysName('test_stack', 'the_sg')
|
sg_name = utils.PhysName('test_stack', 'the_sg')
|
||||||
nova_sg.SecurityGroupManager.list().AndReturn([
|
nova_sg.SecurityGroupManager.list().AndReturn([
|
||||||
@ -430,6 +438,7 @@ Resources:
|
|||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_security_group_nova_with_egress_rules(self):
|
def test_security_group_nova_with_egress_rules(self):
|
||||||
|
self.mock_no_neutron()
|
||||||
t = template_format.parse(self.test_template_nova_with_egress)
|
t = template_format.parse(self.test_template_nova_with_egress)
|
||||||
stack = self.parse_stack(t)
|
stack = self.parse_stack(t)
|
||||||
|
|
||||||
@ -437,7 +446,6 @@ Resources:
|
|||||||
self.assertRaises(exception.EgressRuleNotAllowed, sg.validate)
|
self.assertRaises(exception.EgressRuleNotAllowed, sg.validate)
|
||||||
|
|
||||||
def test_security_group_neutron(self):
|
def test_security_group_neutron(self):
|
||||||
cfg.CONF.set_override('networking_service', 'neutron')
|
|
||||||
#create script
|
#create script
|
||||||
sg_name = utils.PhysName('test_stack', 'the_sg')
|
sg_name = utils.PhysName('test_stack', 'the_sg')
|
||||||
neutronclient.Client.create_security_group({
|
neutronclient.Client.create_security_group({
|
||||||
@ -683,7 +691,6 @@ Resources:
|
|||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_security_group_neutron_exception(self):
|
def test_security_group_neutron_exception(self):
|
||||||
cfg.CONF.set_override('networking_service', 'neutron')
|
|
||||||
#create script
|
#create script
|
||||||
sg_name = utils.PhysName('test_stack', 'the_sg')
|
sg_name = utils.PhysName('test_stack', 'the_sg')
|
||||||
neutronclient.Client.create_security_group({
|
neutronclient.Client.create_security_group({
|
||||||
|
@ -11,8 +11,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 oslo.config import cfg
|
|
||||||
|
|
||||||
from heat.common import exception
|
from heat.common import exception
|
||||||
from heat.common import template_format
|
from heat.common import template_format
|
||||||
from heat.engine import parser
|
from heat.engine import parser
|
||||||
@ -577,7 +575,6 @@ Resources:
|
|||||||
neutronclient.Client.delete_port('dddd').AndReturn(None)
|
neutronclient.Client.delete_port('dddd').AndReturn(None)
|
||||||
|
|
||||||
def test_network_interface(self):
|
def test_network_interface(self):
|
||||||
cfg.CONF.set_override('networking_service', 'neutron')
|
|
||||||
self.mock_create_security_group()
|
self.mock_create_security_group()
|
||||||
self.mock_create_network()
|
self.mock_create_network()
|
||||||
self.mock_create_subnet()
|
self.mock_create_subnet()
|
||||||
@ -603,7 +600,6 @@ Resources:
|
|||||||
self.m.VerifyAll()
|
self.m.VerifyAll()
|
||||||
|
|
||||||
def test_network_interface_existing_groupset(self):
|
def test_network_interface_existing_groupset(self):
|
||||||
cfg.CONF.set_override('networking_service', 'neutron')
|
|
||||||
self.m.StubOutWithMock(parser.Stack, 'resource_by_refid')
|
self.m.StubOutWithMock(parser.Stack, 'resource_by_refid')
|
||||||
|
|
||||||
self.mock_create_security_group()
|
self.mock_create_security_group()
|
||||||
|
Loading…
Reference in New Issue
Block a user