Support for multi-regional apps was added

Now all OpenStack resource classes inherit CloudResource
that provides getRegion method and regionName property.
This allows to assign resources to different regions.
getRegion() returns CloudRegion instance that resource or it
parent belong to. CloudRegion has the similar interface to
Environment class and is the correct way to get HeatStack
instance associated with the regoin, default network
configuration, security group manager and agent listener
instances. Environment acts as the default region so backward
compatibility is not broken. However new applications
should not use environment to set security group rules but
rather a region(s) of their instance(s) in order to work correctly
when their instances were configured to use region other then
the default.

Change-Id: I4dbf40c65042e9a354f3bfadfcd63a63e6e3e418
This commit is contained in:
Stan Lagun 2016-08-04 10:14:11 -07:00
parent be69379968
commit bb2d0e5a84
31 changed files with 316 additions and 220 deletions

View File

@ -0,0 +1,55 @@
Namespaces:
res: io.murano.resources
sys: io.murano.system
=: io.murano
Name: CloudRegion
Properties:
name:
Contract: $.string()
agentListener:
Contract: $.class(sys:AgentListener)
Usage: Runtime
stack:
Contract: $.class(sys:HeatStack)
Usage: Runtime
defaultNetworks:
Contract:
environment: $.class(res:Network)
flat: $.class(res:Network)
securityGroupManager:
Contract: $.class(sys:SecurityGroupManager)
Usage: Runtime
Methods:
getConfig:
Body:
- Return: $._environment.regionConfigs.get(
$.name, $._environment.regionConfigs.get(''))
.init:
Body:
- $._environment: $.find(Environment).require()
- $generatedStackName: $.getAttr(generatedStackName)
- If: $generatedStackName = null
Then:
- $generatedStackName: list($.name, randomName()).join('-')
- $.setAttr(generatedStackName, $generatedStackName)
- $this.agentListener: new(sys:AgentListener, $this, name => $generatedStackName)
- $stackDescriptionFormat: 'This stack was generated by Murano for environment {0} (ID: {1}) - region {2}'
- $this.stack: new(sys:HeatStack, $this,
name => 'murano-' + $generatedStackName,
description => $stackDescriptionFormat.format($._environment.name, id($._environment), $.name))
- $this.securityGroupManager:
coalesce($.defaultNetworks.environment, $.defaultNetworks.flat)?.
generateSecurityGroupManager()
.destroy:
Body:
- $.stack.delete()

View File

@ -0,0 +1,29 @@
Namespaces:
=: io.murano
Name: CloudResource
Properties:
regionName:
Contract: $.string()
Methods:
.init:
Body:
$._region: null
getRegion:
Meta:
'io.murano.metadata.engine.Synchronize':
onThis: false
Body:
- If: $._region = null
Then:
- $env: $.find(Environment).require()
- $regionName: generate($this, $ != null, $.find(CloudResource)).
select($.regionName).where($ != null).first($env.region)
- $._region: $.find(CloudRegion)
- If: $._region = null or $._region.name != $regionName
Then:
$._region: $env.regions[$regionName]
- Return: $._region

View File

