[Azure]使用Powershell将ARM虚拟机(托管磁盘)加入可用性集

60 篇文章 0 订阅
59 篇文章 0 订阅

前面一篇Blob说明了非托管磁盘虚拟机如何使用Powershell通过重建的方式加入可用性集,这一篇给大家提供托管磁盘的版本。

托管磁盘其实与非托管磁盘的代码几乎一样,区别仅仅在于托管磁盘添加磁盘的方式以及可用性集的类型稍有不同,思路是一样的,话不多说,我们直接看代码:

param(
    [Parameter(Mandatory = $true)] 
    [string]$SubscriptionName, 
 
    [Parameter(Mandatory = $true)]
    [string]$ResourceGroupName,

    [Parameter(Mandatory = $true)]
    [string]$VMName,

    [Parameter(Mandatory = $true)]
    [string]$AvailabilitySetName
)

Function GetResourceNameFromResourceId($resourceId)
{
    return $resourceId.Substring($resourceId.LastIndexOf('/') + 1);
}

Function GetResourcePropertyFromResourceId($resourceId, $propertyName)
{
    $propertyName = $propertyName + "/";
    $rgName = $resourceId.Substring($resourceId.IndexOf($propertyName) + $propertyName.Length);
    return $rgName.Substring(0, $rgName.IndexOf("/"));
}

Function CollectVMInformation($rgName, $vmName, $avaSetName)
{
    $vmInfo = @{};
    $vmInfo.Add("ResourceGroup", $rgName);
    $vmInfo.Add("Name", $vmName);
    
    $vm = Get-AzureRmVM -ResourceGroupName $rgName -Name $vmName -ErrorAction Ignore -WarningAction Ignore;
    if ($vm -eq $null)
    {
        return $null;
    }

    $vmInfo.Add("Size", $vm.HardwareProfile.VmSize);
    $vmInfo.Add("Location", $vm.Location);
    if (!(CreateAvailabilitySet $rgName $avaSetName $vm.Location))
    {
        return $null;
    }
    $avaSet = Get-AzureRmAvailabilitySet -ResourceGroupName $rgName -Name $avaSetName;
    $vmInfo.Add("AvailabilitySet", $avaSet.Id);

    $vmInfo.Add("OSType", $vm.StorageProfile.OsDisk.OsType.ToString());

    #network properties
    $nicId = ($vm.NetworkProfile.NetworkInterfaces | where {$_.Primary -eq $true}).Id;
    if ($nicId -eq $null -and $vm.NetworkProfile.NetworkInterfaces.Count -eq 1)
    {
        $nicId = $vm.NetworkProfile.NetworkInterfaces[0].Id;
    }
    #$nicName = GetResourceNameFromResourceId $nicId;
    #$nic = Get-AzureRmNetworkInterface -Name $nicName -ResourceGroupName $rgName;
    #$subnetId = $nic.IpConfigurations[0].Subnet.Id;
    #$subnetName = GetResourceNameFromResourceId $subnetId;
    #$vnetName = GetResourcePropertyFromResourceId $subnetId "virtualNetworks";
    #$vmInfo.Add("VirtualNetwork", $vnetName);
    #$vmInfo.Add("Subnet", $subnetName);
    $vmInfo.Add("PrimaryNetworkInterfaceId", $nicId);

    $secondaryNics = @($vm.NetworkProfile.NetworkInterfaces | where {$_.Primary -eq $false});
    $vmInfo.Add("SecondaryNetworkInterfaces", $secondaryNics);
    #$vnet = Get-AzureRmVirtualNetwork -Name $vnetName -ResourceGroupName $rgName;
    #$subnet01 = Get-AzureRmVirtualNetworkSubnetConfig -Name $subnetName -VirtualNetwork $vnet;

    #disk
    $vmInfo.Add("OSDisk", $vm.StorageProfile.OsDisk);
    $vmInfo.Add("DataDisks", @($vm.StorageProfile.DataDisks));

    return $vmInfo;
}

Function DeleteOldVM($rgName, $vmName)
{
    [void](Remove-AzureRmVM -ResourceGroupName $rgName -Name $vmName -Force);
    #if lease is not broken, we need to sleep for some time
    #sleep 10
}

