Added 'destroy' method that is called on deleted instances
Added ability to modify/remove data from structures (like Heat templates) via jsonpatch and thus added ability to clean up Heat resources that was obtained by deleted instances Closes bug: #1296624 Change-Id: I4db226a5ab00ff363f8b5d44a5d690df942622e8
This commit is contained in:
parent
d000b7b1f8
commit
ac6a0dedec
@ -134,8 +134,8 @@ function init_murano() {
|
||||
recreate_database murano utf8
|
||||
|
||||
$MURANO_BIN_DIR/murano-manage --config-file $MURANO_CONF_FILE db-sync
|
||||
$MURANO_BIN_DIR/murano-manage --config-file $MURANO_CONF_FILE import-package $MURANO_DIR/meta/packages/core
|
||||
$MURANO_BIN_DIR/murano-manage --config-file $MURANO_CONF_FILE import-package $MURANO_DIR/meta/packages/activedirectory
|
||||
$MURANO_BIN_DIR/murano-manage --config-file $MURANO_CONF_FILE import-package $MURANO_DIR/meta/io.murano
|
||||
$MURANO_BIN_DIR/murano-manage --config-file $MURANO_CONF_FILE import-package $MURANO_DIR/meta/io.murano.windows.ActiveDirectory
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
Namespaces:
|
||||
=: io.murano.services.windows.activeDirectory
|
||||
=: io.murano.windows.activeDirectory
|
||||
std: io.murano
|
||||
sys: io.murano.system
|
||||
win: io.murano.services.windows
|
||||
|
||||
Name: ActiveDirectory
|
||||
|
||||
@ -29,5 +28,9 @@ Properties:
|
||||
Workflow:
|
||||
deploy:
|
||||
Body:
|
||||
- $.primaryController.deploy()
|
||||
- $.secondaryControllers.pselect($.deploy())
|
||||
- $.primaryController.deploy()
|
||||
- $.secondaryControllers.pselect($.deploy())
|
||||
- $.reportDeployed()
|
||||
|
||||
destroy:
|
||||
- $.reportDestroyed()
|
@ -1,8 +1,8 @@
|
||||
Namespaces:
|
||||
=: io.murano.services.windows.activeDirectory
|
||||
=: io.murano.windows.activeDirectory
|
||||
std: io.murano
|
||||
sys: io.murano.system
|
||||
win: io.murano.services.windows
|
||||
win: io.murano.windows
|
||||
|
||||
Name: Controller
|
||||
|
@ -0,0 +1,20 @@
|
||||
Namespaces:
|
||||
=: io.murano.windows
|
||||
ad: io.murano.windows.activeDirectory
|
||||
|
||||
Name: DomainHost
|
||||
|
||||
Extends: Host
|
||||
|
||||
Properties:
|
||||
domain:
|
||||
Contract: $.class(ad:ActiveDirectory).notNull()
|
||||
|
||||
Workflow:
|
||||
deploy:
|
||||
Arguments:
|
||||
Body:
|
||||
- $.super($.deploy())
|
||||
#- $.joinDomain($.domain)
|
||||
# Workaround against broken ResourceManager:
|
||||
- $.super($.joinDomain($this.domain))
|
49
meta/io.murano.windows.ActiveDirectory/Classes/Host.yaml
Normal file
49
meta/io.murano.windows.ActiveDirectory/Classes/Host.yaml
Normal file
@ -0,0 +1,49 @@
|
||||
Namespaces:
|
||||
=: io.murano.windows
|
||||
ad: io.murano.windows.activeDirectory
|
||||
res: io.murano.resources
|
||||
sys: io.murano.system
|
||||
|
||||
Name: Host
|
||||
|
||||
Extends: res:Instance
|
||||
|
||||
Properties:
|
||||
adminAccountName:
|
||||
Contract: $.string().notNull()
|
||||
Default: Administrator
|
||||
|
||||
adminPassword:
|
||||
Contract: $.string().notNull()
|
||||
|
||||
Workflow:
|
||||
initialize:
|
||||
Body:
|
||||
- $.super($.initialize())
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- $.super($.deploy())
|
||||
|
||||
- $resources: new(sys:Resources)
|
||||
- $template: $resources.json('SetPassword.template').bind(dict(
|
||||
adminPassword => $.adminPassword
|
||||
))
|
||||
- $.agent.send($template, $resources)
|
||||
|
||||
joinDomain:
|
||||
Arguments:
|
||||
- domain:
|
||||
Contract: $.class(ad:ActiveDirectory).notNull()
|
||||
Body:
|
||||
|
||||
- $resources: new(sys:Resources)
|
||||
- $template: $resources.json('JoinDomain.template').bind(dict(
|
||||
domain => $domain.name,
|
||||
domainUser => $domain.adminAccountName,
|
||||
domainPassword => $domain.adminPassword,
|
||||
ouPath => '',
|
||||
dnsIp => $domain.primaryController.dnsIp
|
||||
))
|
||||
- $.agent.call($template, $resources)
|
||||
|
@ -1,8 +1,7 @@
|
||||
Namespaces:
|
||||
=: io.murano.services.windows.activeDirectory
|
||||
=: io.murano.windows.activeDirectory
|
||||
std: io.murano
|
||||
sys: io.murano.system
|
||||
win: io.murano.services.windows
|
||||
|
||||
Name: PrimaryController
|
||||
|
||||
@ -22,7 +21,6 @@ Workflow:
|
||||
deploy:
|
||||
Arguments:
|
||||
Body:
|
||||
- $.debugPrint('Deploying Primary Controller for domain {0}'.format($this.domain.name))
|
||||
- $.super($.deploy())
|
||||
- $resources: new(io.murano.system.Resources)
|
||||
- $template: $resources.json('CreatePrimaryDC.template').bind(dict(
|
@ -1,5 +1,5 @@
|
||||
Namespaces:
|
||||
=: io.murano.services.windows.activeDirectory
|
||||
=: io.murano.windows.activeDirectory
|
||||
std: io.murano
|
||||
sys: io.murano.system
|
||||
|
||||
@ -15,7 +15,6 @@ Workflow:
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- $.debugPrint('Deploying Secondary Controller for domain {0}'.format($this.domain.name))
|
||||
- $.super($.deploy())
|
||||
- $.host.joinDomain($.domain)
|
||||
- $resources: new(sys:Resources)
|
@ -0,0 +1,25 @@
|
||||
{
|
||||
"Scripts": [
|
||||
"ImportCoreFunctions.ps1",
|
||||
"Join-Domain.ps1"
|
||||
],
|
||||
"Commands": [
|
||||
{
|
||||
"Name": "Set-NetworkAdapterConfiguration",
|
||||
"Arguments": {
|
||||
"FirstAvailable": true,
|
||||
"DNSServer": "$dnsIp"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Join-Domain",
|
||||
"Arguments": {
|
||||
"Username": "$domainUser",
|
||||
"Password": "$domainPassword",
|
||||
"DomainName": "$domain",
|
||||
"OUPath": "$ouPath"
|
||||
}
|
||||
}
|
||||
],
|
||||
"RebootOnCompletion": 1
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
{
|
||||
"Scripts": [
|
||||
"ImportCoreFunctions.ps1",
|
||||
"Set-LocalUserPassword.ps1"
|
||||
],
|
||||
"Commands": [
|
||||
{
|
||||
"Name": "Set-LocalUserPassword",
|
||||
"Arguments": {
|
||||
"UserName": "Administrator",
|
||||
"Password": "$adminPassword",
|
||||
"Force": true
|
||||
}
|
||||
}
|
||||
],
|
||||
"RebootOnCompletion": 0
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
|
||||
trap {
|
||||
&$TrapHandler
|
||||
}
|
||||
|
||||
|
||||
Function Join-Domain {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Executes "Join domain" action.
|
||||
|
||||
Requires 'CoreFunctions' module
|
||||
#>
|
||||
param (
|
||||
[String] $DomainName = '',
|
||||
[String] $UserName = '',
|
||||
[String] $Password = '',
|
||||
[String] $OUPath = '',
|
||||
[Switch] $AllowRestart
|
||||
)
|
||||
begin {
|
||||
Show-InvocationInfo $MyInvocation
|
||||
}
|
||||
end {
|
||||
Show-InvocationInfo $MyInvocation -End
|
||||
}
|
||||
process {
|
||||
trap {
|
||||
&$TrapHandler
|
||||
}
|
||||
|
||||
if ($UserName -eq '') {
|
||||
$UserName = 'Administrator'
|
||||
}
|
||||
|
||||
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password
|
||||
|
||||
|
||||
if (Test-ComputerName -DomainName $DomainName -ErrorAction 'SilentlyContinue') {
|
||||
Write-LogWarning "Computer already joined to domain '$DomainName'"
|
||||
}
|
||||
else {
|
||||
Write-Log "Joining computer to domain '$DomainName' ..."
|
||||
|
||||
if ($OUPath -eq '') {
|
||||
Add-Computer -DomainName $DomainName -Credential $Credential -Force
|
||||
}
|
||||
else {
|
||||
Add-Computer -DomainName $DomainName -Credential $Credential -OUPath $OUPath -Force
|
||||
}
|
||||
|
||||
$null = Exec 'ipconfig' @('/registerdns') -RedirectStreams
|
||||
|
||||
Write-Log "Waiting 30 seconds to restart ..."
|
||||
Start-Sleep -Seconds 30
|
||||
<#
|
||||
if ($AllowRestart) {
|
||||
Write-Log "Restarting computer ..."
|
||||
Restart-Computer -Force
|
||||
}
|
||||
else {
|
||||
Write-Log "Please restart the computer now."
|
||||
}
|
||||
#>
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
|
||||
trap {
|
||||
&$TrapHandler
|
||||
}
|
||||
|
||||
|
||||
Function Set-LocalUserPassword {
|
||||
param (
|
||||
[String] $UserName,
|
||||
[String] $Password,
|
||||
[Switch] $Force
|
||||
)
|
||||
begin {
|
||||
Show-InvocationInfo $MyInvocation
|
||||
}
|
||||
end {
|
||||
Show-InvocationInfo $MyInvocation -End
|
||||
}
|
||||
process {
|
||||
trap {
|
||||
&$TrapHandler
|
||||
}
|
||||
|
||||
if ((Get-WmiObject Win32_UserAccount -Filter "LocalAccount = 'True' AND Name='$UserName'") -eq $null) {
|
||||
throw "Unable to find local user account '$UserName'"
|
||||
}
|
||||
|
||||
if ($Force) {
|
||||
Write-Log "Changing password for user '$UserName' to '*****'" # :)
|
||||
$null = ([ADSI] "WinNT://./$UserName").SetPassword($Password)
|
||||
}
|
||||
else {
|
||||
Write-LogWarning "You are trying to change password for user '$UserName'. To do this please run the command again with -Force parameter."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
27
meta/io.murano.windows.ActiveDirectory/manifest.yaml
Normal file
27
meta/io.murano.windows.ActiveDirectory/manifest.yaml
Normal file
@ -0,0 +1,27 @@
|
||||
Format: 1.0
|
||||
|
||||
Type: Application
|
||||
|
||||
FullName: io.murano.windows.ActiveDirectory
|
||||
|
||||
Name: Active Directory
|
||||
|
||||
Description: |
|
||||
A domain service hosted in Windows environment by using Active Directory Role.
|
||||
May be clustered by combining a number of secondary domain controllers with one primary
|
||||
|
||||
Author: 'murano.io'
|
||||
|
||||
Tags: [Windows, Domain, demo, win2012, microsoft]
|
||||
|
||||
Classes:
|
||||
io.murano.windows.Host: Host.yaml
|
||||
io.murano.windows.DomainHost: DomainHost.yaml
|
||||
io.murano.windows.activeDirectory.ActiveDirectory: ActiveDirectory.yaml
|
||||
io.murano.windows.activeDirectory.Controller: Controller.yaml
|
||||
io.murano.windows.activeDirectory.PrimaryController: PrimaryController.yaml
|
||||
io.murano.windows.activeDirectory.SecondaryController: SecondaryController.yaml
|
||||
|
||||
# UI: ui.yaml # default to ui.yaml, will use default if skipped
|
||||
|
||||
Logo: logo2.png # defaults to logo.png, will use default if skipped
|
81
meta/io.murano/Classes/resources/Instance.yaml
Normal file
81
meta/io.murano/Classes/resources/Instance.yaml
Normal file
@ -0,0 +1,81 @@
|
||||
Namespaces:
|
||||
=: io.murano.resources
|
||||
sys: io.murano.system
|
||||
|
||||
|
||||
Name: Instance
|
||||
|
||||
|
||||
Properties:
|
||||
name:
|
||||
Contract: $.string().notNull()
|
||||
flavor:
|
||||
Contract: $.string().notNull()
|
||||
image:
|
||||
Contract: $.string().notNull()
|
||||
|
||||
agent:
|
||||
Contract: $.class(sys:Agent)
|
||||
Type: Runtime
|
||||
|
||||
|
||||
Workflow:
|
||||
initialize:
|
||||
Body:
|
||||
- $.environment: $.find(Environment).require()
|
||||
- $.agent: new(sys:Agent, host => $)
|
||||
- $.resources: new(sys:Resources)
|
||||
|
||||
deploy:
|
||||
Body:
|
||||
- $userData: $.prepareUserData()
|
||||
- $template:
|
||||
Resources:
|
||||
$.name:
|
||||
Type: 'AWS::EC2::Instance'
|
||||
Properties:
|
||||
InstanceType: $.flavor
|
||||
ImageId: $.image
|
||||
UserData: $userData
|
||||
- $.environment.stack.updateTemplate($template)
|
||||
- $.environment.stack.push()
|
||||
- $.environment.instanceNotifier.trackApplication($this)
|
||||
|
||||
destroy:
|
||||
Body:
|
||||
- $template: $.environment.stack.current()
|
||||
- $patchBlock:
|
||||
op: remove,
|
||||
path: format('/Resources/{0}', $.name)
|
||||
- $template: patch($template, $patchBlock)
|
||||
- $.environment.stack.setTemplate($template)
|
||||
- $.environment.stack.push()
|
||||
- $.environment.instanceNotifier.untrackApplication($this)
|
||||
|
||||
prepareUserData:
|
||||
Body:
|
||||
- If: !yaql "'w' in toLower($.image)"
|
||||
Then:
|
||||
- $configFile: $.resources.string('Agent-v1.template')
|
||||
- $initScript: $.resources.string('windows-init.ps1')
|
||||
Else:
|
||||
- $configFile: $.resources.string('Agent-v2.template')
|
||||
- $initScript: $.resources.string('linux-init.sh')
|
||||
|
||||
- $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_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))
|
||||
"%CA_ROOT_CERT_BASE64%": ""
|
||||
|
||||
- Return: $initScript.replace($scriptReplacements)
|
36
meta/io.murano/Resources/Agent-v1.template
Normal file
36
meta/io.murano/Resources/Agent-v1.template
Normal file
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog"/>
|
||||
</configSections>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
|
||||
</startup>
|
||||
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<targets>
|
||||
<target name="file" xsi:type="File" fileName="${basedir}/log.txt"
|
||||
layout="${date} ${level}: <${logger:shortName=true}> ${message} ${exception:format=tostring}"/>
|
||||
</targets>
|
||||
|
||||
<rules>
|
||||
<logger name="*" minlevel="Debug" writeTo="file" />
|
||||
</rules>
|
||||
</nlog>
|
||||
<appSettings>
|
||||
<add key="rabbitmq.host" value="%RABBITMQ_HOST%"/>
|
||||
<add key="rabbitmq.port" value="%RABBITMQ_PORT%"/>
|
||||
<add key="rabbitmq.user" value="%RABBITMQ_USER%"/>
|
||||
<add key="rabbitmq.password" value="%RABBITMQ_PASSWORD%"/>
|
||||
<add key="rabbitmq.vhost" value="%RABBITMQ_VHOST%"/>
|
||||
<add key="rabbitmq.inputQueue" value="%RABBITMQ_INPUT_QUEUE%"/>
|
||||
<add key="rabbitmq.resultExchange" value=""/>
|
||||
<add key="rabbitmq.resultRoutingKey" value="%RESULT_QUEUE%"/>
|
||||
<add key="rabbitmq.durableMessages" value="true"/>
|
||||
|
||||
<add key="rabbitmq.ssl" value="%RABBITMQ_SSL%"/>
|
||||
<add key="rabbitmq.allowInvalidCA" value="true"/>
|
||||
<add key="rabbitmq.sslServerName" value=""/>
|
||||
|
||||
</appSettings>
|
||||
</configuration>
|
35
meta/io.murano/Resources/Agent-v2.template
Normal file
35
meta/io.murano/Resources/Agent-v2.template
Normal file
@ -0,0 +1,35 @@
|
||||
[DEFAULT]
|
||||
debug=True
|
||||
verbose=True
|
||||
log_file = /var/log/murano-agnet.log
|
||||
|
||||
storage=/var/murano/plans
|
||||
|
||||
[rabbitmq]
|
||||
|
||||
# Input queue name
|
||||
input_queue = %RABBITMQ_INPUT_QUEUE%
|
||||
|
||||
# Output routing key (usually queue name)
|
||||
result_routing_key = %RESULT_QUEUE%
|
||||
|
||||
# Connection parameters to RabbitMQ service
|
||||
|
||||
# Hostname or IP address where RabbitMQ is located.
|
||||
host = %RABBITMQ_HOST%
|
||||
|
||||
# RabbitMQ port (5672 is a default)
|
||||
port = %RABBITMQ_PORT%
|
||||
|
||||
# Use SSL for RabbitMQ connections (True or False)
|
||||
ssl = %RABBITMQ_SSL%
|
||||
|
||||
# Path to SSL CA certificate or empty to allow self signed server certificate
|
||||
ca_certs =
|
||||
|
||||
# RabbitMQ credentials. Fresh RabbitMQ installation has "guest" account with "guest" password.
|
||||
login = %RABBITMQ_USER%
|
||||
password = %RABBITMQ_PASSWORD%
|
||||
|
||||
# RabbitMQ virtual host (vhost). Fresh RabbitMQ installation has "/" vhost preconfigured.
|
||||
virtual_host = %RABBITMQ_VHOST%
|
11
meta/io.murano/Resources/linux-init.sh
Normal file
11
meta/io.murano/Resources/linux-init.sh
Normal file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
service murano-agent stop
|
||||
|
||||
AgentConfigBase64='%AGENT_CONFIG_BASE64%'
|
||||
|
||||
mkdir /etc/murano
|
||||
echo $AgentConfigBase64 | base64 -d > /etc/murano/agent.conf
|
||||
chmod 664 /etc/murano/agent.conf
|
||||
|
||||
service murano-agent start
|
68
meta/io.murano/Resources/windows-init.ps1
Normal file
68
meta/io.murano/Resources/windows-init.ps1
Normal file
@ -0,0 +1,68 @@
|
||||
#ps1
|
||||
|
||||
$WindowsAgentConfigBase64 = '%AGENT_CONFIG_BASE64%'
|
||||
$WindowsAgentConfigFile = "C:\Murano\Agent\WindowsAgent.exe.config"
|
||||
$WindowsAgentLogFile = "C:\Murano\Agent\log.txt"
|
||||
|
||||
$NewComputerName = '%INTERNAL_HOSTNAME%'
|
||||
$MuranoFileShare = '\\%MURANO_SERVER_ADDRESS%\share'
|
||||
|
||||
$CaRootCertBase64 = "%CA_ROOT_CERT_BASE64%"
|
||||
$CaRootCertFile = "C:\Murano\ca.cert"
|
||||
|
||||
$RestartRequired = $false
|
||||
|
||||
Import-Module CoreFunctions
|
||||
Initialize-Logger 'CloudBase-Init' 'C:\Murano\PowerShell.log'
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
trap {
|
||||
Write-LogError '<exception>'
|
||||
Write-LogError $_ -EntireObject
|
||||
Write-LogError '</exception>'
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Log "Importing CA certificate ..."
|
||||
if ($CaRootCertBase64 -eq '') {
|
||||
Write-Log "Importing CA certificate ... skipped"
|
||||
}
|
||||
else {
|
||||
ConvertFrom-Base64String -Base64String $CaRootCertBase64 -Path $CaRootCertFile
|
||||
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 $CaRootCertFile
|
||||
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store("AuthRoot","LocalMachine")
|
||||
$store.Open("MaxAllowed")
|
||||
$store.Add($cert)
|
||||
$store.Close()
|
||||
Write-Log "Importing CA certificate ... done"
|
||||
}
|
||||
|
||||
Write-Log "Updating Murano Windows Agent."
|
||||
Stop-Service "Murano Agent"
|
||||
Backup-File $WindowsAgentConfigFile
|
||||
Remove-Item $WindowsAgentConfigFile -Force -ErrorAction 'SilentlyContinue'
|
||||
Remove-Item $WindowsAgentLogFile -Force -ErrorAction 'SilentlyContinue'
|
||||
ConvertFrom-Base64String -Base64String $WindowsAgentConfigBase64 -Path $WindowsAgentConfigFile
|
||||
Exec sc.exe 'config','"Murano Agent"','start=','delayed-auto'
|
||||
Write-Log "Service has been updated."
|
||||
|
||||
Write-Log "Adding environment variable 'MuranoFileShare' = '$MuranoFileShare' ..."
|
||||
[Environment]::SetEnvironmentVariable('MuranoFileShare', $MuranoFileShare, [EnvironmentVariableTarget]::Machine)
|
||||
Write-Log "Environment variable added."
|
||||
|
||||
Write-Log "Renaming computer to '$NewComputerName' ..."
|
||||
$null = Rename-Computer -NewName $NewComputerName -Force
|
||||
|
||||
Write-Log "New name assigned, restart required."
|
||||
$RestartRequired = $true
|
||||
|
||||
|
||||
Write-Log 'All done!'
|
||||
if ( $RestartRequired ) {
|
||||
Write-Log "Restarting computer ..."
|
||||
Restart-Computer -Force
|
||||
}
|
||||
else {
|
||||
Start-Service 'Murano Agent'
|
||||
}
|
21
meta/io.murano/manifest.yaml
Normal file
21
meta/io.murano/manifest.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
Format: 1.0
|
||||
|
||||
Type: Library
|
||||
|
||||
FullName: io.murano
|
||||
|
||||
Name: Core library
|
||||
|
||||
Description: |
|
||||
Core MuranoPL library
|
||||
|
||||
Author: 'murano.io'
|
||||
|
||||
Tags: [MuranoPL]
|
||||
|
||||
Classes:
|
||||
io.murano.Object: Object.yaml
|
||||
io.murano.Environment: Environment.yaml
|
||||
io.murano.Application: Application.yaml
|
||||
|
||||
io.murano.resources.Instance: resources/Instance.yaml
|
@ -1,16 +0,0 @@
|
||||
Format: 1.0
|
||||
Type: Application
|
||||
FullName: io.murano.windows.activeDirectory.ActiveDirectory
|
||||
Name: Active Directory
|
||||
Description: |
|
||||
A domain service hosted in Windows environment by using Active Directory Role.
|
||||
May be clustered by combining a number of secondary domain controllers with one primary
|
||||
Author: 'murano.io'
|
||||
Tags: [Windows, Domain, demo, win2012, microsoft]
|
||||
Classes:
|
||||
io.murano.windows.activeDirectory.ActiveDirectory: ad.yaml
|
||||
io.murano.windows.activeDirectory.Controller: controller.yaml
|
||||
io.murano.windows.activeDirectory.PrimaryController: primary_controller.yaml
|
||||
io.murano.windows.activeDirectory.SecondaryController: secondary_controller.yaml
|
||||
# UI: ui.yaml # default to ui.yaml, will use default if skipped
|
||||
Logo: logo2.png # defaults to logo.png, will use default if skipped
|
@ -1,12 +0,0 @@
|
||||
Format: 1.0
|
||||
Type: Library
|
||||
FullName: io.murano.core
|
||||
Name: Core library
|
||||
Description: |
|
||||
Core MuranoPL library
|
||||
Author: 'murano.io'
|
||||
Tags: [MuranoPL]
|
||||
Classes:
|
||||
io.murano.Object: object.yaml
|
||||
io.murano.Environment: environment.yaml
|
||||
io.murano.Application: application.yaml
|
@ -92,3 +92,7 @@ def main():
|
||||
CONF.command.func()
|
||||
except Exception as e:
|
||||
sys.exit("ERROR: %s" % e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@ -52,7 +52,8 @@ class TaskProcessingEndpoint(object):
|
||||
exc = executor.MuranoDslExecutor(cl, env)
|
||||
obj = exc.load(task['model'])
|
||||
|
||||
obj.type.invoke('deploy', exc, obj, {})
|
||||
if obj is not None:
|
||||
obj.type.invoke('deploy', exc, obj, {})
|
||||
|
||||
s_res = results_serializer.serialize(obj, exc)
|
||||
rpc.api().process_result(s_res)
|
||||
|
@ -122,13 +122,15 @@ class EnvironmentServices(object):
|
||||
|
||||
#preparing data for removal from conductor
|
||||
env = environment.description
|
||||
env['services'] = {}
|
||||
env['deleted'] = True
|
||||
env['Objects'] = None
|
||||
|
||||
#Set X-Auth-Token for conductor
|
||||
env['token'] = token
|
||||
data = {
|
||||
'model': env,
|
||||
'token': token,
|
||||
'tenant_id': environment.tenant_id
|
||||
}
|
||||
|
||||
rpc.engine().handle_task(env)
|
||||
rpc.engine().handle_task(data)
|
||||
|
||||
with unit.begin():
|
||||
unit.delete(environment)
|
||||
|
@ -12,6 +12,7 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import collections
|
||||
import functools
|
||||
import inspect
|
||||
import types
|
||||
@ -216,5 +217,49 @@ class MuranoDslExecutor(object):
|
||||
if not isinstance(data, types.DictionaryType):
|
||||
raise TypeError()
|
||||
self._attribute_store.load(data.get('Attributes') or [])
|
||||
return self._object_store.load(data.get('Objects') or {},
|
||||
None, self._root_context)
|
||||
result = self._object_store.load(data.get('Objects') or {},
|
||||
None, self._root_context)
|
||||
self.cleanup(data)
|
||||
return result
|
||||
|
||||
def cleanup(self, data):
|
||||
objects_copy = data.get('ObjectsCopy')
|
||||
if not objects_copy:
|
||||
return
|
||||
gc_object_store = object_store.ObjectStore(self._class_loader)
|
||||
gc_object_store.load(objects_copy, None, self._root_context)
|
||||
objects_to_clean = []
|
||||
for object_id in self._list_potential_object_ids(objects_copy):
|
||||
if gc_object_store.has(object_id) \
|
||||
and not self._object_store.has(object_id):
|
||||
obj = gc_object_store.get(object_id)
|
||||
objects_to_clean.append(obj)
|
||||
if objects_to_clean:
|
||||
backup = self._object_store
|
||||
try:
|
||||
self._object_store = gc_object_store
|
||||
for obj in objects_to_clean:
|
||||
methods = obj.type.find_method('destroy')
|
||||
for cls, method in methods:
|
||||
try:
|
||||
cls.invoke(method, self, obj, {})
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
self._object_store = backup
|
||||
|
||||
def _list_potential_object_ids(self, data):
|
||||
if isinstance(data, types.DictionaryType):
|
||||
for val in data.values():
|
||||
for res in self._list_potential_object_ids(val):
|
||||
yield res
|
||||
sys_dict = data.get('?')
|
||||
if isinstance(sys_dict, types.DictionaryType) \
|
||||
and sys_dict.get('id') \
|
||||
and sys_dict.get('type'):
|
||||
yield sys_dict['id']
|
||||
elif isinstance(data, collections.Iterable) and not isinstance(
|
||||
data, types.StringTypes):
|
||||
for val in data:
|
||||
for res in self._list_potential_object_ids(val):
|
||||
yield res
|
||||
|
@ -39,12 +39,17 @@ class ObjectStore(object):
|
||||
return self._parent_store.get(object_id)
|
||||
return None
|
||||
|
||||
def has(self, object_id):
|
||||
return object_id in self._store
|
||||
|
||||
def put(self, murano_object):
|
||||
self._store[murano_object.object_id] = murano_object
|
||||
|
||||
def load(self, value, parent, context, defaults=None):
|
||||
#tmp_store = ObjectStore(self._class_loader, self)
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
if '?' not in value or 'type' not in value['?']:
|
||||
raise ValueError()
|
||||
system_key = value['?']
|
||||
|
@ -23,13 +23,19 @@ class ObjRef(object):
|
||||
|
||||
|
||||
def serialize(root_object, executor):
|
||||
serialized_objects = set()
|
||||
tree = _pass1_serialize(root_object, None, serialized_objects)
|
||||
_pass2_serialize(tree, serialized_objects)
|
||||
if root_object is None:
|
||||
tree = None
|
||||
attributes = []
|
||||
else:
|
||||
serialized_objects = set()
|
||||
tree = _pass1_serialize(root_object, None, serialized_objects)
|
||||
_pass2_serialize(tree, serialized_objects)
|
||||
attributes = executor.attribute_store.serialize(serialized_objects)
|
||||
|
||||
return {
|
||||
'Objects': tree,
|
||||
'Attributes': executor.attribute_store.serialize(serialized_objects)
|
||||
'ObjectsCopy': tree,
|
||||
'Attributes': attributes
|
||||
}
|
||||
|
||||
|
||||
|
@ -166,21 +166,25 @@ class HeatStack(murano_object.MuranoObject):
|
||||
|
||||
current_status = self._get_status()
|
||||
if current_status == 'NOT_FOUND':
|
||||
self._heat_client.stacks.create(
|
||||
stack_name=self._name,
|
||||
parameters=self._parameters,
|
||||
template=self._template,
|
||||
disable_rollback=False)
|
||||
if self._template.get('Resources'):
|
||||
self._heat_client.stacks.create(
|
||||
stack_name=self._name,
|
||||
parameters=self._parameters,
|
||||
template=self._template,
|
||||
disable_rollback=False)
|
||||
|
||||
self._wait_state(
|
||||
lambda status: status == 'CREATE_COMPLETE')
|
||||
self._wait_state(
|
||||
lambda status: status == 'CREATE_COMPLETE')
|
||||
else:
|
||||
self._heat_client.stacks.update(
|
||||
stack_id=self._name,
|
||||
parameters=self._parameters,
|
||||
template=self._template)
|
||||
self._wait_state(
|
||||
lambda status: status == 'UPDATE_COMPLETE')
|
||||
if self._template.get('Resources'):
|
||||
self._heat_client.stacks.update(
|
||||
stack_id=self._name,
|
||||
parameters=self._parameters,
|
||||
template=self._template)
|
||||
self._wait_state(
|
||||
lambda status: status == 'UPDATE_COMPLETE')
|
||||
else:
|
||||
self.delete()
|
||||
|
||||
self._applied = True
|
||||
|
||||
@ -191,3 +195,5 @@ class HeatStack(murano_object.MuranoObject):
|
||||
stack_id=self._name)
|
||||
self._wait_state(
|
||||
lambda status: status in ('DELETE_COMPLETE', 'NOT_FOUND'))
|
||||
self._template = {}
|
||||
self._applied = True
|
||||
|
@ -17,6 +17,8 @@ import base64
|
||||
import re
|
||||
import types
|
||||
|
||||
import jsonpatch
|
||||
import jsonpointer
|
||||
import yaql.context
|
||||
|
||||
import muranoapi.common.config as cfg
|
||||
@ -188,6 +190,18 @@ def _pselect(collection, composer):
|
||||
return helpers.parallel_select(collection(), composer)
|
||||
|
||||
|
||||
def _patch(obj, patch):
|
||||
obj = obj()
|
||||
patch = patch()
|
||||
if not isinstance(patch, types.ListType):
|
||||
patch = [patch]
|
||||
patch = jsonpatch.JsonPatch(patch)
|
||||
try:
|
||||
return patch.apply(obj)
|
||||
except jsonpointer.JsonPointerException:
|
||||
return obj
|
||||
|
||||
|
||||
def register(context):
|
||||
context.register_function(
|
||||
lambda json, mappings: _transform_json(json(), mappings()), 'bind')
|
||||
@ -213,3 +227,4 @@ def register(context):
|
||||
context.register_function(_substr, 'substr')
|
||||
context.register_function(_str, 'str')
|
||||
context.register_function(_int, 'int')
|
||||
context.register_function(_patch, 'patch')
|
||||
|
@ -124,7 +124,7 @@ class OpenstackException(Exception):
|
||||
if _FATAL_EXCEPTION_FORMAT_ERRORS:
|
||||
raise
|
||||
else:
|
||||
# at least get the core message out if something happened
|
||||
# at least get the io.murano message out if something happened
|
||||
self._error_string = self.msg_fmt
|
||||
|
||||
def __str__(self):
|
||||
|
@ -18,6 +18,7 @@ iso8601>=0.1.8
|
||||
six>=1.5.2
|
||||
netaddr>=0.7.6
|
||||
PyYAML>=3.1.0
|
||||
jsonpatch>=1.1
|
||||
|
||||
# Note you will need gcc buildtools installed and must
|
||||
# have installed libxml headers for lxml to be successfully
|
||||
|
Loading…
Reference in New Issue
Block a user