Azure-AutoAccount-实现通过Tag开关机虚拟机

AutoAccount自动化账号

1.前期配置

认证方式:使用automate的“标识” - “托管标识”,这样可以保证认证方式没有过期的风险。

授权:开启托管标识后,将该automate加入到订阅的“参与者”权限中即可

关于托管标识微软的官方描述:https://docs.microsoft.com/zh-cn/azure/automation/enable-managed-identity-for-automation

2.配置代码

上述认证方式配置好后,直接新建runbook运行以下代码即可,输入相关参数设置任务计划即可完成开关机

参数:

ACTION: 开机“Start”, 关机“Stop”

TAGNAME: 输入tag的名字

RAGVALUE:输入tag的值

3.添加计划

在Runbook中 - 计划 - 添加计划 - 设置开机或者关机的时间和执行频率。

设置参数和运行设置。

 

代码如下:

Workflow Start-Stop-VMs
{
    param (

        [Parameter(Mandatory=$true)]  
        [String] $Action,

        [Parameter(Mandatory=$false)]  
        [String] $TagName,

        [Parameter(Mandatory=$false)]
        [String] $TagValue
    ) 

    ## Authentication
    Write-Output ""
    Write-Output "------------------------ Authentication ------------------------"
    Write-Output "Logging into Azure ..."

    # Ensures you do not inherit an AzContext in your runbook
    Disable-AzContextAutosave -Scope Process

    # Connect to Azure with system-assigned managed identity
    $AzureContext = (Connect-AzAccount -Identity).context

    # set and store context
    $AzureContext = Set-AzContext -SubscriptionName $AzureContext.Subscription -DefaultProfile $AzureContext
    # try
    # {
    #     # Ensures you do not inherit an AzContext in your runbook
    #     $null = Disable-AzContextAutosave -Scope Process

    #     $Conn = Get-AutomationConnection -Name AzureRunAsConnection
        
    #     $null = Connect-AzAccount `
    #                     -ServicePrincipal `
    #                     -Tenant $Conn.TenantID `
    #                     -ApplicationId $Conn.ApplicationID `
    #                     -CertificateThumbprint $Conn.CertificateThumbprint

    #     Write-Output "Successfully logged into Azure." 
    # } 
    # catch
    # {
    #     if (!$Conn)
    #     {
    #         $ErrorMessage = "Service principal not found."
    #         throw $ErrorMessage
    #     } 
    #     else
    #     {
    #         Write-Error -Message $_.Exception
    #         throw $_.Exception
    #     }
    # }
    ## End of authentication

    ## Getting all virtual machines
    Write-Output ""
    Write-Output ""
    Write-Output "---------------------------- Status ----------------------------"
    Write-Output "Getting all virtual machines from all resource groups ..."

    try
    {
        if ($TagName)
        {                    
            $instances = Get-AzResource -TagName $TagName -TagValue $TagValue -ResourceType "Microsoft.Compute/virtualMachines"
            
            if ($instances)
            {
                $resourceGroupsContent = @()
                               
                foreach -parallel ($instance in $instances)
                {
                    $instancePowerState = (((Get-AzVM -ResourceGroupName $($instance.ResourceGroupName) -Name $($instance.Name) -DefaultProfile $AzureContext -Status).Statuses.Code[1]) -replace "PowerState/", "")

                    sequence
                    {
                        $resourceGroupContent = New-Object -Type PSObject -Property @{
                            "Resource group name" = $($instance.ResourceGroupName)
                            "Instance name" = $($instance.Name)
                            "Instance type" = (($instance.ResourceType -split "/")[0].Substring(10))
                            "Instance state" = ([System.Threading.Thread]::CurrentThread.CurrentCulture.TextInfo.ToTitleCase($instancePowerState))
                            $TagName = $TagValue
                        }

                        $Workflow:resourceGroupsContent += $resourceGroupContent
                    }
                }
            }
            else
            {
                    #Do nothing
            }            
        }
        else
        {
            $instances = Get-AzResource -ResourceType "Microsoft.Compute/virtualMachines"

            if ($instances)
            {
                $resourceGroupsContent = @()
          
                foreach -parallel ($instance in $instances)
                {
                    $instancePowerState = (((Get-AzVM -ResourceGroupName $($instance.ResourceGroupName) -Name $($instance.Name) -DefaultProfile $AzureContext -Status).Statuses.Code[1]) -replace "PowerState/", "")

                    sequence
                    {
                        $resourceGroupContent = New-Object -Type PSObject -Property @{
                            "Resource group name" = $($instance.ResourceGroupName)
                            "Instance name" = $($instance.Name)
                            "Instance type" = (($instance.ResourceType -split "/")[0].Substring(10))
                            "Instance state" = ([System.Threading.Thread]::CurrentThread.CurrentCulture.TextInfo.ToTitleCase($instancePowerState))
                        }

                        $Workflow:resourceGroupsContent += $resourceGroupContent
                    }
                }
            }
            else
            {
                #Do nothing
            }
        }

        InlineScript
        {
            $Using:resourceGroupsContent | Format-Table -AutoSize
        }
    }
    catch
    {
        Write-Error -Message $_.Exception
        throw $_.Exception    
    }
    ## End of getting all virtual machines

    $runningInstances = ($resourceGroupsContent | Where-Object {$_.("Instance state") -eq "Running" -or $_.("Instance state") -eq "Starting"})
    $deallocatedInstances = ($resourceGroupsContent | Where-Object {$_.("Instance state") -eq "Deallocated" -or $_.("Instance state") -eq "Deallocating"})

    ## Updating virtual machines power state
    if (($runningInstances) -and ($Action -eq "Stop"))
    {
        Write-Output "--------------------------- Updating ---------------------------"
        Write-Output "Trying to stop virtual machines ..."

        try
        {
            $updateStatuses = @()

            foreach -parallel ($runningInstance in $runningInstances)
            {
                sequence
                {
                    Write-Output "$($runningInstance.("Instance name")) is shutting down ..."
                
                    $startTime = Get-Date -Format G

                    $workflow:null = Stop-AzVM -ResourceGroupName $($runningInstance.("Resource group name")) -Name $($runningInstance.("Instance name")) -DefaultProfile $AzureContext -Force
                    
                    $endTime = Get-Date -Format G

                    $updateStatus = New-Object -Type PSObject -Property @{
                        "Resource group name" = $($runningInstance.("Resource group name"))
                        "Instance name" = $($runningInstance.("Instance name"))
                        "Start time" = $startTime
                        "End time" = $endTime
                    }
                
                    $Workflow:updateStatuses += $updateStatus
                }          
            }

            InlineScript
            {
                $Using:updateStatuses | Format-Table -AutoSize
            }
        }
        catch
        {
            Write-Error -Message $_.Exception
            throw $_.Exception    
        }
    }
    elseif (($deallocatedInstances) -and ($Action -eq "Start"))
    {
        Write-Output "--------------------------- Updating ---------------------------"
        Write-Output "Trying to start virtual machines ..."

        try
        {
            $updateStatuses = @()

            foreach -parallel ($deallocatedInstance in $deallocatedInstances)
            {                                    
                sequence
                {
                    Write-Output "$($deallocatedInstance.("Instance name")) is starting ..."

                    $startTime = Get-Date -Format G

                    $workflow:null = Start-AzVM -ResourceGroupName $($deallocatedInstance.("Resource group name")) -Name $($deallocatedInstance.("Instance name")) -DefaultProfile $AzureContext

                    $endTime = Get-Date -Format G

                    $updateStatus = New-Object -Type PSObject -Property @{
                        "Resource group name" = $($deallocatedInstance.("Resource group name"))
                        "Instance name" = $($deallocatedInstance.("Instance name"))
                        "Start time" = $startTime
                        "End time" = $endTime
                    }
                
                    $Workflow:updateStatuses += $updateStatus
                }           
            }

            InlineScript
            {
                $Using:updateStatuses | Format-Table -AutoSize
            }
        }
        catch
        {
            Write-Error -Message $_.Exception
            throw $_.Exception    
        }
    }
    #### End of updating virtual machines power state
}

 

posted @ 2022-03-17 09:05  罐头瓶  阅读(66)  评论(0编辑  收藏  举报