Allow murano-agent to be disabled
In some circumstances murano-agent isn't required (e.g. in environments where heat SW config is capable alone of performing configuration). In this case it's not necessary to have the additional overhead of rabbitMQ connections for the AgentListener that will never receive a message. Patch adds a config option 'disable_murano_agent' that no-ops AgentLister.start() and raises an exception on Agent._send() Change-Id: I565caaae21925c48f2a0adea18036239cac91c77 Implements: blueprint disable-murano-agent
This commit is contained in:
parent
68b220e179
commit
e2bea76426
|
@ -270,6 +270,16 @@
|
|||
#db_max_retries=20
|
||||
|
||||
|
||||
[engine]
|
||||
|
||||
#
|
||||
# Options defined in murano.common.config
|
||||
#
|
||||
|
||||
# Disallow the use of murano-agent (boolean value)
|
||||
#disable_murano_agent=false
|
||||
|
||||
|
||||
[heat]
|
||||
|
||||
#
|
||||
|
|
|
@ -168,6 +168,12 @@ stats_opt = [
|
|||
'Default value is 5 minutes.'))
|
||||
]
|
||||
|
||||
engine_opts = [
|
||||
cfg.BoolOpt('disable_murano_agent', default=False,
|
||||
help=_('Disallow the use of murano-agent'))
|
||||
]
|
||||
|
||||
# TODO(sjmc7): move into engine opts?
|
||||
metadata_dir = cfg.StrOpt('metadata-dir', default='./meta',
|
||||
help='Metadata dir')
|
||||
|
||||
|
@ -196,6 +202,7 @@ CONF.register_opts(heat_opts, group='heat')
|
|||
CONF.register_opts(neutron_opts, group='neutron')
|
||||
CONF.register_opts(keystone_opts, group='keystone')
|
||||
CONF.register_opts(murano_opts, group='murano')
|
||||
CONF.register_opts(engine_opts, group='engine')
|
||||
CONF.register_opt(cfg.StrOpt('file_server'))
|
||||
CONF.register_cli_opt(cfg.StrOpt('murano_metadata_url'))
|
||||
CONF.register_cli_opt(metadata_dir)
|
||||
|
|
|
@ -20,7 +20,9 @@ import types
|
|||
import uuid
|
||||
|
||||
import eventlet.event
|
||||
import logging
|
||||
|
||||
import murano.common.config as config
|
||||
import murano.common.messaging as messaging
|
||||
import murano.dsl.murano_class as murano_class
|
||||
import murano.dsl.murano_object as murano_object
|
||||
|
@ -28,6 +30,9 @@ import murano.dsl.yaql_expression as yaql_expression
|
|||
import murano.engine.system.common as common
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AgentException(Exception):
|
||||
pass
|
||||
|
||||
|
@ -35,19 +40,36 @@ class AgentException(Exception):
|
|||
@murano_class.classname('io.murano.system.Agent')
|
||||
class Agent(murano_object.MuranoObject):
|
||||
def initialize(self, _context, host):
|
||||
environment = yaql_expression.YaqlExpression(
|
||||
self._enabled = False
|
||||
if config.CONF.engine.disable_murano_agent:
|
||||
LOG.debug("murano-agent is disabled by the server")
|
||||
return
|
||||
|
||||
self._environment = self._get_environment(_context)
|
||||
self._enabled = True
|
||||
self._queue = str('e%s-h%s' % (
|
||||
self._environment.object_id, host.object_id)).lower()
|
||||
|
||||
def _get_environment(self, _context):
|
||||
return yaql_expression.YaqlExpression(
|
||||
"$host.find('io.murano.Environment').require()"
|
||||
).evaluate(_context)
|
||||
|
||||
self._queue = str('e%s-h%s' % (
|
||||
environment.object_id, host.object_id)).lower()
|
||||
self._environment = environment
|
||||
@property
|
||||
def enabled(self):
|
||||
return self._enabled
|
||||
|
||||
def queueName(self):
|
||||
return self._queue
|
||||
|
||||
def _send(self, template, wait_results):
|
||||
def _check_enabled(self):
|
||||
if config.CONF.engine.disable_murano_agent:
|
||||
raise AgentException(
|
||||
"Use of murano-agent is disallowed "
|
||||
"by the server configuration")
|
||||
|
||||
def _send(self, template, wait_results):
|
||||
"""Send a message over the MQ interface"""
|
||||
msg_id = template.get('ID', uuid.uuid4().hex)
|
||||
if wait_results:
|
||||
event = eventlet.event.Event()
|
||||
|
@ -77,17 +99,21 @@ class Agent(murano_object.MuranoObject):
|
|||
return None
|
||||
|
||||
def call(self, template, resources):
|
||||
self._check_enabled()
|
||||
plan = self.buildExecutionPlan(template, resources)
|
||||
return self._send(plan, True)
|
||||
|
||||
def send(self, template, resources):
|
||||
self._check_enabled()
|
||||
plan = self.buildExecutionPlan(template, resources)
|
||||
return self._send(plan, False)
|
||||
|
||||
def callRaw(self, plan):
|
||||
self._check_enabled()
|
||||
return self._send(plan, True)
|
||||
|
||||
def sendRaw(self, plan):
|
||||
self._check_enabled()
|
||||
return self._send(plan, False)
|
||||
|
||||
def _process_v1_result(self, result):
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import eventlet
|
||||
|
||||
import murano.common.config as config
|
||||
import murano.dsl.murano_class as murano_class
|
||||
import murano.dsl.murano_object as murano_object
|
||||
import murano.engine.system.common as common
|
||||
|
@ -24,26 +25,49 @@ from murano.openstack.common import log as logging
|
|||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AgentListenerException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
@murano_class.classname('io.murano.system.AgentListener')
|
||||
class AgentListener(murano_object.MuranoObject):
|
||||
def initialize(self, _context, name):
|
||||
self._enabled = False
|
||||
if config.CONF.engine.disable_murano_agent:
|
||||
return
|
||||
self._enabled = True
|
||||
self._results_queue = str('-execution-results-%s' % name.lower())
|
||||
self._subscriptions = {}
|
||||
self._receive_thread = None
|
||||
|
||||
@property
|
||||
def enabled(self):
|
||||
return self._enabled
|
||||
|
||||
def queueName(self):
|
||||
return self._results_queue
|
||||
|
||||
def start(self):
|
||||
if config.CONF.engine.disable_murano_agent:
|
||||
# Noop
|
||||
LOG.debug("murano-agent is disabled by the server")
|
||||
return
|
||||
|
||||
if self._receive_thread is None:
|
||||
self._receive_thread = eventlet.spawn(self._receive)
|
||||
|
||||
def stop(self):
|
||||
# _receive_thread will be None if agent is disabled
|
||||
if self._receive_thread is not None:
|
||||
self._receive_thread.kill()
|
||||
self._receive_thread = None
|
||||
|
||||
def subscribe(self, message_id, event):
|
||||
if config.CONF.engine.disable_murano_agent:
|
||||
raise AgentListenerException(
|
||||
"Use of murano-agent is disallowed "
|
||||
"by the server configuration")
|
||||
|
||||
self._subscriptions[message_id] = event
|
||||
|
||||
def _receive(self):
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
Name: AgentListenerTests
|
||||
|
||||
Namespaces:
|
||||
sys: io.murano.system
|
||||
|
||||
Properties:
|
||||
agentListener:
|
||||
Contract: $.class(sys:AgentListener)
|
||||
Usage: Runtime
|
||||
|
||||
|
||||
Methods:
|
||||
testAgentListener:
|
||||
Body:
|
||||
- $.agentListener: new(sys:AgentListener, name => 'hello')
|
||||
- Return: $.agentListener
|
|
@ -0,0 +1,16 @@
|
|||
Name: AgentTests
|
||||
|
||||
Namespaces:
|
||||
sys: io.murano.system
|
||||
|
||||
Properties:
|
||||
agent:
|
||||
Contract: $.class(sys:Agent)
|
||||
Usage: Runtime
|
||||
|
||||
|
||||
Methods:
|
||||
testAgent:
|
||||
Body:
|
||||
- $.agent: new(sys:Agent, host => $)
|
||||
- Return: $.agent
|
|
@ -0,0 +1,82 @@
|
|||
# Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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
|
||||
|
||||
from murano.engine.system import agent
|
||||
from murano.engine.system import agent_listener
|
||||
from murano.tests.dsl.foundation import object_model as om
|
||||
from murano.tests.dsl.foundation import test_case
|
||||
|
||||
|
||||
class TestAgentListener(test_case.DslTestCase):
|
||||
def setUp(self):
|
||||
super(TestAgentListener, self).setUp()
|
||||
|
||||
# Register Agent class
|
||||
self.class_loader.import_class(agent_listener.AgentListener)
|
||||
model = om.Object(
|
||||
'AgentListenerTests')
|
||||
self.runner = self.new_runner(model)
|
||||
|
||||
def test_listener_enabled(self):
|
||||
self.override_config('disable_murano_agent', False, 'engine')
|
||||
al = self.runner.testAgentListener()
|
||||
self.assertTrue(al.enabled)
|
||||
al.subscribe('msgid', 'event')
|
||||
self.assertEqual({'msgid': 'event'}, al._subscriptions)
|
||||
|
||||
def test_listener_disabled(self):
|
||||
self.override_config('disable_murano_agent', True, 'engine')
|
||||
al = self.runner.testAgentListener()
|
||||
self.assertFalse(al.enabled)
|
||||
self.assertRaises(agent_listener.AgentListenerException,
|
||||
al.subscribe, 'msgid', 'event')
|
||||
|
||||
|
||||
class TestAgent(test_case.DslTestCase):
|
||||
def setUp(self):
|
||||
super(TestAgent, self).setUp()
|
||||
|
||||
# Register Agent class
|
||||
self.class_loader.import_class(agent.Agent)
|
||||
model = om.Object(
|
||||
'AgentTests')
|
||||
self.runner = self.new_runner(model)
|
||||
|
||||
def test_agent_enabled(self):
|
||||
self.override_config('disable_murano_agent', False, 'engine')
|
||||
m = mock.MagicMock()
|
||||
# Necessary because otherwise there'll be an Environment lookup
|
||||
agent_cls = 'murano.engine.system.agent.Agent'
|
||||
with mock.patch(agent_cls + '._get_environment') as f:
|
||||
f.return_value = m
|
||||
a = self.runner.testAgent()
|
||||
self.assertTrue(a.enabled)
|
||||
self.assertEqual(m, a._environment)
|
||||
|
||||
with mock.patch(agent_cls + '._send') as s:
|
||||
s.return_value = mock.MagicMock()
|
||||
a.sendRaw({})
|
||||
s.assert_called_with({}, False)
|
||||
|
||||
def test_agent_disabled(self):
|
||||
self.override_config('disable_murano_agent', True, 'engine')
|
||||
a = self.runner.testAgent()
|
||||
self.assertFalse(a.enabled)
|
||||
self.assertRaises(agent.AgentException, a.call, {}, None)
|
||||
self.assertRaises(agent.AgentException, a.send, {}, None)
|
||||
self.assertRaises(agent.AgentException, a.callRaw, {})
|
||||
self.assertRaises(agent.AgentException, a.sendRaw, {})
|
Loading…
Reference in New Issue