@ -38,9 +38,8 @@ Properties:
defaultNetworks:
Contract:
environment: $.class(res:Network)
flat: $.class(res:Network)
Usage: In
environment: $.template(res:Network)
flat: $.template(res:Network)
securityGroupManager:
Contract: $.class(sys:SecurityGroupManager)
@ -67,33 +66,53 @@ Properties:
Contract: $.string()
Usage: InOut
homeRegionName:
Contract: $.string()
Usage: Runtime
regions:
Contract:
$.string(): $.class(CloudRegion)
Usage: InOut
Methods:
initialize:
.init:
Body:
- $.homeRegionName: config(home_region) or ''
- $._assignRegions()
- $generatedEnvironmentName: $.getAttr(generatedEnvironmentName)
- If: $generatedEnvironmentName = null
- $.instanceNotifier: new(sys:InstanceNotifier, environment => $this)
- $.reporter: new(sys:StatusReporter, environment => $this)
- $.regions: $.regions + $.regionConfigs.keys().
where($ and not $this.regions.containsKey($)).
select($this._createRegion($)).
toDict($.name)
- If: not $.regions.containsKey(null)
Then:
- $generatedEnvironmentName: randomName()
- $.setAttr(generatedEnvironmentName, $generatedEnvironmentName)
- $this.agentListener: new(sys:AgentListener, $this, name => $generatedEnvironmentName)
- $stackDescriptionFormat: 'This stack was generated by Murano for environment {0} (ID: {1})'
- $this.stack: new(sys:HeatStack, $this,
name => 'murano-' + $generatedEnvironmentName,
description => $stackDescriptionFormat.format($.name, $.id()))
- $this.instanceNotifier: new(sys:InstanceNotifier, environment => $this)
- $this.reporter: new(sys:StatusReporter, environment => $this)
- $net: null
- If: $.defaultNetworks.environment != null
Then:
- $net: $.defaultNetworks.environment
- If: $.defaultNetworks.flat != null
Then:
- $net: $.defaultNetworks.flat
- If: $net != null
Then:
- $this.securityGroupManager: $net.generateSecurityGroupManager($this)
- If: $.homeRegionName
Then:
$.regions['']: $.regions[$.homeRegionName]
Else:
$.regions['']: $._createRegion('')
- $defaultRegion: $.regions['']
- $.stack: $defaultRegion.stack
- $.securityGroupManager: $defaultRegion.securityGroupManager
_createRegion:
Arguments:
regionName:
Contract: $.string()
Body:
- $envNet: $.defaultNetworks.environment?.set(regionName => $regionName)
- $flatNet: $.defaultNetworks.flat?.set(regionName => $regionName)
- Return: new(CloudRegion, $this,
name => $regionName,
defaultNetworks => {
environment => $envNet,
flat => $flatNet
}
)
deploy:
Usage: Action
@ -106,10 +125,9 @@ Methods:
_assignRegions:
Body:
- $homeRegion: config(home_region)
- If: $.region = null
Then:
$.region: $homeRegion
$.region: $.homeRegionName
- $defaultRegionConfig:
agentRabbitMq:
@ -120,10 +138,10 @@ Methods:
virtual_host: config(rabbitmq, virtual_host)
ssl: config(rabbitmq, ssl)
- If: not (null in $.regionConfigs.keys())
- If: not $.regionConfigs.containsKey('')
Then:
- $.regionConfigs: $.regionConfigs.set(null => $defaultRegionConfig)
- $.regionConfigs: $.regionConfigs.set('' => $defaultRegionConfig)
- If: $homeRegion != null and not ($homeRegion in $.regionConfigs.keys())
- If: $.homeRegionName and not $.regionConfigs.containsKey($.homeRegionName)
Then:
- $.regionConfigs: $.regionConfigs.set($homeRegion => $defaultRegionConfig)
- $.regionConfigs: $.regionConfigs.set($.homeRegionName => $defaultRegionConfig)

View File

@ -29,8 +29,9 @@ Properties:
Methods:
initialize:
Body:
- $.environment: $.find(Environment).require()
- $.network: $.environment.defaultNetworks.environment
- $._environment: $.find(Environment).require()
- $._region: $.getRegion()
- $.network: $._environment.defaultNetworks.environment
- $.instances: []
@ -38,10 +39,10 @@ Methods:
Body:
- If: not $.getAttr(deployed, false)
Then:
- $reporter: $.environment.reporter
- $reporter: $._environment.reporter
- $.network.deploy()
- $networkData: $.network.describe()
- $aapPortName: format('AllowedAddressPairsPort-{0}', $.id())
- $aapPortName: format('AllowedAddressPairsPort-{0}', id($))
- $template:
resources:
$aapPortName:
@ -55,12 +56,12 @@ Methods:
$aapPortName+'-virtualIp':
value:
get_attr: [$aapPortName, fixed_ips, 0, ip_address]
description: format('SharedIP Address of SharedIp group {0}', $.id())
- $.environment.stack.updateTemplate($template)
description: format('SharedIP Address of SharedIp group {0}', id($))
- $._region.stack.updateTemplate($template)
- If: $.assignFloatingIp
Then:
- $extNetId: $networkData.floatingIpNetId
- $fipName: format('Shared-Floating-ip-{0}', $.id())
- $fipName: format('Shared-Floating-ip-{0}', id($))
- $template:
resources:
@ -75,13 +76,13 @@ Methods:
value:
get_attr: [$fipName, floating_ip_address]
description: Shared Floating IP assigned
- $.environment.stack.updateTemplate($template)
- $._region.stack.updateTemplate($template)
- $reporter.report($this, 'Allocating shared ip address')
- $.environment.stack.push()
- $outputs: $.environment.stack.output()
- $.virtualIp: $outputs.get(format('AllowedAddressPairsPort-{0}-virtualIp', $.id()))
- $.floatingIpAddress: $outputs.get(format('Shared-Floating-ip-{0}-val', $.id()))
- $._region.stack.push()
- $outputs: $._region.stack.output()
- $.virtualIp: $outputs.get(format('AllowedAddressPairsPort-{0}-virtualIp', id($)))
- $.floatingIpAddress: $outputs.get(format('Shared-Floating-ip-{0}-val', id($)))
- $reporter.report($this, format('Shared IP allocated at {0}', $.virtualIp))
- If: $.assignFloatingIp
Then:
@ -91,21 +92,21 @@ Methods:
getSharedIpRef:
Body:
- $aapPortName: format('AllowedAddressPairsPort-{0}', $.id())
- $aapPortName: format('AllowedAddressPairsPort-{0}', id($))
- Return:
get_attr: [$aapPortName, fixed_ips, 0, ip_address]
releaseResources:
Body:
- $template: $.environment.stack.current()
- $template: $._region.stack.current()
- $template.resources: $template.resources.delete(format('AllowedAddressPairsPort-{0}', id($)))
- $template.outputs: $template.outputs.delete(format('AllowedAddressPairsPort-{0}-virtualIp', id($)))
- If: $.assignFloatingIp
Then:
- $template.resources: $template.resources.delete(format('Shared-Floating-ip-{0}', id($)))
- $template.outputs: $template.outputs.delete(format('Shared-Floating-ip-{0}-val', id($)))
- $._environment.stack.setTemplate($template)
- $._environment.stack.push()
- $._region.stack.setTemplate($template)
- $._region.stack.push()
- $.floatingIpAddress: null
- $.virtualIp: null