Function CreateAvailabilitySet($rgName, $avaSetName, $location)
{
    $avaSet = Get-AzureRmAvailabilitySet -ResourceGroupName $rgName -Name $avaSetName -ErrorAction Ignore;
    if ($avaSet -eq $null)
    {
        $avaSet = New-AzureRmAvailabilitySet -ResourceGroupName $rgName -Name $avaSetName -Location $location -Sku "Aligned" -PlatformUpdateDomainCount 5 -PlatformFaultDomainCount 2 -Managed;
        return $true;
    } 
    elseif ($avaSet.Sku -ne "Aligned")
    {
        Write-Host "There's an existing availability set whose sku is not Aligned, conflict with managed-disk";
        return $false;
    }
    else 
    {
        return $true;
    }
}

Function RebuildVM($vmInfo)
{
    #basic information
    $rgName = $vmInfo["ResourceGroup"];
    $vmName = $vmInfo["Name"];
    $vmSize = $vmInfo["Size"];
    $location = $vmInfo["Location"];
    $osType = $vmInfo["OSType"];

    #network
    #$vnetName = $vmInfo["VirtualNetwork"];
    #$subnetName = $vmInfo["Subnet"];
    $primaryNicId = $vmInfo["PrimaryNetworkInterfaceId"];
    $secondaryNics = $vmInfo["SecondaryNetworkInterfaces"];
    
    #disk
    $osDisk = $vmInfo["OSDisk"];
    $dataDisks = $vmInfo["DataDisks"];

    $avaSetId = $vmInfo["AvailabilitySet"];
    $vmconfig = New-AzureRmVMConfig -VMName $vmName -VMSize $vmSize -AvailabilitySetId $avaSetId;
    $vmconfig = $vmconfig | Set-AzureRmVMBootDiagnostics -Disable;

    if ($osType -eq "Windows")
    {
        $vmconfig = $vmconfig | Set-AzureRmVMOSDisk -ManagedDiskId $osDisk.ManagedDisk.Id -Caching $osDisk.Caching -CreateOption attach -Windows;
    } else {
        $vmconfig = $vmconfig | Set-AzureRmVMOSDisk -ManagedDiskId $osDisk.ManagedDisk.Id -Caching $osDisk.Caching -CreateOption attach -Linux;
    }
    #下面这个步骤是必须要有而且非常重要的,实测下来发现上面的命令有个小bug,就是托管磁盘添加后,磁盘名默认会被设置成虚拟机名称
    #导致创建的时候报错“New-AzureRmVM : Changing property 'osDisk.name' is not allowed”
    $vmconfig.StorageProfile.OsDisk.Name = $osDisk.Name;
    $vmconfig.StorageProfile.ImageReference = $null;

    $index = 0;
    foreach ($dataDisk in $dataDisks)
    {
        $vmconfig = $vmconfig | Add-AzureRmVMDataDisk -ManagedDiskId $dataDisk.ManagedDisk.Id -Lun $dataDisk.Lun -Caching $dataDisk.Caching -CreateOption attach;
        #下面这个步骤是必须要有而且非常重要的,实测下来发现上面的命令有个小bug,就是托管磁盘添加后,磁盘名默认会被设置成虚拟机名称
        #导致创建的时候报错“New-AzureRmVM : Changing property 'dataDisk.name' is not allowed”
        $vmconfig.StorageProfile.DataDisks[$index].Name = $dataDisk.Name;
        $index += 1;
    }

    $vmconfig = $vmconfig | Add-AzureRmVMNetworkInterface -Id $primaryNicId -Primary;
    foreach ($secondaryNic in $secondaryNics)
    {
        $secondaryNicId = $secondaryNic.Id;
        $vmconfig = $vmconfig | Add-AzureRmVMNetworkInterface -Id $secondaryNicId;
    }

    [void](New-AzureRmVM -ResourceGroupName $rgName -Location $location -VM $vmconfig);
}

[void](Select-AzureRmSubscription -SubscriptionName $SubscriptionName);

Write-Host "Collecting VM information...";
$vmInfo = (CollectVMInformation $ResourceGroupName $VMName $AvailabilitySetName);
if ($vmInfo -eq $null)
{
    Write-Host "Failed to collect vm information." -ForegroundColor Red;
    return;
}

Write-Host "Deleting old VM...";
DeleteOldVM $ResourceGroupName $VMName;

Write-Host "Rebuilding VM...";
RebuildVM $vmInfo;

Write-Host "Finished";

脚本运行示例:



脚本参数中指定的AvailabilitySetName可以是已有的,也可以指定不存在的,如果不存在的话,会新建一个AvailabilitySet,注意AvailabilitySet是区分托管和非托管的。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值