machine by calling the Update-AzureVM cmdlet and piping in the updated configuration.
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 configuration object, or you can pass multiple scripts to the FileUri pa-rameter.
Implementing Windows PowerShell Desired State Configuration
Windows PowerShell Desired State Configuration (DSC) allows you to declaratively configure the state of the virtual machine. Using built-in resource providers or custom providers with a DSC script enables you to declaratively configure settings such as roles and features, registry settings, files and directories, firewall 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 defined 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.
{
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 file share to the destination website folder.
# ContosoAdvanced.psd1
configuration ContosoAdvanced {
# Import the module that defines custom resources Import-DscResource -Module xWebAdministration Node "localhost"
Recurse = $true
Using the Azure PowerShell cmdlets and the DSC Script Extension, you can publish this configuration complete with the custom resources and have them deployed to an Azure virtual machine. The first step is to publish the DSC configuration (including the resources) to an Azure Storage account. The following example does just that.
Publish-AzureVMDscConfiguration .\ContosoAdvanced.ps1
The Publish-AzureVMDscConfiguration cmdlet takes the Windows PowerShell DSC Script, imports all of the resources such as xWebAdministration in the example, and produces a .zip file that it then uploads to the storage account specified with CurrentStorageAccount name in your subscription. The .zip file’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 file created by the Publish-AzureVMDscConfiguration cmdlet, specify the ConfigurationArchivePath parameter with the path, and a complete file name, and the cmdlet will produce the .zip file locally as shown here.
$dscFileName = "ContosoAdvanced.ps1.zip"
Publish-AzureVMDscConfiguration .\ContosoAdvanced.ps1 `
-ConfigurationArchivePath $dscFileName
You can upload the generated .zip file directly using the same cmdlet. If the .zip file 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 specified with Set-AzureSubscription $subscription CurrentStorageAccount, you can pass a storage context object to the Publish-AzureVMDscConfiguration 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
After the configuration 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 first example shows creating a new virtual machine and specifying a DSC configuration. The changes specific to the DSC configuration are in bold.
$configArchive = "ContosoAdvanced.ps1.zip"
$configName = "ContosoAdvanced"
$imageFamily = "Windows Server 2012 R2 Datacenter"
$imageName = Get-AzureVMImage |
The example to apply the DSC configuration 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 file, and the name of the configuration 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 specified with ConfigurationArchive and unzips it to a temporary directory. It installs any resources that were previously imported into the .zip file, 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 specific file share and most of the configuration values are defined inline in the script, its reusability is limited. Windows PowerShell DSC scripts support specifying a secondary file that contains variables to be applied at runtime.
For example, to make the previous example flexible enough to deploy any web application with the same dependencies, you could move some of the parameters to a Windows PowerShell
data file (file with a .psd1 extension) and create a hashtable with the configuration values specific to the web application for deployment, as in the following example of ContosoConfig.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 configuration 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 file are in bold.
#DeployWebApp.ps1
configuration WebsiteConfig {
# Import the module that defines custom resources Import-DscResource -Module xWebAdministration
Node "localhost"
# Copy the website content
Because the script and configuration has changed, the Publish-AzureVMDscConfiguration cmdlet is used to publish this configuration, as shown below. Note in the following example that the Windows PowerShell script has changed from ContosoApp.ps1 to DeployWebApp.
ps1 to reflect that the script is now generic and not specific to the Contoso application.
Publish-AzureVMDscConfiguration .\DeployWebApp.ps1
NOTE OVERWRITING AN EXISTING DSC CONFIGURATION
If the DSC configuration already exists in the Azure Storage account, you can use the Force parameter to overwrite it.
Use the Set-AzureVMDscExtension to apply the configuration as before. The following example also uses the ConfigurationDataPath parameter to specify the ContosoConfig.psd1 file, which contains the application-specific 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 configuration, the Azure PowerShell cmdlets allow you to view the current DSC extension configuration 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 file if it is. The following example shows how to call the cmdlet.
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 configuration with the Get-AzureVM cmdlet, modifying the configuration, 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 configuration 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 configuration could be piped as a separate variable.