Friday, August 15, 2014

Getting errors from the Azure VM custom script extension without RDP

Since Azure has begun adding the VM agent and other extension to IaaS virtual machines (persistent VM Roles) a number of scenarios and possibilities have opened up.

The extension is a simple binary that is dropped into your VM and built to be triggered and to perform very specific actions in the security context of Local System.

The Desired State Configuration Azure extension is the very latest. 

Prior to this I have been spending some time with the Custom Script Extension.  And it is rather nifty.  But the biggest pain that I have had is in working through the process of troubleshooting the script as I develop it.

I have found no way to capture the standard output - other than directing to a text file.  But then I have to RDP into the VM to fetch it.

I can also look at the runtime status of the extension while connected over RDP - that that is one file with bad line endings, making it difficult to read in Notepad.

Trough a bit of searching I came across a few tips and started poking around a bit with the Azure PowerShell cmdlets. 

What I discovered is that you cannot get the standard output, but you can get the standard error through the API.  So, if the script tosses some terminating error, there is output to be fetched. If there was no error, there is no output to be returned.

What I ended up doing is the following:

New-AzureVM -Location $location -VM $vmConfig -ServiceName $Service

(Get-Date -Format s) + " .. Watch the script extionsion to monitor the deployment and configuration"
Do {
    $Vm = Get-AzureVM -Name $vmName -ServiceName $Service

    Get-Date -Format s
    "  Machine status: " + $Vm.Status
    "  Guest agent status: " + $Vm.GuestAgentStatus.FormattedMessage.Message
    foreach ( $extension in $Vm.ResourceExtensionStatusList ) {
        If ( $extension.HandlerName -match 'CustomScriptExtension' ) {
            "  ExtensionStatus: " + $extension.ExtensionSettingStatus.FormattedMessage.Message
            $scriptStatus = $extension.ExtensionSettingStatus.FormattedMessage.Message
            $scriptError = foreach ($substatus in $extension.ExtensionSettingStatus.SubStatusList) { ($substatus.FormattedMessage.Message).Replace("\n","`n") }
    Start-Sleep 10
} until ( ($scriptStatus -eq "Finished executing command") )

I fetch the VM, then drill into the object for the Custom Script Extension, then I dig into the Extension status, and it even has sub status.  It is in this sub status where the Standard Error ends up being bubbled up for the extension.

I realize that this leaves me waiting around and calling back and forth.  But a green light on "Finished executing command" only means the script extension is completed running whatever I told it to run, not that it worked.

I just wish I could get the standard output.


Friday, August 1, 2014

WAP Gallery Image, Dynamic IP address, and the SCVMM DHCP switch extension

Recently I had to put together a hands on lab for a number of sales engineers.
The lab involved SCVMM Service Templates, a custom Windows Azure Pack Gallery Image, and a Desired State Configuration module.

I had my environment of Hyper-V 2012 R2, SCVMM 2012 R2, and WAP about 95% configured.  As much as I could and still support the students re-using my VMs with their own Hyper-V Server.

Since the lab was not about WAP, but instead about my gallery image, I wanted to keep it as simple as possible.  I had a cloud, the cloud had a VM Network assigned, the students created a static IP pool.

(I already had an Internal Virtual Switch being created by SCVMM as a Logical Switch so that all lines of dependency were properly drawn)

In the WAP Admin portal - I had the students add the cloud and the VM Network to their plan.

I deploy my Gallery Image, and the domain join failed. 
I look closer, and I see that my VM ended up with an APIPA address and not an address from the IP Pool. 

Come to find out, the default behavior of a WAP Gallery Image is for dynamic IP address assignment. 
Which, if you only ever deploy a gallery image to a Windows Network Virtualization VM Network, you will never notice.  You will instead see that you get an IP from the IP Pool.

Something that I discovered long ago was that there is a custom Hyper-V Virtual Switch extension that ships with SCVMM.  It is actually a DHCP responder.  It catches the IP request, notifies SCVMM, and SCVMM responds with an IP from the SCVMM IP Pool assigned to the VM.  Nifty.

But, this path only happens if the VM is attached to a Windows Network Virtualization (NVGRE) network managed by SCVMM.

Back to the default Gallery Image behavior of a dynamic IP address.  No WNV network, no IP from an IP Pool.  How to fix this?

The only way to fix this is to open the Resource Definition of the Gallery Image, and then open the Network Profile, then the NIC.
And change the AllocationMethod to Static.

While you are in there, you will most likely notice a number of other interesting settings.

But the thing to be aware of is this, these are hard coded values, unless you work through making them settings that are actually exposed to your end customer (at this time you can't expose these settings).
If you change a setting here, that makes a dependency on an SCVMM placement rule, SCVMM will have to find a place that this VM can go to support all of the settings.  If it cannot, your VM will not be deployed.  And your tenant will call.