Automation–PowerShell Workflow Script Spotlight–Deploying Virtual Machine Manager Service Templates-More Examples!

Hello,

So I was  having an #8minutediscussionwithCharlesJoy recently, and we thought it could be a good idea to build upon his recent blog post on scripting Service Templates, to provide another set of examples.

Charles covered how you could create a tenant with VMM through PowerShell, and create/deploy objects on behalf of this tenant, leveraging the -ForOnBehalfOf and –OnBehalfOf switches in VMM cmdlets.

In today’s post, we’ll look at a PowerShell script showcasing how 3 very simple and specific actions can be achieved in a generic way (not using the –OnBehalfOf syntax):

  1. Deploy a Service Template
  2. Scale out a Service Template
  3. Assigning an encrypted Global Setting in a Service Template (in addition to a few standard non-encrypted Global Settings, just like Charles had in his post)

These examples could be used in any context : PowerShell, Service Management Automation (SMA), Orchestrator. While the syntaxes below will be extracts from SMA, I’ll actually finish the post by explaining how you could modify the scripts to have them run in Orchestrator as well.

 

The sample script

This single PowerShell workflow shows all the different items I’d like to show in this post:

  • It checks if a specific service name already exists (lines 17-24)
  • If it does not exist, the service is created, ans assigns the different global settings, including an encrypted setting (lines 41-58 – see the notes below, as this part of the script could be much shorter if there was no global settings and if the VM was not explicitely given a name)
  • If it exists already, the service is scaled out (lines 63-69)
  • The name of the new VM was actually computed before in the script (lines 28-35)
  • finally, the script outputs the name of the VM that was created (line 73)

In the sample below, the script actually deploys the template from the Oracle Self-Service Kit. The encrypted global setting “OracleUserPass” is used during VM deployment to install Oracle Database 12c with a specific Oracle Home User account (see the notes for more information).

 

