machine by calling the Update-AzureVM cmdlet and piping in the updated coniguration.
Get-AzureVM -ServiceName $serviceName -Name $vmName | Set-AzureVMCustomScriptExtension -FileUri $scriptUri `
-Run $scriptname `
-Argument "$domain $password" | Update-AzureVM
To run multiple scripts, make multiple calls to the Set-AzureVMCustomScriptExtension cmdlet on the same coniguration object, or you can pass multiple scripts to the FileUri pa-rameter.
Implementing Windows PowerShell Desired State Coniguration
Windows PowerShell Desired State Coniguration (DSC) allows you to declaratively conigure the state of the virtual machine. Using built-in resource providers or custom providers with a DSC script enables you to declaratively conigure settings such as roles and features, registry settings, iles and directories, irewall rules, and most settings available to Windows. One of the compelling features of DSC is that, instead of writing logic to detect and correct the state of the machine, the providers do that work for you and make the system state as deined in the script.
For example, the following DSC script declares that the Web-Server role should be installed, along with the Web-Asp-Net45 feature. The WindowsFeature code block represents a DSC resource. The resource has a property named Ensure that can be set to Present or Absent. In this example, the WindowsFeature resource will verify whether the Web-Server role is present on the target machine and if it is not, the resource will install it. It will repeat the process for the Web-Asp-Net45 feature.
104 CHAPTER 2 Implement virtual machines
In addition to the DSC resources that come with Windows Server 2012 R2, there are several
”waves” of DSC resources that have been released by the Windows PowerShell engineering team, and of course you can write your own. To install a custom resource, download it and unzip it into the C:\Program Files\WindowsPowerShell\Modules folder. To download the latest DSC resources from Microsoft and the community, navigate to the TechNet Script Center at https://gallery.technet.microsoft.com/scriptcenter and search for “DSC Resource”.
The following example (ContosoAdvanced.ps1) uses a downloadable resource xWebAd-ministration to create a new IIS website, stop the default website, and deploy an application from a ile share to the destination website folder.
# ContosoAdvanced.psd1
configuration ContosoAdvanced {
# Import the module that defines custom resources Import-DscResource -Module xWebAdministration Node "localhost"
Objective 2.3: Perform coniguration management CHAPTER 2 105
Using the Azure PowerShell cmdlets and the DSC Script Extension, you can publish this coniguration complete with the custom resources and have them deployed to an Azure virtual machine. The irst step is to publish the DSC coniguration (including the resources) to an Azure Storage account. The following example does just that.
Publish-AzureVMDscConfiguration .\ContosoAdvanced.ps1
The Publish-AzureVMDscConiguration cmdlet takes the Windows PowerShell DSC Script, imports all of the resources such as xWebAdministration in the example, and produces a .zip ile that it then uploads to the storage account speciied with CurrentStorageAccount name in your subscription. The .zip ile’s name is in the format of scriptname.ps1.zip and by default will be uploaded to the windows-powershell-dsc container in the storage account.
To see the .zip ile created by the Publish-AzureVMDscConiguration cmdlet, specify the ConigurationArchivePath parameter with the path, and a complete ile name, and the cmdlet will produce the .zip ile locally as shown here.
$dscFileName = "ContosoAdvanced.ps1.zip"
Publish-AzureVMDscConfiguration .\ContosoAdvanced.ps1 `
-ConfigurationArchivePath $dscFileName
You can upload the generated .zip ile directly using the same cmdlet. If the .zip ile already exists in the storage account, specify the Force parameter to overwrite it as shown below.
Publish-AzureVMDscConfiguration $dscFileName -Force
To specify an alternative storage account instead of the account speciied with Set-AzureSubscription $subscription CurrentStorageAccount, you can pass a storage context object to the Publish-AzureVMDscConiguration cmdlet, as shown in this example.
$storageAccount = "[storage account name]"
$storageKey = (Get-AzureStorageKey -StorageAccountName $storageAccount).Primary
$ctx = New-AzureStorageContext -StorageAccountName $storageAccount ` -StorageAccountKey $storageKey
Publish-AzureVMDscConfiguration -ConfigurationPath ".\ContosoAdvanced.ps1" ` -StorageContext $ctx
106 CHAPTER 2 Implement virtual machines
After the coniguration is published, it can be applied to any virtual machine at provi-sioning time or after the fact using the Set-AzureVMDscExtension cmdlet. To show how this works, this example uses the same code previously used with the custom script extension. The irst example shows creating a new virtual machine and specifying a DSC coniguration. The changes speciic to the DSC coniguration are in bold.
$configArchive = "ContosoAdvanced.ps1.zip"
$configName = "ContosoAdvanced"
$imageFamily = "Windows Server 2012 R2 Datacenter"
$imageName = Get-AzureVMImage |
The example to apply the DSC coniguration to an existing virtual machine uses the same pattern to update the virtual machine as using the custom script extension. The change is calling Set-AzureVMDscExtension with the name of the produced .zip ile, and the name of the coniguration in the script instead of Set-AzureVMCustomScriptExtension.
$configArchive = "Contoso.ps1.zip"
$configName = "ContosoAdvanced"
Get-AzureVM -ServiceName $serviceName -Name $vmName | Set-AzureVMDscExtension -ConfigurationArchive $configArchive ` -ConfigurationName $configName | Update-AzureVM
The Set-AzureVMDscExtension downloads the .zip package speciied with ConigurationArchive and unzips it to a temporary directory. It installs any resources that were previously imported into the .zip ile, and then looks for a script with the same name (minus the .zip extension), and runs it on the virtual machine.
The previous example is a good start, but because the script is pointing to a speciic ile share and most of the coniguration values are deined inline in the script, its reusability is limited. Windows PowerShell DSC scripts support specifying a secondary ile that contains variables to be applied at runtime.
For example, to make the previous example lexible enough to deploy any web application with the same dependencies, you could move some of the parameters to a Windows PowerShell
Objective 2.3: Perform coniguration management CHAPTER 2 107 data ile (ile with a .psd1 extension) and create a hashtable with the coniguration values speciic
to the web application for deployment, as in the following example of ContosoConig.psd1.
#ContosoConfig.psd1
The Windows PowerShell DSC script itself could reference the variable names inline us-ing the $Node.Variable name syntax. In the followus-ing example, $Node.SourcePath, $Node.
DestinationPath, and $Node.WebsiteName are all used in place of the hard coded values in the earlier example. The Node syntax is also introduced to the script. This line allows you to selectively apply the coniguration based on the node name, which in this case is localhost, because you are applying it to a single virtual machine at a time. The changes to reference the parameters ile are in bold.
#DeployWebApp.ps1
configuration WebsiteConfig {
# Import the module that defines custom resources Import-DscResource -Module xWebAdministration
Node "localhost"
108 CHAPTER 2 Implement virtual machines
Because the script and coniguration has changed, the Publish-AzureVMDscConiguration cmdlet is used to publish this coniguration, as shown below. Note in the following example that the Windows PowerShell script has changed from ContosoApp.ps1 to DeployWebApp.
ps1 to relect that the script is now generic and not speciic to the Contoso application.
Publish-AzureVMDscConfiguration .\DeployWebApp.ps1
NOTE OVERWRITING AN EXISTING DSC CONFIGURATION
If the DSC coniguration already exists in the Azure Storage account, you can use the Force parameter to overwrite it.
Use the Set-AzureVMDscExtension to apply the coniguration as before. The following example also uses the ConigurationDataPath parameter to specify the ContosoConig.psd1 ile, which contains the application-speciic deployment information. Changes to the script are in bold.
$configArchive = "DeployWebApp.ps1.zip"
$configName = "WebsiteConfig"
Get-AzureVM -ServiceName $serviceName -Name $vmName |
Set-AzureVMDscExtension -ConfigurationArchive $configArchive ` -ConfigurationName $configName `
-ConfigurationDataPath .\ContosoConfig.psd1 | Update-AzureVM
In addition to publishing and setting the DSC coniguration, the Azure PowerShell cmdlets allow you to view the current DSC extension coniguration using the Get-AzureVMDscExtension cmdlet, as shown in Figure 2-27. This cmdlet shows whether the extension is applied and the URL in Azure Storage to the .zip ile if it is. The following example shows how to call the cmdlet.
Objective 2.3: Perform coniguration management CHAPTER 2 109 Get-AzureVM -ServiceName $serviceName -Name $vmName | Get-AzureVMDscExtension
FIGURE 2-27 Viewing the current DSC extension configuration of a virtual machine
One more cmdlet to be aware of is the Remove-AzureVMDscExtension. This cmdlet, as the name implies, will remove the DSC extension from the virtual machine. Its usage follows the familiar update pattern of returning the virtual machine coniguration with the Get-AzureVM cmdlet, modifying the coniguration, and using the Update-AzureVM cmdlet to complete the update as the example shows.
Get-AzureVM -ServiceName $serviceName -Name $vmName | Remove-AzureVMDscExtension |
Update-AzureVM
$config = Get-AzureVM -ServiceName $serviceName -Name $vmName
$config | Remove-AzureVMDscExtension
$config | Update-AzureVM
The coniguration could be passed on using the VM parameter like this:
Remove-AzureVMDscExtension –VM $config.
EXAM TIP
Just a reminder that Windows PowerShell examples like the previous example can be writ-ten in multiple ways. For instance the coniguration could be piped as a separate variable.