
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
378 lines
12 KiB
YAML
378 lines
12 KiB
YAML
# 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.
|
|
|
|
Namespaces:
|
|
=: io.murano.resources
|
|
std: io.murano
|
|
sys: io.murano.system
|
|
|
|
|
|
Name: Instance
|
|
Extends: std:CloudResource
|
|
|
|
Properties:
|
|
name:
|
|
Contract: $.string().notNull()
|
|
flavor:
|
|
Contract: $.string().notNull()
|
|
image:
|
|
Contract: $.string()
|
|
Default: null
|
|
keyname:
|
|
Contract: $.string()
|
|
Default: null
|
|
openstackId:
|
|
Contract: $.string()
|
|
Usage: Out
|
|
availabilityZone:
|
|
Contract: $.string().notNull()
|
|
Default: nova
|
|
agent:
|
|
Contract: $.class(sys:Agent)
|
|
Usage: Runtime
|
|
ipAddresses:
|
|
Contract: [$.string()]
|
|
Usage: Out
|
|
networks:
|
|
Contract:
|
|
useEnvironmentNetwork: $.bool().notNull()
|
|
useFlatNetwork: $.bool().notNull()
|
|
customNetworks: [$.class(Network).notNull()]
|
|
primaryNetwork: $.class(Network).notOwned()
|
|
Default:
|
|
useEnvironmentNetwork: true
|
|
useFlatNetwork: false
|
|
customNetworks: []
|
|
primaryNetwork: null
|
|
assignFloatingIp:
|
|
Contract: $.bool().notNull()
|
|
Default: false
|
|
floatingIpAddress:
|
|
Contract: $.string()
|
|
Usage: Out
|
|
securityGroupName:
|
|
Contract: $.string()
|
|
Default: null
|
|
sharedIps:
|
|
Contract:
|
|
- $.class(std:SharedIp)
|
|
Usage: InOut # as it is set in setSharedIps
|
|
volumes:
|
|
Contract:
|
|
$.string().notNull(): $.class(Volume).notNull()
|
|
blockDevices:
|
|
Contract:
|
|
- volume: $.class(Volume).notNull()
|
|
deviceName: $.string()
|
|
deviceType: $.string().check($ in list(disk, cdrom, null))
|
|
bootIndex: $.int()
|
|
Default: []
|
|
|
|
Methods:
|
|
initialize:
|
|
Body:
|
|
- $._environment: $.find(std:Environment).require()
|
|
- $.agent: new(sys:Agent, host => $)
|
|
- $.resources: new(sys:Resources)
|
|
- $.instanceTemplate: {}
|
|
- $._floatingIpOutputName: null
|
|
|
|
# Called after the Instance template pieces are in place. It
|
|
# is at this stage alterations to the template should be made
|
|
prepareStackTemplate:
|
|
Arguments:
|
|
instanceTemplate:
|
|
Contract: {}
|
|
Body:
|
|
- Return: $instanceTemplate
|
|
|
|
setSharedIps:
|
|
Arguments:
|
|
ips:
|
|
Contract:
|
|
- $.class(std:SharedIp)
|
|
Body:
|
|
$.sharedIps: $ips
|
|
|
|
beginDeploy:
|
|
Body:
|
|
- $.validateBootSource()
|
|
- $region: $.getRegion()
|
|
- $securityGroupName: coalesce(
|
|
$.securityGroupName,
|
|
$region.securityGroupManager.defaultGroupName
|
|
)
|
|
- $.createDefaultInstanceSecurityGroupRules($securityGroupName)
|
|
- $.detectPrimaryNetwork()
|
|
- $.ensureSharedIpsDeployed()
|
|
- $.ensureNetworksDeployed()
|
|
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
|
|
Then:
|
|
$.joinNet($region.defaultNetworks.environment, $securityGroupName)
|
|
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
|
|
Then:
|
|
$.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
|
|
user_data_format: $preparedUserData.format
|
|
key_name: $.keyname
|
|
|
|
- If: len($.blockDevices) > 0
|
|
Then:
|
|
- $bdmDefinition: $.blockDevices.select($this.buidBlockDeviceDefinition($))
|
|
- $properties.block_device_mapping_v2: $bdmDefinition
|
|
Else:
|
|
$properties.image: $.image
|
|
|
|
- $template:
|
|
resources:
|
|
$.name:
|
|
type: 'OS::Nova::Server'
|
|
properties: $properties
|
|
|
|
outputs:
|
|
format('{0}-assigned-ips', $.name):
|
|
description: format('Network IPs assigned to {0} instance', $.name)
|
|
value:
|
|
get_attr: [ $.name, networks ]
|
|
format('{0}-id', $.name):
|
|
description: format('ID of {0} instance', $.name)
|
|
value:
|
|
get_resource: $.name
|
|
|
|
- $.instanceTemplate: $.instanceTemplate.mergeWith($template)
|
|
- $.volumes.items().select(
|
|
$.unpack(path, volume) -> $this.attachVolume($path, $volume))
|
|
|
|
# Any additional template preparation
|
|
- $.instanceTemplate: $.prepareStackTemplate($.instanceTemplate)
|
|
- $region.stack.updateTemplate($.instanceTemplate)
|
|
|
|
endDeploy:
|
|
Body:
|
|
- $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
|
|
Then:
|
|
- $.floatingIpAddress: $outputs.get($._floatingIpOutputName)
|
|
- If: $.floatingIpAddress != null
|
|
Then: $.setAttr(fipAssigned, true)
|
|
- $._environment.instanceNotifier.trackCloudInstance($this)
|
|
|
|
deploy:
|
|
Body:
|
|
- $this.beginDeploy()
|
|
- $this.endDeploy()
|
|
|
|
detectPrimaryNetwork:
|
|
Body:
|
|
- $region: $.getRegion()
|
|
- $._primaryNetwork: null
|
|
- If: $.networks.primaryNetwork != null
|
|
Then:
|
|
- $._primaryNetwork: $.networks.primaryNetwork
|
|
Else:
|
|
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
|
|
Then:
|
|
- $._primaryNetwork: $region.defaultNetworks.environment
|
|
Else:
|
|
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
|
|
Then:
|
|
- $._primaryNetwork: $region.defaultNetworks.flat
|
|
Else:
|
|
- If: $.networks.customNetworks!= null
|
|
Then:
|
|
- $._primaryNetwork: $.networks.customNetworks.firstOrDefault()
|
|
|
|
ensureNetworksDeployed:
|
|
Body:
|
|
- $region: $.getRegion()
|
|
- If: $.networks.useEnvironmentNetwork and $region.defaultNetworks.environment!=null
|
|
Then:
|
|
- $region.defaultNetworks.environment.deploy()
|
|
- If: $.networks.useFlatNetwork and $region.defaultNetworks.flat!=null
|
|
Then:
|
|
- $region.defaultNetworks.flat.deploy()
|
|
- $.networks.customNetworks.pselect($.deploy())
|
|
|
|
ensureSharedIpsDeployed:
|
|
Body:
|
|
- $.sharedIps.pselect($.deploy())
|
|
|
|
joinNet:
|
|
Arguments:
|
|
- net:
|
|
Contract: $.class(Network).notNull()
|
|
- securityGroupName:
|
|
Contract: $.string()
|
|
Body:
|
|
- $primary: $net = $._primaryNetwork
|
|
- $assignFip: $primary and $.assignFloatingIp and not $.getAttr(fipAssigned, false)
|
|
- $sharedIps: []
|
|
- If: $primary
|
|
Then:
|
|
$sharedIps: $.sharedIps
|
|
- $joinResult: $net.joinInstance(
|
|
instance => $this,
|
|
securityGroupName => $securityGroupName,
|
|
assignFloatingIp => $assignFip,
|
|
sharedIps => $sharedIps
|
|
)
|
|
- $.setAttr(instanceResources, $.getAttr(instanceResources, []).concat($joinResult.get(instanceResources, [])))
|
|
- $.setAttr(instanceOutputs, $.getAttr(instanceOutputs, []).concat($joinResult.get(instanceOutputs, [])))
|
|
|
|
- If: $joinResult.template != null
|
|
Then:
|
|
- $.instanceTemplate: $.instanceTemplate.mergeWith($joinResult.template)
|
|
|
|
- If: $joinResult.portRef != null
|
|
Then:
|
|
- $template:
|
|
resources:
|
|
$.name:
|
|
properties:
|
|
networks:
|
|
- port:
|
|
$joinResult.portRef
|
|
- $.instanceTemplate: $.instanceTemplate.mergeWith($template)
|
|
- If: $joinResult.get(secGroupName) != null
|
|
Then:
|
|
- $template:
|
|
resources:
|
|
$.name:
|
|
properties:
|
|
security_groups:
|
|
- $joinResult.secGroupName
|
|
- $.instanceTemplate: $.instanceTemplate.mergeWith($template)
|
|
|
|
- $._floatingIpOutputName: coalesce($._floatingIpOutputName, $joinResult.instanceFipOutput)
|
|
|
|
attachVolume:
|
|
Arguments:
|
|
- path:
|
|
Contract: $.string().notNull()
|
|
- volume:
|
|
Contract: $.class(Volume).notNull()
|
|
Body:
|
|
- $attachment: $volume.attachTo($this, $path)
|
|
- $.instanceTemplate: $.instanceTemplate.mergeWith($attachment.template)
|
|
- $.setAttr(instanceResources, $.getAttr(instanceResources, []).concat($attachment.get(instanceResources, [])))
|
|
- $.setAttr(instanceOutputs, $.getAttr(instanceOutputs, []).concat($attachment.get(instanceOutputs, [])))
|
|
|
|
buidBlockDeviceDefinition:
|
|
Arguments:
|
|
blockDevice:
|
|
Contract:
|
|
volume: $.class(Volume).notNull()
|
|
deviceName: $.string()
|
|
deviceType: $.string().check($ in list(disk, cdrom, null))
|
|
bootIndex: $.int()
|
|
|
|
Body:
|
|
- $blockDevice.volume.deploy()
|
|
- Return:
|
|
device_name: $blockDevice.deviceName
|
|
volume_id: $blockDevice.volume.getRef()
|
|
device_type: $blockDevice.deviceType
|
|
boot_index: $blockDevice.bootIndex
|
|
|
|
beginReleaseResources:
|
|
Body:
|
|
- $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)
|
|
|
|
- $outputsToDelete: list(
|
|
'{0}-assigned-ips'.format($.name),
|
|
'{0}-id'.format($.name)).concat($.getAttr(instanceOutputs, []))
|
|
- $template.outputs: $template.outputs.deleteAll($outputsToDelete)
|
|
|
|
- $region.stack.setTemplate($template)
|
|
|
|
endReleaseResources:
|
|
Body:
|
|
- $region: $.getRegion()
|
|
- $template: $region.stack.current()
|
|
- If: $template.get(resources) and $template.get(outputs)
|
|
Then:
|
|
- $region.stack.push()
|
|
- $.setAttr(instanceResources, [])
|
|
- $.setAttr(instanceOutputs, [])
|
|
- $.setAttr(fipAssigned, false)
|
|
- $.openstackId: null
|
|
- $.ipAddresses: []
|
|
- $.floatingIpAddress: null
|
|
|
|
releaseResources:
|
|
Body:
|
|
- $this.beginReleaseResources()
|
|
- $this.endReleaseResources()
|
|
|
|
validateBootSource:
|
|
Body:
|
|
- If: $.image = null and len($.blockDevices) = 0
|
|
Then:
|
|
- $msg: format('Neither image nor bootable volumes is specified for instance {0}', $.name)
|
|
- Throw: ResourceNotFound
|
|
Message: $msg
|
|
- If: $.image != null and len($.blockDevices) > 0
|
|
Then:
|
|
- $msg: 'Both image and list of bootable volumes are specified'
|
|
- Throw: ResourceConflict
|
|
Message: $msg
|
|
|
|
destroy:
|
|
Body:
|
|
- $.releaseResources()
|
|
|
|
|
|
createDefaultInstanceSecurityGroupRules:
|
|
Arguments:
|
|
- groupName:
|
|
Contract: $.string().notNull()
|
|
|
|
prepareUserData:
|
|
Body:
|
|
Return:
|
|
data: null
|
|
# Valid values are HEAT_CFNTOOLS, RAW and SOFTWARE_CONFIG
|
|
format: HEAT_CFNTOOLS
|
|
|
|
isDeployed:
|
|
Body:
|
|
- $region: $.getRegion()
|
|
- $template: $region.stack.current()
|
|
- Return: $template.get(resources, {}).containsKey($.name)
|
|
|
|
getRef:
|
|
Body:
|
|
Return:
|
|
get_resource: $.name
|