Initial commit

This commit is contained in:
efedorova 2013-10-07 15:30:11 +04:00
parent 87ce33fcf7
commit 3c2b1b65f1
58 changed files with 6780 additions and 0 deletions

View File

@ -0,0 +1,12 @@
{
"Scripts": [
"Get-DnsListeningIpAddress.ps1"
],
"Commands": [
{
"Name": "Get-DnsListeningIpAddress",
"Arguments": {}
}
],
"RebootOnCompletion": 0
}

View File

@ -0,0 +1,16 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"Install-RolePrimaryDomainController.ps1"
],
"Commands": [
{
"Name": "Install-RolePrimaryDomainController",
"Arguments": {
"DomainName": "$domain",
"SafeModePassword": "$recoveryPassword"
}
}
],
"RebootOnCompletion": 1
}

View File

@ -0,0 +1,18 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"Install-RoleSecondaryDomainController.ps1"
],
"Commands": [
{
"Name": "Install-RoleSecondaryDomainController",
"Arguments": {
"DomainName": "$domain",
"UserName": "Administrator",
"Password": "$domainPassword",
"SafeModePassword": "$recoveryPassword"
}
}
],
"RebootOnCompletion": 1
}

View File

@ -0,0 +1,7 @@
{
"Scripts": [
],
"Commands": [
],
"RebootOnCompletion": 0
}

View File

@ -0,0 +1,15 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"DeployWebApp.ps1"
],
"Commands": [
{
"Name": "Deploy-WebAppFromGit",
"Arguments": {
"URL": "$repository"
}
}
],
"RebootOnCompletion": 0
}

View File

@ -0,0 +1,22 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"CopyPrerequisites.ps1",
"InstallIIS.ps1"
],
"Commands": [
{
"Name": "Copy-Prerequisites",
"Arguments": {
"Destination": "C:\\Prerequisites"
}
},
{
"Name": "Install-WebServer",
"Arguments": {
"PrerequisitesPath": "C:\\Prerequisites"
}
}
],
"RebootOnCompletion": 0
}

View File

@ -0,0 +1,24 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"OptionParser.ps1",
"SQLServerOptionParsers.ps1",
"SQLServerInstaller.ps1",
"Install-SQLServer.ps1",
"Alter-FirewallRulesForSQL.ps1"
],
"Commands": [
{
"Name": "Install-SQLServer",
"Arguments": {
"SAPassword": "$saPassword",
"MixedModeAuth": "$mixedModeAuth"
}
},
{
"Name": "Enable-SQLExternalAccess",
"Arguments": {}
}
],
"RebootOnCompletion": 0
}

View File

@ -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
}

View File

@ -0,0 +1,5 @@
{
"Scripts": [],
"Commands": [],
"RebootOnCompletion": 0,
}

View File

@ -0,0 +1,17 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"Set-LocalUserPassword.ps1"
],
"Commands": [
{
"Name": "Set-LocalUserPassword",
"Arguments": {
"UserName": "Administrator",
"Password": "$adminPassword",
"Force": true
}
}
],
"RebootOnCompletion": 0
}

View File

@ -0,0 +1,18 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"SQLServerForAOAG.ps1"
],
"Commands": [
{
"Name": "Enable-TrustedHosts",
"Arguments": {}
},
{
"Name": "New-SharedFolderForAOAG",
"Arguments": {
"PrimaryNode": "$primaryNode"
}
}
]
}

View File

@ -0,0 +1,21 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"Start-PowerShellProcess.ps1",
"Failover-Cluster.ps1"
],
"Commands": [
{
"Name": "New-FailoverCluster",
"Arguments": {
"UserName": "$domainAdminAccountName",
"ClusterNodes": "$clusterNodes",
"DomainName": "$domainName",
"ClusterName": "$clusterName",
"UserPassword": "$domainAdminAccountPassword",
"StaticAddress": "$clusterIP"
}
}
],
"RebootOnCompletion": 0
}

View File

@ -0,0 +1,28 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"Update-ServiceConfig.ps1",
"SQLServerForAOAG.ps1",
"Failover-Cluster.ps1"
],
"Commands": [
{
"Name": "Install-FailoverClusterPrerequisites",
"Arguments": {}
},
{
"Name": "Enable-TrustedHosts",
"Arguments": {}
},
{
"Name": "Update-ServiceConfig",
"Arguments": {
"Password": "$domainAdminAccountPassword",
"Name": "Murano Agent",
"RunAsUser": "$domainAdminAccountName",
"DomainName": "$domainName"
}
}
],
"RebootOnCompletion": 1
}

View File

@ -0,0 +1,28 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"OptionParser.ps1",
"SQLServerOptionParsers.ps1",
"SQLServerInstaller.ps1",
"Export-Function.ps1",
"Start-PowerShellProcess.ps1",
"SQLServerForAOAG.ps1"
],
"Commands": [
{
"Name": "Initialize-AOAGPrimaryReplica",
"Arguments": {
"UserName": "$domainAdminAccountName",
"NodeList": "$nodeList",
"PrimaryNode": "$primaryNode",
"DomainName": "$domainName",
"UserPassword": "$domainAdminAccountPassword",
"GroupName": "$groupName",
"ListenerName": "$listenerName",
"SyncModeNodeList": "$syncModeNodeList",
"ListenerIP": "$listenerIP",
"DatabaseList": "$databaseList"
}
}
]
}

View File

@ -0,0 +1,23 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"OptionParser.ps1",
"SQLServerOptionParsers.ps1",
"SQLServerInstaller.ps1",
"Export-Function.ps1",
"Start-PowerShellProcess.ps1",
"SQLServerForAOAG.ps1"
],
"Commands": [
{
"Name": "Initialize-AOAGSecondaryReplica",
"Arguments": {
"UserName": "$domainAdminAccountName",
"UserPassword": "$domainAdminAccountPassword",
"NodeList": "$nodeList",
"PrimaryNode": "$primaryNode",
"DomainName": "$domainName"
}
}
]
}

View File

@ -0,0 +1,23 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"OptionParser.ps1",
"SQLServerOptionParsers.ps1",
"SQLServerInstaller.ps1",
"Export-Function.ps1",
"Start-PowerShellProcess.ps1",
"SQLServerForAOAG.ps1"
],
"Commands": [
{
"Name": "Initialize-AlwaysOnAvailabilityGroup",
"Arguments": {
"DomainAdminAccountName": "$domainAdminAccountName",
"DomainAdminAccountPassword": "$domainAdminAccountPassword",
"NodeList": "$nodeList",
"PrimaryNode": "$primaryNode",
"DomainName": "$domainName"
}
}
]
}

View File

@ -0,0 +1,27 @@
{
"Scripts": [
"ImportCoreFunctions.ps1",
"OptionParser.ps1",
"SQLServerOptionParsers.ps1",
"SQLServerInstaller.ps1",
"SQLServerForAOAG.ps1"
],
"Commands": [
{
"Name": "Disable-Firewall",
"Arguments": {}
},
{
"Name": "Install-SQLServerForAOAG",
"Arguments": {
"SQLServiceUserPassword": "$domainAdminAccountPassword",
"SQLServiceUserDomain": "$domainName",
"SQLServiceUserName": "$domainAdminAccountName"
}
},
{
"Name": "Install-SqlServerPowerShellModule",
"Arguments": {}
}
]
}

View File

@ -0,0 +1,26 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters" : {
"KeyName" : {
"Description" : "Key Pair name for Load Balancer",
"Type" : "String",
"Default" : "murano-lb-key"
}
},
"Resources" : {
"$instanceName": {
"Type" : "AWS::EC2::Instance",
"Properties": {
"InstanceType" : "$instanceType",
"ImageId" :"$imageName",
"AvailabilityZone" : "$availabilityZone",
"UserData": "$userData"
}
}
},
"Outputs" : {
}
}

View File

@ -0,0 +1,22 @@
{
"Resources" : {
"$lbName" : {
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
"Properties" : {
"AvailabilityZones" : { "Fn::GetAZs" : "" },
"Instances" : [{"Ref": "$instanceName"}],
"Listeners" : [ {
"LoadBalancerPort" : "$lbPort",
"InstancePort" : "80",
"Protocol" : "HTTP"
}]
}
}
},
"Outputs": {
"LoadBalancerIP": {
"Value": { "Fn::GetAtt": [ "$lbName", "DNSName" ] },
"Description": ""
}
}
}

View File

@ -0,0 +1,41 @@
{
"Resources": {
"$instancePort": {
"Properties": {
"SecurityGroups" : [ {"Ref" : "MsSqlSecurityGroup"} ]
}
},
"MsSqlSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
{
"ToPort": "4022",
"IpProtocol": "tcp",
"FromPort": "4022",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "135",
"IpProtocol": "tcp",
"FromPort": "135",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "1433",
"IpProtocol": "tcp",
"FromPort": "1433",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "1434",
"IpProtocol": "tcp",
"FromPort": "1434",
"CidrIp": "0.0.0.0/0"
}
],
"GroupDescription": "Enable MS SQL access"
}
}
}
}

View File

@ -0,0 +1,50 @@
{
"Resources": {
"$instancePort": {
"Properties": {
"allowed_address_pairs": [
{
"ip_address": "$clusterIp"
}
],
"SecurityGroups": [
{
"Ref": "MsSqlSecurityGroup"
}
]
}
},
"MsSqlSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
{
"ToPort": "4022",
"IpProtocol": "tcp",
"FromPort": "4022",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "135",
"IpProtocol": "tcp",
"FromPort": "135",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "1433",
"IpProtocol": "tcp",
"FromPort": "1433",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "1434",
"IpProtocol": "tcp",
"FromPort": "1434",
"CidrIp": "0.0.0.0/0"
}
],
"GroupDescription": "Enable MS SQL access"
}
}
}
}

View File

@ -0,0 +1,113 @@
{
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters": {
"KeyName": {
"Description": "Key Pair name for Load Balancer",
"Type": "String",
"Default": "murano-lb-key"
}
},
"Resources": {
"$instanceName": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": "$instanceType",
"ImageId": "$imageName",
"AvailabilityZone": "$availabilityZone",
"UserData": "$userData",
"NetworkInterfaces": [
{
"Ref": "$instancePort"
}
]
}
},
"$instancePort": {
"Type": "OS::Neutron::Port",
"Properties": {
"security_groups": [
{
"Ref": "MuranoDefaultSecurityGroup"
}
],
"network_id": {
"Ref": "network"
},
"fixed_ips": [
{
"subnet_id": {
"Ref": "subnet"
}
}
]
}
},
"MuranoDefaultSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
{
"ToPort": "3389",
"IpProtocol": "tcp",
"FromPort": "3389",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "22",
"IpProtocol": "tcp",
"FromPort": "22",
"CidrIp": "0.0.0.0/0"
},
{
"ToPort": "-1",
"IpProtocol": "icmp",
"FromPort": "-1",
"CidrIp": "0.0.0.0/0"
}
],
"GroupDescription": "Default security group for Murano Environments"
}
},
"network": {
"Type": "OS::Neutron::Net",
"Properties": {
"name": "$networkName"
}
},
"subnet": {
"Type": "OS::Neutron::Subnet",
"Properties": {
"network_id": {
"Ref": "network"
},
"ip_version": 4,
"cidr": "10.0.0.0/24",
"allocation_pools": [
{
"start": "10.0.0.20",
"end": "10.0.0.250"
}
]
}
},
"router": {
"Type": "OS::Neutron::Router"
},
"router_interface": {
"Type": "OS::Neutron::RouterInterface",
"Properties": {
"router_id": {
"Ref": "router"
},
"subnet_id": {
"Ref": "subnet"
}
}
}
},
"Outputs": {
}
}

View File

@ -0,0 +1,61 @@
trap {
&$TrapHandler
}
$FW_Rules = @{
"SQL Server Data Connection" = "1433";
"SQL Admin Connection" = "1434";
"SQL Service Broker" = "4022";
"SQL Debugger/RPC"="135";
}
$FW_Proto = "TCP"
function Add-NetshFirewallRule {
param (
[HashTable] $hshRules,
[String] $proto
)
foreach ($h in $hshRules.GetEnumerator()) {
try {
$command="advfirewall firewall add rule name=`"$($h.Name)`" dir=in action=allow protocol=$proto localport=$($h.Value)"
Start-Process -FilePath netsh -ArgumentList $command -Wait
}
catch {
$except= $_ | Out-String
Write-LogError "Add rule $($h.Name) FAILS with $except"
}
}
}
function Remove-NetShFirewallRule {
param (
[HashTable] $hshRules
)
foreach ($h in $hshRules.GetEnumerator()) {
try {
$command="advfirewall firewall delete rule name=`"$($h.Name)`""
Start-Process -FilePath netsh -ArgumentList $command -Wait
}
catch {
$except= $_ | Out-String
Write-LogError "Delete rule $($h.Name) FAILS with $except"
}
}
}
function Enable-SQLExternalAccess {
Add-NetshFirewallRule $FW_Rules $FW_Proto
}
function Disable-SQLExternalAccess {
Remove-NetshFirewallRule $FW_Rules $FW_Proto
}

View File

@ -0,0 +1,50 @@
trap {
&$TrapHandler
}
Function Copy-Prerequisites {
param (
[String] $Path = '',
[String] $Destination = ''
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "--> Copy-Prerequisites"
if ($Destination -eq '') {
throw("Copy-Prerequisites: Destination path not specified!")
}
if ($Path -eq '') {
$Path = [Environment]::GetEnvironmentVariable('MuranoFileShare')
if ($Path -eq $null) {
throw("Copy-Prerequisites: Unable to determine source path for prerequisites.")
}
}
Write-Log "Creating new PSDrive ..."
New-PSDrive -Name 'P' -PSProvider 'FileSystem' -Root $Path | Out-Null
Write-Log "Creating destination folder ..."
New-Item -Path $Destination -ItemType Container -Force | Out-Null
Write-Log "Copying items ..."
Copy-Item -Path 'P:\Prerequisites\IIS' -Destination $Destination -Recurse -Force | Out-Null
Write-Log "Removing PSDrive ..."
Remove-PSDrive -Name 'P' -PSProvider 'FileSystem' -Force | Out-Null
Write-Log "<-- Copy-Prerequisites"
}
}

View File

