使用 PowerShell 调用 REST API 完成经典部署资源的跨订阅迁移

资源管理器 (ARM) 模式部署的资源可以通过新管理门户中的 Move 功能轻易地进行跨资源组或跨订阅迁移。 然而在跨订阅迁移经典部署资源时,除了通用的限制以外,还额外存在以下限制:

  • 必须在同一操作中移动订阅中的所有经典资源。
  • 目标订阅不得包含任何其他经典资源。
  • 只能通过独立的适用于经典移动的 REST API 来请求移动。 将经典资源移到新订阅时,不能使用标准的 Resource Manager 移动命令。

具体限制请参阅文档将资源移到新资源组或订阅中的“移动资源前需查看的清单”和“经典部署限制”。

在文档将资源移到新资源组或订阅中,列出了如何调用 REST API 执行迁移操作。对不熟悉 REST API 的用户来说,可能对文档里的步骤无从下手。本文列举了使用 PowerShell 命令 Invode-RestMethod 调用 REST API 的示例,以供参考。

  1. 定义 Azure AD 租户和迁移操作的源、目标订阅。

    Azure AD 的租户就是登录 Azure 门户所用的账号后缀名,还需要用户提供源订阅与目标订阅的订阅号。

     $Tenant = "xxx.partner.onmschina.cn"
     $sourcesubid = "source-subscription-id"
     $targetsubid = "target-subscription-id"
    
  2. 定义 function GetAuthToken,以抓取登录时产生的验证令牌。

     function GetAuthToken
     {
         param
         (
             [Parameter(Mandatory=$true)]
             $ApiEndpointUri,
    
             [Parameter(Mandatory=$true)]
             $AADTenant
         )
    
         $adal = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\" + `
                 "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
         $adalforms = "${env:ProgramFiles(x86)}\Microsoft SDKs\Azure\PowerShell\ServiceManagement\Azure\Services\" + `
                     "Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll"
    
        [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
        [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null

        $clientId = "1950a258-227b-4e31-a9cf-717495945fc2"
        $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
        $authorityUri = “https://login.partner.microsoftonline.cn/$aadTenant”

        $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authorityUri

        $authResult = $authContext.AcquireToken($ApiEndpointUri, $clientId,$redirectUri, "Auto")

        return $authResult
    }

    $token = GetAuthToken -ApiEndPointUri "https://management.core.chinacloudapi.cn/" -AADTenant $Tenant
  1. 生成 REST API 请求的 header。

     $header = @{
         "Accept"="application/json"
         ‘Content-Type’="application/json"
         "Authorization"=$token.CreateAuthorizationHeader()
     }
    
  2. 针对迁移的源订阅,生成 REST API 请求的 body,并调用 API 检查源订阅是否支持迁移。

     $sourcebody = ConvertTo-Json @{
         "role"="source"
     }
    
     $sourceuri = "https://management.chinacloudapi.cn/subscriptions/$sourcesubid/providers/Microsoft.ClassicCompute/validateSubscriptionMoveAvailability?api-version=2016-04-01"
     $sourceresponse = Invoke-RestMethod -Uri $sourceuri -Headers $header -Body $sourcebody -Method POST
    
  3. 针对迁移的目标订阅,生成 REST API 请求的 body,并调用 API 检查目标订阅是否支持迁移。

     $targetbody = ConvertTo-Json @{
         "role"="target"
     }
    
     $targeturi = "https://management.chinacloudapi.cn/subscriptions/$targetsubid/providers/Microsoft.ClassicCompute/validateSubscriptionMoveAvailability?api-version=2016-04-01"
     $targetresponse = Invoke-RestMethod -Uri $targeturi -Headers $header -Body $targetbody -Method POST
    
  4. 抓取 REST API 的响应,查看是否源订阅与目标订阅是否支持迁移。

     Write-Host "----------Source subscription error------------"
     $sourceresponse.reasons
    
     Write-Host "----------Target subscription error------------"
     $targetresponse.reasons
    
  5. 如果源订阅与目标订阅都未报错,那说明迁移可以正常执行,继续生成迁移的 REST API 请求 body,调用 REST API 执行迁移动作。

     $executebody = ConvertTo-Json @{
         "target"="/subscriptions/$targetsubid"
     }
    
     $executeuri = "https://management.chinacloudapi.cn/subscriptions/$sourcesubid/providers/Microsoft.ClassicCompute/moveSubscriptionResources?api-version=2016-04-01"
     $executeresponse = Invoke-RestMethod -Uri $executeuri -Headers $header -body $executebody -Method POST
    
  6. 如果源订阅与目标订阅有报错,请先仔细查看报错信息,将阻碍迁移的资源事先迁移或移除之后再进行操作。

后续步骤

关于资源管理器部署的资源迁移,请参考文档将资源移到新资源组或订阅中