View File

@ -52,6 +52,7 @@ Methods:
.init:
Body:
- $._environment: $.find(std:Environment).require()
- $._region: $.getRegion()
buildResourceDefinition:
Body:
@ -111,11 +112,11 @@ Methods:
- $snippet: $.buildResourceDefinition()
- If: $.getAttr(lastTemplate) != $snippet
Then:
- $template: $._environment.stack.current()
- $template: $._region.stack.current()
- $template: $template.mergeWith($snippet, maxLevels => 2)
- $._environment.stack.setTemplate($template)
- $._environment.stack.push()
- $outputs: $._environment.stack.output()
- $._region.stack.setTemplate($template)
- $._region.stack.push()
- $outputs: $._region.stack.output()
- $.openstackId: $outputs.get(format('vol-{0}-id', id($)))
- $.setAttr(lastTemplate, $snippet)
@ -123,11 +124,11 @@ Methods:
Body:
- If: $.getAttr(lastTemplate) != null
Then:
- $template: $._environment.stack.current()
- $template: $._region.stack.current()
- $template.resources: $template.resources.delete(format('vol-{0}', id($)))
- $template.outputs: $template.outputs.delete(format('vol-{0}-id', id($)))
- $._environment.stack.setTemplate($template)
- $._environment.stack.push()
- $._region.stack.setTemplate($template)
- $._region.stack.push()
- $.setAttr(lastTemplate, null)
- $.openstackId: null

View File

@ -21,7 +21,7 @@ Methods:
- userData:
Contract: $.string().notNull()
Body:
- $environment: $.find(std:Environment).require()
- $region: $.getRegion()
- $cloudInitConf: $.generateCloudConfig()
- $bootConfigResourceName: format('boot_config_{0}', $.name)
- $bootScriptResourceName: format('boot_script_{0}', $.name)
@ -44,14 +44,13 @@ Methods:
- config: {get_resource: $bootConfigResourceName}
- config: {get_resource: $bootScriptResourceName}
- $environment.stack.updateTemplate($template)
- $region.stack.updateTemplate($template)
- Return: {get_resource: $userDataResourceName}
generateCloudConfig:
Body:
- $resources: new(sys:Resources)
- $cloudConfigData: $.cast(LinuxMuranoInstance).generateCloudConfig()
- $confLang: $resources.yaml('conflang.conf')
- $cloudInitConf: $cloudConfigData.mergeWith($confLang)
- Return: $cloudInitConf
- $cloudConfigData: cast($, LinuxMuranoInstance).generateCloudConfig()
- $confLang: sys:Resources.yaml('conflang.conf')
- $cloudInitConf: $cloudConfigData.mergeWith($confLang)
- Return: $cloudInitConf

View File