@ -0,0 +1,152 @@
trap {
&$TrapHandler
}
Function Register-WebApp {
<#
.LINKS
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 = ""
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$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)
}
$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
$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())
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$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
$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
#------------------------
}
}

View File

@ -0,0 +1,61 @@
trap {
&$TrapHandler
}
function Export-Function {
param (
[String[]] $Name,
[Parameter(ValueFromPipeline=$true)]
[String] $Path = [IO.Path]::GetTempFileName(),
[Switch] $All
)
if ([IO.Path]::GetExtension($Path) -ne 'ps1') {
$null = Rename-Item -Path $Path -NewName "$Path.ps1" -Force
$Path = "$Path.ps1"
}
$SystemFunctions = @(
'A:', 'B:', 'C:', 'D:', 'E:', 'F:', 'G:', 'H:', 'I:', 'J:',
'K:', 'L:', 'M:', 'N:', 'O:', 'P:', 'Q:', 'R:', 'S:', 'T:',
'U:', 'V:', 'W:', 'X:', 'Y:', 'Z:',
'cd..', 'cd\', 'help', 'mkdir', 'more', 'oss', 'prompt',
'Clear-Host', 'Get-Verb', 'Pause', 'TabExpansion2'
)
if ($All) {
Get-ChildItem Function: |
Where-Object {$_.ModuleName -eq ''} |
Where-Object {$SystemFunctions -notcontains $_.Name} |
ForEach-Object {
Add-Content -Path $Path -Value @"
function $($_.Name) {
$($_.ScriptBlock)
}
"@
}
}
else {
foreach ($FunctionName in $Name) {
$FunctionObject = Get-ChildItem "Function:\$FunctionName"
if ($FunctionObject -ne $null) {
Add-Content -Path $Path -Value @"
function $FunctionName {
$($FunctionObject.ScriptBlock)
}
"@
}
}
}
return $Path
}

View File

