Added property to associate environment with OS region
The Environment class got two additional properties: region - name of the region where environment should be deployed. If null then home region is used. regionConfigs - config property (taken from class config) that specifies region parameters. It is a dictionary of a form regionName -> regionSettings. Currently the only setting available is a agentRabbitMq that is itself a dictionary containing the same options as [rabbitmq] section of murano.conf Thus the configuration file io.murano.Environment.yaml may look like: regionConfigs: RegionOne: agentRabbitMq: host: rabbitMqHostName port: 5672 login: murano password: murano virtual_host: / ssl: false ca_certs: null Implements Blueprint: assign-environment-to-region Change-Id: I3c84c96f8eeae738f83ed7b3691be38100b30e1d
This commit is contained in:
parent
73f798da57
commit
322ba88742
@ -23,7 +23,7 @@ Methods:
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- If: !yaql "not bool($.getAttr(deployed))"
|
||||
- If: not $.getAttr(deployed, false)
|
||||
Then:
|
||||
- $._environment.reporter.report($this, 'Creating VM ')
|
||||
- $securityGroupIngress:
|
||||
|
@ -14,8 +14,9 @@ Properties:
|
||||
Methods:
|
||||
validateImage:
|
||||
Body:
|
||||
- $environment: $.find(std:Environment).require()
|
||||
- Try:
|
||||
- $glance: new('io.murano.extensions.mirantis.example.Glance')
|
||||
- $glance: new('io.murano.extensions.mirantis.example.Glance', $environment)
|
||||
Catch:
|
||||
With: 'murano.dsl.exceptions.NoPackageForClassFound'
|
||||
Do:
|
||||
|
@ -20,20 +20,24 @@ import glanceclient
|
||||
from oslo_config import cfg as config
|
||||
from oslo_log import log as logging
|
||||
|
||||
|
||||
from murano.common import auth_utils
|
||||
|
||||
from murano.dsl import session_local_storage
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GlanceClient(object):
|
||||
def __init__(self, context):
|
||||
self.client = self.create_glance_client()
|
||||
def __init__(self, this):
|
||||
self._owner = this.find_owner('io.murano.Environment')
|
||||
|
||||
@property
|
||||
def _client(self):
|
||||
region = None if self._owner is None else self._owner['region']
|
||||
return self.create_glance_client(region)
|
||||
|
||||
def list(self):
|
||||
images = self.client.images.list()
|
||||
images = self._client.images.list()
|
||||
while True:
|
||||
try:
|
||||
image = next(images)
|
||||
@ -42,7 +46,7 @@ class GlanceClient(object):
|
||||
break
|
||||
|
||||
def get_by_name(self, name):
|
||||
images = list(self.client.images.list(filters={"name": name}))
|
||||
images = list(self._client.images.list(filters={"name": name}))
|
||||
if len(images) > 1:
|
||||
raise AmbiguousNameException(name)
|
||||
elif len(images) == 0:
|
||||
@ -51,7 +55,7 @@ class GlanceClient(object):
|
||||
return GlanceClient._format(images[0])
|
||||
|
||||
def get_by_id(self, imageId):
|
||||
image = self.client.images.get(imageId)
|
||||
image = self._client.images.get(imageId)
|
||||
return GlanceClient._format(image)
|
||||
|
||||
@staticmethod
|
||||
@ -65,11 +69,13 @@ class GlanceClient(object):
|
||||
def init_plugin(cls):
|
||||
cls.CONF = cfg.init_config(CONF)
|
||||
|
||||
def create_glance_client(self):
|
||||
@staticmethod
|
||||
@session_local_storage.execution_session_memoize
|
||||
def create_glance_client(region):
|
||||
LOG.debug("Creating a glance client")
|
||||
params = auth_utils.get_session_client_parameters(
|
||||
service_type='image', conf=self.CONF)
|
||||
return glanceclient.Client(self.CONF.api_version, **params)
|
||||
service_type='image', conf=CONF, region=region)
|
||||
return glanceclient.Client(CONF.api_version, **params)
|
||||
|
||||
|
||||
class AmbiguousNameException(Exception):
|
||||
|
@ -50,9 +50,28 @@ Properties:
|
||||
Contract: $.class(sys:StatusReporter)
|
||||
Usage: Runtime
|
||||
|
||||
regionConfigs:
|
||||
Contract:
|
||||
$.string():
|
||||
agentRabbitMq:
|
||||
host: $.string().notNull()
|
||||
port: $.int() or 5672
|
||||
login: $.string().notNull()
|
||||
password: $.string().notNull()
|
||||
virtual_host: $.string() or '/'
|
||||
ssl: $.bool() or false
|
||||
ca_certs: $.string() or ''
|
||||
Usage: Config
|
||||
|
||||
region:
|
||||
Contract: $.string()
|
||||
Usage: InOut
|
||||
|
||||
|
||||
Methods:
|
||||
initialize:
|
||||
Body:
|
||||
- $._assignRegions()
|
||||
- $generatedEnvironmentName: $.getAttr(generatedEnvironmentName)
|
||||
- If: $generatedEnvironmentName = null
|
||||
Then:
|
||||
@ -60,7 +79,7 @@ Methods:
|
||||
- $.setAttr(generatedEnvironmentName, $generatedEnvironmentName)
|
||||
- $this.agentListener: new(sys:AgentListener, name => $generatedEnvironmentName)
|
||||
- $stackDescriptionFormat: 'This stack was generated by Murano for environment {0} (ID: {1})'
|
||||
- $this.stack: new(sys:HeatStack,
|
||||
- $this.stack: new(sys:HeatStack, $this,
|
||||
name => 'murano-' + $generatedEnvironmentName,
|
||||
description => $stackDescriptionFormat.format($.name, $.id()))
|
||||
- $this.instanceNotifier: new(sys:InstanceNotifier, environment => $this)
|
||||
@ -84,3 +103,28 @@ Methods:
|
||||
destroy:
|
||||
Body:
|
||||
- $.stack.delete()
|
||||
|
||||
_assignRegions:
|
||||
Body:
|
||||
- $homeRegion: config(home_region)
|
||||
- If: $.region = null
|
||||
Then:
|
||||
$.region: $homeRegion
|
||||
|
||||
- $defaultRegionConfig:
|
||||
agentRabbitMq:
|
||||
host: config(rabbitmq, host)
|
||||
port: config(rabbitmq, port)
|
||||
login: config(rabbitmq, login)
|
||||
password: config(rabbitmq, password)
|
||||
virtual_host: config(rabbitmq, virtual_host)
|
||||
ssl: config(rabbitmq, ssl)
|
||||
ca_certs: config(rabbitmq, ca_certs)
|
||||
|
||||
- If: not (null in $.regionConfigs.keys())
|
||||
Then:
|
||||
- $.regionConfigs: $.regionConfigs.set(null => $defaultRegionConfig)
|
||||
|
||||
- If: $homeRegion != null and not ($homeRegion in $.regionConfigs.keys())
|
||||
Then:
|
||||
- $.regionConfigs: $.regionConfigs.set($homeRegion => $defaultRegionConfig)
|
||||
|
@ -38,7 +38,8 @@ Properties:
|
||||
Workflow:
|
||||
initialize:
|
||||
Body:
|
||||
- $._netExplorer: new(sys:NetworkExplorer)
|
||||
- $environment: $.find(std:Environment).require()
|
||||
- $._netExplorer: new(sys:NetworkExplorer, $environment)
|
||||
- $._networks: null
|
||||
- $._subnetworks: null
|
||||
- $._ports: null
|
||||
|
@ -58,6 +58,7 @@ Methods:
|
||||
generateUserData:
|
||||
Body:
|
||||
- $environment: $.find(std:Environment).require()
|
||||
- $rabbitMqParams: $environment.regionConfigs.get($environment.region).agentRabbitMq
|
||||
- $resources: new(sys:Resources)
|
||||
- $configFile: $resources.string('Agent-v2.template')
|
||||
- $initScript: $resources.string('linux-init.sh')
|
||||
@ -66,18 +67,18 @@ Methods:
|
||||
- $muranoAgentService: $resources.string('murano-agent.service')
|
||||
- $muranoAgent: $resources.string('murano-agent')
|
||||
- $configReplacements:
|
||||
"%RABBITMQ_HOST%": config(rabbitmq, host)
|
||||
"%RABBITMQ_PORT%": config(rabbitmq, port)
|
||||
"%RABBITMQ_USER%": config(rabbitmq, login)
|
||||
"%RABBITMQ_PASSWORD%": config(rabbitmq, password)
|
||||
"%RABBITMQ_VHOST%": config(rabbitmq, virtual_host)
|
||||
"%RABBITMQ_SSL%": str(config(rabbitmq, ssl)).toLower()
|
||||
"%RABBITMQ_HOST%": $rabbitMqParams.host
|
||||
"%RABBITMQ_PORT%": $rabbitMqParams.port
|
||||
"%RABBITMQ_USER%": $rabbitMqParams.login
|
||||
"%RABBITMQ_PASSWORD%": $rabbitMqParams.password
|
||||
"%RABBITMQ_VHOST%": $rabbitMqParams.virtual_host
|
||||
"%RABBITMQ_SSL%": str($rabbitMqParams.ssl).toLower()
|
||||
"%RABBITMQ_INPUT_QUEUE%": $.agent.queueName()
|
||||
"%RESULT_QUEUE%": $environment.agentListener.queueName()
|
||||
- $scriptReplacements:
|
||||
"%AGENT_CONFIG_BASE64%": base64encode($configFile.replace($configReplacements))
|
||||
"%INTERNAL_HOSTNAME%": $.name
|
||||
"%MURANO_SERVER_ADDRESS%": coalesce(config(file_server), config(rabbitmq, host))
|
||||
"%MURANO_SERVER_ADDRESS%": coalesce(config(file_server), $rabbitMqParams.host)
|
||||
"%CA_ROOT_CERT_BASE64%": ""
|
||||
- $muranoReplacements:
|
||||
"%MURANO_AGENT_CONF%": base64encode($muranoAgentConf)
|
||||
|
@ -53,7 +53,7 @@ Methods:
|
||||
initialize:
|
||||
Body:
|
||||
- $._environment: $.find(std:Environment).require()
|
||||
- $._netExplorer: new(sys:NetworkExplorer)
|
||||
- $._netExplorer: new(sys:NetworkExplorer, $._environment)
|
||||
|
||||
|
||||
deploy:
|
||||
|
@ -38,21 +38,22 @@ Methods:
|
||||
Body:
|
||||
- $resources: new(sys:Resources)
|
||||
- $environment: $.find(std:Environment).require()
|
||||
- $rabbitMqParams: $environment.regionConfigs.get($environment.region).agentRabbitMq
|
||||
- $configFile: $resources.string('Agent-v1.template')
|
||||
- $initScript: $resources.string('windows-init.ps1')
|
||||
- $configReplacements:
|
||||
"%RABBITMQ_HOST%": config(rabbitmq, host)
|
||||
"%RABBITMQ_PORT%": config(rabbitmq, port)
|
||||
"%RABBITMQ_USER%": config(rabbitmq, login)
|
||||
"%RABBITMQ_PASSWORD%": config(rabbitmq, password)
|
||||
"%RABBITMQ_VHOST%": config(rabbitmq, virtual_host)
|
||||
"%RABBITMQ_SSL%": str(config(rabbitmq, ssl)).toLower()
|
||||
"%RABBITMQ_HOST%": $rabbitMqParams.host
|
||||
"%RABBITMQ_PORT%": $rabbitMqParams.port
|
||||
"%RABBITMQ_USER%": $rabbitMqParams.login
|
||||
"%RABBITMQ_PASSWORD%": $rabbitMqParams.password
|
||||
"%RABBITMQ_VHOST%": $rabbitMqParams.virtual_host
|
||||
"%RABBITMQ_SSL%": str($rabbitMqParams.ssl).toLower()
|
||||
"%RABBITMQ_INPUT_QUEUE%": $.agent.queueName()
|
||||
"%RESULT_QUEUE%": $environment.agentListener.queueName()
|
||||
- $scriptReplacements:
|
||||
"%AGENT_CONFIG_BASE64%": base64encode($configFile.replace($configReplacements))
|
||||
"%INTERNAL_HOSTNAME%": $.name
|
||||
"%MURANO_SERVER_ADDRESS%": coalesce(config(file_server), config(rabbitmq, host))
|
||||
"%MURANO_SERVER_ADDRESS%": coalesce(config(file_server), $rabbitMqParams.host)
|
||||
"%CA_ROOT_CERT_BASE64%": ""
|
||||
- Return:
|
||||
data: $initScript.replace($scriptReplacements)
|
||||
|
@ -200,14 +200,17 @@ class MuranoObjectInterface(dsl_types.MuranoObjectInterface):
|
||||
|
||||
@property
|
||||
def owner(self):
|
||||
return self.__object.owner
|
||||
owner = self.__object.owner
|
||||
if owner is None:
|
||||
return None
|
||||
return MuranoObjectInterface(owner, self.__executor)
|
||||
|
||||
def find_owner(self, type, optional=False):
|
||||
if isinstance(type, six.string_types):
|
||||
type = helpers.get_class(type)
|
||||
elif isinstance(type, dsl_types.MuranoTypeReference):
|
||||
type = type.type
|
||||
p = self.owner
|
||||
p = self.__object.owner
|
||||
while p is not None:
|
||||
if type.is_compatible(p):
|
||||
return MuranoObjectInterface(p, self.__executor)
|
||||
|
@ -43,7 +43,7 @@ class PropertyUsages(object):
|
||||
Config = 'Config'
|
||||
Static = 'Static'
|
||||
All = {In, Out, InOut, Runtime, Const, Config, Static}
|
||||
Writable = {Out, InOut, Runtime, Static}
|
||||
Writable = {Out, InOut, Runtime, Static, Config}
|
||||
|
||||
|
||||
class MethodUsages(object):
|
||||
|
@ -20,6 +20,8 @@ import itertools
|
||||
import re
|
||||
import sys
|
||||
import uuid
|
||||
import weakref
|
||||
|
||||
|
||||
import eventlet.greenpool
|
||||
import eventlet.greenthread
|
||||
@ -552,3 +554,11 @@ def list_value(v):
|
||||
if not yaqlutils.is_sequence(v):
|
||||
v = [v]
|
||||
return v
|
||||
|
||||
|
||||
def weak_proxy(obj):
|
||||
if obj is None or isinstance(obj, weakref.ProxyType):
|
||||
return obj
|
||||
if isinstance(obj, weakref.ReferenceType):
|
||||
obj = obj()
|
||||
return weakref.proxy(obj)
|
||||
|
@ -275,7 +275,7 @@ class MuranoClass(dsl_types.MuranoClass, MuranoType, dslmeta.MetaProvider):
|
||||
|
||||
def new(self, owner, object_store, executor, **kwargs):
|
||||
obj = murano_object.MuranoObject(
|
||||
self, owner, object_store, executor, **kwargs)
|
||||
self, helpers.weak_proxy(owner), object_store, executor, **kwargs)
|
||||
|
||||
def initializer(__context, **params):
|
||||
if __context is None:
|
||||
|
@ -41,7 +41,7 @@ class HeatStackError(Exception):
|
||||
|
||||
@dsl.name('io.murano.system.HeatStack')
|
||||
class HeatStack(object):
|
||||
def __init__(self, name, description=None):
|
||||
def __init__(self, this, name, description=None):
|
||||
self._name = name
|
||||
self._template = None
|
||||
self._parameters = {}
|
||||
@ -51,8 +51,7 @@ class HeatStack(object):
|
||||
self._description = description
|
||||
self._last_stack_timestamps = (None, None)
|
||||
self._tags = ''
|
||||
self._client = self._get_client(CONF.home_region)
|
||||
pass
|
||||
self._owner = this.find_owner('io.murano.Environment')
|
||||
|
||||
@staticmethod
|
||||
def _create_client(session, region_name):
|
||||
@ -61,16 +60,21 @@ class HeatStack(object):
|
||||
conf=CONF.heat, session=session)
|
||||
return hclient.Client('1', **parameters)
|
||||
|
||||
@property
|
||||
def _client(self):
|
||||
region = None if self._owner is None else self._owner['region']
|
||||
return self._get_client(region)
|
||||
|
||||
@staticmethod
|
||||
@session_local_storage.execution_session_memoize
|
||||
def _get_client(region_name):
|
||||
session = auth_utils.get_client_session(conf=CONF.heat)
|
||||
return HeatStack._create_client(session, region_name)
|
||||
|
||||
@classmethod
|
||||
def _get_token_client(cls):
|
||||
def _get_token_client(self):
|
||||
ks_session = auth_utils.get_token_client_session(conf=CONF.heat)
|
||||
return cls._create_client(ks_session, CONF.home_region)
|
||||
region = None if self._owner is None else self._owner['region']
|
||||
return self._create_client(ks_session, region)
|
||||
|
||||
def current(self):
|
||||
if self._template is not None:
|
||||
|
@ -36,8 +36,13 @@ class MistralError(Exception):
|
||||
|
||||
@dsl.name('io.murano.system.MistralClient')
|
||||
class MistralClient(object):
|
||||
def __init__(self):
|
||||
self._client = self._create_client(CONF.home_region)
|
||||
def __init__(self, this):
|
||||
self._owner = this.find_owner('io.murano.Environment')
|
||||
|
||||
@property
|
||||
def _client(self):
|
||||
region = None if self._owner is None else self._owner['region']
|
||||
return self._create_client(region)
|
||||
|
||||
@staticmethod
|
||||
@session_local_storage.execution_session_memoize
|
||||
|
@ -35,12 +35,12 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
@dsl.name('io.murano.system.NetworkExplorer')
|
||||
class NetworkExplorer(object):
|
||||
def __init__(self):
|
||||
def __init__(self, this):
|
||||
session = helpers.get_execution_session()
|
||||
self._project_id = session.project_id
|
||||
self._settings = CONF.networking
|
||||
self._available_cidrs = self._generate_possible_cidrs()
|
||||
self._client = self._get_client(CONF.home_region)
|
||||
self._owner = this.find_owner('io.murano.Environment')
|
||||
|
||||
@staticmethod
|
||||
@session_local_storage.execution_session_memoize
|
||||
@ -50,6 +50,11 @@ class NetworkExplorer(object):
|
||||
service_type='network', region=region_name, conf=neutron_settings
|
||||
))
|
||||
|
||||
@property
|
||||
def _client(self):
|
||||
region = None if self._owner is None else self._owner['region']
|
||||
return self._get_client(region)
|
||||
|
||||
# NOTE(starodubcevna): to avoid simultaneous router requests we use retry
|
||||
# decorator with random delay 1-10 seconds between attempts and maximum
|
||||
# delay time 30 seconds.
|
||||
|
@ -281,7 +281,7 @@ class HotPackage(package_base.PackageBase):
|
||||
]
|
||||
},
|
||||
{YAQL('$stack'): YAQL(
|
||||
"new('io.murano.system.HeatStack', "
|
||||
"new('io.murano.system.HeatStack', $environment, "
|
||||
"name => $.getAttr(generatedHeatStackName))")},
|
||||
|
||||
YAQL("$reporter.report($this, "
|
||||
|
@ -20,7 +20,8 @@ Properties:
|
||||
Methods:
|
||||
initialize:
|
||||
Body:
|
||||
- $this.mistralClient: new(sys:MistralClient)
|
||||
- $environment: $.find(std:Environment).require()
|
||||
- $this.mistralClient: new(sys:MistralClient, $environment)
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
|
@ -113,7 +113,7 @@ class TestPropertyAccess(test_case.DslTestCase):
|
||||
exceptions.NoWriteAccessError,
|
||||
self._runner.on(self._multi_derived).
|
||||
testModifyUsageTestProperty6)
|
||||
self.assertRaises(
|
||||
exceptions.NoWriteAccessError,
|
||||
self._runner.on(self._multi_derived).
|
||||
testModifyUsageTestProperty7)
|
||||
self.assertEqual(
|
||||
77,
|
||||
self._runner.on(
|
||||
self._multi_derived).testModifyUsageTestProperty7())
|
||||
|
@ -36,6 +36,8 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
return_value=self.heat_client_mock)
|
||||
heat_stack.HeatStack._get_client = mock.Mock(
|
||||
return_value=self.heat_client_mock)
|
||||
self._this = mock.MagicMock()
|
||||
self._this.owner = None
|
||||
|
||||
@mock.patch(CLS_NAME + '._wait_state')
|
||||
@mock.patch(CLS_NAME + '._get_status')
|
||||
@ -44,7 +46,8 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
|
||||
status_get.return_value = 'NOT_FOUND'
|
||||
wait_st.return_value = {}
|
||||
hs = heat_stack.HeatStack('test-stack', 'Generated by TestHeatStack')
|
||||
hs = heat_stack.HeatStack(
|
||||
self._this, 'test-stack', 'Generated by TestHeatStack')
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
hs._files = {}
|
||||
hs._hot_environment = ''
|
||||
@ -52,7 +55,8 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
hs._applied = False
|
||||
hs.push()
|
||||
|
||||
hs = heat_stack.HeatStack('test-stack', 'Generated by TestHeatStack')
|
||||
hs = heat_stack.HeatStack(
|
||||
self._this, 'test-stack', 'Generated by TestHeatStack')
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
hs._files = {}
|
||||
hs._parameters = {}
|
||||
@ -82,7 +86,7 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
|
||||
status_get.return_value = 'NOT_FOUND'
|
||||
wait_st.return_value = {}
|
||||
hs = heat_stack.HeatStack('test-stack', None)
|
||||
hs = heat_stack.HeatStack(self._this, 'test-stack', None)
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
hs._files = {}
|
||||
hs._hot_environment = ''
|
||||
@ -112,7 +116,7 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
|
||||
status_get.return_value = 'NOT_FOUND'
|
||||
wait_st.return_value = {}
|
||||
hs = heat_stack.HeatStack('test-stack', None)
|
||||
hs = heat_stack.HeatStack(self._this, 'test-stack', None)
|
||||
hs._description = None
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
hs._files = {"heatFile": "file"}
|
||||
@ -143,7 +147,7 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
|
||||
status_get.return_value = 'NOT_FOUND'
|
||||
wait_st.return_value = {}
|
||||
hs = heat_stack.HeatStack('test-stack', None)
|
||||
hs = heat_stack.HeatStack(self._this, 'test-stack', None)
|
||||
hs._description = None
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
hs._files = {"heatFile": "file"}
|
||||
@ -171,7 +175,8 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
def test_update_wrong_template_version(self, current):
|
||||
"""Template version other than expected should cause error."""
|
||||
|
||||
hs = heat_stack.HeatStack('test-stack', 'Generated by TestHeatStack')
|
||||
hs = heat_stack.HeatStack(
|
||||
self._this, 'test-stack', 'Generated by TestHeatStack')
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
|
||||
invalid_template = {
|
||||
@ -208,7 +213,7 @@ class TestHeatStack(base.MuranoTestCase):
|
||||
wait_st.return_value = {}
|
||||
CONF.set_override('stack_tags', ['test-murano', 'murano-tag'], 'heat',
|
||||
enforce_type=True)
|
||||
hs = heat_stack.HeatStack('test-stack', None)
|
||||
hs = heat_stack.HeatStack(self._this, 'test-stack', None)
|
||||
hs._description = None
|
||||
hs._template = {'resources': {'test': 1}}
|
||||
hs._files = {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user