Alexander Tivelkov d698116869 Configuration is now properly applied to new nodes
If the configuration of software component has not been changed, but a
set of nodes in the server group has been modified, the component's
default checkClusterIsConfigured method will now properly return true,
thus the configuration will be applied on newly added nodes.

This is achieved by storing instance ids as part of component's
'configuration' attributed stored for its server group.

Change-Id: Ic8bbddc577518071d90a6e33518156047a1d2e2e
Closes-bug: #1634206
2016-11-17 00:48:11 +00:00

441 lines
13 KiB
YAML

Namespaces:
=: io.murano.applications
std: io.murano
res: io.murano.resources
m: io.murano.metadata.engine
--- # ------------------------------------------------------------------ # ---
Name: Installable
Properties:
allowedInstallFailures:
Contract: $.string().notNull().check($ in ['none', 'one', 'two', 'three', 'any', 'quorum'])
Default: 'none'
beforeInstallEvent:
Contract: $.class(Event).notNull()
Usage: Runtime
Default:
name: beforeInstall
installServerEvent:
Contract: $.class(Event).notNull()
Usage: Runtime
Default:
name: installServer
completeInstallationEvent:
Contract: $.class(Event).notNull()
Usage: Runtime
Default:
name: completeInstallation
Methods:
install:
Arguments:
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $serversToInstall: $serverGroup.getServers().pselect(
switch($this.checkServerIsInstalled($) => null, true => $)).where($ != null)
- If: any($serversToInstall)
Then:
- $.beforeInstall($serversToInstall, $serverGroup)
- $failures: $serversToInstall.pselect($this.installServer($, $serverGroup)).where($ != null)
- $.completeInstallation($serversToInstall, $serverGroup, $failures)
checkServerIsInstalled:
Meta:
- m:Synchronize:
onArgs: server
Arguments:
- server:
Contract: $.class(res:Instance)
Body:
- Return: $server.getAttr(installed, false)
beforeInstall:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $this.report(format('Installing {0}', name($this)))
- $this.beforeInstallEvent.notify($this, $servers, $serverGroup)
- $this.onBeforeInstall($servers, $serverGroup)
onBeforeInstall:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
installServer:
Meta:
- m:Synchronize:
onArgs: server
Arguments:
- server:
Contract: $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
Try:
- $this.report(format('Began installing {0} on {1}', name($this),
$server.name))
- $this.installServerEvent.notify($this, $server, $serverGroup)
- $this.onInstallServer($server, $serverGroup)
Catch:
- As: e
Do:
- $this.report(format('Unable to install {0} on {1} due to {2}',
name($this), $server.name, $e.message))
- Return: $server
Else:
- $this.report(format('{0} is installed on {1}',
name($this),
$server.name))
- $server.setAttr(installed, true)
- Return: null
onInstallServer:
Meta:
- m:Synchronize:
onArgs: server
Arguments:
- server:
Contract: $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
completeInstallation:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
- failedServers:
Contract:
- $.class(res:Instance).notNull()
Body:
- $success: :SoftwareComponent.detectSuccess($this.allowedInstallFailures, $serverGroup, $failedServers)
- If: $success
Then:
- $this.completeInstallationEvent.notify($this, $servers, $serverGroup, $failedServers)
- $this.onCompleteInstallation($servers, $serverGroup, $failedServers)
- $this.report(format('Finished installing {0} ({1} errors encountered)',
name($this), len($failedServers) or 'no'))
Else:
- Throw: TooManyInstallationErrors
Message: format('Too many errors ({0}) encountered while installing {1}',
len($failedServers), name($this))
onCompleteInstallation:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
- failedServers:
Contract:
- $.class(res:Instance).notNull()
report:
Arguments:
- message:
Contract: $.string().notNull()
Body:
- $env: $this.find(std:Environment)
- If: $env
Then:
- $env.reporter.report($this, $message)
--- # ------------------------------------------------------------------ # ---
Name: Configurable
Properties:
allowedConfigurationFailures:
Contract: $.string().notNull().check($ in ['none', 'one', 'two', 'three', 'any', 'quorum'])
Default: 'none'
preConfigureEvent:
Contract: $.class(Event).notNull()
Usage: Runtime
Default:
name: preConfigure
configureServerEvent:
Contract: $.class(Event).notNull()
Usage: Runtime
Default:
name: configureServer
completeConfigurationEvent:
Contract: $.class(Event).notNull()
Usage: Runtime
Default:
name: completeConfiguration
Methods:
.init:
Body:
- $this._randomName: randomName()
configure:
Arguments:
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- If: $this.checkClusterIsConfigured($serverGroup)
Then:
- Return:
- $serversToConfigure: $serverGroup.getServers().pselect(
switch($this.checkServerIsConfigured($, $serverGroup) => null, true => $)).where($ != null)
- $this.preConfigure($serversToConfigure, $serverGroup)
- $failures: $serversToConfigure.pselect($this.configureServer($, $serverGroup)).where($ != null)
- $.completeConfiguration($serversToConfigure, $serverGroup, $failures)
checkClusterIsConfigured:
Arguments:
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $key: list($this.getConfigurationKey()) + $serverGroup.getKey()
- $state: $serverGroup.getAttr(configuration)
- Return: $key = $state
checkServerIsConfigured:
Meta:
- m:Synchronize:
onArgs: server
Arguments:
- server:
Contract: $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $key: $this.getConfigurationKey()
- $state: $server.getAttr(configuration, null)
- Return: $key = $state
getConfigurationKey:
Body:
# should be redefined in subclasses to contain semantical signature
# of the object's configuration
- Return: $this._randomName
preConfigure:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $this.report(format('Applying configuration of {0}', name($this)))
- $this.configureSecurity($servers, $serverGroup)
- $this.preConfigureEvent.notify($this, $servers, $serverGroup)
- $this.onPreConfigure($servers, $serverGroup)
configureSecurity:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
onPreConfigure:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
configureServer:
Meta:
- m:Synchronize:
onArgs: server
Arguments:
- server:
Contract: $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- Try:
- $this.report(format('Began configuring {0} on {1}',
name($this), $server.name))
- $this.configureServerEvent.notify($this, $server, $serverGroup)
- $this.onConfigureServer($server, $serverGroup)
Catch:
- As: e
Do:
- $this.report(format('Unable to configure {0} on {1} due to {2}',
name($this), $server.name, $e.message))
- Return: $server
Else:
- $key: $this.getConfigurationKey()
- $server.setAttr(configuration, $key)
- $this.report(format('{0} is configured at {1}', name($this), $server.name))
- Return: null
onConfigureServer:
Meta:
- m:Synchronize:
onArgs: server
Arguments:
- server:
Contract: $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
completeConfiguration:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
- failedServers:
Contract:
- $.class(res:Instance).notNull()
Body:
- $success: :SoftwareComponent.detectSuccess($this.allowedConfigurationFailures, $serverGroup, $failedServers)
- If: $success
Then:
- $this.completeConfigurationEvent.notify($this, $servers, $serverGroup, $failedServers)
- $this.onCompleteConfiguration($servers, $serverGroup, $failedServers)
- $key: list($this.getConfigurationKey()) + $serverGroup.getKey()
- $serverGroup.setAttr(configuration, $key)
- $this.report(format('Finished configuring {0} ({1} errors encountered)',
name($this), $numFailures or 'no'))
Else:
- Throw: TooManyConfigurationErrors
Message: format('Too many errors ({0}) encountered while configuring {1}',
$numFailures, name($this))
onCompleteConfiguration:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
- failedServers:
Contract:
- $.class(res:Instance).notNull()
report:
Arguments:
- message:
Contract: $.string().notNull()
Body:
- $env: $this.find(std:Environment)
- If: $env
Then:
- $env.reporter.report($this, $message)
--- # ------------------------------------------------------------------ # ---
Name: OpenStackSecurityConfigurable
Extends: Configurable
Methods:
configureSecurity:
Arguments:
- servers:
Contract:
- $.class(res:Instance).notNull()
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $sr: $this.getSecurityRules()
- If: $sr
Then:
- $regions: $servers.select($.getRegion()).distinct()
- $regions.pselect($this._configureSecurityGroup($, $sr))
_configureSecurityGroup:
Usage: Static
Arguments:
- region:
Contract: $.class(std:CloudRegion).notNull()
- rules:
Contract:
- FromPort: $.int().notNull()
ToPort: $.int().notNull()
IpProtocol: $.string().notNull()
External: $.bool().notNull()
Ethertype: $.string().check($ in list(null, 'IPv4', 'IPv6'))
Body:
- $region.securityGroupManager.addGroupIngress($rules)
- $region.stack.push()
getSecurityRules:
Body:
- Return: {}
--- # ------------------------------------------------------------------ # ---
Name: SoftwareComponent
Extends:
- Installable
- Configurable
Methods:
deployAt:
Arguments:
- serverGroup:
Contract: $.class(ServerGroup).notNull()
Body:
- $serverGroup.deploy()
- $this.install($serverGroup)
- $this.configure($serverGroup)
report:
Arguments:
- message:
Contract: $.string().notNull()
Body:
- cast($this, Installable).report($message)
detectSuccess:
Usage: Static
Arguments:
- allowedFailures:
Contract: $.string().notNull().check($ in ['none', 'one', 'two', 'three', 'any', 'quorum'])
- serverGroup:
Contract: $.class(ServerGroup).notNull()
- failedServers:
Contract:
- $.class(res:Instance).notNull()
Body:
- $numFailures: len($failedServers)
- Match:
none:
- Return: $numFailures = 0
one:
- Return: $numFailures <= 1
two:
- Return: $numFailures <= 2
three:
- Return: $numFailures <= 3
any:
- Return: true
quorum:
- $numServers: $serverGroup.getServers().count()
- $maxFailures: $numServers - ($numServers/2 + 1)
- Return: $numFailures <= $maxFailures
Value: $allowedFailures