@ -0,0 +1,239 @@
<#
.DESCRIPTION
## Failover Cluster Input Data (from the UI)
* Domain Membership
- [String] / [Select box] $DomainName - Domain name
* Domain User Credentials
- [String] $UserName - Username
- [Password string] $UserPassword - User password
* Shared Folder Information
- [String] $ShareServer - Server which will host the folder
- [String] $ShareName - Share name
- [String] $SharePath - Shared folder internal path
* Failover Cluster Members
- [String] $ClusterName - Cluster name
- [String] $ClusterIP - Static IP address that will be assigned to the cluster
- [String[]] $ClusterNodes - List of node names
## Failover Cluster creation workflow
* Create AD domain
* Join all the VMs to that domain
* Prepare nodes
- Install Failover Cluster prerequisites on all FC nodes
* Create failover cluster
- Create new cluster
- Add members
* Confugure FC quorum
- Create new folder that will be shared
- Share that folder with appropriate permissions
- Configure quorum mode
## Helpful SmbShare* Functions
* New-SmbShare
* Grant-SmbShareAccess
#>
trap {
&$TrapHandler
}
function Install-FailoverClusterPrerequisites {
#Import-Module FailoverClusters
#Add-WindowsFeature Failover-Clustering, RSAT-Clustering-PowerShell
}
function New-FailoverClusterSharedFolder {
param (
[String] $ClusterName,
[String] $DomainName,
[String] $ShareServer,
[String] $SharePath = $($Env:SystemDrive + '\FCShare'),
[String] $ShareName = 'FCShare',
[String] $UserName,
[String] $UserPassword,
$Credential = $null
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "--> New-FailoverClusterSharedFolder"
Write-Log "Creating shared folder for Failover Cluster ..."
if ($Credential -eq $null) {
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
}
if ((Test-Connection -ComputerName $ShareServer -Count 1 -Quiet) -eq $false) {
throw("Server '$ShareServer' is unreachable via ICMP.")
}
$Session = New-PSSession -ComputerName $ShareServer -Credential $Credential
Write-Log "Creating folder on '$ShareServer' ..."
Invoke-Command -Session $Session -ScriptBlock {
param (
[String] $SharePath,
[String] $ShareName,
[String] $ClusterAccount
)
Remove-SmbShare -Name $ShareName -Force -ErrorAction 'SilentlyContinue'
Remove-Item -Path $SharePath -Force -ErrorAction 'SilentlyContinue'
New-Item -Path $SharePath -ItemType Container -Force
New-SmbShare -Path $SharePath `
-Name $ShareName `
-FullAccess "$ClusterAccount", 'Everyone' `
-Description "Shared folder for Failover Cluster."
} -ArgumentList $SharePath, $ShareName, "$DomainName\$ClusterName`$"
Write-Log "Confguring Failover Cluster to use shared folder as qourum resourse ..."
$null = Set-ClusterQuorum -NodeAndFileShareMajority "\\$ShareServer\$ShareName"
Write-Log "<-- New-FailoverClusterSharedFolder"
}
}
function New-FailoverCluster {
param (
[String] $ClusterName,
[String] $StaticAddress,
[String[]] $ClusterNodes,
[String] $DomainName,
[String] $UserName,
[String] $UserPassword,
$Credential
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "ClusterNodes: $($ClusterNodes -join ', ')"
if ($Credential -eq $null) {
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
}
foreach ($Node in $ClusterNodes) {
Write-LogDebug "Installing Failover Cluster modules on '$Node' ..."
$null = Invoke-Command `
-ComputerName $Node `
-Credential $Credential `
-ScriptBlock {
Add-WindowsFeature Failover-Clustering, RSAT-Clustering-PowerShell
}
}
Import-Module FailoverClusters
if ((Get-Cluster $ClusterName -ErrorAction SilentlyContinue) -eq $null) {
Write-Log "Creating new cluster '$ClusterName' ..."
<#
Start-PowerShellProcess -Command @"
Import-Module FailoverClusters
New-Cluster -Name '$ClusterName' -StaticAddress '$StaticAddress'
"@ -Credential $Credential -NoBase64
#>
New-Cluster -Name "$ClusterName" -StaticAddress "$StaticAddress"
Start-Sleep -Seconds 30
}
else {
Write-Log "Cluster '$ClusterName' already exists."
}
foreach ($Node in $ClusterNodes) {
Write-Log "Adding node '$Node' to the cluster '$ClusterName' ..."
if ((Get-ClusterNode $Node -ErrorAction SilentlyContinue) -eq $null) {
Write-Log "Adding node ..."
<#
Start-PowerShellProcess -Command @"
Import-Module FailoverClusters
Add-ClusterNode -Cluster '$ClusterName' -Name '$Node'
"@ -Credential $Credential -NoBase64
#>
Add-ClusterNode -Cluster "$ClusterName" -Name "$Node"
}
else {
Write-Log "Node '$Node' already a part of the cluster '$ClusterName'."
}
}
}
}
<#
# Example
$DomainName = 'fc-acme.local'
$DomainUser = 'Administrator'
$DomainPassword = 'P@ssw0rd'
$ClusterName = 'fc-test'
$ClusterIP = '10.200.0.60'
$ClusterNodes = @('fc-node-01','fc-node-02','fc-node-03')
$ShareServer = 'fc-dc-01'
$ShareName = 'FCShare'
$SharePath = "C:\$ShareName"
Import-Module CoreFunctions -Force
$Creds = New-Credential `
-UserName "$DomainName\$DomainUser" `
-Password "$DomainPassword"
New-FailoverCluster `
-ClusterName $ClusterName `
-StaticAddress $ClusterIP `
-ClusterNodes $ClusterNodes `
-Credential $Creds
New-FailoverClusterSharedFolder `
-ClusterName $ClusterName `
-DomainName $DomainName `
-ShareServer $ShareServer `
-SharePath "$SharePath" `
-ShareName "$ShareName" `
-Credential $Creds
#>

View File

@ -0,0 +1,7 @@
function Get-DnsListeningIpAddress {
Import-Module DnsServer
(Get-DNSServer -ComputerName localhost).ServerSetting.ListeningIpAddress |
Where-Object { $_ -match "\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" }
}

View File

@ -0,0 +1,68 @@
Import-Module CoreFunctions -Force
Initialize-Logger 'MuranoAgent' 'C:\Murano\PowerShell.log'
function Show-InvocationInfo {
param (
$Invocation,
[Switch] $End
)
if ($End) {
Write-LogDebug "</function name='$($Invocation.MyCommand.Name)'>"
}
else {
Write-LogDebug "<function name='$($Invocation.MyCommand.Name)'>"
Write-LogDebug "<param>"
foreach ($Parameter in $Invocation.MyCommand.Parameters) {
foreach ($Key in $Parameter.Keys) {
$Type = $Parameter[$Key].ParameterType.FullName
foreach ($Value in $Invocation.BoundParameters[$Key]) {
Write-LogDebug "[$Type] $Key = '$Value'"
}
}
}
Write-LogDebug "</param>"
}
}
$TrapHandler = {
Write-LogError "<exception>"
Write-LogError $_ -EntireObject
Write-LogError "</exception>"
break
}
trap {
&$TrapHandler
}
$ErrorActionPreference = 'Stop'
<#
# Usage example for Show-InvocationInfo
function MyFunction {
param (
[String] $Value1,
[String] $Value2,
[Int] $Int1
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
# Main code here
}
}
#>

View File

@ -0,0 +1,43 @@
trap {
&$TrapHandler
}
Function Install-RolePrimaryDomainController {
param (
[String] $DomainName,
[String] $SafeModePassword
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Add-WindowsFeatureWrapper `
-Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" `
-IncludeManagementTools `
-NotifyRestart
Write-Log "Creating first domain controller ..."
$SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force
$null = Install-ADDSForest `
-DomainName $DomainName `
-SafeModeAdministratorPassword $SMAP `
-DomainMode Default `
-ForestMode Default `
-NoRebootOnCompletion `
-Force
Write-Log "Waiting 60 seconds for reboot ..."
Start-Sleep -Seconds 60
}
}

View File

@ -0,0 +1,69 @@
trap {
&$TrapHandler
}
Function Install-RoleSecondaryDomainController
{
<#
.SYNOPSIS
Install additional (secondary) domain controller.
#>
param
(
[String]
# Domain name to join to.
$DomainName,
[String]
# Domain user who is allowed to join computer to domain.
$UserName,
[String]
# User's password.
$Password,
[String]
# Domain controller recovery mode password.
$SafeModePassword
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
$Credential = New-Credential -UserName "$DomainName\$UserName" -Password $Password
# Add required windows features
Add-WindowsFeatureWrapper `
-Name "DNS","AD-Domain-Services","RSAT-DFS-Mgmt-Con" `
-IncludeManagementTools `
-NotifyRestart
Write-Log "Adding secondary domain controller ..."
$SMAP = ConvertTo-SecureString -String $SafeModePassword -AsPlainText -Force
Install-ADDSDomainController `
-DomainName $DomainName `
-SafeModeAdministratorPassword $SMAP `
-Credential $Credential `
-NoRebootOnCompletion `
-Force `
-ErrorAction Stop | Out-Null
Write-Log "Waiting for restart ..."
# Stop-Execution -ExitCode 3010 -ExitString "Computer must be restarted to finish domain controller promotion."
# Write-Log "Restarting computer ..."
# Restart-Computer -Force
}
}

View File

@ -0,0 +1,84 @@
trap {
&$TrapHandler
}
Function ConvertTo-Boolean {
param (
$InputObject,
[Boolean] $Default = $false
)
try {
[System.Convert]::ToBoolean($InputObject)
}
catch {
$Default
}
}
Function Show-Environment {
foreach ($item in (Get-ChildItem Env:)) {
Write-Log ("'{0}' --> '{1}'" -f $item.Name, $item.Value)
}
}
Function Install-SqlServer {
param (
[String] $SetupRoot = '',
[String] $SAPassword = '',
[String] $MuranoFileShare = '',
[Switch] $MixedModeAuth = $false,
[Switch] $UpdateEnabled = $false
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
if ($SetupRoot -eq '') {
if ($MuranoFileShare -eq '') {
$MuranoFileShare = [Environment]::GetEnvironmentVariable('MuranoFileShare')
if ($MuranoFileShare -eq '') {
throw("Unable to find MuranoFileShare path.")
}
}
$SetupRoot = [IO.Path]::Combine($MuranoFileShare, 'Prerequisites\SQL Server\2012')
}
#$MixedModeAuthSwitch = ConvertTo-Boolean $MixedModeAuth
$ExtraOptions = @{}
if ($MixedModeAuth -eq $true) {
$ExtraOptions += @{'SECURITYMODE' = 'SQL'}
if ($SAPassword -eq '') {
throw("SAPassword must be set when MixedModeAuth is requisted!")
}
}
if ($SAPassword -ne '') {
$ExtraOptions += @{'SAPWD' = $SAPassword}
}
if (-not $UpdateEnabled) {
$ExtraOptions += @{'UpdateEnabled' = $false}
}
Show-Environment
New-SqlServer -SetupRoot $SetupRoot -ExtraOptions $ExtraOptions
}
}

View File

@ -0,0 +1,72 @@
trap {
&$TrapHandler
}
Function Install-WebServer {
param (
[String] $PrerequisitesPath
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "--> Install-WebServer"
$FeatureList = @(
'Web-Server',
'Web-Net-Ext45',
'Web-ASP',
'Web-Asp-Net45',
'Web-ISAPI-Ext',
'Web-ISAPI-Filter',
'Web-Includes'
)
$PrerequisitesList = @(
'AspNetMvc4Setup.exe',
'WebApplications.exe'
)
$PrerequisitesPath = [IO.Path]::Combine($PrerequisitesPath, 'IIS')
Write-Log "Validating prerequisites based on the list ..."
foreach ($FileName in $PrerequisitesList) {
$FilePath = [IO.Path]::Combine($PrerequisitesPath, $FileName)
if (-not (Test-Path -Path $FilePath -PathType Leaf)) {
throw("Prerequisite file not found: '$FilePath'")
}
}
Import-Module ServerManager
Write-Log "Installing Web Server ..."
Install-WindowsFeature $FeatureList -IncludeManagementTools
Write-Log "Installing AspNetMvp4 ..."
$Exec = Exec -FilePath $([IO.Path]::Combine($PrerequisitesPath, 'AspNetMvc4Setup.exe')) -ArgumentList '/q' -PassThru
if ($Exec.ExitCode -ne 0) {
throw("Installation of 'AspNetMvc4Setup.exe' failed. Process exit code '$($Exec.ExitCode)'")
}
# Extract WebApplications folder with *.target files to
# C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0
Write-Log "Installing WebApplication targets ..."
$WebApplicationsTargetsRoot = 'C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0'
$null = New-Item -Path $WebApplicationsTargetsRoot -ItemType Container
$Exec = Exec -FilePath $([IO.Path]::Combine($PrerequisitesPath, 'WebApplications.exe')) -ArgumentList @("-o`"$WebApplicationsTargetsRoot`"", '-y') -PassThru
if ($Exec.ExitCode -ne 0) {
throw("Installation of 'WebApplications.exe' failed. Process exit code '$($Exec.ExitCode)'")
}
Write-Log "<-- Install-WebServer"
}
}

View File

@ -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."
}
#>
}
}
}

View File

@ -0,0 +1,64 @@
trap {
&$TrapHandler
}
function New-SqlServerSystemAccount {
param (
# (REQUIRED) Domain Name
[Parameter(Mandatory=$true)]
[String] $DomainName,
# (REQUIRED) User name who has permissions to create and modify userPassword
# Usually this is the domain administrator '$domainName\Administrator' account
[Parameter(Mandatory=$true)]
[String] $UserName,
# (REQUIRED) Password for that user
[Parameter(Mandatory=$true)]
[String] $UserPassword,
# (REQUIRED) User name for a new account that will be used to run SQL Server
[Parameter(Mandatory=$true)]
[String] $SQLServiceUserName,
# (REQUIRED) Password for that user
[Parameter(Mandatory=$true)]
[String] $SQLServiceUserPassword,
[String] $PrimaryNode = ' '
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
if ($PrimaryNode.ToLower() -ne ($Env:ComputerName).ToLower()) {
Write-Log "THis function runs on AOAG primary node only."
Write-Log "Exiting."
return
}
Write-Log "Installing 'RSAT-AD-PowerShell' ... "
Add-WindowsFeature RSAT-AD-PowerShell
Import-Module ActiveDirectory
$Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
Write-Log "Adding new user ..."
$null = New-ADUser `
-Name $SQLServiceUserName `
-AccountPassword $(ConvertTo-SecureString -String $SQLServiceUserPassword -AsPlainText -Force) `
-Credential $Creds `
-ErrorAction 'Stop'
}
}

View File

@ -0,0 +1,280 @@
function New-Option ([string]$Name, [switch]$Switch, [switch]$Boolean, [switch]$String, [switch]$List, $Constraints=$null) {
<#
.SYNOPSIS
Creates Option object
.DESCRIPTION
Option object is a virtual object represtnting typed command line option. These objects encapsulate escaping and
validation matters.
One and only one of the switches 'Switch', 'Boolean', 'String' or 'List' should be provided.
.PARAMETER Name
Option name as it appears in the command line.
.PARAMETER Switch
Use this switch to create valueless option (a switch).
.PARAMETER Boolean
Use this switch to create boolean option. Its value is always converted to "1" or "0"
.PARAMETER String
Use this switch to create string option. Its value will be properly quoted if necessary.
.PARAMETER List
Use this switch to create option with list value. Values will be put into command line using valid value delemiter (a comma)
.PARAMETER Constraints
When this parameter is specified, option values are limited to options from that list.
#>
$Option = New-Object -TypeName PSObject
# Fields
$Option | Add-Member NoteProperty Type -value $null
$Option | Add-Member NoteProperty Name -value $null
$Option | Add-Member NoteProperty AllowedValues -value $null
# Init
$Option | Add-Member ScriptMethod __init__ {
param([string]$Name, $Switch, $Boolean, $String, $List)
$this.Name = $Name
# With respect for our developers we do not check for double type selected
if ($Switch) {
AugmentOptionSwitch($this)
} elseif ($Boolean) {
AugmentOptionBoolean($this)
} elseif ($String) {
AugmentOptionString($this)
} elseif ($List) {
AugmentOptionList($this)
} else {
throw "Switch, Boolean, String or List option type must be provided for option '$Name'"
}
}
$Option | Add-Member ScriptMethod __post_init__ {
param($Constraints=$null)
if ($Constraints -ne $null) {
$this.AllowedValues = @()
$this.AllowedValues = $this.AllowedValues + $Constraints
} else {
$Constraints = $null
}
}
# Methods
$Option | Add-Member -Force ScriptMethod Validate {
if ($this.AllowedValues -ne $null) {
if (-not($this.AllowedValues -contains $this.Value)) {
$Cts = $this.AllowedValues -join ','
throw "Option '$($this.Name)' may have values ($Cts) but not '$($this.Value)'"
}
}
}
$Option | Add-Member -Force ScriptMethod ToString {
return "/$($this.Name)"
}
# invoke constructor
$Option.__init__($Name, $Switch, $Boolean, $String, $List)
$Option.__post_init__($Constraints)
return $Option
}
function AugmentOptionSwitch($Option) {
}
function AugmentOptionBoolean($Option) {
# Fields
$Option | Add-Member NoteProperty Value -value $false
# Methods
$Option | Add-Member -Force ScriptMethod ToString {
if ($this.Value) {
return "/$($this.Name)=1"
} else {
return "/$($this.Name)=0"
}
}
}
function AugmentOptionString($Option) {
# Fields
$Option | Add-Member NoteProperty Value -value ""
# Methods
$Option | Add-Member -Force ScriptMethod ToString {
$v = "$($this.Value)"
if ($v -match '.* .*') {
# TODO: Escape double quote characters if possible
return "/$($this.Name)=`"$v`""
} else {
return "/$($this.Name)=$v"
}
}
}
function AugmentOptionList($Option) {
# Fields
$Option | Add-Member NoteProperty Value -value @()
# Methods
$Option | Add-Member -Force ScriptMethod Validate {
if ($this.AllowedValues -ne $null) {
foreach ($V in $this.Value) {
if (-not($this.AllowedValues -contains $V)) {
$Cts = $this.AllowedValues -join ','
throw "Option '$($this.Name)' may have values ($Cts) but not '$V'"
}
}
}
}
$Option | Add-Member -Force ScriptMethod ToString {
return "/$($this.Name)=$($this.Value -join ',')"
}
}
function New-OptionParser() {
<#
.SYNOPSIS
Creates OptionParser object.
.DESCRIPTION
OptionParser object leverages Option objects capabilities and builds valid command line using specified options.
An application may also be invoked with OptionParser.
#>
$OptionParser = New-Object -TypeName PSObject
# Fields
$OptionParser | Add-Member NoteProperty Options -value @{}
$OptionParser | Add-Member NoteProperty Defaults -value @{}
$OptionParser | Add-Member NoteProperty RequiredOptions -value @()
# Methods
$OptionParser | Add-Member ScriptMethod AddOption {
<#
.SYNOPSIS
Adds supported option into OptionParser.
.DESCRIPTION
OptionParser does not allow using unrecognized options. Use this method to fill OptionParser with recognized options
.PARAMETER Option
Option object
.PARAMETER Required
Required option switch
.PARAMETER Default
Option default value
#>
param($Option, [bool]$Required=$false, $Default=$null)
$this.Options.Add($Option.Name, $Option)
if ($Required) {
$this.RequiredOptions = $this.RequiredOptions + $Option.Name
if ($Option | Get-Member "Value") {
if ($Default) {
$this.Defaults.Add($Option.Name, $Default)
}
} else {
$this.Defaults.Add($Option.Name, $null)
}
}
}
$OptionParser | Add-Member ScriptMethod Parse {
<#
.SYNOPSIS
Parses supplied options and returns command line parameters array.
.DESCRIPTION
This method verifies that only supported options are provided, all mandatory options are in place,
all option meet constraints if any. Unspecified options with default values are added to command line.
So, mandatory option with default value never causes exception.
.PARAMETER Options
A hash map of options to parse. Option names should be mapped to corresponding values.
#>
param([hashtable]$Options)
$CommandLine = @()
foreach ($RequiredOptionName in $this.RequiredOptions) {
if (-not $Options.ContainsKey($RequiredOptionName)) {
$Default = $this.Defaults.Get_Item($RequiredOptionName)
if ($this.Defaults.ContainsKey($RequiredOptionName)) {
$Options.Add($RequiredOptionName, $this.Defaults.Get_Item($RequiredOptionName))
} else {
throw "Required option '$RequiredOptionName' is missing"
}
}
}
foreach ($OptionName in $($Options.keys)) {
$Option = $this.Options.Get_Item($OptionName)
if ($Option -eq $null) {
throw "Option '$OptionName' is not allowed"
}
if ($Option | Get-Member "Value") {
$Option.Value = $Options.Get_Item($OptionName)
}
$Option.Validate()
$CommandLine = $CommandLine + $Option.ToString()
}
return $CommandLine
}
$OptionParser | Add-Member ScriptMethod ExecuteBinary {
param($Binary, [hashtable]$Options = @{}, $CommandLineSuffix = @())
<#
.SYNOPSIS
Executes binary with a command line constructed from provided options. An arbitrary suffix may be
appended to the command line.
.DESCRIPTION
This method uses OptionParser.Parse method to construct command line. If there a command line suffix
was supplied, it is appended to the end of command line. Normally command line suffix should contain
leading space character.
Method waits for executable process to complete and returns its exit code.
.PARAMETER Binary
Full or relative path to the executable to run.
.PARAMETER Options
A hash map of options to pass to the executable.
.PARAMETER CommandLineSuffix
Arbitrary command line suffix. Normally it shoud have leading space character.
#>
$Binary = Get-Item $Binary
$CommandLine = $this.Parse($Options)
if ($CommandLineSuffix) {
$CommandLine = $CommandLine + $CommandLineSuffix
}
Write-Log "Executing: $($Binary.FullName) $($CommandLine -join ' ')"
$process = [System.Diagnostics.Process]::Start($Binary, $CommandLine)
$process.WaitForExit()
$process.Refresh()
return $process.ExitCode
}
return $OptionParser
}

View File

@ -0,0 +1,538 @@
trap {
&$TrapHandler
}
function Install-SqlServerPowerShellModule {
param (
[String] $SetupRoot = ''
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
if ((Get-Module SQLPS -ListAvailable) -ne $null) {
Write-Log "Module SQLSP already installed."
return
}
if ($MuranoFileShare -eq '') {
$MuranoFileShare = [String]([Environment]::GetEnvironmentVariable('MuranoFileShare'))
if ($MuranoFileShare -eq '') {
throw "Unable to find MuranoFileShare path."
}
}
Write-LogDebug "MuranoFileShare = '$MuranoFileShare'"
if ($SetupRoot -eq '') {
$SetupRoot = [IO.Path]::Combine("$MuranoFileShare", 'Prerequisites\SQL Server\Tools')
}
Write-LogDebug "SetupRoot = '$SetupRoot'"
$FileList = @(
'SQLSysClrTypes.msi',
'SharedManagementObjects.msi',
'PowerShellTools.msi'
)
foreach ($MsiFile in $FileList) {
Write-Log "Trying to install '$MsiFile' ..."
$MsiPath = Join-Path $SetupRoot $MsiFile
if ([IO.File]::Exists($MsiPath)) {
Write-Log "Starting msiexe ..."
$Result = Exec -FilePath "msiexec.exe" -ArgumentList @('/i', "`"$MsiPath`"", '/quiet') -PassThru
if ($Result.ExitCode -ne 0) {
throw "Installation of MSI package '$MsiPath' failed with error code '$($Result.ExitCode)'"
}
}
else {
Write-Log "File '$MsiPath' not found."
}
}
}
}
function Install-SqlServerForAOAG {
param (
# Path to folder where msi files for additional SQL features are located
[String] $SetupRoot = '',
# Path to folder where msi files for additional SQLPS module are located
[String] $SqlpsSetupRoot = '',
[String] $MuranoFileShare = '',
# (REQUIRED) Domain name
[String] $SQLServiceUserDomain = 'fc-acme.local',
# (REQUIRED) User name for the account which will be used by SQL service
[String] $SQLServiceUserName = 'Administrator',
# (REQUIRED) Password for that user
[String] $SQLServiceUserPassword = 'P@ssw0rd',
[Switch] $UpdateEnabled
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
if ($MuranoFileShare -eq '') {
$MuranoFileShare = [String]([Environment]::GetEnvironmentVariable('MuranoFileShare'))
if ($MuranoFileShare -eq '') {
throw "Unable to find MuranoFileShare path."
}
}
Write-LogDebug "MuranoFileShare = '$MuranoFileShare'"
if ($SetupRoot -eq '') {
$SetupRoot = [IO.Path]::Combine("$MuranoFileShare", 'Prerequisites\SQL Server\2012')
}
Write-LogDebug "SetupRoot = '$SetupRoot'"
$ExtraOptions = @{}
if ($UpdateEnabled) {
$ExtraOptions += @{'UpdateEnabled' = $true}
}
else {
$ExtraOptions += @{'UpdateEnabled' = $false}
}
$null = New-SQLServerForAOAG `
-SetupRoot $SetupRoot `
-SQLSvcUsrDomain $SQLServiceUserDomain `
-SQLSvcUsrName $SQLServiceUserName `
-SQLSvcUsrPassword $SQLServiceUserPassword `
-ExtraOptions $ExtraOptions
}
}
function Initialize-AlwaysOnAvailabilityGroup {
param (
[String] $DomainName,
[String] $DomainAdminAccountName,
[String] $DomainAdminAccountPassword,
[String] $SqlServiceAccountName,
[String] $PrimaryNode,
[String] $ShareName = 'SharedWorkDir'
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
$ShareNetworkPath = '\\' + $PrimaryNode + '\' + $ShareName
$DomainAdminAccountCreds = New-Credential `
-UserName "$DomainName\$DomainAdminAccountName" `
-Password "$DomainAdminAccountPassword"
$FunctionsFile = Export-Function 'Get-NextFreePort', 'Initialize-AlwaysOn'
$null = Start-PowerShellProcess @"
trap {
`$_
exit 1
}
Import-Module CoreFunctions
Write-Log "Importing functions file '$FunctionsFile' ..."
. "$FunctionsFile"
Write-Log "Starting 'Initialize-AlwaysOn' ..."
`$XmlFile = [IO.Path]::Combine("$ShareNetworkPath", "`$(`$Env:ComputerName).xml")
Write-Log "Output XML file is '`$XmlFile'"
Initialize-AlwaysOn | Export-CliXml -Path `$XmlFile
"@ -Credential $DomainAdminAccountCreds -NoBase64
}
}
function New-SharedFolderForAOAG {
param (
# (OPTIONAL)
[String] $SharePath = [IO.Path]::Combine($Env:SystemDrive + '\', 'SharedWorkDir'),
# (OPTIONAL)
[String] $ShareName = 'SharedWorkDir',
[String] $PrimaryNode = ' '
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
if ($PrimaryNode.ToLower() -ne ($Env:ComputerName).ToLower()) {
Write-Log "This script runs on primary node only."
Write-Log "Exiting script."
return
}
if ($ShareName -eq '') {
$ShareName = [IO.Path]::GetFileNameWithoutExtension($SharePath)
}
Write-LogDebug "SharePath = '$SharePath'"
Write-LogDebug "ShareName = '$ShareName'"
try {
Write-LogDebug "Trying to remove share '$ShareName'"
$null = Get-SmbShare -Name $ShareName -ErrorAction 'Stop'
$null = Remove-SmbShare -Name $ShareName -Force
write-Log "Share '$ShareName' removed."
}
catch {
Write-LogWarning "Share '$ShareName' not exists or cannot be deleted."
}
try {
Write-LogDebug "Trying to remove folder '$SharePath"
$null = Get-Item -Path $SharePath -ErrorAction 'Stop'
$null = Remove-Item -Path $SharePath -Recurse -Force
Write-Log "Folder '$SharePath' removed."
}
catch {
Write-LogWarning "Folder '$SharePath' not exists or cannot be deleted."
}
$null = New-Item -Path $SharePath -ItemType Container -Force
$null = New-SmbShare -Path $SharePath `
-Name $ShareName `
-FullAccess "Everyone" `
-Description "Shared folder for AlwaysOn Availability Group setup."
return '\\' + $Env:ComputerName + '\' + $ShareName
}
}
function New-DatabaseForAOAG {
param (
[String] $DatabaseName,
[String] $DomainName,
[String] $UserName,
[String] $UserPassword
)
$Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
$FunctionsFile = Export-Function 'Invoke-SQLText', 'ConvertTo-SQLName', 'ConvertTo-SQLString', 'New-SQLDatabase'
Start-PowerShellProcess @"
trap {
`$_
exit 1
}
Import-Module CoreFunctions
Write-Log "Importing functions from file '$FunctionsFile' ..."
. "$FunctionsFile"
Write-Log "Starting 'New-SQLDatabase' ..."
New-SQLDatabase $DatabaseName
"@ -Credential $Creds -NoBase64
}
function Initialize-AOAGPrimaryReplica {
param (
# (OPTIONAL) Name of the new Availability Group. If not specified then default name will be used.
[String] $GroupName = 'MuranoAG',
# (REQUIRED) Nodes that will be configured as replica partners.
#[Parameter(Mandatory=$true)]
[String[]] $NodeList,
# (REQUIRED) Node name that will be primary for selected Availability Group
#[Parameter(Mandatory=$true)]
[String] $PrimaryNode,
# (REQUIRED) Database list that will be added to the Availability Group
#[Parameter(Mandatory=$true)]
[String[]] $DatabaseList,
# (REQUIRED) Listener name that will be used by clients to connect to databases in that AG
#[Parameter(Mandatory=$true)]
[String] $ListenerName = 'MuranoAG_Listener',
# (REQUIRED) IP address of the listener
#[Parameter(Mandatory=$true)]
[String] $ListenerIP,
[String] $ListenerIPMask = '255.255.255.0',
[String] $ListenerPort = '5023',
# Sync Mode Node List
[String[]] $SyncModeNodeList,
[String] $SharedWorkDir = 'SharedWorkDir',
[String] $CliXmlFile = '',
[String] $DomainName,
[String] $UserName,
[String] $UserPassword
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Write-Log "Primary node: '$($PrimaryNode.ToLower())'"
Write-Log "Current node: '$(($Env:ComputerName).ToLower())'"
if ($PrimaryNode.ToLower() -ne $($Env:ComputerName).ToLower()) {
Write-Log "This function works on PrimaryNode only."
Write-Log "Exiting."
return
}
if ($CliXmlFile -eq '') {
$ReplicaDefinitionList = @()
foreach ($Node in $NodeList) {
try {
$NodeEndpointPort = Import-CliXml -Path "\\$PrimaryNode\SharedWorkDir\$Node.xml"
}
catch {
Write-Log "Using default endpoint port 5022"
$NodeEndpointPort = 5022
}
$ReplicaDefinition = @{
"SERVER_INSTANCE" = "$Node";
"ENDPOINT_URL" = "TCP://${Node}:${NodeEndpointPort}";
"AVAILABILITY_MODE" = "ASYNCHRONOUS_COMMIT";
"FAILOVER_MODE"="MANUAL";
}
if ($SyncModeNodeList -contains $Node) {
Write-Log "$Node is in SyncModeNodeList"
$ReplicaDefinition['AVAILABILITY_MODE'] = "SYNCHRONOUS_COMMIT"
$ReplicaDefinition['FAILOVER_MODE'] = "AUTOMATIC"
}
else {
Write-Log "$Node is NOT in SyncModeNodeList"
}
$ReplicaDefinitionList += @($ReplicaDefinition)
}
$Preferences = @{}
$ListenerDefinition = @{
"NAME"=$ListenerName;
"PORT" = "$ListenerPort";
"STATIC" = "$ListenerIP/$ListenerIPMask"
}
$Parameters = @{
'WorkDir' = "\\$PrimaryNode\$SharedWorkDir";
'Name' = $GroupName;
'DatabaseNames' = $DatabaseList;
'ReplicaDefs' = $ReplicaDefinitionList;
'Preferences' = $Preferences;
'ListenerDef' = $ListenerDefinition;
}
$null = Remove-Item -Path "\\$PrimaryNode\SharedWorkDir\*" -Force
$CliXmlFile = [IO.Path]::GetTempFileName()
Write-LogDebug "CliXml file: '$CliXmlFile'"
$null = Export-CliXml -Path $CliXmlFile -InputObject $Parameters -Depth 10
$null = Initialize-AOAGPrimaryReplica `
-CliXmlFile $CliXmlFile `
-DomainName $DomainName `
-UserName $UserName `
-UserPassword $UserPassword `
-PrimaryNode $PrimaryNode
Write-LogDebug "Inner 'Initialize-AOAGPrimaryReplica' call completed."
}
else {
$Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
$FunctionsFile = Export-Function -All
$null = Start-PowerShellProcess @"
trap {
`$_
exit 1
}
Import-Module CoreFunctions
Write-Log "Importing functions from '$FunctionsFile' ..."
. "$FunctionsFile"
Write-Log "Importing CliXml parameters file ..."
`$Parameters = Import-CliXml -Path $CliXmlFile
Write-Log "Starting 'New-AlwaysOnAvailabilityGroup' ..."
New-AlwaysOnAvailabilityGroup ``
-WorkDir `$Parameters['WorkDir'] ``
-Name `$Parameters['Name'] ``
-DatabaseNames `$Parameters['DatabaseNames'] ``
-ReplicaDefs `$Parameters['ReplicaDefs'] ``
-Preferences `$Parameters['Preferences'] ``
-ListenerDef `$Parameters['ListenerDef']
"@ -Credential $Creds -NoBase64
}
}
}
function Initialize-AOAGSecondaryReplica {
param (
# (REQUIRED) Nodes that will be configured as replica partners.
[Parameter(Mandatory=$true)]
[String[]] $NodeList,
# (REQUIRED) Node name that will be primary for selected Availability Group
[Parameter(Mandatory=$true)]
[String] $PrimaryNode,
[String] $SharedWorkDir = 'SharedWorkDir',
[String] $DomainName,
[String] $UserName,
[String] $UserPassword
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
if ($PrimaryNode.ToLower() -eq ($Env:ComputerName).ToLower()) {
Write-Log "This function works on any SecondaryNode only."
Write-Log "Exiting."
return
}
$Creds = New-Credential -UserName "$DomainName\$UserName" -Password "$UserPassword"
$FunctionsFile = Export-Function -All
$null = Start-PowerShellProcess @"
trap {
$_
exit 1
}
Import-Module CoreFunctions
Write-Log "Importing functions from '$FunctionsFile' ..."
. "$FunctionsFile"
Write-Log "Starting 'New-AlwaysOnAvailabilityGroupReplica' ..."
New-AlwaysOnAvailabilityGroupReplica -WorkDir "\\$PrimaryNode\$SharedWorkDir"
"@ -Credential $Creds -NoBase64
}
}
function Disable-Firewall {
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
netsh advfirewall set allprofiles state off
}
}
function Enable-Firewall {
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
netsh advfirewall set allprofiles state on
}
}
function Enable-TrustedHosts {
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
Set-Item WSMan:\localhost\Client\TrustedHosts -Value '*' -Force
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,367 @@
function New-OptionParserInstall {
<#
.SYNOPSIS
Creates an option parser for MS SQL Server 2012 setup "INSTALL" action.
.DESCRIPTION
Use this cmdlet to create an option parser for MS SQL Server 2012 setup "INSTALL" action.
All documented option are supported. See the following link for details:
http://msdn.microsoft.com/en-us/library/ms144259.aspx
#>
$OptionParser = New-OptionParser
$IsPartOfDomain = (Get-WmiObject Win32_ComputerSystem).PartOfDomain
$OptionParser.AddOption((New-Option "ACTION" -String -Constraints "INSTALL"), $true, "INSTALL")
$OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true)
$OptionParser.AddOption((New-Option "ENU" -Switch))
#$OptionParser.AddOption((New-Option "UpdateEnabled" -Switch))
$OptionParser.AddOption((New-Option "UpdateEnabled" -Boolean))
$OptionParser.AddOption((New-Option "UpdateSource" -String))
$OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String))
$OptionParser.AddOption((New-Option "ERRORREPORTING" -Boolean))
$OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","DREPLAY_CTLR","DREPLAY_CLT","SNAC_SDK","SDK","LocalDB")))
$OptionParser.AddOption((New-Option "ROLE" -String -Constraints ("SPI_AS_ExistingFarm", "SPI_AS_NewFarm", "AllFeatures_WithDefaults")))
$OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch))
$OptionParser.AddOption((New-Option "INSTALLSHAREDDIR" -String))
$OptionParser.AddOption((New-Option "INSTALLSHAREDWOWDIR" -String))
$OptionParser.AddOption((New-Option "INSTANCEDIR" -String))
$OptionParser.AddOption((New-Option "INSTANCEID" -String))
$OptionParser.AddOption((New-Option "INSTANCENAME" -String), $true, "MSSQLSERVER")
$OptionParser.AddOption((New-Option "PID" -String))
$OptionParser.AddOption((New-Option "Q" -Switch))
$OptionParser.AddOption((New-Option "QS" -Switch))
$OptionParser.AddOption((New-Option "UIMODE" -String -Constraints ("Normal", "AutoAdvance")))
$OptionParser.AddOption((New-Option "SQMREPORTING" -Boolean))
$OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch))
$OptionParser.AddOption((New-Option "AGTSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "AGTSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "AGTSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "ASBACKUPDIR" -String))
$OptionParser.AddOption((New-Option "ASCOLLATION" -String))
$OptionParser.AddOption((New-Option "ASCONFIGDIR" -String))
$OptionParser.AddOption((New-Option "ASDATADIR" -String))
$OptionParser.AddOption((New-Option "ASLOGDIR" -String))
$OptionParser.AddOption((New-Option "ASSERVERMODE" -String -Constraints ("MULTIDIMENSIONAL", "POWERPIVOT", "TABULAR")))
$OptionParser.AddOption((New-Option "ASSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "ASSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "ASSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
#$OptionParser.AddOption((New-Option "ASSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME")
if ($IsPartOfDomain) {
$OptionParser.AddOption((New-Option "ASSYSADMINACCOUNTS" -String), $true, "$Env:USERDOMAIN\Administrator")
}
else {
$OptionParser.AddOption((New-Option "ASSYSADMINACCOUNTS" -String), $true, "$Env:COMPUTERNAME\Administrator")
}
$OptionParser.AddOption((New-Option "ASTEMPDIR" -String))
$OptionParser.AddOption((New-Option "ASPROVIDERMSOLAP" -Boolean))
$OptionParser.AddOption((New-Option "FARMACCOUNT" -String))
$OptionParser.AddOption((New-Option "FARMPASSWORD" -String))
$OptionParser.AddOption((New-Option "PASSPHRASE" -String))
$OptionParser.AddOption((New-Option "FARMADMINIPORT" -String))
$OptionParser.AddOption((New-Option "BROWSERSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "ENABLERANU" -Switch))
$OptionParser.AddOption((New-Option "INSTALLSQLDATADIR" -String))
$OptionParser.AddOption((New-Option "SAPWD" -String))
$OptionParser.AddOption((New-Option "SECURITYMODE" -String -Constrainrs ("SQL")))
$OptionParser.AddOption((New-Option "SQLBACKUPDIR" -String))
$OptionParser.AddOption((New-Option "SQLCOLLATION" -String))
$OptionParser.AddOption((New-Option "ADDCURRENTUSERASSQLADMIN" -Switch))
$OptionParser.AddOption((New-Option "SQLSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "SQLSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "SQLSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
#$OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME")
if ($IsPartOfDomain) {
$OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\Administrator")
}
else {
$OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:COMPUTERNAME\Administrator")
}
$OptionParser.AddOption((New-Option "SQLTEMPDBDIR" -String))
$OptionParser.AddOption((New-Option "SQLTEMPDBLOGDIR" -String))
$OptionParser.AddOption((New-Option "SQLUSERDBDIR" -String))
$OptionParser.AddOption((New-Option "SQLUSERDBLOGDIR" -String))
$OptionParser.AddOption((New-Option "FILESTREAMLEVEL" -String -Constraints ("0", "1", "2", "3")))
$OptionParser.AddOption((New-Option "FILESTREAMSHARENAME" -String))
$OptionParser.AddOption((New-Option "FTSVCACCOUNT" -String))
$OptionParser.AddOption((New-Option "FTSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "ISSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "ISSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "ISSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "NPENABLED" -Boolean))
$OptionParser.AddOption((New-Option "TCPENABLED" -Boolean))
$OptionParser.AddOption((New-Option "RSINSTALLMODE" -String -Constraints ("SharePointFilesOnlyMode", "DefaultNativeMode", "FilesOnlyMode")))
$OptionParser.AddOption((New-Option "RSSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "RSSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "RSSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled")))
return $OptionParser
}
function New-OptionParserPrepareImage {
<#
.SYNOPSIS
Creates an option parser for MS SQL Server 2012 setup "PrepareImage" action.
.DESCRIPTION
Use this cmdlet to create an option parser for MS SQL Server 2012 setup "PrepareImage" action.
Note that for installer version of MS SQL Server prior to 2012 SP1 Cumulative Update 2 only the
following features are supported: SQLEngine, Replication, FullText, RS
All documented option are supported. See the following link for details:
http://msdn.microsoft.com/en-us/library/ms144259.aspx
#>
$OptionParser = New-OptionParser
$OptionParser.AddOption((New-Option "ACTION" -String -Constraints "PrepareImage"), $true, "PrepareImage")
$OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true)
$OptionParser.AddOption((New-Option "ENU" -Switch))
$OptionParser.AddOption((New-Option "UpdateEnabled" -Switch))
$OptionParser.AddOption((New-Option "UpdateSource" -String))
$OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String))
# $OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQLEngine","Replication","FullText","RS")))
$OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","DREPLAY_CTLR","DREPLAY_CLT","SNAC_SDK","SDK","LocalDB")))
$OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch))
$OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch))
$OptionParser.AddOption((New-Option "INSTALLSHAREDDIR" -String))
$OptionParser.AddOption((New-Option "INSTANCEDIR" -String))
$OptionParser.AddOption((New-Option "INSTANCEID" -String), $true, "MSSQLSERVER")
$OptionParser.AddOption((New-Option "Q" -Switch))
$OptionParser.AddOption((New-Option "QS" -Switch))
return $OptionParser
}
function New-OptionParserPrepareImageSP1U2 {
<#
.SYNOPSIS
Creates an option parser for MS SQL Server 2012 setup "PrepareImage" action.
.DESCRIPTION
Use this cmdlet to create an option parser for MS SQL Server 2012 setup "PrepareImage" action.
This cmdlet should be used only for MS SQL Server 2012 SP1 Cimilative Update 2 or later.
Note that for installer version of MS SQL Server prior to 2012 SP1 Cimilative Update 2 only the
following features are supported: SQLEngine, Replication, FullText, RS
All documented option are supported. See the following link for details:
http://msdn.microsoft.com/en-us/library/ms144259.aspx
#>
$OptionParser = New-OptionParser
$OptionParser.AddOption((New-Option "ACTION" -String -Constraints "PrepareImage"), $true, "PrepareImage")
$OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true)
$OptionParser.AddOption((New-Option "ENU" -Switch))
$OptionParser.AddOption((New-Option "UpdateEnabled" -Switch))
$OptionParser.AddOption((New-Option "UpdateSource" -String))
$OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String))
$OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","SNAC_SDK","SDK","LocalDB")))
$OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch))
$OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch))
$OptionParser.AddOption((New-Option "INSTALLSHAREDDIR" -String))
$OptionParser.AddOption((New-Option "INSTANCEDIR" -String))
$OptionParser.AddOption((New-Option "INSTANCEID" -String), $true, "MSSQLSERVER")
$OptionParser.AddOption((New-Option "Q" -Switch))
$OptionParser.AddOption((New-Option "QS" -Switch))
return $OptionParser
}
function New-OptionParserCompleteImage {
<#
.SYNOPSIS
Creates an option parser for MS SQL Server 2012 setup "CompleteImage" action.
.DESCRIPTION
Use this cmdlet to create an option parser for MS SQL Server 2012 setup "CompleteImage" action.
Note that INSTANCEID parameter value MUST be the same as specified on "PrepareImage" phase.
All documented option are supported. See the following link for details:
http://msdn.microsoft.com/en-us/library/ms144259.aspx
#>
$OptionParser = New-OptionParser
$OptionParser.AddOption((New-Option "ACTION" -String -Constraints "CompleteImage"), $true, "CompleteImage")
$OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true)
$OptionParser.AddOption((New-Option "ENU" -Switch))
$OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String))
$OptionParser.AddOption((New-Option "ERRORREPORTING" -Boolean))
$OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch))
$OptionParser.AddOption((New-Option "INSTANCEID" -String), $true, "MSSQLSERVER")
$OptionParser.AddOption((New-Option "INSTANCENAME" -String), $true, "MSSQLSERVER")
$OptionParser.AddOption((New-Option "PID" -String))
$OptionParser.AddOption((New-Option "Q" -Switch))
$OptionParser.AddOption((New-Option "QS" -Switch))
$OptionParser.AddOption((New-Option "SQMREPORTING" -Boolean))
$OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch))
$OptionParser.AddOption((New-Option "AGTSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "AGTSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "AGTSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "BROWSERSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "ENABLERANU" -Switch))
$OptionParser.AddOption((New-Option "INSTALLSQLDATADIR" -String))
$OptionParser.AddOption((New-Option "SAPWD" -String))
$OptionParser.AddOption((New-Option "SECURITYMODE" -String -Constrainrs ("SQL")))
$OptionParser.AddOption((New-Option "SQLBACKUPDIR" -String))
$OptionParser.AddOption((New-Option "SQLCOLLATION" -String))
$OptionParser.AddOption((New-Option "SQLSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "SQLSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "SQLSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME")
$OptionParser.AddOption((New-Option "SQLTEMPDBDIR" -String))
$OptionParser.AddOption((New-Option "SQLTEMPDBLOGDIR" -String))
$OptionParser.AddOption((New-Option "SQLUSERDBDIR" -String))
$OptionParser.AddOption((New-Option "SQLUSERDBLOGDIR" -String))
$OptionParser.AddOption((New-Option "FILESTREAMLEVEL" -String -Constraints ("0", "1", "2", "3")))
$OptionParser.AddOption((New-Option "FILESTREAMSHARENAME" -String))
$OptionParser.AddOption((New-Option "FTSVCACCOUNT" -String))
$OptionParser.AddOption((New-Option "FTSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "NPENABLED" -Boolean))
$OptionParser.AddOption((New-Option "TCPENABLED" -Boolean))
$OptionParser.AddOption((New-Option "RSINSTALLMODE" -String -Constraints ("SharePointFilesOnlyMode", "DefaultNativeMode", "FilesOnlyMode")))
$OptionParser.AddOption((New-Option "RSSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "RSSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "RSSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled")))
return $OptionParser
}
function New-OptionParserCompleteImageSP1U2 {
<#
.SYNOPSIS
Creates an option parser for MS SQL Server 2012 setup "CompleteImage" action.
.DESCRIPTION
Use this cmdlet to create an option parser for MS SQL Server 2012 setup "CompleteImage" action.
This cmdlet should be used only for MS SQL Server 2012 SP1 Cimilative Update 2 or later.
All documented option are supported. See the following link for details:
http://msdn.microsoft.com/en-us/library/ms144259.aspx
#>
$OptionParser = New-OptionParser
$OptionParser.AddOption((New-Option "ACTION" -String -Constraints "CompleteImage"), $true, "CompleteImage")
$OptionParser.AddOption((New-Option "IACCEPTSQLSERVERLICENSETERMS" -Switch), $true)
$OptionParser.AddOption((New-Option "ENU" -Switch))
$OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String))
$OptionParser.AddOption((New-Option "ERRORREPORTING" -Boolean))
$OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch))
$OptionParser.AddOption((New-Option "INSTANCEID" -String))
$OptionParser.AddOption((New-Option "INSTANCENAME" -String))
$OptionParser.AddOption((New-Option "PID" -String))
$OptionParser.AddOption((New-Option "Q" -Switch))
$OptionParser.AddOption((New-Option "QS" -Switch))
$OptionParser.AddOption((New-Option "SQMREPORTING" -Boolean))
$OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch))
$OptionParser.AddOption((New-Option "AGTSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "AGTSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "AGTSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "BROWSERSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "ENABLERANU" -Switch))
$OptionParser.AddOption((New-Option "INSTALLSQLDATADIR" -String))
$OptionParser.AddOption((New-Option "SAPWD" -String))
$OptionParser.AddOption((New-Option "SECURITYMODE" -String -Constrainrs ("SQL")))
$OptionParser.AddOption((New-Option "SQLBACKUPDIR" -String))
$OptionParser.AddOption((New-Option "SQLCOLLATION" -String))
$OptionParser.AddOption((New-Option "SQLSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "SQLSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "SQLSVCSTARTUPTYPE" -String -Constraints ("Manual", "Automatic", "Disabled")))
$OptionParser.AddOption((New-Option "SQLSYSADMINACCOUNTS" -String), $true, "$ENV:USERDOMAIN\$ENV:USERNAME")
$OptionParser.AddOption((New-Option "SQLTEMPDBDIR" -String))
$OptionParser.AddOption((New-Option "SQLTEMPDBLOGDIR" -String))
$OptionParser.AddOption((New-Option "SQLUSERDBDIR" -String))
$OptionParser.AddOption((New-Option "SQLUSERDBLOGDIR" -String))
$OptionParser.AddOption((New-Option "FILESTREAMLEVEL" -String -Constraints ("0", "1", "2", "3")))
$OptionParser.AddOption((New-Option "FILESTREAMSHARENAME" -String))
$OptionParser.AddOption((New-Option "FTSVCACCOUNT" -String))
$OptionParser.AddOption((New-Option "FTSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "NPENABLED" -Boolean))
$OptionParser.AddOption((New-Option "TCPENABLED" -Boolean))
$OptionParser.AddOption((New-Option "RSINSTALLMODE" -String -Constraints ("SharePointFilesOnlyMode", "DefaultNativeMode", "FilesOnlyMode")))
$OptionParser.AddOption((New-Option "RSSVCACCOUNT" -String), $true, "NT AUTHORITY\Network Service")
$OptionParser.AddOption((New-Option "RSSVCPASSWORD" -String))
$OptionParser.AddOption((New-Option "RSSVCStartupType" -String -Constraints ("Manual", "Automatic", "Disabled")))
return $OptionParser
}
function New-OptionParserUpgrade {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserEditionUpgrade {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserRepair {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserRebuilddatabase {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserUninstall {
<#
.SYNOPSIS
Creates an option parser for MS SQL Server 2012 setup "INSTALL" action.
.DESCRIPTION
Use this cmdlet to create an option parser for MS SQL Server 2012 setup "INSTALL" action.
All documented option are supported. See the following link for details:
http://msdn.microsoft.com/en-us/library/ms144259.aspx
#>
$OptionParser = New-OptionParser
$OptionParser.AddOption((New-Option "ACTION" -String -Constraints "UNINSTALL"), $true, "UNINSTALL")
$OptionParser.AddOption((New-Option "CONFIGURATIONFILE" -String))
$OptionParser.AddOption((New-Option "FEATURES" -List -Constraints ("SQL","SQLEngine","Replication","FullText","DQ","AS","RS","DQC","IS","MDS","Tools","BC","BOL","BIDS","Conn","SSMS","ADV_SSMS","DREPLAY_CTLR","DREPLAY_CLT","SNAC_SDK","SDK","LocalDB")), $true)
$OptionParser.AddOption((New-Option "INDICATEPROGRESS" -Switch))
$OptionParser.AddOption((New-Option "INSTANCENAME" -String), $true, "MSSQLSERVER")
$OptionParser.AddOption((New-Option "Q" -Switch))
$OptionParser.AddOption((New-Option "HIDECONSOLE" -Switch))
return $OptionParser
}
function New-OptionParserInstallFailoverCluster {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserPrepareFailoverCluster {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserCompleteFailoverCluster {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserUpgrade {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserAddNode {
# ToDo: Implement
throw "Not yet implemented"
}
function New-OptionParserRemoveNode {
# ToDo: Implement
throw "Not yet implemented"
}

View File

@ -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."
}
}
}

View File

@ -0,0 +1,151 @@
trap {
&$TrapHandler
}
function Select-CliXmlBlock {
param (
[String] $Path,
[String] $OutFile = [IO.Path]::GetTempFileName()
)
$TagFound = $false
Get-Content $Path |
ForEach-Object {
if ($_ -eq '#< CLIXML') {
$TagFound = $true
}
if ($TagFound) {
Add-Content -Path $OutFile -Value $_
}
}
$OutFile
}
function Start-PowerShellProcess {
param (
[String] $Command,
$Credential = $null,
[Switch] $IgnoreStdErr,
[Switch] $NoBase64
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
$StdOut = [IO.Path]::GetTempFileName()
$StdErr = [IO.Path]::GetTempFileName()
$ArgumentList = @('-OutputFormat', 'XML')
if ($NoBase64) {
$TmpScript = [IO.Path]::GetTempFileName()
Rename-Item -Path "$TmpScript" -NewName "$TmpScript.ps1" -Force
$TmpScript = "$TmpScript.ps1"
Write-LogDebug $TmpScript
$Command | Out-File $TmpScript
$ArgumentList += @('-File', "$TmpScript")
}
else {
$Bytes = [Text.Encoding]::Unicode.GetBytes($Command)
$EncodedCommand = [Convert]::ToBase64String($Bytes)
Write-LogDebug $EncodedCommand
$ArgumentList += @('-EncodedCommand', $EncodedCommand)
}
Write-LogDebug $ArgumentList
Write-Log "Starting external PowerShell process ..."
if ($Credential -eq $null) {
$Process = Start-Process -FilePath 'powershell.exe' `
-ArgumentList @($ArgumentList) `
-RedirectStandardOutput $StdOut `
-RedirectStandardError $StdErr `
-NoNewWindow `
-Wait `
-PassThru
}
else {
$Process = Start-Process -FilePath 'powershell.exe' `
-ArgumentList @($ArgumentList) `
-RedirectStandardOutput $StdOut `
-RedirectStandardError $StdErr `
-Credential $Credential `
-NoNewWindow `
-Wait `
-PassThru
}
Write-Log "External PowerShell process exited with exit code '$($Process.ExitCode)'."
#if ($ArgumentList -contains '-File') {
# Remove-Item -Path $TmpScript -Force
#}
$ErrorActionPreferenceSaved = $ErrorActionPreference
$ErrorActionPreference = 'SilentlyContinue'
Write-LogDebug "StdOut file is '$StdOut'"
Write-LogDebug "StdErr file is '$StdErr'"
if ((Get-Item $StdOut).Length -gt 0) {
try {
Write-LogDebug "Loading StdOut from '$StdOut'"
$TmpFile = Select-CliXmlBlock $StdOut
$StdOutObject = Import-Clixml $TmpFile
Write-LogDebug "<StdOut>"
Write-LogDebug ($StdOutObject)
Write-LogDebug "</StdOut>"
$StdOutObject
#Remove-Item -Path $TmpFile -Force
}
catch {
Write-LogDebug "An error occured while loading StdOut from '$TmpFile'"
}
}
if ((Get-Item $StdErr).Length -gt 0) {
try {
Write-LogDebug "Loading StdErr ..."
$TmpFile = Select-CliXmlBlock $StdErr
$StdErrObject = Import-Clixml $TmpFile
Write-LogDebug "<StdErr>"
Write-LogDebug ($StdErrObject)
Write-LogDebug "</StdErr>"
if (-not $IgnoreStdErr) {
$StdErrObject
}
#Remove-Item -Path $TmpFile -Force
}
catch {
Write-LogDebug "An error occured while loading StdErr from '$TmpFile'"
}
}
$ErrorActionPreference = $ErrorActionPreferenceSaved
if ($Process.ExitCode -ne 0) {
throw("External PowerShell process exited with code '$($Process.ExitCode)'")
}
#Remove-Item $StdOut -Force
#Remove-Item $StdErr -Force
}
}

View File

@ -0,0 +1,60 @@
trap {
&$TrapHandler
}
function Update-ServiceConfig {
param (
[String] $Name,
[String] $RunAsUser = '',
[String] $DomainName = '.',
[String] $Password = '',
[Switch] $RunAsLocalService
)
begin {
Show-InvocationInfo $MyInvocation
}
end {
Show-InvocationInfo $MyInvocation -End
}
process {
trap {
&$TrapHandler
}
$ArgumentList = @('config', "`"$Name`"")
if ($RunAsLocalService) {
$ArgumentList += @("obj=", "`"NT AUTHORITY\LocalService`"")
}
elseif ($RunAsUser -ne '') {
$ArgumentList += @("obj=", "`"$DomainName\$RunAsUser`"", "password=", "`"$Password`"")
}
$Process = Exec 'sc.exe' $ArgumentList -PassThru -RedirectStreams
if ($Process.ExitCode -ne 0) {
throw "Command 'sc.exe' returned exit code '$($Process.ExitCode)'"
}
$NtRights = "C:\Murano\Tools\ntrights.exe"
if (-not ([IO.File]::Exists($NtRights))) {
throw "File '$NtRights' not found."
}
$Process = Exec $NtRights @('-u', "$DomainName\$RunAsUser", '+r', 'SeServiceLogonRight') -RedirectStreams -PassThru
if ($Process.ExitCode -ne 0) {
throw "Command '$NtRights' returned exit code '$($Process.ExitCode)'"
}
$Process = Exec $NtRights @('-u', "$DomainName\$RunAsUser", '+r', 'SeBatchLogonRight') -RedirectStreams -PassThru
if ($Process.ExitCode -ne 0) {
throw "Command '$NtRights' returned exit code '$($Process.ExitCode)'"
}
}
}

View File

@ -0,0 +1,126 @@
name: Active Directory
type: activeDirectory
description: >-
<strong> The Active Directory Service </strong>
includes one primary and optionally a few secondary
Domain Controllers, with DNS
unitTemplates:
- isMaster: true
recoveryPassword: {YAQL: $.serviceConfiguration.recoveryPassword}
- isMaster: false
recoveryPassword: {YAQL: $.serviceConfiguration.recoveryPassword}
forms:
- serviceConfiguration:
fields:
- name: configuration
type: string
hidden: true
initial: standalone
- name: name
type: string
label: Domain Name
description: >-
Enter a desired name for a new domain. This name should fit to
DNS Domain Name requirements: it should contain
only A-Z, a-z, 0-9, (.) and (-) and should not end with a dash.
DNS server will be automatically set up on each of the Domain
Controller instances. Note: Only first 15 characters or characters
before first period is used as NetBIOS name.
attributeNames: [name, domain]
minLength: 2
maxLength: 255
regexpValidator: '^[0-9A-Za-z](?!--)[0-9A-Za-z\-]{0,13}[0-9A-Za-z]\.[0-9A-Za-z][0-9A-Za-z\-]{0,61}[0-9A-Za-z]$'
errorMessages:
invalid: >-
Only letters, numbers and dashes in the middle are
allowed. Period characters are allowed only when they are
used to delimit the components of domain style
names. Single-level domain is not appropriate.
helpText: >-
Just letters, numbers and dashes are allowed.
A dot can be used to create subdomains
- name: dcInstances
type: instance
label: Instance Count
description: >-
You can create several Active Directory instances by setting
instance number larger than one. One primary Domain Controller
and a few secondary DCs will be created.
attributeNames: units
minValue: 1
maxValue: 100
initial: 1
helpText: Enter an integer value between 1 and 100
- name: adminAccountName
type: string
label: Account Name
initial: Administrator
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: 'Just letters, numbers, underscores and hyphens are allowed.'
- name: adminPassword
type: password
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
Once you forget your password you won't be able to
operate the service until recovery password would be entered. So it's
better for Recovery and Administrator password to be different.
- name: recoveryPassword
type: password
label: Recovery password
attributeNames: false
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: {YAQL: $.serviceConfiguration.dcInstances < 2 or not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
message: Incrementation symbol "#" is required in the Hostname template
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,104 @@
name: ASP.NET Application
type: aspNetApp
description: >-
<strong> The ASP.NET Application Service </strong> installs
custom application onto one IIS Web Server
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
description: ASP.NET application will be installed onto one IISWeb Server
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: dcInstances
type: instance
hidden: true
attributeNames: units
initial: 1
- name: adminPassword
type: password
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
- name: domain
type: domain
label: Domain
required: false
description: >-
Service can be joined to the Active Directory domain. If you want to
create an AD domain create the AD Service first.
helpText: Optional field for a domain to which service can be joined
- name: repository
type: string
label: Git repository
description: >-
URL of a git repository with the application you want to deploy.
regexpValidator: '/(\w+://)(.+@)*([\w\d\.]+)(:[\d]+)?/*(.*)/i'
errorMessages:
invalid: Enter correct git repository url
helpText: Enter a valid git repository URL
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,129 @@
name: ASP.NET Application Web Farm
type: aspNetAppFarm
description: >-
<strong> The ASP.NET Farm Service </strong> installs a custom application
on a load-balanced array of IIS servers
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
description: >-
The ASP.NET application will be installed on a number of IIS Web
Servers, and load balancing will be configured.
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: username
type: string
hidden: true
initial: Administrator
attributeNames: credentials.username
- name: adminPassword
type: password
attributeNames: [adminPassword, credentials.password]
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
- name: domain
type: domain
label: Domain
required: false
description: >-
Service can be joined to the Active Directory domain. If you want to
create an AD domain create the AD Service first.
helpText: Optional field for a domain to which service can be joined
- name: repository
type: string
label: Git repository
description: >-
URL of a git repository with the application you want to deploy.
regexpValidator: '/(\w+://)(.+@)*([\w\d\.]+)(:[\d]+)?/*(.*)/i'
errorMessages:
invalid: Enter correct git repository url
helpText: Enter a valid git repository URL
- name: dcInstances
type: instance
label: Instance Count
description: >-
Several instances with ASP.NET application can be created at one time.
attributeNames: units
minValue: 2
maxValue: 100
initial: 2
helpText: Enter an integer value between 2 and 100
- name: loadBalancerPort
type: integer
label: Load Balancer port
minValue: 1
maxValue: 65536
initial: 80
description: Specify port number where Load Balancer will be running
helpText: Enter an integer value from 1 to 65536
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: {YAQL: not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
message: Incrementation symbol "#" is required in the Hostname template
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,79 @@
name: Demo Service
type: demoService
description: >-
<strong> Demo Service </strong>
shows how Murano is working.
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: configuration
type: string
hidden: true
initial: standalone
- name: name
type: string
label: Service Name
description: >-
To identify your service in logs please specify a service name
- name: dcInstances
type: instance
label: Instance Count
description: >-
Murano can provision more then one instance of the service at a time.
For a demo scenario only 2 instances are allowed.
attributeNames: units
minValue: 1
maxValue: 2
initial: 2
helpText: Enter 1 and 2 value
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: {YAQL: not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
message: Incrementation symbol "#" is required in the Hostname template
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,83 @@
name: Demo Service
type: demoService
description: >-
<strong> Demo Service </strong>
shows how Murano is working.
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: configuration
type: string
hidden: true
initial: standalone
- name: name
type: string
label: Service Name
description: >-
To identify your service in logs please specify a service name
- name: dcInstances
type: instance
label: Instance Count
description: >-
Murano can provision more then one instance of the service at a time.
For a demo scenario only 2 instances are allowed.
attributeNames: units
minValue: 1
maxValue: 2
initial: 2
<<<<<<< HEAD
helpText: Enter 1 and 2 value
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: {YAQL: not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
message: Incrementation symbol "#" is required in the Hostname template
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false
=======
helpText: Enter 1 and 2 value
>>>>>>> 0dffd2a... Add new service for demo

View File

@ -0,0 +1,230 @@
name: MS SQL Server Cluster
type: msSqlClusterServer
description: >-
<strong> The MS SQL Failover Cluster </strong> installs
Microsoft SQL Failover Cluster Server
unitTemplates:
- isMaster: true
isSync: true
name: 'node-#'
- isMaster: false
isSync: true
name: 'node-#'
- isMaster: false
isSync: false
name: 'node-#'
forms:
- serviceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
description: MS SQL Failover Cluster
# temporaryHack
widgetMedia:
js: [muranodashboard/js/mixed-mode.js, muranodashboard/js/external-ad.js]
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: adminPassword
type: password
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
- name: externalAD
type: boolean
label: Active Directory is configured by the System Administrator
widgetAttrs: # temporary hack
class: external-ad
required: false
- name: domainAdminUserName
type: string
label: Active Directory User
enabled: {YAQL: $.serviceConfiguration.externalAD}
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
- name: domainAdminPassword
type: password
label: Active Directory Password
enabled: {YAQL: $.serviceConfiguration.externalAD}
- name: domain
type: domain
label: Domain
enabled: {YAQL: not $.serviceConfiguration.externalAD}
description: >-
Service can be joined to the Active Directory domain. If you want to
create an AD domain create the AD Service first.
helpText: Optional field for a domain to which service can be joined
- name: mixedModeAuth
type: boolean
label: Mixed-mode Authentication
initial: true
required: false
description: >-
Mixed authentication mode allows the use of Windows
credentials but supplements them with local SQL Server user
accounts that the administrator may create and maintain within
SQL Server. If this mode is on SA password is required
- name: saPassword
type: password
label: SA Password
description: Set system administrator password for the MS SQL Server.
helpText: SQL server System Administrator account
enabled: {YAQL: $.serviceConfiguration.mixedModeAuth}
- clusterConfiguration:
fields:
- name: clusterIP
type: clusterip
label: Cluster Static IP
description: Specify a valid IPv4 fixed IP.
- name: clusterName
type: string
label: Cluster Name
helpText: Service name for new SQL Cluster service
description: >-
Specify a name of a cluster. Just A-Z, a-z, 0-9, dash and underline are allowed.
- name: agGroupName
type: string
label: Availability Group Name
helpText: Name of AG during SQL setup
regexpValidator: '^[A-Za-z0-9_-]+$'
description: >-
Specify a name of an AG. Just A-Z, a-z, 0-9, dash and underline are allowed.
- name: agListenerName
type: string
label: Availability Group Listener Name
helpText: FQDN name of a new DNS entry for AG Listener endpoint
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
description: >-
Specify a name of an AG Listener . Just A-Z, a-z, 0-9, dash and underline are allowed.
- name: agListenerIP
type: clusterip
label: Availability Group Listener IP
description: Specify a valid IPv4 fixed IP.
- name: sqlServiceUserName
type: string
label: SQL User Name
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
description: User name that will be created to manage cluster instances.
- name: sqlServicePassword
type: password
label: SQL User Password
description: User password that will be created to manage cluster instances.
- name: dcInstances
type: instance
label: Instance Count
minValue: 2
maxValue: 5
initial: 2
attributeNames: false
helpText: Enter an integer value between 2 and 5
description: Microsoft SQL Failover Cluster includes up to 5 instances.
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: {YAQL: not $.clusterConfiguration.unitNamingPattern.bool() or '#' in $.clusterConfiguration.unitNamingPattern}
message: Incrementation symbol "#" is required in the Hostname template
# if IP is not valid on its own, it will be empty - the
# first check is needed to not emit comparison error when
# both IPs are not valid
- expr: {YAQL: not $.clusterConfiguration.clusterIP.bool() or $.clusterConfiguration.clusterIP != $.clusterConfiguration.agListenerIP}
message: Listener IP and Cluster Static IP should be different
- unitsConfiguration:
fields:
- name: nodes
type: table
label: Nodes
attributeNames: units
columns:
- columnName: name
columnType: label
title: Node
- columnName: isSync
columnType: checkbox
title: Sync
- columnName: isMaster
columnType: radio
title: Master
initial: {YAQL: $.clusterConfiguration.dcInstances}
description: >-
Configure cluster instances. Cluster node quantity can be set
with 'Add' and 'Remove' buttons. Configure Sync mode by
enabling corresponding checkbox. All other nodes will be in
Async mode. Just 2 nodes are allowed to be Sync. Also one
Master node need to be selected. SQL Failover cluster has
limit of 5 instances.
- name: databases
type: databaselist
label: Database list
description: >-
Specify names for new databases which will be created as part
of service installation. Here should come comma-separated list
of database names, where each name has the following syntax:
first symbol should be latin letter or underscore; subsequent
symbols can be latin letter, numeric, underscore, at sign,
number sign or dollar sign.
helpText: Enter comma separated list of databases that will be created
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,114 @@
name: MS SQL Server
type: msSqlServer
description: >-
<strong> The MS SQL Service </strong> installs an instance of
Microsoft SQL Server
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
description: MS SQL Server
# temporaryHack
widgetMedia:
js: [muranodashboard/js/mixed-mode.js]
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: dcInstances
type: instance
hidden: true
attributeNames: units
initial: 1
- name: adminPassword
type: password
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
- name: domain
type: domain
label: Domain
required: false
description: >-
Service can be joined to the Active Directory domain. If you want to
create an AD domain create the AD Service first.
helpText: Optional field for a domain to which service can be joined
- name: mixedModeAuth
type: boolean
label: Mixed-mode Authentication
initial: true
required: false
description: >-
Mixed authentication mode allows the use of Windows
credentials but supplements them with local SQL Server user
accounts that the administrator may create and maintain within
SQL Server. If this mode is on SA password is required
- name: saPassword
type: password
label: SA Password
description: Set system administrator password for the MS SQL Server.
helpText: SQL server System Administrator account
required: {YAQL: $.serviceConfiguration.mixedModeAuth}
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,95 @@
name: Internet Information Services
type: webServer
description: >-
<strong> The Internet Information Service </strong>
sets up an IIS server and joins it into an existing domain
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
description: Standalone IIS Server
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: dcInstances
type: instance
hidden: true
attributeNames: units
initial: 1
- name: adminPassword
type: password
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
- name: domain
type: domain
label: Domain
required: false
description: >-
Service can be joined to the Active Directory domain. If you want to
create an AD domain create the AD Service first.
helpText: Optional field for a domain to which service can be joined
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

View File

@ -0,0 +1,116 @@
name: Internet Information Services Web Farm
type: webServerFarm
description: >-
<strong> The IIS Farm Service </strong> sets up a load-balanced set of IIS servers
unitTemplates:
- {}
forms:
- serviceConfiguration:
fields:
- name: title
type: string
hidden: true
required: false
attributeNames: false
description: A load-balanced array of IIS servers
- name: name
type: string
label: Service Name
description: >-
Enter a desired name for a service. Just A-Z, a-z, 0-9, dash and
underline are allowed.
minLength: 2
maxLength: 64
regexpValidator: '^[-\w]+$'
errorMessages:
invalid: Just letters, numbers, underscores and hyphens are allowed.
helpText: Just letters, numbers, underscores and hyphens are allowed.
- name: username
type: string
hidden: true
initial: Administrator
attributeNames: credentials.username
- name: adminPassword
type: password
attributeNames: [adminPassword, credentials.password]
label: Administrator password
descriptionTitle: Passwords
description: >-
Windows requires strong password for service administration.
Your password should have at least one letter in each
register, a number and a special character. Password length should be
a minimum of 7 characters.
- name: domain
type: domain
label: Domain
required: false
description: >-
Service can be joined to the Active Directory domain. If you want to
create an AD domain create the AD Service first.
helpText: Optional field for a domain to which service can be joined
- name: dcInstances
type: instance
minValue: 2
maxValue: 100
attributeNames: [units, instanceCount]
initial: 2
label: Instance Count
description: Several instances with IIS Service can be created at one time.
helpText: Enter an integer value between 2 and 100
- name: loadBalancerPort
type: integer
label: Load Balancer port
minValue: 1
maxValue: 65536
initial: 80
description: Specify port number where Load Balancer will be running
helpText: Enter an integer value from 1 to 65536
- name: unitNamingPattern
type: string
label: Hostname template
description: >-
For your convenience all instance hostnames can be named
in the same way. Enter a name and use # character for incrementation.
For example, host# turns into host1, host2, etc. Please follow Windows
hostname restrictions.
required: false
regexpValidator: '^(([a-zA-Z0-9#][a-zA-Z0-9-#]*[a-zA-Z0-9#])\.)*([A-Za-z0-9#]|[A-Za-z0-9#][A-Za-z0-9-#]*[A-Za-z0-9#])$'
helpText: Optional field for a machine hostname template
# temporaryHack
widgetMedia:
js: [muranodashboard/js/support_placeholder.js]
css: {all: [muranodashboard/css/support_placeholder.css]}
validators:
# if unitNamingPattern is given and dcInstances > 1, then '#' should occur in unitNamingPattern
- expr: {YAQL: not $.serviceConfiguration.unitNamingPattern.bool() or ('#' in $.serviceConfiguration.unitNamingPattern)}
message: Incrementation symbol "#" is required in the Hostname template
- instanceConfiguration:
fields:
- name: title
type: string
required: false
hidden: true
attributeNames: false
descriptionTitle: Instance Configuration
description: Specify some instance parameters on which service would be created.
- name: flavor
type: flavor
label: Instance flavor
description: >-
Select registered in Openstack flavor. Consider that service performance
depends on this parameter.
required: false
- name: osImage
type: image
label: Instance image
description: >-
Select valid image for a service. Image should already be prepared and
registered in glance.
- name: availabilityZone
type: azone
label: Availability zone
description: Select availability zone where service would be installed.
required: false

321
Services/workflows/AD.xml Normal file
View File

@ -0,0 +1,321 @@
<workflow>
<rule match="$.services[?(@.type == 'activeDirectory' and @.domain)].units[?(not @.isMaster)]"
desc="Slave units of AD services">
<set path="domain">
<select path="::domain"/>
</set>
<mute/>
</rule>
<rule match="$.services[?(@.type == 'activeDirectory' and @.osImage.name)].units[?(@.state.hostname and not @.temp.instanceName)]"
desc="Units of AD services which have got hostname and image assigned, but instances not deployed yet">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Windows" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="networkName">network-<select path="/id"/></mapping>
<mapping name="userData">
<prepare-user-data>
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
<mapping name="instanceType"><select path="::flavor" default="m1.medium"/></mapping>
<mapping name="imageName"><select path="::osImage.name"/></mapping>
<mapping name="availabilityZone"><select path="::availabilityZone" default="nova"/></mapping>
</map>
</parameter>
<success>
<set path="temp.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Instance <select path="state.hostname"/> (<select path="name"/>) created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy instance <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type == 'activeDirectory')].units[?(@.temp.instanceName and @.adminPassword and @.adminPassword != @.state.adminPassword)]"
desc="Units of AD services which have got instances deployed but the local admin passwords not set yet">
<send-command template="SetPassword" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="adminPassword">
<select path="adminPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.adminPassword">
<select path="adminPassword"/>
</set>
</success>
<failure>
<report entity="unit" level="warning">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to set admin password on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<mute/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'activeDirectory' and @.adminPassword and @.adminPassword != @.state.domainAdminPassword)].units[?(@.temp.instanceName and @.isMaster)]"
desc="Deployed master-units of AD services for which the domain admin password is not set yet">
<send-command template="SetPassword" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="adminPassword">
<select path="::adminPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.domainAdminPassword">
<select path="::adminPassword"/>
</set>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to set domain administrator password on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'activeDirectory' and @.state.primaryDc is None)].units[?(@.temp.instanceName and @.isMaster)]"
desc="Deployed master-units of AD services on which the Primary DC has not been installed yet ">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating Primary Domain Controller on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="CreatePrimaryDC" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domain">
<select path="::domain"/>
</mapping>
<mapping name="recoveryPassword">
<select path="recoveryPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.primaryDc"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Primary Domain Controller created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to create a Primary DC on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'activeDirectory' and @.state.primaryDc and not @.state.primaryDcIp)].units[?(@.temp.instanceName and @.isMaster)]"
desc="Master Units of AD services on which the Primary Domain Controller has been configured but DNS ip has not been asked for">
<send-command template="AskDnsIp" result="ip" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<success>
<set path="::state.primaryDcIp">
<select source="ip" path="0.Result.0"/>
</set>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable assign DNS IP on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type != 'activeDirectory')].units[?(@.state.domain and not @.domain)]"
desc="Any non-AD services of the environment which has been part of the domain but needs to leave it">
<send-command template="LeaveDomain" error="exception">
<parameter name="unit">
<select path="id" source="unit"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domain">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<report entity="unit">
<parameter name="id"><select path="id" source="unit"/></parameter>
<parameter name="text">Unit <select path="state.hostname" source="unit"/> (<select path="name" source="unit"/>) has left domain <select path="state.domain"/></parameter>
</report>
<set path="state.domain"><null/></set>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unit <select path="state.hostname" source="unit"/> (<select path="name" source="unit"/>) was unable to leave the domain due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$..units[?(@.temp.instanceName and @.domain and @.domain != @.state.domain)]"
desc="Any deployed unit which need to enter the domain">
<set path="#unit">
<select/>
</set>
<set path="#service">
<select path="::"/>
</set>
<rule desc="Domain controller exists with the assigned DNS IP">
<parameter name="match">/$.services[?(@.type == 'activeDirectory' and @.domain == '<select path="domain"/>' and @.state.primaryDcIp)]</parameter>
<send-command template="JoinDomain" error="exception">
<parameter name="unit">
<select path="id" source="unit"/>
</parameter>
<parameter name="service">
<select path="id" source="service"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domain">
<select path="domain"/>
</mapping>
<mapping name="domainPassword">
<select path="adminPassword"/>
</mapping>
<mapping name="dnsIp">
<select path="state.primaryDcIp"/>
</mapping>
<mapping name="domainUser">
<select path="adminAccountName" default="Administrator"/>
</mapping>
<mapping name="ouPath"></mapping>
</map>
</parameter>
<success>
<set path="state.domain" target="unit">
<select path="domain"/>
</set>
<set path="state.domainIp" target="unit">
<select path="state.primaryDcIp"/>
</set>
<report entity="unit">
<parameter name="id"><select path="id" source="unit"/></parameter>
<parameter name="text">Unit <select path="state.hostname" source="unit"/> (<select path="name" source="unit"/>) has joined domain <select path="domain"/></parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unit <select path="state.hostname" source="unit"/> (<select path="name" source="unit"/>) was unable to join the domain due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</rule>
<rule match="$.services[?(@.type == 'activeDirectory')].units[?(@.state.domain and not @.isMaster and not @.state.installed)]"
desc="Slave units of AD services which has not got secondary DC installed yet">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating Secondary Domain Controller on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="CreateSecondaryDC" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="recoveryPassword">
<select path="recoveryPassword"/>
</mapping>
<mapping name="domainPassword">
<select path="::adminPassword"/>
</mapping>
<mapping name="domain">
<select path="::domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.installed"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Secondary Domain Controller created</parameter>
</report>
<report entity="service">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Domain <select path="::domain"/> created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to create Secondary Domain Controller on unit <select path="state.hostname" /> (<select path="name" />) due to <select source="exception" path="0.messages.0" default="unknown Agent error"/> </parameter>
</report>
<report entity="service" level="error">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Unable to create domain <select path="::domain"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</workflow>

View File

@ -0,0 +1,174 @@
<workflow>
<rule match="$.services[?(@.type in ('webServer', 'aspNetApp', 'webServerFarm', 'aspNetAppFarm') and @.domain)].units[*]"
desc='Units of web services with domain'>
<set path="domain">
<select path="::domain"/>
</set>
<mute/>
</rule>
<rule match="$.services[?(@.type in ('webServer', 'aspNetApp', 'webServerFarm', 'aspNetAppFarm') and @.osImage.name)].units[?(@.state.hostname and not @.temp.instanceName)]"
desc="Units of web services having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Windows" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="networkName">network-<select path="/id"/></mapping>
<mapping name="userData">
<prepare-user-data>
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
<mapping name="instanceType"><select path="::flavor" default="m1.medium"/></mapping>
<mapping name="imageName"><select path="::osImage.name"/></mapping>
<mapping name="availabilityZone"><select path="::availabilityZone" default="nova"/></mapping>
</map>
</parameter>
<success>
<set path="temp.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Instance <select path="state.hostname"/> (<select path="name"/>) created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy instance <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type in ('webServerFarm', 'aspNetAppFarm'))].units[?(@.state.hostname and not @.temp.registeredWithLB)]"
desc="Units of web-farms services which have a hostname assigned but are not registered with LB">
<update-cf-stack template="LoadBalancer" result="outputs" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="lbPort"><select path="::loadBalancerPort"/></mapping>
<mapping name="lbName"><select path="::name"/></mapping>
</map>
</parameter>
<success>
<set path="temp.registeredWithLB"><true/></set>
<set path="::uri">http://<select source="outputs" path="LoadBalancerIP"/>:<select path="::loadBalancerPort"/></set>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to create a Server Farm load balancer on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type in ('webServer', 'aspNetApp', 'webServerFarm', 'aspNetAppFarm') and @.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.temp.instanceName)]"
desc="Units of web services which have got an instance deployed but has not got a correct admin password ">
<send-command template="SetPassword" error='exception'>
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="adminPassword">
<select path="::adminPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.adminPassword">
<select path="::adminPassword"/>
</set>
</success>
<failure>
<report entity="unit" level="warning">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to set admin password on unit <select path="state.hostname"/> (<select path="name"/>) <format-error error="exception"/></parameter>
</report>
<mute/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type in ('webServer', 'aspNetApp', 'webServerFarm', 'aspNetAppFarm'))].units[?(@.temp.instanceName and not @.state.iisInstalled)]"
desc="Units of web services which have got an instance deployed but have not got an IIS installed">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating IIS Web Server on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="InstallIIS" error='exception'>
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<success>
<set path="state.iisInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">IIS <select path="state.hostname"/> (<select path="name"/>) has started</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to install IIS on <select path="state.hostname"/> (<select path="name"/>) <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type in ('aspNetApp', 'aspNetAppFarm'))].units[?(@.state.iisInstalled and not @.state.webAppDeployed)]"
desc="Units of ASP.NET app services which have got IIS installed but not the WebApplication deployed">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Deploying WebApp <select path="::name"/> on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="DeployWebApp" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="repository">
<select path="::repository"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.webAppDeployed"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">WebApp <select path="::name"/> has been deployed on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy WebApp on <select path="state.hostname"/> (<select path="name"/>) <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</workflow>

