From 8fc771e980ab9db196bd4b7052f06ea6fb79f860 Mon Sep 17 00:00:00 2001 From: Igor Yozhikov Date: Tue, 13 Aug 2013 16:27:23 +0400 Subject: [PATCH] Cherry-pick following change-ids from release-0.2. Iec6b3c56d464d26e4f1fc143e6a7804add67a35d I3f2d3a12fcb53759a906fcbae6fae768833d325e I566811521da16055a73c73052ffcd497aaa8e475 I2ee04b6d5aaa26d49243cf7e0b6045026f052625 I329620f3c8aa7e7f1bdd658cbaa8ea20d9aa4ba5 I5ff3d9146b4fbec74d8d65de84d7ab61d869725c Ib38fd52811812170bdd9bf9df90a66f1a2e6c8d9 I64ce3efaec6df2e402ca2acf6a3cf1a6f2bb1909 I66c3659ab0f33772d7a51c8961a37e32c65354c2 I29ce4a6ef165daa0fe60003301a0d807fd1cce42 Ibd2a4f55e2a64d9a992833200a791dbb20c41eca I16133a213ef25a1b374f10fa80cd5a03d1f40753 Ie09f32fcacfe70f436cad71e5749edf94be038ed Iaba6a6bf07ff223e41f705f0f1db5688a5290f5c I64a0474ecfe5ea38393fe681d520a7b6ce00d959 I270b3ce5ef776522a62d9622b36f0d6b50b9cc57 Ic5f6849ea166bb0295f84685b0a2b5c4701f972a I51190cb02255254a888f66404ecdc3dfc5be0386 I0c2180c603cd09e29d4e6c5e592b987e2b447972 Iae1cdbeb7fa3e49c2cb5cac7c92eceffef477e7e I6c643f58aada0a8525711bc452d0c581625f3d26 I9c4f999b1b3006b8ae5f18a030d5b30c7e85e03b I32eaad36edcb889b448c45ba36f4e97f7c87d1e5 I8c91c40a922690b475aac1c0a3b2c0c28274b130 I574fd1dbeea58dbf41f77d295dc03c23d2feaf96 Change-Id: I0ffb3c38c0c1b3aafa8617364e22036c47aaef76 --- data/init.ps1 | 13 +- .../SqlServerCluster/FailoverCluster.template | 10 - data/templates/agent/scripts/DeployWebApp.ps1 | 208 +++++++++--------- .../agent/scripts/ImportCoreFunctions.ps1 | 5 +- .../Install-RoleSecondaryDomainController.ps1 | 2 +- data/templates/agent/scripts/Join-Domain.ps1 | 2 + data/templates/cf/Windows.template | 20 +- data/workflows/AD.xml | 22 +- data/workflows/AspNetApps.xml | 18 +- data/workflows/ExternalAD.xml.example | 2 +- data/workflows/Images.xml | 29 --- data/workflows/MsSqlCluster.xml | 20 +- data/workflows/MsSqlServer.xml | 20 +- doc/source/index.rst | 25 ++- etc/conductor.conf | 25 ++- muranoconductor/app.py | 10 +- muranoconductor/cloud_formation.py | 4 +- muranoconductor/commands/cloud_formation.py | 63 +++--- muranoconductor/config.py | 13 ++ muranoconductor/windows_agent.py | 8 +- requirements.txt | 5 +- setup-centos.sh | 9 +- setup.py | 2 +- setup.sh | 27 +-- 24 files changed, 289 insertions(+), 273 deletions(-) delete mode 100644 data/workflows/Images.xml diff --git a/data/init.ps1 b/data/init.ps1 index 790b65e..b522123 100644 --- a/data/init.ps1 +++ b/data/init.ps1 @@ -10,6 +10,16 @@ $MuranoFileShare = '\\%MURANO_SERVER_ADDRESS%\share' $RestartRequired = $false Import-Module CoreFunctions +Initialize-Logger 'CloudBase-Init' 'C:\Murano\PowerShell.log' + +$ErrorActionPreference = 'Stop' + +trap { + Write-LogError '' + Write-LogError $_ -EntireObject + Write-LogError '' + exit 1 +} Write-Log "Updating Murano Windows Agent." Stop-Service "Murano Agent" @@ -25,7 +35,8 @@ Write-Log "Adding environment variable 'MuranoFileShare' = '$MuranoFileShare' .. Write-Log "Environment variable added." Write-Log "Renaming computer to '$NewComputerName' ..." -Rename-Computer -NewName $NewComputerName | Out-Null +$null = Rename-Computer -NewName $NewComputerName -Force + Write-Log "New name assigned, restart required." $RestartRequired = $true diff --git a/data/templates/agent/SqlServerCluster/FailoverCluster.template b/data/templates/agent/SqlServerCluster/FailoverCluster.template index b30c9ac..cf13598 100644 --- a/data/templates/agent/SqlServerCluster/FailoverCluster.template +++ b/data/templates/agent/SqlServerCluster/FailoverCluster.template @@ -15,16 +15,6 @@ "UserPassword": "$domainAdminAccountPassword", "StaticAddress": "$clusterIP" } - }, - { - "Name": "New-FailoverClusterSharedFolder", - "Arguments": { - "ClusterName": "$clusterName", - "UserName": "$domainAdminAccountName", - "UserPassword": "$domainAdminAccountPassword", - "ShareServer": "$shareServer", - "DomainName": "$domainName" - } } ], "RebootOnCompletion": 0 diff --git a/data/templates/agent/scripts/DeployWebApp.ps1 b/data/templates/agent/scripts/DeployWebApp.ps1 index 8c4ca69..5dd90f4 100644 --- a/data/templates/agent/scripts/DeployWebApp.ps1 +++ b/data/templates/agent/scripts/DeployWebApp.ps1 @@ -10,13 +10,13 @@ Function Register-WebApp { http://www.iis.net/learn/manage/powershell/powershell-snap-in-creating-web-sites-web-applications-virtual-directories-and-application-pools #> - param ( - [String] $Source, - [String] $Path = "C:\inetpub\wwwroot", - [String] $Name = "", - [String] $Username = "", - [String] $Password = "" - ) + param ( + [String] $Source, + [String] $Path = "C:\inetpub\wwwroot", + [String] $Name = "", + [String] $Username = "", + [String] $Password = "" + ) begin { Show-InvocationInfo $MyInvocation } @@ -28,70 +28,74 @@ http://www.iis.net/learn/manage/powershell/powershell-snap-in-creating-web-sites &$TrapHandler } - Import-Module WebAdministration - - if ($Name -eq "") { - $Name = @([IO.Path]::GetDirectoryName($Source) -split '\\')[-1] - if ($Name -eq "wwwroot") { - throw("Application pool name couldn't be 'wwwroot'.") - } - } - else { - $Path = [IO.Path]::Combine($Path, $Name) - } + Import-Module WebAdministration - Copy-Item -Path $Source -Destination $Path -Recurse -Force - + if ($Name -eq "") { + $Name = @([IO.Path]::GetDirectoryName($Source) -split '\\')[-1] + if ($Name -eq "wwwroot") { + throw("Application pool name couldn't be 'wwwroot'.") + } + } + else { + $Path = [IO.Path]::Combine($Path, $Name) + } - # Create new application pool - $AppPool = New-WebAppPool -Name $Name -Force - #$AppPool = Get-Item "IIS:\AppPools\$Name" - $AppPool.managedRuntimeVersion = 'v4.0' - $AppPool.managedPipelineMode = 'Classic' - $AppPool.processModel.loadUserProfile = $true - $AppPool.processModel.logonType = 'LogonBatch' - - #Set Identity type - if ($Username -eq "") { - $AppPool.processModel.identityType = 'ApplicationPoolIdentity' - } - else { - $AppPool.processModel.identityType = 'SpecificUser' - $AppPool.processModel.userName = $Username - $AppPool.processModel.password = $Password - $AppPool | Set-Item - } + $null = Copy-Item -Path $Source -Destination $Path -Recurse -Force + + # Create new application pool + $AppPool = New-WebAppPool -Name $Name -Force + #$AppPool = Get-Item "IIS:\AppPools\$Name" + $AppPool.managedRuntimeVersion = 'v4.0' + $AppPool.managedPipelineMode = 'Classic' + $AppPool.processModel.loadUserProfile = $true + $AppPool.processModel.logonType = 'LogonBatch' + + #Set Identity type + if ($Username -eq "") { + $AppPool.processModel.identityType = 'ApplicationPoolIdentity' + } + else { + $AppPool.processModel.identityType = 'SpecificUser' + $AppPool.processModel.userName = $Username + $AppPool.processModel.password = $Password + $null = $AppPool | Set-Item + } - # Create Website - $WebSite = New-WebSite -Name $Name -Port 80 -HostHeader $Name -PhysicalPath $Path -Force - #$WebSite = Get-Item "IIS:\Sites\$Name" - - # Set the Application Pool - Set-ItemProperty "IIS:\Sites\$Name" 'ApplicationPool' $Name - - #Turn on Directory Browsing - #Set-WebConfigurationProperty -Filter '/system.webServer/directoryBrowse' -Name 'enabled' -Value $true -PSPath "IIS:\Sites\$Name" - - # Update Authentication - #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/AnonymousAuthentication' -Name 'enabled' -Value $true -Location $name - #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/windowsAuthentication' -Name 'enabled' -Value $false -Location $Name - #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/basicAuthentication' -Name 'enabled' -Value $false -Location $Name - - $WebSite.Start() + # Create Website + $WebSite = New-WebSite -Name $Name -Port 80 -HostHeader $Name -PhysicalPath $Path -Force + #$WebSite = Get-Item "IIS:\Sites\$Name" - Add-Content -Path "C:\Windows\System32\Drivers\etc\hosts" -Value "127.0.0.1 $Name" - } + # Set the Application Pool + $null = Set-ItemProperty "IIS:\Sites\$Name" 'ApplicationPool' $Name + + #Turn on Directory Browsing + #Set-WebConfigurationProperty -Filter '/system.webServer/directoryBrowse' -Name 'enabled' -Value $true -PSPath "IIS:\Sites\$Name" + + # Update Authentication + #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/AnonymousAuthentication' -Name 'enabled' -Value $true -Location $name + #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/windowsAuthentication' -Name 'enabled' -Value $false -Location $Name + #Set-WebConfigurationProperty -Filter '/system.WebServer/security/authentication/basicAuthentication' -Name 'enabled' -Value $false -Location $Name + + $null = $WebSite.Start() + + $null = Add-Content -Path "C:\Windows\System32\Drivers\etc\hosts" -Value "127.0.0.1 $Name" + + # Remove standard IIS 'Hello World' application from localhost:80 + $null = Get-WebBinding 'Default Web Site' | Remove-WebBinding + # Add new application on http://localhost:80 + $null = New-WebBinding -Name "$Name" -IP "*" -Port 80 -Protocol http + } } Function Deploy-WebAppFromGit { - param ( - [String] $URL, - [String] $TempPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName()), - [String] $OutputPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName()) - ) + param ( + [String] $URL, + [String] $TempPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName()), + [String] $OutputPath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName()) + ) begin { Show-InvocationInfo $MyInvocation } @@ -103,46 +107,46 @@ Function Deploy-WebAppFromGit { &$TrapHandler } - Write-Log "TempPath = '$TempPath'" - Write-Log "OutputPath = '$OutputPath'" - - - # Fetch web application - #---------------------- - Write-Log "Fetching sources from Git ..." - - $null = New-Item -Path $TempPath -ItemType Container - Exec -FilePath 'git.exe' -ArgumentList @('clone', $URL) -WorkingDir $TempPath -RedirectStreams - - $Path = @(Get-ChildItem $TempPath)[0].FullName - #---------------------- - - - # Build web application - #---------------------- - Write-Log "Building sources ..." - - $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" - - $null = New-Item -Path $OutputPath -ItemType Container - - $SlnFiles = @(Get-ChildItem -Path $Path -Filter *.sln -Recurse) + Write-Log "TempPath = '$TempPath'" + Write-Log "OutputPath = '$OutputPath'" - # Start new processs with additional env variables: - #* VisualStudioVersion = "10.0" - #* EnableNuGetPackageRestore = "true" - Exec -FilePath $msbuild ` - -ArgumentList @($SlnFiles[0].FullName, "/p:OutputPath=$OutputPath") ` - -Environment @{'VisualStudioVersion' = '10.0'; 'EnableNuGetPackageRestore' = 'true'} ` - -RedirectStreams - - $AppFolder = @(Get-ChildItem ([IO.Path]::Combine($OutputPath, '_PublishedWebsites')))[0] - #---------------------- - - - # Install web application - #------------------------ - Register-WebApp -Source $AppFolder.FullName -Name $AppFolder.Name - #------------------------ - } + + # Fetch web application + #---------------------- + Write-Log "Fetching sources from Git ..." + + $null = New-Item -Path $TempPath -ItemType Container + $null = Exec -FilePath 'git.exe' -ArgumentList @('clone', $URL) -WorkingDir $TempPath -RedirectStreams + + $Path = @(Get-ChildItem $TempPath)[0].FullName + #---------------------- + + + # Build web application + #---------------------- + Write-Log "Building sources ..." + + $msbuild = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe" + + $null = New-Item -Path $OutputPath -ItemType Container + + $SlnFiles = @(Get-ChildItem -Path $Path -Filter *.sln -Recurse) + + # Start new processs with additional env variables: + #* VisualStudioVersion = "10.0" + #* EnableNuGetPackageRestore = "true" + $null = Exec -FilePath $msbuild ` + -ArgumentList @($SlnFiles[0].FullName, "/p:OutputPath=$OutputPath") ` + -Environment @{'VisualStudioVersion' = '10.0'; 'EnableNuGetPackageRestore' = 'true'} ` + -RedirectStreams + + $AppFolder = @(Get-ChildItem ([IO.Path]::Combine($OutputPath, '_PublishedWebsites')))[0] + #---------------------- + + + # Install web application + #------------------------ + $null = Register-WebApp -Source $AppFolder.FullName -Name $AppFolder.Name + #------------------------ + } } diff --git a/data/templates/agent/scripts/ImportCoreFunctions.ps1 b/data/templates/agent/scripts/ImportCoreFunctions.ps1 index 33ee499..85e6434 100644 --- a/data/templates/agent/scripts/ImportCoreFunctions.ps1 +++ b/data/templates/agent/scripts/ImportCoreFunctions.ps1 @@ -1,4 +1,6 @@ + Import-Module CoreFunctions -Force +Initialize-Logger 'MuranoAgent' 'C:\Murano\PowerShell.log' function Show-InvocationInfo { @@ -27,7 +29,8 @@ function Show-InvocationInfo { $TrapHandler = { - Write-LogError @("", $_) -EntireObject + Write-LogError "" + Write-LogError $_ -EntireObject Write-LogError "" break } diff --git a/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 b/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 index 47e5980..be9258e 100644 --- a/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 +++ b/data/templates/agent/scripts/Install-RoleSecondaryDomainController.ps1 @@ -1,4 +1,4 @@ - + trap { &$TrapHandler } diff --git a/data/templates/agent/scripts/Join-Domain.ps1 b/data/templates/agent/scripts/Join-Domain.ps1 index 025555d..4716709 100644 --- a/data/templates/agent/scripts/Join-Domain.ps1 +++ b/data/templates/agent/scripts/Join-Domain.ps1 @@ -49,6 +49,8 @@ Requires 'CoreFunctions' module. 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 <# diff --git a/data/templates/cf/Windows.template b/data/templates/cf/Windows.template index f562de3..d42d425 100644 --- a/data/templates/cf/Windows.template +++ b/data/templates/cf/Windows.template @@ -6,20 +6,6 @@ "Description" : "Key Pair name for Load Balancer", "Type" : "String", "Default" : "murano-lb-key" - }, - "InstanceType" : { - "Description" : "Amazon EC2 instance type", - "Type" : "String", - "Default" : "m1.medium" - }, - "ImageName" : { - "Description" : "Image name", - "Type" : "String" - }, - "AvailabilityZone" : { - "Description" : "The Availability Zone in which to launch the instance.", - "Type" : "String", - "Default" : "nova" } }, @@ -27,9 +13,9 @@ "$instanceName": { "Type" : "AWS::EC2::Instance", "Properties": { - "InstanceType" : { "Ref" : "InstanceType" }, - "ImageId" : { "Ref" : "ImageName" }, - "AvailabilityZone" : { "Ref" : "AvailabilityZone" }, + "InstanceType" : "$instanceType", + "ImageId" : "$imageName", + "AvailabilityZone" : "$availabilityZone", "UserData": "$userData" } } diff --git a/data/workflows/AD.xml b/data/workflows/AD.xml index da7fa7c..b961a84 100644 --- a/data/workflows/AD.xml +++ b/data/workflows/AD.xml @@ -4,9 +4,10 @@ @@ -23,13 +24,9 @@ - + + Unable to set admin password on unit ) due to + + - Unable to create Secondary Domain Controller on unit ) due to ( + - + + - - - - Unable to set admin password on unit ) due to - - - - - \ No newline at end of file diff --git a/data/workflows/MsSqlCluster.xml b/data/workflows/MsSqlCluster.xml index b1b7da5..47acb35 100644 --- a/data/workflows/MsSqlCluster.xml +++ b/data/workflows/MsSqlCluster.xml @@ -5,9 +5,10 @@ @@ -24,16 +25,11 @@ + - - - - @@ -85,11 +81,11 @@ - + ( - + @@ -184,7 +180,7 @@ - diff --git a/data/workflows/MsSqlServer.xml b/data/workflows/MsSqlServer.xml index 01cee9e..484c3e6 100644 --- a/data/workflows/MsSqlServer.xml +++ b/data/workflows/MsSqlServer.xml @@ -4,9 +4,10 @@ @@ -23,18 +24,13 @@ + - - - - + Instance ) created @@ -72,11 +68,11 @@ - + ( - + diff --git a/doc/source/index.rst b/doc/source/index.rst index 2b551cb..6cd8e02 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -61,12 +61,33 @@ Configure # "data" must be subdirectory to this. data_dir = /etc/murano-conductor - [heat] - + [keystone] # URL of OpenStack KeyStone service REST API. # Typically only hostname (or IP) needs to be changed auth_url = http://localhost:5000/v2.0 + # Keystone SSL parameters + # Optional CA cert file to use in SSL connections + ca_file = + # Optional PEM-formatted certificate chain file + cert_file = + # Optional PEM-formatted file that contains the private key + key_file = + # If set then the server's certificate will not be verified + insecure = False + + [heat] + # Heat SSL parameters + # Optional CA cert file to use in SSL connections + ca_file = + # Optional PEM-formatted certificate chain file + cert_file = + # Optional PEM-formatted file that contains the private key + key_file = + # If set then the server's certificate will not be verified + insecure = False + # Valid endpoint types: publicURL (default), internalURL, adminURL + endpoint_type = publicURL [rabbitmq] # Connection parameters to RabbitMQ service diff --git a/etc/conductor.conf b/etc/conductor.conf index 778b356..1af8b22 100644 --- a/etc/conductor.conf +++ b/etc/conductor.conf @@ -14,12 +14,33 @@ data_dir = /etc/murano-conductor # Maximum number of environments that can be processed simultaneously max_environments = 20 -[heat] - +[keystone] # URL of OpenStack KeyStone service REST API. # Typically only hostname (or IP) needs to be changed auth_url = http://localhost:5000/v2.0 +# Keystone SSL parameters +# Optional CA cert file to use in SSL connections +ca_file = +# Optional PEM-formatted certificate chain file +cert_file = +# Optional PEM-formatted file that contains the private key +key_file = +# If set then the server's certificate will not be verified +insecure = False + +[heat] +# Heat SSL parameters +# Optional CA cert file to use in SSL connections +ca_file = +# Optional PEM-formatted certificate chain file +cert_file = +# Optional PEM-formatted file that contains the private key +key_file = +# If set then the server's certificate will not be verified +insecure = False +# Valid endpoint types: publicURL (default), internalURL, adminURL +endpoint_type = publicURL [rabbitmq] # Connection parameters to RabbitMQ service diff --git a/muranoconductor/app.py b/muranoconductor/app.py index ac8f17f..c25b6c0 100644 --- a/muranoconductor/app.py +++ b/muranoconductor/app.py @@ -26,6 +26,7 @@ from openstack.common import log as logging from config import Config import reporting from muranocommon.messaging import MqClient, Message +from muranocommon.helpers.token_sanitizer import TokenSanitizer from muranoconductor import config as cfg import windows_agent @@ -34,6 +35,11 @@ import cloud_formation log = logging.getLogger(__name__) +def secure_task(task): + sanitizer = TokenSanitizer() + return sanitizer.sanitize(task) + + class ConductorWorkflowService(service.Service): def __init__(self): super(ConductorWorkflowService, self).__init__() @@ -80,7 +86,7 @@ class ConductorWorkflowService(service.Service): with self.create_rmq_client() as mq: try: log.info('Starting processing task {0}: {1}'.format( - message_id, anyjson.dumps(task))) + message_id, anyjson.dumps(secure_task(task)))) reporter = reporting.Reporter(mq, message_id, task['id']) config = Config() @@ -135,7 +141,7 @@ class ConductorWorkflowService(service.Service): mq.send(message=result_msg, key='task-results') message.ack() log.info('Finished processing task {0}. Result = {1}'.format( - message_id, anyjson.dumps(task))) + message_id, anyjson.dumps(secure_task(task)))) def cleanup(self, model, reporter): try: diff --git a/muranoconductor/cloud_formation.py b/muranoconductor/cloud_formation.py index 7b52241..80b8d34 100644 --- a/muranoconductor/cloud_formation.py +++ b/muranoconductor/cloud_formation.py @@ -57,8 +57,8 @@ def update_cf_stack(engine, context, body, template, result=None, error=None, command_dispatcher.execute( name='cf', command='CreateOrUpdate', template=template, - mappings=kwargs.get('mappings', {}), - arguments=kwargs.get('arguments', {}), + mappings=(kwargs.get('mappings') or {}), + arguments=(kwargs.get('arguments') or {}), callback=callback) diff --git a/muranoconductor/commands/cloud_formation.py b/muranoconductor/commands/cloud_formation.py index bd7e829..48f5170 100644 --- a/muranoconductor/commands/cloud_formation.py +++ b/muranoconductor/commands/cloud_formation.py @@ -12,13 +12,10 @@ # implied. # See the License for the specific language governing permissions and # limitations under the License. -import sys import anyjson import eventlet -from muranoconductor.reporting import ReportedException import types -import jsonpath from muranoconductor.openstack.common import log as logging import muranoconductor.helpers @@ -37,24 +34,36 @@ class HeatExecutor(CommandBase): self._delete_pending_list = [] self._stack = stack self._reporter = reporter - settings = muranoconductor.config.CONF.heat - client = ksclient.Client(endpoint=settings.auth_url) - auth_data = client.tokens.authenticate( - tenant_id=tenant_id, - token=token) + keystone_settings = muranoconductor.config.CONF.keystone + heat_settings = muranoconductor.config.CONF.heat - scoped_token = auth_data.id + client = ksclient.Client( + endpoint=keystone_settings.auth_url, + cacert=keystone_settings.ca_file or None, + cert=keystone_settings.cert_file or None, + key=keystone_settings.key_file or None, + insecure=keystone_settings.insecure) - heat_url = jsonpath.jsonpath( - auth_data.serviceCatalog, - "$[?(@.name == 'heat')].endpoints[0].publicURL")[0] + if not client.authenticate( + auth_url=keystone_settings.auth_url, + tenant_id=tenant_id, + token=token): + raise heatclient.exc.HTTPUnauthorized() + + heat_url = client.service_catalog.url_for( + service_type='orchestration', + endpoint_type=heat_settings.endpoint_type) self._heat_client = Client( '1', heat_url, token_only=True, - token=scoped_token) + token=client.auth_token, + ca_file=heat_settings.ca_file or None, + cert_file=heat_settings.cert_file or None, + key_file=heat_settings.key_file or None, + insecure=heat_settings.insecure) def execute(self, command, callback, **kwargs): log.debug('Got command {0} on stack {1}'.format(command, self._stack)) @@ -93,6 +102,8 @@ class HeatExecutor(CommandBase): self._delete_pending_list) > 0 def execute_pending(self): + # wait for the stack not to be IN_PROGRESS + self._wait_state(lambda status: True) r1 = self._execute_pending_updates() r2 = self._execute_pending_deletes() return r1 or r2 @@ -126,7 +137,8 @@ class HeatExecutor(CommandBase): log.debug( 'Waiting for the stack {0} to be update'.format( self._stack)) - outs = self._wait_state('UPDATE_COMPLETE') + outs = self._wait_state( + lambda status: status == 'UPDATE_COMPLETE') log.info('Stack {0} updated'.format(self._stack)) else: self._heat_client.stacks.create( @@ -137,7 +149,8 @@ class HeatExecutor(CommandBase): log.debug('Waiting for the stack {0} to be create'.format( self._stack)) - outs = self._wait_state('CREATE_COMPLETE') + outs = self._wait_state( + lambda status: status == 'CREATE_COMPLETE') log.info('Stack {0} created'.format(self._stack)) pending_list = self._update_pending_list @@ -163,7 +176,8 @@ class HeatExecutor(CommandBase): stack_id=self._stack) log.debug( 'Waiting for the stack {0} to be deleted'.format(self._stack)) - self._wait_state(['DELETE_COMPLETE', '']) + self._wait_state( + lambda status: status in ('DELETE_COMPLETE', 'NOT_FOUND')) log.info('Stack {0} deleted'.format(self._stack)) except Exception as ex: log.exception(ex) @@ -186,15 +200,10 @@ class HeatExecutor(CommandBase): except heatclient.exc.HTTPNotFound: return {}, {} - def _wait_state(self, state): + def _wait_state(self, status_func): tries = 4 delay = 1 while tries > 0: - if isinstance(state, types.ListType): - states = state - else: - states = [state] - while True: try: stack_info = self._heat_client.stacks.get( @@ -204,19 +213,21 @@ class HeatExecutor(CommandBase): delay = 1 except heatclient.exc.HTTPNotFound: stack_info = None - status = '' + status = 'NOT_FOUND' except Exception: tries -= 1 delay *= 2 + if not tries: + raise eventlet.sleep(delay) break if 'IN_PROGRESS' in status: - eventlet.sleep(1) + eventlet.sleep(2) continue - if status not in states: + if not status_func(status): raise EnvironmentError( - "Unexpected state {0}".format(status)) + "Unexpected stack state {0}".format(status)) try: return dict([(t['output_key'], t['output_value']) diff --git a/muranoconductor/config.py b/muranoconductor/config.py index 70c12e8..a40727d 100644 --- a/muranoconductor/config.py +++ b/muranoconductor/config.py @@ -45,13 +45,26 @@ rabbit_opts = [ ] heat_opts = [ + cfg.BoolOpt('insecure', default=False), + cfg.StrOpt('ca_file'), + cfg.StrOpt('cert_file'), + cfg.StrOpt('key_file'), + cfg.StrOpt('endpoint_type', default='publicURL') +] + +keystone_opts = [ cfg.StrOpt('auth_url'), + cfg.BoolOpt('insecure', default=False), + cfg.StrOpt('ca_file'), + cfg.StrOpt('cert_file'), + cfg.StrOpt('key_file') ] CONF = cfg.CONF CONF.register_opts(paste_deploy_opts, group='paste_deploy') CONF.register_opts(rabbit_opts, group='rabbitmq') CONF.register_opts(heat_opts, group='heat') +CONF.register_opts(keystone_opts, group='keystone') CONF.register_opt(cfg.StrOpt('file_server')) CONF.register_cli_opt(cfg.StrOpt('data_dir', default='./')) diff --git a/muranoconductor/windows_agent.py b/muranoconductor/windows_agent.py index 01986cb..7459eeb 100644 --- a/muranoconductor/windows_agent.py +++ b/muranoconductor/windows_agent.py @@ -12,6 +12,7 @@ # implied. # See the License for the specific language governing permissions and # limitations under the License. +import os.path from muranoconductor.commands.windows_agent import AgentTimeoutException from muranoconductor.commands.windows_agent import UnhandledAgentException @@ -22,10 +23,13 @@ from openstack.common import log as logging log = logging.getLogger(__name__) -def send_command(engine, context, body, template, service, unit, mappings=None, - result=None, error=None, timeout=None, **kwargs): +def send_command(engine, context, body, template, service, unit, + mappings=None, result=None, error=None, timeout=None, + osVersion=None, **kwargs): if not mappings: mappings = {} + if osVersion: + template = os.path.join(osVersion, template) command_dispatcher = context['/commandDispatcher'] if timeout: timeout = int(timeout) diff --git a/requirements.txt b/requirements.txt index 10718ca..47b02b8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,13 +1,14 @@ +pbr>=0.5.21,<1.0 anyjson eventlet>=0.9.12 jsonpath Paste PasteDeploy iso8601>=0.1.4 -python-heatclient==0.2.1 +python-heatclient>=0.2.4 jsonschema==2.0.0 netaddr oslo.config deep -http://github.com/sergmelikyan/murano-common/releases/download/0.2.1/muranocommon-0.2.1.tar.gz#egg=muranocommon-0.2.1 +http://tarballs.openstack.org/murano-common/murano-common-release-0.2.tar.gz#egg=muranocommon-dev diff --git a/setup-centos.sh b/setup-centos.sh index 372cbd9..0192302 100644 --- a/setup-centos.sh +++ b/setup-centos.sh @@ -17,7 +17,7 @@ LOGLVL=1 SERVICE_CONTENT_DIRECTORY=`cd $(dirname "$0") && pwd` -PREREQ_PKGS="upstart wget git make python-pip python-devel mysql-connector-python" +PREREQ_PKGS="upstart wget git make python-pip python-devel mysql-connector-python libffi-devel" PIPAPPS="pip python-pip pip-python" PIPCMD="" SERVICE_SRV_NAME="murano-conductor" @@ -152,8 +152,7 @@ CLONE_FROM_GIT=$1 fi # making sample configs log "Making sample configuration files at \"$ETC_CFG_DIR\"" - #for file in `ls $GIT_CLONE_DIR/$SERVICE_SRV_NAME/etc` - for file in `ls $SERVICE_CONTENT_DIRECTORY/etc` + for file in $(ls $SERVICE_CONTENT_DIRECTORY/etc) do cp -f "$SERVICE_CONTENT_DIRECTORY/etc/$file" "$ETC_CFG_DIR/$file.sample" done @@ -166,7 +165,7 @@ CLONE_FROM_GIT=$1 get_service_exec_path() { if [ -z "$SERVICE_EXEC_PATH" ]; then - SERVICE_EXEC_PATH=`which conductor` + SERVICE_EXEC_PATH=$(which muranoconductor) if [ $? -ne 0 ]; then log "Can't find \"conductor ($SERVICE_SRV_NAME)\", please install the \"$SERVICE_SRV_NAME\" by running \"$(basename "$0") install\" or set variable SERVICE_EXEC_PATH=/path/to/daemon before running setup script, exiting!" exit 1 @@ -206,7 +205,7 @@ uninst() # Uninstall trough pip find_pip # looking up for python package installed - PYPKG=`echo $SERVICE_SRV_NAME | sed -e 's/murano-//'` + PYPKG=$SERVICE_SRV_NAME _pkg=$($PIPCMD freeze | grep $PYPKG) if [ $? -eq 0 ]; then log "Removing package \"$PYPKG\" with pip" diff --git a/setup.py b/setup.py index d0f89e4..14f18d1 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ import setuptools setuptools.setup( setup_requires=[ 'd2to1>=0.2.10,<0.3', - 'pbr>=0.5,<0.6' + 'pbr>=0.5.21,<1.0' ], d2to1=True, pbr=True diff --git a/setup.sh b/setup.sh index b5b6c3c..09f76fe 100644 --- a/setup.sh +++ b/setup.sh @@ -17,7 +17,7 @@ LOGLVL=1 SERVICE_CONTENT_DIRECTORY=`cd $(dirname "$0") && pwd` -PREREQ_PKGS="upstart wget git make python-pip python-dev python-mysqldb libxml2-dev libxslt-dev" +PREREQ_PKGS="upstart wget git make python-pip python-dev python-mysqldb libxml2-dev libxslt-dev libffi-dev" SERVICE_SRV_NAME="murano-conductor" GIT_CLONE_DIR=`echo $SERVICE_CONTENT_DIRECTORY | sed -e "s/$SERVICE_SRV_NAME//"` ETC_CFG_DIR="/etc/$SERVICE_SRV_NAME" @@ -72,7 +72,6 @@ CLONE_FROM_GIT=$1 do in_sys_pkg $PKG done - # If clone from git set if [ ! -z $CLONE_FROM_GIT ]; then # Preparing clone root directory @@ -92,20 +91,13 @@ CLONE_FROM_GIT=$1 # Setupping... log "Running setup.py" - #MRN_CND_SPY=$GIT_CLONE_DIR/$SERVICE_SRV_NAME/setup.py MRN_CND_SPY=$SERVICE_CONTENT_DIRECTORY/setup.py if [ -e $MRN_CND_SPY ];then chmod +x $MRN_CND_SPY - log "$MRN_CND_SPY output:_____________________________________________________________" - #cd $GIT_CLONE_DIR/$SERVICE_SRV_NAME && $MRN_CND_SPY install - #if [ $? -ne 0 ]; then - # log "\"$MRN_CND_SPY\" python setup FAILS, exiting!" - # exit 1 - #fi + log "$MRN_CND_SPY output:_____________________________________________________________" ## Setup through pip # Creating tarball - #cd $GIT_CLONE_DIR/$SERVICE_SRV_NAME && $MRN_CND_SPY sdist - rm -rf $SERVICE_CONTENT_DIRECTORY/*.egg-info + rm -rf $SERVICE_CONTENT_DIRECTORY/*.egg-info cd $SERVICE_CONTENT_DIRECTORY && python $MRN_CND_SPY egg_info if [ $? -ne 0 ];then log "\"$MRN_CND_SPY\" egg info creation FAILS, exiting!!!" @@ -118,8 +110,6 @@ CLONE_FROM_GIT=$1 exit 1 fi # Running tarball install - #TRBL_FILE=$(basename `ls $GIT_CLONE_DIR/$SERVICE_SRV_NAME/dist/*.tar.gz`) - #pip install $GIT_CLONE_DIR/$SERVICE_SRV_NAME/dist/$TRBL_FILE TRBL_FILE=$(basename `ls $SERVICE_CONTENT_DIRECTORY/dist/*.tar.gz`) pip install $SERVICE_CONTENT_DIRECTORY/dist/$TRBL_FILE if [ $? -ne 0 ];then @@ -140,15 +130,12 @@ CLONE_FROM_GIT=$1 fi # making sample configs log "Making sample configuration files at \"$ETC_CFG_DIR\"" - #for file in `ls $GIT_CLONE_DIR/$SERVICE_SRV_NAME/etc` - for file in `ls $SERVICE_CONTENT_DIRECTORY/etc` + for file in $(ls $SERVICE_CONTENT_DIRECTORY/etc) do - #cp -f "$GIT_CLONE_DIR/$SERVICE_SRV_NAME/etc/$file" "$ETC_CFG_DIR/$file.sample" cp -f "$SERVICE_CONTENT_DIRECTORY/etc/$file" "$ETC_CFG_DIR/$file.sample" done # making templates data log "Making templates directory" - #cp -f -R "$GIT_CLONE_DIR/$SERVICE_SRV_NAME/data" "$ETC_CFG_DIR/" cp -f -R "$SERVICE_CONTENT_DIRECTORY/data" "$ETC_CFG_DIR/" } @@ -156,7 +143,7 @@ CLONE_FROM_GIT=$1 get_service_exec_path() { if [ -z "$SERVICE_EXEC_PATH" ]; then - SERVICE_EXEC_PATH=`which muranoconductor` + SERVICE_EXEC_PATH=$(which muranoconductor) if [ $? -ne 0 ]; then log "Can't find \"conductor ($SERVICE_SRV_NAME)\", please install the \"$SERVICE_SRV_NAME\" by running \"$(basename "$0") install\" or set variable SERVICE_EXEC_PATH=/path/to/daemon before running setup script, exiting!" exit 1 @@ -199,11 +186,9 @@ purgeinit() # uninstall uninst() { - #rm -f $SERVICE_EXEC_PATH - #rm -rf $SERVICE_CONTENT_DIRECTORY # Uninstall trough pip # looking up for python package installed - PYPKG=`echo $SERVICE_SRV_NAME | sed -e 's/murano-//'` + PYPKG=$SERVICE_SRV_NAME pip freeze | grep $PYPKG if [ $? -eq 0 ]; then log "Removing package \"$PYPKG\" with pip"