Installing Azure powershell in an azure Virtual Machine

2.7k views Asked by At

I need to write a powershell workflow that creates an Azure Virtual Machine and executes some azure cmdlets in that Azure Virtual Machine. But the newly created VM has no azure powershell module installed in it. My code would be like this

    New-AzureQuickVM -Windows -ServiceName $serviceName -Name $vmname -ImageName $VMImage  -Password $password -AdminUserName $username -InstanceSize "ExtraSmall" -WaitForBoot

    $WinRmUri = Get-AzureWinRMUri -ServiceName $serviceName -Name $vmname
    $Cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $username, $password

    Invoke-Command -ConnectionUri $WinRmUri -Credential $Cred -ScriptBlock {
         Add-AzureAccount ......  ## These cmdlets need Azure Powershell Module 
         Set-AzureSubscription........
         New-AzureStorageAccount......
    }

I am not supposed to manually get rdp of that VM and open it to install Azure Powershell Module but to dynamically create a VM using powershell cmdlet and install azure module in that vm using powershell itself.

4

There are 4 answers

1
citleon On

You may use Azure Automation service implementing your Powershell code into a runbook.

http://azure.microsoft.com/en-us/documentation/services/automation/

1
theadriangreen On

This can easily be done with an ARM (Azure Resource Manager) template. This is a JSON template which defines objects to be deployed. In your case, you would want to deploy a VM with a custom script extension. Upon provisioning of the VM, the Azure Resource Manager will fetch the supplied files and run your custom powershell. See the example below, and replace the line https://<YOUR-BLOB-HERE>.blob.core.windows.net/resources/CUSTOM-POWERSHELL-SCRIPT.ps1 with your blob and powershell script. To run the script you can use Azure powershell, as described here: https://azure.microsoft.com/en-us/documentation/articles/powershell-azure-resource-manager/

The key cmdlet for your purposes is New-AzureResourceGroup. The invocation will be something like:

Switch-AzureMode -Name AzureResourceManager
New-AzureResourceGroup -Name TestRG1 -Location "West US" -TemplateFile <YOUR-JSON-ARM-TEMPLATE>.json