View File

@ -0,0 +1,25 @@
<workflow>
<rule match="$.services[*].units[?(@.state.hostname is None)]" desc="Units with no hostname">
<set path="state.hostname">
<generate-hostname>
<parameter name="pattern"><select path="::unitNamingPattern"/></parameter>
<parameter name="service_id"><select path="::id"/></parameter>
</generate-hostname>
</set>
</rule>
<rule match="$[?(not @.state.deleted)]" desc="Search through all the environments..">
<rule match="$.services[*].units[*]" desc="If any units exists" limit="1">
<mute/>
<empty>
<delete-cf-stack>
<success>
<set path="/state.deleted"><true/></set>
</success>
</delete-cf-stack>
</empty>
</rule>
</rule>
</workflow>

View File

@ -0,0 +1,76 @@
<workflow>
<rule match="$.services[?(@.type == 'demoService')].units[*]"
desc='Service for demo purpose'>
</rule>
<rule match="$.services[?(@.type == 'demoService')].units[?(@.state.hostname and not @.temp.instanceName)]"
desc="Units of demo service having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Demo" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="userData">
<prepare-user-data template="Demo" initFile="demo_init.sh">
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
<mapping name="instanceType"><select path="::flavor" default="m1.medium"/></mapping>
<mapping name="imageName"><select path="::osImage.name"/></mapping>
<mapping name="availabilityZone"><select path="::availabilityZone" default="nova"/></mapping>
</map>
</parameter>
<success>
<set path="temp.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Instance <select path="state.hostname"/> (<select path="name"/>) created!</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy instance <select path="state.hostname"/> (<select path="name"/>) due to <select source="exception" path="message" default="unknown Heat error"/> </parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type == 'demoService')].units[?(@.temp.instanceName and not @.state.demoInstalled)]"
desc="Units of demo service which have got an instance deployed but have not got demo service installed">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating demo service on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="Demo" error='exception'>
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<success>
<set path="state.demoInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Demo service <select path="state.hostname"/> (<select path="name"/>) has started</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to install demo service on <select path="state.hostname"/> (<select path="name"/>) due to <select source="exception" path="0.messages.0" default="unknown Agent error"/> </parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</workflow>