001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 workflow DeployScaleOut-VMMTemplate { param ( [parameter(Mandatory=$true)] [string]$ServiceName ) $VMMServer = Get-AutomationVariable -Name 'Blog-STSample-VMMServerName' $VMMCreds = Get-AutomationPSCredential -Name 'Blog-STSample-VMMCreds' $VMPrefix = "ORCL-DEMO" $DomainNameFQDN = "CONTOSO.COM" $VMMCloud = "Cloud for Contoso BU" $VMMServiceTemplate = "Oracle Farm" #First, we check if the service already exists in VMM $ServiceExists = InlineScript { $ServiceExists = $false import-module virtualmachinemanager $result = Get-SCVMMServer -ComputerName $Using:VMMServer $Svc = Get-SCService -Name $Using:ServiceName If ($Svc) {$ServiceExists = $true} $ServiceExists }-PSComputerName $VMMServer -PSCredential $VMMCreds # Then we determine the name of the VM we need to create, using the chosen naming pattern # This is mandatory for scale out, not for creation (see the blog notes) $NbVM = InlineScript { import-module virtualmachinemanager $result = Get-SCVMMServer -ComputerName $Using:VMMServer $NbVM = (Get-VM | where-object {$_.Name -match $Using:VMPrefix}).Count $NbVM = $NbVM+1 $NbVM }-PSComputerName $VMMServer -PSCredential $VMMCreds $NewVMName = $VMPrefix + "-" + $NbVM + "." + $DomainNameFQDN If ($ServiceExists -eq $false) { #Create a new service InlineScript{ import-module virtualmachinemanager $result = Get-SCVMMServer -ComputerName $Using:VMMServer $Cloud = Get-SCCloud -Name $Using:VMMCloud $ST=Get-SCServiceTemplate -Name $Using:VMMServiceTemplate $ServiceConfig = New-SCServiceConfiguration -ServiceTemplate $ST -Name $Using:ServiceName -Cloud $Cloud Get-SCServiceSetting -ServiceConfiguration $ServiceConfig -Name "AdminPort" | Set-SCServiceSetting -Value "5501" Get-SCServiceSetting -ServiceConfiguration $ServiceConfig -Name "DBPort" | Set-SCServiceSetting -Value "1521" Get-SCServiceSetting -ServiceConfiguration $ServiceConfig -Name "LocalFolder" | Set-SCServiceSetting -Value "C:\Or12c" Get-SCServiceSetting -ServiceConfiguration $ServiceConfig -Name "OracleDBMedia" | Set-SCServiceSetting -Value "\\fileserver1\sources\Oracle\Database\12cR1\database" Get-SCServiceSetting -ServiceConfiguration $ServiceConfig -Name "OracleUserAcct" | Set-SCServiceSetting -Value "oracleuser" $SecurePass = "YouDidNotSeeAnything!01" | ConvertTo-SecureString -AsPlainText -Force Get-SCServiceSetting -ServiceConfiguration $ServiceConfig -Name "OracleUserPass" | Set-SCServiceSetting -SecureValue $SecurePass $CT = Get-SCComputerTierConfiguration -ServiceConfiguration $ServiceConfig $VMConfig = Get=SCVMConfiguration -ComputerTierConfiguration $CT Set-SCVMConfiguration -VMConfiguration $VMConfig -Name $Using:NewVMName -ComputerName $Using:NewVMName $NewService = New-SCService -ServiceConfiguration $ServiceConfig } -PSComputerName $VMMServer -PSCredential $VMMCreds } Else { #Scale out the existing service InlineScript{ import-module virtualmachinemanager $result = Get-SCVMMServer -ComputerName $Using:VMMServer $Svc = Get-SCService -Name $Using:ServiceName $CT = Get-SCComputerTier -Service $Svc $result = New-SCVirtualMachine -ComputerTier $CT -Name $Using:NewVMName -ComputerName $Using:NewVMName } -PSComputerName $VMMServer -PSCredential $VMMCreds } # We return the name of the VM that was created Return $NewVMName }

 

Notes :

  • The script does similar items multiple times through InlineScript – while it could be optimized, there are some benefits in doing so : you could have PowerShell checkpoint for easy retart. Plus the current formatting makes it easy to port this to an Orchestrator Runbook if needed (see the next paragraph in this blog post)
  • Both when creating and scaling out the service, the script explicitly assigns a name and computer name to the VM. While the VM name is mandatory when scaling out, no VM name or computer name is actually needed when creating the service, if you use a patterm in your service template in VMM. Here, I assign a name in both situations, to be consistent. Assigning the VM name and computer name when creating the service is at lines 54 to 56.
  • As a best practices, I try to use as many SMA variables (or Orchestrator variables) as possible, and some of the PowerShell variables in this could be SMA variables as well. I just wanted to show you this is not mandatory, and you can mix and match as needed.
  • The password is in clear text here. This is obvisouly not a best practice, and this is just to be explicit about what is being done. But in the real world you would likely have it as an encrypted SMA or Orchestrator variable. The nice thing about this is that both Orchestrator and SMA just let you treat encrypted variables just like standard variables. For example with SMA, you would just call the encrypted variable using the Get-AutomationVariable cmdlet, as in line 9.
  • This scale out example is for a single-tier service template. If your service template has multiple tiers, you would have to filter to pick the right tier with the Get-SCComputerTier cmdlet, using a Where clause

 

Wait, what if I am using Orchestrator? Can I still use this script?

Of course! The previous script can easily be used in Orchestrator as well. While it could certainly be optimized with less remoting when running for SMA, the scructure of the previous sample actually lends itself well for multiple “Run .NET Script” activities within PowerShell, one for each InlineScript paragraph, with published data when values need to flow between activities.

For example, getting the new VM information would look like this, also using Orchestrator variables instead of SMA variables:

image_thumb7

image_thumb8

And scaling out would look like this, using a mix of variables and the published data:

image_thumb11

When it comes to the script itself, you may notice that the only change is that, instead of using a InlineScript call, you would be using Invoke-Command. Simple and easy!

Note : The Orchestrator example does things a bit differently than the SMA example : The first part of the Orchestrator sample is getting the new VM number and the new VM name is computed in the second activity, whereas in the SMA example the full name is directly computed in the first part. But you get the idea Smile

 

I hope you enjoyed this quick post and will find its content valuable. Be sure to check our blog for more Windows Server and System Center adventures!