See a list of ARM templates here for reference: https://github.com/Azure/azure-quickstart-templates . Sample template to modify to run custom code/install Azure powershell.

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "newStorageAccountName": {
            "type": "string",
            "metadata": {
                "description": "Unique DNS Name for the Storage Account where the Virtual Machine's disks will be placed."
            }
        },
        "adminUsername": {
            "type": "string",
            "metadata": {
                "description": "Username for the Virtual Machine."
            }
        },
        "adminPassword": {
            "type": "securestring",
            "metadata": {
                "description": "Password for the Virtual Machine."
            }
        },
        "dnsNameForPublicIP": {
            "type": "string",
            "metadata": {
                "description": "Unique DNS Name for the Public IP used to access the Virtual Machine."
            }
        },
        "windowsOSVersion": {
            "type": "string",
            "defaultValue": "2012-R2-Datacenter",
            "allowedValues": [
                "2008-R2-SP1",
                "2012-Datacenter",
                "2012-R2-Datacenter"
            ],
            "metadata": {
                "description": "The Windows version for the VM. This will pick a fully patched image of this given Windows version. Allowed values: 2008-R2-SP1, 2012-Datacenter, 2012-R2-Datacenter."
            }
        }
    },
    "variables": {
        "location": "West US",
        "imagePublisher": "MicrosoftWindowsServer",
        "imageOffer": "WindowsServer",
        "OSDiskName": "osdiskforwindowssimple",
        "nicName": "myVMNic",
        "addressPrefix": "10.0.0.0/16",
        "subnetName": "Subnet",
        "subnetPrefix": "10.0.0.0/24",
        "storageAccountType": "Standard_LRS",
        "publicIPAddressName": "myPublicIP",
        "publicIPAddressType": "Dynamic",
        "vmStorageAccountContainerName": "vhds",
        "vmName": "MyWindowsVM",
        "vmSize": "Standard_A2",
        "virtualNetworkName": "MyVNET",
        "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
        "subnetRef": "[concat(variables('vnetID'),'/subnets/',variables('subnetName'))]"
    },
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[parameters('newStorageAccountName')]",
            "apiVersion": "2015-05-01-preview",
            "location": "[variables('location')]",
            "properties": {
                "accountType": "[variables('storageAccountType')]"
            }
        },
        {
            "apiVersion": "2015-05-01-preview",
            "type": "Microsoft.Network/publicIPAddresses",
            "name": "[variables('publicIPAddressName')]",
            "location": "[variables('location')]",
            "properties": {
                "publicIPAllocationMethod": "[variables('publicIPAddressType')]",
                "dnsSettings": {
                    "domainNameLabel": "[parameters('dnsNameForPublicIP')]"
                }
            }
        },
        {
            "apiVersion": "2015-05-01-preview",
            "type": "Microsoft.Network/virtualNetworks",
            "name": "[variables('virtualNetworkName')]",
            "location": "[variables('location')]",
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "[variables('addressPrefix')]"
                    ]
                },
                "subnets": [
                    {
                        "name": "[variables('subnetName')]",
                        "properties": {
                            "addressPrefix": "[variables('subnetPrefix')]"
                        }
                    }
                ]
            }
        },
        {
            "apiVersion": "2015-05-01-preview",
            "type": "Microsoft.Network/networkInterfaces",
            "name": "[variables('nicName')]",
            "location": "[variables('location')]",
            "dependsOn": [
                "[concat('Microsoft.Network/publicIPAddresses/', variables('publicIPAddressName'))]",
                "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]"
            ],
            "properties": {
                "ipConfigurations": [
                    {
                        "name": "ipconfig1",
                        "properties": {
                            "privateIPAllocationMethod": "Dynamic",
                            "publicIPAddress": {
                                "id": "[resourceId('Microsoft.Network/publicIPAddresses',variables('publicIPAddressName'))]"
                            },
                            "subnet": {
                                "id": "[variables('subnetRef')]"
                            }
                        }
                    }
                ]
            },            
        },
        {
            "apiVersion": "2015-05-01-preview",
            "type": "Microsoft.Compute/virtualMachines",
            "name": "[variables('vmName')]",
            "location": "[variables('location')]",
            "dependsOn": [
                "[concat('Microsoft.Storage/storageAccounts/', parameters('newStorageAccountName'))]",
                "[concat('Microsoft.Network/networkInterfaces/', variables('nicName'))]"
            ],
            "properties": {
                "hardwareProfile": {
                    "vmSize": "[variables('vmSize')]"
                },
                "osProfile": {
                    "computername": "[variables('vmName')]",
                    "adminUsername": "[parameters('adminUsername')]",
                    "adminPassword": "[parameters('adminPassword')]"
                },
                "storageProfile": {
                    "imageReference": {
                        "publisher": "[variables('imagePublisher')]",
                        "offer": "[variables('imageOffer')]",
                        "sku" : "[parameters('windowsOSVersion')]",
                        "version":"latest"
                    },
                    "osDisk" : {
                        "name": "osdisk",
                        "vhd": {
                            "uri": "[concat('http://',parameters('newStorageAccountName'),'.blob.core.windows.net/',variables('vmStorageAccountContainerName'),'/',variables('OSDiskName'),'.vhd')]"
                        },
                        "caching": "ReadWrite",
                        "createOption": "FromImage"
                    }
                },
                "networkProfile": {
                    "networkInterfaces": [
                        {
                            "id": "[resourceId('Microsoft.Network/networkInterfaces',variables('nicName'))]"
                        }
                    ]
                }
            },
            "resources": [
                {
                    "name": "CustomScript",
                    "type": "extensions",
                    "location": "[variables('location')]",
                    "apiVersion": "2015-05-01-preview",
                    "dependsOn": [
                        "[concat('Microsoft.Compute/virtualMachines/', variables('vmName')]"
                    ],                    
                    "properties": {
                        "publisher": "Microsoft.Compute",
                        "type": "CustomScriptExtension",
                        "typeHandlerVersion": "[variables('customScriptExtensionVersion')]",
                        "settings": {
                            "fileUris": [
                                "https://<YOUR-BLOB-HERE>.blob.core.windows.net/resources/CUSTOM-POWERSHELL-SCRIPT.ps1",
                                "http://go.microsoft.com/?linkid=9811175&clcid=0x409"
                            ],
                            "commandToExecute": "[concat('powershell.exe -ExecutionPolicy Unrestricted -Command .\\CUSTOM-POWERSHELL-SCRIPT.ps1 -Argument1 argument1')]"
                        }
                    }
                }
            ]
        }
    ]
}
0
saravanan On

Though not a straight forward approach I implemented this idea that satisfied my need.

  1. Create a new azure VM from Portal and connect it through RDP https://azure.microsoft.com/en-in/documentation/articles/virtual-machines-windows-tutorial/
  2. Now download azure powershell msi in YOUR machine ( In AzureVM downloading is blocked) http://az635501.vo.msecnd.net/azcopy-3-1-0/MicrosoftAzureStorageTools.msi
  3. Manually copy the msi file to the virtual machine and install it in that VM

  4. Now Capture the image of that VM and upload it in Azure My images https://azure.microsoft.com/en-in/documentation/articles/virtual-machines-capture-image-windows-server/

  5. When I write automation script to create a VM, I used this newly created customVM image, where AzurePowershell is already installed
0
Aman Sharma On

If your VM has PowerShell 5.0, then you can use the PowerShell Gallery to install your modules. You will not require any steps mentioned in other answers. All you need to do is write the PowerShell script as you would normally do. Just add the Module from PowerShell gallery using just one cmdlet.

You can either use Install-Module to install a module from the gallery, or you can use Install-Script to install a sample script from the PowerShell public gallery.

You can even put your own modules in the gallery and install from there.

Reference: Get Started with the PowerShell Gallery