View File

@ -0,0 +1,96 @@
<workflow>
<rule match="$.services[?(@.type != 'activeDirectory' and @.availabilityZone)].units[?(@.temp.instanceName and @.state.hostname and not @.domain)]"
desc="Units of Non-AD services with availability zone specified which are deployed and are not part of the domain">
<set path="#externalADmap">
<map>
<!-- ======================================================================= -->
<!-- Specify here parameters of domain controllers at each availability zone -->
<!-- ======================================================================= -->
<mapping name="nova">
<map>
<mapping name="domain">domain1</mapping>
<mapping name="domainUser">Administrator</mapping>
<mapping name="domainPassword">password1</mapping>
<mapping name="dnsIp">ip1</mapping>
<mapping name="ou"></mapping>
</map>
</mapping>
<mapping name="AnotherAvailabilityZone">
<map>
<mapping name="domain">domain2</mapping>
<mapping name="domainUser">Administrator</mapping>
<mapping name="domainPassword">password2</mapping>
<mapping name="dnsIp">ip2</mapping>
<mapping name="ou"></mapping>
</map>
</mapping>
<!-- ======================================================================= -->
</map>
</set>
<set path="#ad">
<select source="externalADmap">
<parameter name="path"><select path="::availabilityZone"/></parameter>
</select>
</set>
<rule>
<parameter name="match">$[?(@.state.domain != '<select path="domain" source="ad"/>')]</parameter>
<parameter name="desc">Units which are not part of the target domain but need to join</parameter>
<send-command template="JoinDomain" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domain">
<select path="domain" source="ad"/>
</mapping>
<mapping name="domainUser">
<select path="domainUser" source="ad"/>
</mapping>
<mapping name="domainPassword">
<select path="domainPassword" source="ad"/>
</mapping>
<mapping name="dnsIp">
<select path="dnsIp" source="ad"/>
</mapping>
<mapping name="ouPath">
<select path="ou" source="ad"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.domain">
<select path="domain" source="ad"/>
</set>
<set path="state.domainIp">
<select path="dnsIp" source="ad"/>
</set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unit <select path="state.hostname"/> (<select path="name"/>) has joined domain <select path="domain" source="ad"/></parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unit <select path="state.hostname"/> (<select path="name"/>) was unable to join the domain due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</rule>
</workflow>

