1
votes

I'm trying to write an Azure Powershell Runbook that will start a VM, and then check if a windows service on the VM is running or not and start it.

I can get the VM started, but enumerating the services isn't working. I'm brand new on Azure Runbooks so I could be doing something wrong. I limited the below code to only the Get-Service bit and not the VM starting.

# Returns strings with status messages
[OutputType([String])]

param (
    [Parameter(Mandatory=$false)] 
    [String]  $AzureConnectionAssetName = "AzureRunAsConnection",

    [Parameter(Mandatory=$false)] 
    [String] $ResourceGroupName = ""
)

try {
    # Connect to Azure using service principal auth
    $ServicePrincipalConnection = Get-AutomationConnection -Name $AzureConnectionAssetName         

    Write-Output "Logging in to Azure..."

    $Null = Add-AzureRmAccount `
        -ServicePrincipal `
        -TenantId $ServicePrincipalConnection.TenantId `
        -ApplicationId $ServicePrincipalConnection.ApplicationId `
        -CertificateThumbprint $ServicePrincipalConnection.CertificateThumbprint 
}
catch {
    if(!$ServicePrincipalConnection) {
        throw "Connection $AzureConnectionAssetName not found."
    }
    else {
        throw $_.Exception
    }
}

# If there is a specific resource group, then get all VMs in the resource group,
# otherwise get all VMs in the subscription.
if ($ResourceGroupName) { 
    $VMs = Get-AzureRmVM -ResourceGroupName $ResourceGroupName
}
else { 
    $VMs = Get-AzureRmVM
}

# Try and enumerate the VM's services 
foreach ($VM in $VMs) {
        Write-Output "Listing all services..."
        Write-Output ("VM: {0}" -f $VM.Name)
        $VM | Get-Service | Format-Table -AutoSize

        Write-Output "Listing alternative method..."
        Get-Service -ComputerName $VM.Name | Format-Table -AutoSize
        Write-Output "Finished listing..."
}

And the output is this:

Logging in to Azure...

Listing all services...

VM: demo-0

Listing alternative method...

Finished listing...

3
Are you using hybrid workers? or are you using the default Azure queue?CtrlDot
I'd say the default Azure queueAlex Kwitny

3 Answers

0
votes

When you are running Azure Automation runbooks, you have the choice of the azure queue or creating a hybrid worker. The azure queue is good for many processes, but it will not have access to the VMs directly to run commands such as get-service.

To expand on @4c74356b41 answer, you will need to use remote powershell to execute the command (using New-PSSession) but you will also have to ensure that those commands are running on an Azure Automation Hybrid Worker

In the comments below, you asked about credentials. You can set credentials in the Azure Automation account and then have them used by your script when creating a new session. See this link

1
votes

Well, first of all, Starting VM is asynchronous, so you need to wait for the VM to actually boot, and the Get-Service wouldn't work anyway, as to get the services from a VM you need to authenticate against that VM, so either user PSsessions or invoke-command, something like that. Just look on how to remote into servers with powershell or how to issue powershell command to remote PC's. This case is nothing different. And it has nothing to do with how Azure Automation works.

0
votes

You could try to use the following cmdlets. It works for me.

# Try and enumerate the VM's services 
foreach ($VM in $VMs) {
        Write-Output "Listing all services..."
        Write-Output ("VM: {0}" -f $VM.Name)
        $ResourceGroupName=$VM.ResourceGroupName
        $Name=$VM.Name
        $status=(Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $Name -Status).Statuses[1].code
        if($status -like "PowerState/deallocated")
        {
            Write-Output "VM is stopped, starting VM"
            if (Start-AzureRmVm -ResourceGroupName $ResourceGroupName -Name $Name)
            {
                Write-Output "Start VM successfuly"
            }else
            {
                Write-Output "Start VM failed"
                break
            }

        }
        ##get VM's Public IP
        $nicName = ($VM.NetworkInterfaceIDs[0] -split '/')[-1]
        $pip = (Get-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $ResourceGroupName).IpConfigurations.publicipaddress.id
        $PublicIP=(Get-AzureRmPublicIpAddress -ResourceGroupName shui -Name ($pip -split '/')[-1]).IpAddress

        $Uri="http://$($PublicIP):5986"
        Write-Output "Get ConnectionUri $Uri"

        ##get Credential from assets
        $shui=Get-AutomationPSCredential -Name 'shui' 

        $session=New-PSSession -ConnectionUri $Uri -Credential $shui -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)

        $result=Invoke-Command -Session $session -ScriptBlock {ipconfig}
        Write-Output "$result"
        Write-Output "Finished listing..."
}

Before you use this script. Firstly,you should open ports 5896 on your VM's firewall and NSG, you could check as the following link. Please ensure you could telnet IP 5986 on your local PC.

  1. You should import AzureRM.Network modules to your Automation Account. More information about how to import Modules please refer to this link.

3.Store your VMs's passord to Runbook, you could refer to this link. When you want to use the credentials, you could use the script below:

##get Credential from assets
$shui=Get-AutomationPSCredential -Name 'shui' 

$session=New-PSSession -ConnectionUri $Uri -Credential $shui -SessionOption (New-PSSessionOption -SkipCACheck -SkipCNCheck -SkipRevocationCheck)