@ -130,7 +130,7 @@ Workflow:
- If: $assignFloatingIp
Then:
- $floatingIpNetRef: $._externalNetworkId
- $fipName: format('fip-{0}-{1}', $.id(), $instance.name)
- $fipName: format('fip-{0}-{1}', id($), $instance.name)
- Return: $.joinInstanceToNetwork(
instance => $instance,

View File

@ -124,7 +124,6 @@ Methods:
instanceTemplate:
Contract: {}
Body:
- $environment: $.find(std:Environment)
- For: fragment
In: $.softwareConfigs
Do:
@ -139,13 +138,13 @@ Methods:
releaseResources:
Body:
- $environment: $.find(std:Environment)
- $template: $environment.stack.current()
- If: bool($template.resources) and bool($template.outputs)
- $region: $.getRegion()
- $template: $region.stack.current()
- If: $template.get(resources) and $template.get(outputs)
Then:
- $template.resources: $template.resources.deleteAll($.getAttr(scResources, []))
- $template.outputs: $template.outputs.deleteAll($.getAttr(scOutputs, []))
- $environment.stack.setTemplate($template)
- $.super($.releaseResources())
- $region.stack.setTemplate($template)
- super($, $.releaseResources())
- $.setAttr(scResources, [])
- $.setAttr(scOutputs, [])

View File

@ -17,7 +17,7 @@ Namespaces:
Name: Instance
Extends: std:CloudResource
Properties:
name:
@ -80,7 +80,7 @@ Properties:
Methods:
initialize:
Body:
- $.environment: $.find(std:Environment).require()
- $._environment: $.find(std:Environment).require()
- $.agent: new(sys:Agent, host => $)
- $.resources: new(sys:Resources)
- $.instanceTemplate: {}
@ -106,26 +106,28 @@ Methods:
beginDeploy:
Body:
- $.validateBootSource()
- $region: $.getRegion()
- $securityGroupName: coalesce(
$.securityGroupName,
$.environment.securityGroupManager.defaultGroupName
$region.securityGroupManager.defaultGroupName
)
- $.createDefaultInstanceSecurityGroupRules($securityGroupName)
- $.detectPrimaryNetwork()
- $.ensureSharedIpsDeployed()
- $.ensureNetworksDeployed()
- If: $.networks.useEnvironmentNetwork and $.environment.defaultNetworks.environment!=null
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
Then:
$.joinNet($.environment.defaultNetworks.environment, $securityGroupName)
- If: $.networks.useFlatNetwork and $.environment.defaultNetworks.flat!=null
$.joinNet($region.defaultNetworks.environment, $securityGroupName)
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
Then:
$.joinNet($.environment.defaultNetworks.flat, $securityGroupName)
$.joinNet($region.defaultNetworks.flat, $securityGroupName)
- $.networks.customNetworks.select($this.joinNet($, $securityGroupName))
- $preparedUserData: $.prepareUserData()
# Create MQ queue to communicate with the VM
- $.agent.prepare()
- $properties:
name: $.name
flavor: $.flavor
availability_zone: $.availabilityZone
user_data: $preparedUserData.data
@ -161,12 +163,13 @@ Methods:
# Any additional template preparation
- $.instanceTemplate: $.prepareStackTemplate($.instanceTemplate)
- $.environment.stack.updateTemplate($.instanceTemplate)
- $region.stack.updateTemplate($.instanceTemplate)
endDeploy:
Body:
- $.environment.stack.push()
- $outputs: $.environment.stack.output()
- $region: $.getRegion()
- $region.stack.push()
- $outputs: $region.stack.output()
- $.ipAddresses: $outputs.get(format('{0}-assigned-ips', $this.name)).values().flatten().distinct()
- $.openstackId: $outputs.get(format('{0}-id', $this.name))
- If: $._floatingIpOutputName != null
@ -174,7 +177,7 @@ Methods:
- $.floatingIpAddress: $outputs.get($._floatingIpOutputName)
- If: $.floatingIpAddress != null
Then: $.setAttr(fipAssigned, true)
- $.environment.instanceNotifier.trackCloudInstance($this)
- $._environment.instanceNotifier.trackCloudInstance($this)
deploy:
Body:
@ -183,18 +186,19 @@ Methods:
detectPrimaryNetwork:
Body:
- $region: $.getRegion()
- $._primaryNetwork: null
- If: $.networks.primaryNetwork != null
Then:
- $._primaryNetwork: $.networks.primaryNetwork
Else:
- If: $.networks.useEnvironmentNetwork and $.environment.defaultNetworks.environment!=null
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
Then:
- $._primaryNetwork: $.environment.defaultNetworks.environment
- $._primaryNetwork: $region.defaultNetworks.environment
Else:
- If: $.networks.useFlatNetwork and $.environment.defaultNetworks.flat!=null
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
Then:
- $._primaryNetwork: $.environment.defaultNetworks.flat
- $._primaryNetwork: $region.defaultNetworks.flat
Else:
- If: $.networks.customNetworks!= null
Then:
@ -202,12 +206,13 @@ Methods:
ensureNetworksDeployed:
Body:
- If: $.networks.useEnvironmentNetwork and $.environment.defaultNetworks.environment!=null
- $region: $.getRegion()
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
Then:
- $.environment.defaultNetworks.environment.deploy()
- If: $.networks.useFlatNetwork and $.environment.defaultNetworks.flat!=null
- $region.defaultNetworks.environment.deploy()
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
Then:
- $.environment.defaultNetworks.flat.deploy()
- $region.defaultNetworks.flat.deploy()
- $.networks.customNetworks.pselect($.deploy())
ensureSharedIpsDeployed:
@ -250,7 +255,7 @@ Methods:
- port:
$joinResult.portRef
- $.instanceTemplate: $.instanceTemplate.mergeWith($template)
- If: $joinResult.secGroupName != null
- If: $joinResult.get(secGroupName) != null
Then:
- $template:
resources:
@ -293,29 +298,31 @@ Methods:
beginReleaseResources:
Body:
- $template: $.environment.stack.current()
- If: bool($template.resources) and bool($template.outputs)
- $region: $.getRegion()
- $template: $region.stack.current()
- If: $template.get(resources) and $template.get(outputs)
Then:
- $resourcesToDelete: list($.name).concat($.getAttr(instanceResources, []))
- $lenBefore: len($template.resources)
- $template.resources: $template.resources.deleteAll($resourcesToDelete)
- If: $lenBefore > len($template.resources)
Then:
- $.environment.instanceNotifier.untrackCloudInstance($this)
- $._environment.instanceNotifier.untrackCloudInstance($this)
- $outputsToDelete: list(
'{0}-assigned-ips'.format($.name),
'{0}-id'.format($.name)).concat($.getAttr(instanceOutputs, []))
- $template.outputs: $template.outputs.deleteAll($outputsToDelete)
- $.environment.stack.setTemplate($template)
- $region.stack.setTemplate($template)
endReleaseResources:
Body:
- $template: $.environment.stack.current()
- If: bool($template.resources) and bool($template.outputs)
- $region: $.getRegion()
- $template: $region.stack.current()
- If: $template.get(resources) and $template.get(outputs)
Then:
- $.environment.stack.push()
- $region.stack.push()
- $.setAttr(instanceResources, [])
- $.setAttr(instanceOutputs, [])
- $.setAttr(fipAssigned, false)
@ -360,8 +367,9 @@ Methods:
isDeployed:
Body:
- $template: $.environment.stack.current()
- Return: $template.resources != null and $.name in $template.resources
- $region: $.getRegion()
- $template: $region.stack.current()
- Return: $template.get(resources, {}).containsKey($.name)
getRef:
Body:

View File

@ -24,11 +24,11 @@ Methods:
- groupName:
Contract: $.string().notNull()
Body:
- $environment: $.find(std:Environment).require()
- $region: $.getRegion()
- $rules:
- ToPort: 22
IpProtocol: tcp
FromPort: 22
External: true
- $environment.securityGroupManager.addGroupIngress(
- $region.securityGroupManager.addGroupIngress(
rules => $rules, groupName => $groupName)

View File

@ -21,7 +21,7 @@ Methods:
- userData:
Contract: $.string().notNull()
Body:
- $environment: $.find(std:Environment).require()
- $region: $.getRegion()
- $resources: new(sys:Resources)
- $muranoInitConf: $.generateCloudConfig()
- $bootScriptResourceName: format('boot_script_{0}', $.name)
@ -46,7 +46,7 @@ Methods:
- config: {get_resource: $bootScriptResourceName}
- $.setAttr(resourceCloudConfig, [$bootScriptResourceName, $userDataResourceName, $bootConfigResourceName])
- $environment.stack.updateTemplate($template)
- $region.stack.updateTemplate($template)
- Return: {get_resource: $userDataResourceName}
@ -58,9 +58,8 @@ Methods:
generateUserData:
Body:
- $environment: $.find(std:Environment).require()
- $rabbitMqParams: $environment.regionConfigs.get($environment.region,
$environment.regionConfigs.get(null)).agentRabbitMq
- $region: $.getRegion()
- $rabbitMqParams: $region.getConfig().agentRabbitMq
- $resources: new(sys:Resources)
- $configFile: $resources.string('Agent-v2.template')
- $initScript: $resources.string('linux-init.sh')
@ -77,7 +76,7 @@ Methods:
"%RABBITMQ_SSL%": str($rabbitMqParams.ssl).toLower()
"%RABBITMQ_INSECURE%": str($rabbitMqParams.insecure).toLower()
"%RABBITMQ_INPUT_QUEUE%": $.agent.queueName()
"%RESULT_QUEUE%": $environment.agentListener.queueName()
"%RESULT_QUEUE%": $region.agentListener.queueName()
- $scriptReplacements:
"%AGENT_CONFIG_BASE64%": base64encode($configFile.replace($configReplacements))
"%INTERNAL_HOSTNAME%": $.name
@ -97,12 +96,12 @@ Methods:
releaseResources:
Body:
- $environment: $.find(std:Environment).require()
- $template: $environment.stack.current()
- If: bool($template.resources) and bool($template.outputs)
- $region: $.getRegion()
- $template: $region.stack.current()
- If: $template.get(resources) and $template.get(outputs)
Then:
- $resourcesToDelete: $.getAttr(resourceCloudConfig, [])
- $template.resources: $template.resources.deleteAll($resourcesToDelete)
- $environment.stack.setTemplate($template)
- $region.stack.setTemplate($template)
- $.super($.releaseResources())
- super($, $.releaseResources())

View File

@ -15,6 +15,7 @@ Namespaces:
std: io.murano
Name: Network
Extends: std:CloudResource
Methods:
deploy:
@ -32,8 +33,5 @@ Methods:
- $.class(std:SharedIp)
generateSecurityGroupManager:
Arguments:
- environment:
Contract: $.class(std:Environment).notNull()
describe:

View File

@ -50,10 +50,10 @@ Properties:
Usage: InOut
Methods:
initialize:
.init:
Body:
- $._environment: $.find(std:Environment).require()
- $._netExplorer: new(sys:NetworkExplorer, $._environment)
- $._region: $.getRegion()
- $._netExplorer: new(sys:NetworkExplorer, $this)
deploy:
@ -69,16 +69,16 @@ Methods:
- $.externalRouterId: $._netExplorer.getDefaultRouter()
- If: $.autogenerateSubnet and (not bool($.subnetCidr))
Then:
- $.subnetCidr: $._netExplorer.getAvailableCidr($.externalRouterId, $.id())
- $.subnetCidr: $._netExplorer.getAvailableCidr($.externalRouterId, id($))
- $template: $template.mergeWith($._createSubnet())
- If: $.externalRouterId != null
Then:
- $template: $template.mergeWith($._createRouterInterface())
- $._environment.stack.updateTemplate($template)
- $._environment.stack.push()
- $outputs: $._environment.stack.output()
- $._region.stack.updateTemplate($template)
- $._region.stack.push()
- $outputs: $._region.stack.output()
- $.openstackId: $outputs.get(format('{0}-id', $this.name))
- $.setAttr(deployed, true)
@ -91,7 +91,7 @@ Methods:
$netName:
type: 'OS::Neutron::Net'
properties:
name: format('{0}-{1}', $.name, $.id())
name: format('{0}-{1}', $.name, id($))
outputs:
format('{0}-id', $.name):
description: format('ID of {0} network', $.name)
@ -144,7 +144,7 @@ Methods:
- If: $assignFloatingIp
Then:
- $extNetId: $._getExternalNetId()
- $fipName: format('fip-{0}-{1}', $.id(), $instance.name)
- $fipName: format('fip-{0}-{1}', id($), $instance.name)
- $result: $.joinInstanceToNetwork(
instance => $instance,
@ -186,9 +186,9 @@ Methods:
releaseResources:
Body:
- $template: $.environment.stack.current()
- $template: $._region.stack.current()
- $template.resources: $template.resources.delete(format('{0}-{1}', $.name, $.id()))
- $template.resources: $template.resources.delete(format('{0}-{1}', $.name, id($)))
- $template.resources: $template.resources.delete($._getSubnetName())
- $template.outputs: $template.outputs.delete(format('{0}-id', $.name))
@ -197,24 +197,24 @@ Methods:
Then:
$template.resources: $template.resources.delete($._getRouterInterfaceName())
- $._environment.stack.setTemplate($template)
- $._environment.stack.push()
- $._regiont.stack.setTemplate($template)
- $._region.stack.push()
- $.openstackId: null
_getRouterInterfaceName:
Body:
Return: format('ri-{0}', $.id())
Return: format('ri-{0}', id($))
_getNetworkName:
Body:
Return: format('network-{0}', $.id())
Return: format('network-{0}', id($))
_getSubnetName:
Body:
Return: format('subnet-{0}', $.id())
Return: format('subnet-{0}', id($))
_getExternalNetId:

View File

@ -20,8 +20,10 @@ Name: NeutronNetworkBase
Extends: Network
Methods:
initialize:
.init:
Body:
- $._environment: $.find(std:Environment)
- $._region: $.getRegion()
- $._netExplorer: new(sys:NetworkExplorer, $this)
- $._securityGroupsEnabled: $._netExplorer.listNeutronExtensions().alias.contains('security-group')
@ -43,7 +45,7 @@ Methods:
- floatingIpNetRef:
Contract: $
Body:
- $portName: format('port-{0}-{1}', $.id(), $instance.name)
- $portName: format('port-{0}-{1}', id($), $instance.name)
- $patchTemplate:
resources:
$portName:
@ -108,13 +110,10 @@ Methods:
generateSecurityGroupManager:
Arguments:
- environment:
Contract: $.class(std:Environment).notNull()
Body:
- If: $this._securityGroupsEnabled
Then:
- Return: new(sys:NeutronSecurityGroupManager, environment => $environment)
- Return: new(sys:NeutronSecurityGroupManager, $._region)
Else:
- $environment.reporter.report($this, "Warning! Security groups are disabled!")
- Return: new(sys:DummySecurityGroupManager, environment => $environment)
- $._environment.reporter.report($this, "Warning! Security groups are disabled!")
- Return: new(sys:DummySecurityGroupManager, $._region)

View File

@ -69,11 +69,8 @@ Methods:
generateSecurityGroupManager:
Arguments:
- environment:
Contract: $.class(std:Environment).notNull()
Body:
- Return: new(sys:AwsSecurityGroupManager, environment => $environment)
- Return: new(sys:AwsSecurityGroupManager)
describe:

View File

@ -12,9 +12,11 @@
Namespaces:
=: io.murano.resources
std: io.murano
Name: Volume
Extends: std:CloudResource
Properties:

View File

@ -19,6 +19,11 @@ Name: AwsSecurityGroupManager
Extends: SecurityGroupManager
Methods:
.init:
Body:
- $._environment: $.find(std:Environment)
- $._region: $.find(std:CloudRegion).require()
addGroupIngress:
Arguments:
- rules:
@ -82,19 +87,19 @@ Methods:
Message: $msg
- $groupDirection: dict(egress => SecurityGroupEgress).get($direction, SecurityGroupIngress)
- $stack: $.environment.stack
- $stack: $._region.stack
- $template:
resources:
$groupName:
type: 'AWS::EC2::SecurityGroup'
properties:
GroupDescription: format('Composite security group of Murano environment {0}', $.environment.name)
GroupDescription: format('Composite security group of Murano environment {0}', $._environment.name)
$groupDirection:
- FromPort: '-1'
ToPort: '-1'
IpProtocol: icmp
CidrIp: '0.0.0.0/0'
- $.environment.stack.updateTemplate($template)
- $._region.stack.updateTemplate($template)
- $rulesList: $rules.select(dict(
FromPort => str($.FromPort),
@ -109,4 +114,4 @@ Methods:
type: 'AWS::EC2::SecurityGroup'
properties:
$groupDirection: $rulesList
- $.environment.stack.updateTemplate($template)
- $._region.stack.updateTemplate($template)

View File

@ -19,6 +19,11 @@ Name: NeutronSecurityGroupManager
Extends: SecurityGroupManager
Methods:
.init:
Body:
- $._environment: $.find(std:Environment)
- $._region: $.find(std:CloudRegion).require()
addGroupIngress:
Arguments:
- rules:
@ -71,17 +76,18 @@ Methods:
ext_key: remote_mode
ext_val: remote_group_id
- $stack: $.environment.stack
- $template:
resources:
$groupName:
type: 'OS::Neutron::SecurityGroup'
properties:
description: format('Composite security group of Murano environment {0}', $.environment.name)
description: format(
'Composite security group of Murano environment {0}',
$._environment.name)
rules:
- protocol: icmp
remote_ip_prefix: '0.0.0.0/0'
- $.environment.stack.updateTemplate($template)
- $._region.stack.updateTemplate($template)
- $rulesList: $rules.select(dict(
port_range_min => $.FromPort,
@ -98,4 +104,4 @@ Methods:
type: 'OS::Neutron::SecurityGroup'
properties:
rules: $rulesList
- $.environment.stack.updateTemplate($template)
- $._region.stack.updateTemplate($template)

View File

@ -17,12 +17,9 @@ Namespaces:
Name: SecurityGroupManager
Properties:
environment:
Contract: $.class(std:Environment).notNull()
defaultGroupName:
Contract: $.string()
Default: format('MuranoSecurityGroup-{0}', $.environment.id())
Default: id($.find(std:CloudRegion))
Methods:
addGroupIngress:

View File

@ -46,11 +46,8 @@ Methods:
- Return: {}
generateSecurityGroupManager:
Arguments:
- environment:
Contract: $.class(std:Environment).notNull()
Body:
- Return: new(sys:SecurityGroupManager, environment => $environment)
- Return: new(sys:DummySecurityGroupManager)
describe:
Body:

View File

@ -10,7 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
Format: 1.1
Format: 1.4
Type: Library
@ -28,6 +28,8 @@ Tags: [MuranoPL]
Classes:
io.murano.Object: Object.yaml
io.murano.Environment: Environment.yaml
io.murano.CloudRegion: CloudRegion.yaml
io.murano.CloudResource: CloudResource.yaml
io.murano.Application: Application.yaml
io.murano.Exception: Exception.yaml
io.murano.StackTrace: StackTrace.yaml

View File

@ -162,9 +162,10 @@ class MuranoObjectInterface(dsl_types.MuranoObjectInterface):
def func(*args, **kwargs):
self._insert_instruction()
with helpers.with_object_store(self.__object_store):
return self.__object.type.invoke(
context = helpers.get_context()
return to_mutable(self.__object.type.invoke(
item, self.__object, args, kwargs,
helpers.get_context())
context), helpers.get_yaql_engine(context))
return func
@staticmethod

View File

@ -198,7 +198,7 @@ def get_current_method(context=None):
def get_yaql_engine(context=None):
context = context or get_context()
return context[constants.CTX_YAQL_ENGINE]
return None if context is None else context[constants.CTX_YAQL_ENGINE]
def get_current_exception(context=None):

View File

@ -47,10 +47,10 @@ class Agent(object):
'by the server configuration')
return
self._environment = host.find_owner('io.murano.Environment')
self._host = host
self._enabled = True
self._queue = str('e%s-h%s' % (
self._environment.id, host.id)).lower()
env = host.find_owner('io.murano.Environment')
self._queue = str('e%s-h%s' % (env.id, host.id)).lower()
@property
def enabled(self):
@ -63,7 +63,8 @@ class Agent(object):
'by the server configuration')
return
with common.create_rmq_client(self._environment) as client:
region = dsl.MuranoObjectInterface.create(self._host().getRegion())
with common.create_rmq_client(region) as client:
client.declare(self._queue, enable_ha=True, ttl=86400000)
def queue_name(self):
@ -83,14 +84,15 @@ class Agent(object):
def _send(self, template, wait_results, timeout):
"""Send a message over the MQ interface."""
region = self._host().getRegion()
msg_id = template.get('ID', uuid.uuid4().hex)
if wait_results:
event = eventlet.event.Event()
listener = self._environment['agentListener']
listener = region['agentListener']
listener().subscribe(msg_id, event)
msg = self._prepare_message(template, msg_id)
with common.create_rmq_client(self._environment) as client:
with common.create_rmq_client(region) as client:
client.send(message=msg, key=self._queue)
if wait_results:

View File

@ -68,7 +68,7 @@ class AgentListener(object):
lambda: self.stop())
self._receive_thread = dsl.spawn(
self._receive,
dsl.get_this().find_owner('io.murano.Environment'))
dsl.get_this().find_owner('io.murano.CloudRegion'))
def stop(self):
if CONF.engine.disable_murano_agent:
@ -94,8 +94,8 @@ class AgentListener(object):
self._check_enabled()
self._subscriptions.pop(message_id)
def _receive(self, environment):
with common.create_rmq_client(environment) as client:
def _receive(self, region):
with common.create_rmq_client(region) as client:
client.declare(self._results_queue, enable_ha=True, ttl=86400000)
with client.open(self._results_queue) as subscription:
while True:

View File

@ -20,10 +20,8 @@ from murano.common.messaging import mqclient
CONF = cfg.CONF
def create_rmq_client(environment):
region_name = environment['region']
region_configs = environment['regionConfigs']
region_config = region_configs.get(region_name, region_configs[None])
rmq_settings = region_config['agentRabbitMq'].copy()
def create_rmq_client(region):
region_config = region().getConfig()
rmq_settings = dict(region_config['agentRabbitMq'])
rmq_settings['ca_certs'] = CONF.rabbitmq.ca_certs.strip() or None
return mqclient.MqClient(**rmq_settings)

View File

@ -14,6 +14,7 @@
# limitations under the License.
import copy
import json
import eventlet
import heatclient.client as hclient
@ -50,7 +51,7 @@ class HeatStack(object):
self._description = description
self._last_stack_timestamps = (None, None)
self._tags = ''
self._owner = this.find_owner('io.murano.Environment')
self._owner = this.find_owner('io.murano.CloudRegion')
@staticmethod
def _create_client(session, region_name):
@ -61,7 +62,7 @@ class HeatStack(object):
@property
def _client(self):
region = None if self._owner is None else self._owner['region']
region = None if self._owner is None else self._owner['name']
return self._get_client(region)
@staticmethod
@ -72,7 +73,7 @@ class HeatStack(object):
def _get_token_client(self):
ks_session = auth_utils.get_token_client_session(conf=CONF.heat)
region = None if self._owner is None else self._owner['region']
region = None if self._owner is None else self._owner['name']
return self._create_client(ks_session, region)
def current(self):
@ -212,7 +213,7 @@ class HeatStack(object):
self._template['description'] = self._description
template = copy.deepcopy(self._template)
LOG.debug('Pushing: {template}'.format(template=template))
LOG.debug('Pushing: {template}'.format(template=json.dumps(template)))
while True:
try:

View File

@ -40,7 +40,7 @@ class NetworkExplorer(object):
self._project_id = session.project_id
self._settings = CONF.networking
self._available_cidrs = self._generate_possible_cidrs()
self._owner = this.find_owner('io.murano.Environment')
self._region = this.find_owner('io.murano.CloudRegion')
@staticmethod
@session_local_storage.execution_session_memoize
@ -52,7 +52,7 @@ class NetworkExplorer(object):
@property
def _client(self):
region = None if self._owner is None else self._owner['region']
region = None if self._region is None else self._region['name']
return self._get_client(region)
# NOTE(starodubcevna): to avoid simultaneous router requests we use retry

View File

@ -1,16 +0,0 @@
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

View File

@ -60,36 +60,20 @@ class TestAgentListener(test_case.DslTestCase):
class TestAgent(test_case.DslTestCase):
def setUp(self):
super(TestAgent, self).setUp()
# Register Agent class
self.package_loader.load_package('io.murano', None).register_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'
obj_if_cls = 'murano.dsl.dsl.MuranoObjectInterface'
with mock.patch(obj_if_cls + '.find_owner') as f:
f.return_value = m
a = self.runner.testAgent().extension
self.assertTrue(a.enabled)
self.assertEqual(m, a._environment)
a = agent.Agent(mock.MagicMock())
self.assertTrue(a.enabled)
with mock.patch(agent_cls + '._send') as s:
s.return_value = mock.MagicMock()
a.send_raw({})
s.assert_called_with({}, False, 0)
with mock.patch(agent_cls + '._send') as s:
s.return_value = mock.MagicMock()
a.send_raw({})
s.assert_called_with({}, False, 0)
def test_agent_disabled(self):
self.override_config('disable_murano_agent', True, 'engine')
a = self.runner.testAgent().extension
a = agent.Agent(mock.MagicMock())
self.assertFalse(a.enabled)
self.assertRaises(exc.PolicyViolationException, a.call, {}, None)
self.assertRaises(exc.PolicyViolationException, a.send, {}, None)

View File

@ -0,0 +1,14 @@
---
features:
- Support for application deployment across OpenStack regions was added.
Now all OpenStack resource classes inherit CloudResource that provides
getRegion method and regionName property. This allows to assign resources
to different regions. getRegion() returns CloudRegion instance that
resource or it parent belong to. CloudRegion has the similar interface
to Environment class and is the correct way to get HeatStack instance
associated with the regoin, default network configuration, security
group manager and agent listener instances. Environment acts as the
default region so backward compatibility is not broken. However new
applications should not use environment to set security group rules but
rather a region(s) of their instance(s) in order to work correctly when
their instances were configured to use region other then the default.