View File

@ -0,0 +1,439 @@
<workflow>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.domain)].units[*]"
desc="Units of SQL Server Cluster services which are part of the domain">
<set path="domain">
<select path="::domain"/>
</set>
<mute/>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.osImage.name)].units[?(@.state.hostname and not @.temp.instanceName)]"
desc="Units of SQL Server Cluster services having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Windows" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="networkName">network-<select path="/id"/></mapping>
<mapping name="userData">
<prepare-user-data>
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
<mapping name="instanceType"><select path="::flavor" default="m1.medium"/></mapping>
<mapping name="imageName"><select path="::osImage.name"/></mapping>
<mapping name="availabilityZone"><select path="::availabilityZone" default="nova"/></mapping>
</map>
</parameter>
<success>
<set path="temp.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Instance <select path="state.hostname"/> (<select path="name"/>) created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy instance <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Applying address pair and opening SQL ports on <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="SQLCluster" error="exception">
<parameter name="mappings">
<map>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="clusterIp"><select path="::clusterIp"/></mapping>
</map>
</parameter>
<success>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Address pair and SQL ports are open on <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to assign address pair and open SQL ports on instance <select path="state.hostname"/> (<select path="name"/>) due to <select source="exception" path="message" default="unknown Heat error"/> </parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.domain and not @.domainAdminUserName and not @.domainAdminPassword)]"
desc="SQL Server Cluster service instance with domain configured but without admin account name/password">
<set path="#service">
<select/>
</set>
<rule desc="Domain controller exists with the assigned DNS IP">
<parameter name="match">/$.services[?(@.type == 'activeDirectory' and @.domain == '<select path="domain"/>')]</parameter>
<set path="domainAdminUserName" target="service"><select path="adminAccountName" default="Administrator"/></set>
<set path="domainAdminPassword" target="service"><select path="adminPassword"/></set>
</rule>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.temp.instanceName)]"
desc="Units of SQL Server Cluster services which have got an instance deployed but has not got a correct admin password">
<send-command template="SetPassword" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="adminPassword">
<select path="::adminPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.adminPassword">
<select path="::adminPassword"/>
</set>
</success>
<failure>
<report entity="unit" level="warning">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to set admin password on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<mute/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.domain and not @.state.failoverClusterPrerequisitesInstalled)]"
desc="Units of SQL Server Cluster services that are already joined AD domain">
<send-command template="SqlServerCluster/FailoverClusterPrerequisites" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.failoverClusterPrerequisitesInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Failover cluster prerequisites installed on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to install prerequisites on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and not @.state.failoverClusterCreated)].units[?(@.state.failoverClusterPrerequisitesInstalled)]" limit="1"
desc="First unit of SQL Server Cluster services that is already has failover cluster prerequisites installed">
<send-command template="SqlServerCluster/FailoverCluster" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="clusterName">
<select path="::clusterName"/>
</mapping>
<mapping name="clusterNodes">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="clusterIP">
<select path="::clusterIP"/>
</mapping>
<mapping name="shareServer">
<select path="state.domainIp"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.failoverClusterCreated"><true/></set>
<report entity="service">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Failover cluster created for SQL Server Cluster service (<select path="::name"/>)</parameter>
</report>
</success>
<failure>
<report entity="Service" level="error">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Unable to create failover cluster for SQL Server Service <select path="::name"/> due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.state.failoverClusterCreated and not @.state.agEnvironmentConfigured)].units[*]"
desc="First unit of SQL Server Cluster services that is already has failover cluster created">
<send-command template="SqlServerCluster/ConfigureEnvironmentForAOAG" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="primaryNode">
<select-single path=":$[?(@.isMaster)].state.hostname"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.agEnvironmentConfigured"><true/></set>
<report entity="service">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Environment for AlwaysOn Availability Group of SQL Server Cluster service (<select path="::name"/>) configured</parameter>
</report>
</success>
<failure>
<report entity="service" level="error">
<parameter name="id"><select path="::id"/></parameter>
<parameter name="text">Unable to configure the environment for AlwaysOn Availability Group of SQL Server Cluster service (<select path="::name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer' and @.state.agEnvironmentConfigured)].units[?(@.state.failoverClusterPrerequisitesInstalled and not @.state.sqlServerInstalled)]"
desc="All units of SQL Server Cluster services that is already has environment configured">
<send-command template="SqlServerCluster/InstallSqlServerForAOAG" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="sqlServiceAccountName">
<select path="::sqlServiceUserName"/>
</mapping>
<mapping name="sqlServiceAccountPassword">
<select path="::sqlServicePassword"/>
</mapping>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.sqlServerInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">SQL Server installed on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to install SQL Server on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.sqlServerInstalled and not @.state.alwaysOnInitialized)]"
desc="All units of SQL Server Cluster services that has SQL Server installed">
<send-command template="SqlServerCluster/InitializeAlwaysOn" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="nodeList">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="primaryNode">
<select-single path=":$[?(@.isMaster)].state.hostname"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.alwaysOnInitialized"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">AlwaysOn AG initialized for <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to initialize AlwaysOn AG for <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.alwaysOnInitialized and not @.state.primaryReplicaInitialized)]"
desc="All units of SQL Server Cluster services that has AlwaysOn initialized">
<send-command template="SqlServerCluster/InitializeAOAGPrimaryReplica" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="groupName">
<select path="::agGroupName"/>
</mapping>
<mapping name="nodeList">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="primaryNode">
<select-single path=":$[?(@.isMaster)].state.hostname"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
<mapping name="syncModeNodeList">
<select-all path=":$[?(@.isSync)].state.hostname"/>
</mapping>
<mapping name="listenerIP">
<select path="::agListenerIP"/>
</mapping>
<mapping name="listenerName">
<select path="::agListenerName"/>
</mapping>
<mapping name="databaseList">
<select path="::databases"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.primaryReplicaInitialized"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Primary replica for SQL Server AG initialized for <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to initialize primary replica for SQL Server AG for <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlClusterServer')].units[?(@.state.primaryReplicaInitialized and not @.state.secondaryReplicaInitialized)]"
desc="All units of SQL Server Cluster services that has primary replica initialized">
<send-command template="SqlServerCluster/InitializeAOAGSecondaryReplica" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="domainAdminAccountName">
<select path="::domainAdminUserName"/>
</mapping>
<mapping name="domainAdminAccountPassword">
<select path="::domainAdminPassword"/>
</mapping>
<mapping name="nodeList">
<select-all path=":$[*].state.hostname"/>
</mapping>
<mapping name="primaryNode">
<select-single path=":$[?(@.isMaster)].state.hostname"/>
</mapping>
<mapping name="domainName">
<select path="state.domain"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.secondaryReplicaInitialized"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Secondary replica for SQL Server AG initialized for <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to initialize secondary replica for SQL Server AG for <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</workflow>

