| Works
vCloud Director環境下のStorage vMotion
お仕事で「vCloud Director管理下のVMをストレージポリシーは変更せずにStorage vMotionできる?」と質問されたので、ちょっと確認した備忘録。
VMwareのKBでは、だいぶ古いけど該当項目がありました(もっと新しいのがあるかも?)。
ストレージポリシーとかの整合性に注意すれば普通にvCenter ServerからStorage vMotionしても問題なさそうですが、REST APIで実行するのが良さそうです。
ただ、APIを一つ一つ手作業で操作するのは手間なので、いつも通りスクリプトにしました。
実行環境は例によってWindowsなので、PowerShellの"Invoke-RestMethod"とかでAPIにアクセスしていきます。
Param (
[Parameter(Mandatory = $True, HelpMessage="Target Organization")][alias("org","o")][ValidateNotNullOrEmpty()][string]$OrgName,
[Parameter(Mandatory = $True, HelpMessage="Target VM name")][alias("name","n")][ValidateNotNullOrEmpty()][string]$TargetVmName,
[Parameter(Mandatory = $True, HelpMessage="Destination Datastore")][alias("dest","d")][ValidateNotNullOrEmpty()][string]$DestStore
)
# vCloud Director
$VcdUser = "administrator"
$VcdPass = "password"
# vCloud API
$ApiEp = "https://vcd.example.com/api"
$ApiVer = "20.0"
# Authentication
$Auth = $VcdUser + "@system:" + $VcdPass
$Encoded = [System.Text.Encoding]::UTF8.GetBytes($Auth)
$EncodedPassword = [System.Convert]::ToBase64String($Encoded)
$SendUri = $ApiEp + "/sessions"
$Headers = @{
"Authorization" = "Basic " + $EncodedPassword;
"Accept" = "application/*+xml;version=$ApiVer"
}
$Res = Invoke-WebRequest -Headers $Headers -Uri $SendUri -Method POST
$VcdAuth = $Res.Headers["x-vcloud-authorization"]
$Headers = @{
"x-vcloud-authorization" = $VcdAuth;
"Accept" = "application/*+xml;version=$ApiVer"
}
# Get Organization Information
$SendUri = $ApiEp + "/admin"
$Res = Invoke-RestMethod -Headers $Headers -Uri $SendUri -Method GET
foreach ($objOrg in $Res.vCloud.OrganizationReferences.OrganizationReference) {
if ($objOrg.Name -eq $OrgName) {
$OrgUri = $objOrg.href
}
}
# Get Target VM Information
$SendUri = $ApiEp + "/query?type=adminVM&fields=name,datastoreName&filter=org==" + $OrgUri
$Res = Invoke-RestMethod -Headers $Headers -Uri $SendUri -Method GET
foreach ($objVm in $Res.QueryResultRecords.AdminVMRecord) {
if ($objVm.Name -eq $TargetVmName) {
if ($objVm.DatastoreName -ne $DestStore) {
$VmUri = $objVm.href
} else {
exit
}
}
}
# Get Destination Datastore Information
$SendUri = $ApiEp + "/query?type=datastore&fields=name"
$Res = Invoke-RestMethod -Headers $Headers -Uri $SendUri -Method GET
foreach ($objStore in $Res.QueryResultRecords.DatastoreRecord) {
if ($objStore.Name -eq $DestStore) {
$StoreUri = $objStore.href
}
}
# Relocate Vm
$RelocateXml = @"
<?xml version="1.0" encoding="UTF-8"?>
<RelocateParams xmlns="http://www.vmware.com/vcloud/v1.5">
<Datastore href="$StoreUri"/>
</RelocateParams>
"@
$SendUri = $VmUri + "/action/relocate"
$Headers = @{
"x-vcloud-authorization" = $VcdAuth;
"Accept" = "application/*+xml;version=$ApiVer";
"Content-Type" = "application/vnd.vmware.vcloud.relocateVmParams+xml";
}
$Res = Invoke-RestMethod -Headers $Headers -Uri $SendUri -Method POST -Body $RelocateXml
$Res.Task | Format-List
exit
最終的に必要となるパラメータは「対象VMのURL」と「移行先データストアのURL」となるので、"/query"等を使って必要な情報を集めていきます。
スクリプト実行時の引数は3つにしました。
.\RelocateVm.ps1 -o <対象VMの所属する組織名> -n <対象VM名> -d <移行先データストア名>
簡単に確認した限りでは期待した動作になったので、あとはいつも通り使いながら修正していく感じで。