View File

@ -0,0 +1,149 @@
<workflow>
<rule match="$.services[?(@.type == 'msSqlServer' and @.domain)].units[*]"
desc="Units of SQL Server services which are part of the domain">
<set path="domain">
<select path="::domain"/>
</set>
<mute/>
</rule>
<rule match="$.services[?(@.type == 'msSqlServer' and @.osImage.name)].units[?(@.state.hostname and not @.temp.instanceName)]"
desc="Units of SQL Server services having hostname and image names assigned but without instances">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Windows" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="networkName">network-<select path="/id"/></mapping>
<mapping name="userData">
<prepare-user-data>
<parameter name="hostname"><select path="state.hostname"/></parameter>
<parameter name="unit"><select path="id"/></parameter>
<parameter name="service"><select path="::id"/></parameter>
</prepare-user-data>
</mapping>
<mapping name="instanceType"><select path="::flavor" default="m1.medium"/></mapping>
<mapping name="imageName"><select path="::osImage.name"/></mapping>
<mapping name="availabilityZone"><select path="::availabilityZone" default="nova"/></mapping>
</map>
</parameter>
<success>
<set path="temp.instanceName"><select path="name"/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Instance <select path="state.hostname"/> (<select path="name"/>) created</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to deploy instance <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Opening SQL ports on <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="SQL-security" error="exception">
<parameter name="mappings">
<map>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
</map>
</parameter>
<success>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">SQL ports open on <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to open SQL ports on instance <select path="state.hostname"/> (<select path="name"/>) due to <select source="exception" path="message" default="unknown Heat error"/> </parameter>
</report>
<stop/>
</failure>
</update-cf-stack>
</rule>
<rule match="$.services[?(@.type == 'msSqlServer' and @.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.temp.instanceName)]"
desc="Units of SQL Server services which have got an instance deployed but has not got a correct admin password">
<send-command template="SetPassword" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="adminPassword">
<select path="::adminPassword"/>
</mapping>
</map>
</parameter>
<success>
<set path="::state.adminPassword">
<select path="::adminPassword"/>
</set>
</success>
<failure>
<report entity="unit" level="warning">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to set admin password on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<mute/>
</failure>
</send-command>
</rule>
<rule match="$.services[?(@.type == 'msSqlServer')].units[?(@.temp.instanceName and not @.state.msSqlServerInstalled and (not @.domain or @.domain == @.state.domain))]"
desc="Units of SQL Server services which have got an instance deployed but have not got an SQL Server installed">
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating MS SQL Server on unit <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<send-command template="InstallMsSqlServer" error="exception">
<parameter name="unit">
<select path="id"/>
</parameter>
<parameter name="service">
<select path="::id"/>
</parameter>
<parameter name="mappings">
<map>
<mapping name="saPassword">
<select path="::saPassword"/>
</mapping>
<mapping name="mixedModeAuth">
<select path="::mixedModeAuth"/>
</mapping>
</map>
</parameter>
<success>
<set path="state.msSqlServerInstalled"><true/></set>
<report entity="unit">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">MS SQL Server <select path="state.hostname"/> (<select path="name"/>) has started</parameter>
</report>
</success>
<failure>
<report entity="unit" level="error">
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Unable to install MS SQL Server on unit <select path="state.hostname"/> (<select path="name"/>) due to <format-error error="exception"/></parameter>
</report>
<stop/>
</failure>
</send-command>
</rule>
</workflow>