概要
QueryChangedDiskAreas
は CBT の機能を使って VM のスナップショット間でディスクの差分情報を取得する API です
CBT に関してはここでは紹介しないので CBT について知りたい、試してみたいかたはこちらで紹介しています
今回は特定の VM のスナップショットの作成から QueryChangedDiskAreas
API をコールするまでの一連の流れをすべてコードにしたので紹介します
環境
- CentOS 7.5.1804
- golang 1.11.2
- govmomi 6712f991d8852a25ae4304a720463301c1ac4c64
コード全体
まずコード全体です
かなり長いです
あとでコードの説明をします
package main
import (
"context"
"flag"
"fmt"
"net/url"
"os"
"time"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
)
var envURL = "https://192.168.100.20/sdk"
var user = "administrator@vsphere.local"
var pass = "xxxxxxxxxxx"
var vmname = "dist"
var urlDescription = fmt.Sprintf("ESX or vCenter URL [%s]", envURL)
var urlFlag = flag.String("url", envURL, urlDescription)
var envInsecure = true
var insecureDescription = fmt.Sprintf("Don't verify the server's certificate chain [%s]", envInsecure)
var insecureFlag = flag.Bool("insecure", envInsecure, insecureDescription)
func main() {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
flag.Parse()
u, err := url.Parse(*urlFlag)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// (1)
u.User = url.UserPassword(user, pass)
c, err := govmomi.NewClient(ctx, u, *insecureFlag)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(c.Client.Client.Version)
// (2)
f := find.NewFinder(c.Client, true)
dc, err := f.DefaultDatacenter(ctx)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
f.SetDatacenter(dc)
fmt.Println(dc)
// vm list (3)
vss, err := f.VirtualMachineList(ctx, "*")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// virtualdevice from vm (4, 5)
devices := object.VirtualDeviceList{}
device := &types.VirtualDevice{}
ref := types.ManagedObjectReference{}
tvm := &object.VirtualMachine{}
for _, vm := range vss {
name := vm.Name()
if name == vmname {
fmt.Println(name)
devices, _ = vm.Device(ctx)
for _, d := range devices {
vd := d.GetVirtualDevice()
// fmt.Println(vd.Key)
// fmt.Println(vd.DeviceInfo)
// fmt.Println(vd.Backing)
// fmt.Println(vd.Connectable)
// fmt.Println(vd.SlotInfo)
// fmt.Println(vd.ControllerKey)
// fmt.Println(vd.UnitNumber)
if vd.DeviceInfo.GetDescription().Label == "Hard disk 1" {
device = vd
}
}
ref = vm.Common.Reference()
tvm = vm
fmt.Printf("%v\n", ref)
break
}
}
fmt.Println(device.Key)
// snapshot from vm (6)
ssreq := new(types.CreateSnapshot_Task)
ssreq.Description = "Snapshot created by govmomi"
ssreq.Name = vmname + "ss"
ssreq.Memory = false
ssreq.This.Type = ref.Type
ssreq.This.Value = ref.Value
_, err = methods.CreateSnapshot_Task(ctx, c.RoundTripper, ssreq)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
time.Sleep(5 * time.Second)
ssref, err := tvm.FindSnapshot(ctx, vmname + "ss")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(ssref.Type)
fmt.Println(ssref.Value)
// change disk areas (7)
query := new(types.QueryChangedDiskAreas)
query.ChangeId = "*"
query.DeviceKey = device.Key
query.Snapshot = ssref
query.StartOffset = 0
query.This.Type = ref.Type
query.This.Value = ref.Value
res, err := methods.QueryChangedDiskAreas(ctx, c.RoundTripper, query)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("%v\n", res) // DiskChangeInfo
fmt.Println(res.Returnval.StartOffset)
fmt.Println(res.Returnval.Length)
for i, area := range res.Returnval.ChangedArea {
fmt.Println(i)
fmt.Println(area.Start)
fmt.Println(area.Length)
}
}
流れとしては
- vCenter 接続
- Datacenter 取得
- VirtualMachine のリストの取得
- リストから対象の VirtualMachine の取得
- 対象の VirtualMachine から HardDisk デバイスの情報を取得
- 対象の VM に対してスナップショットの作成
QueryChangedDiskAreas
を実行して作成したスナップショットと元 VM の差分を取得
という流れになります
この流れのなかで QueryChangedDiskAreas
を実行するために実行していないのは対象の VM に対しての CBT の有効化です
VM の設定で changeTrackingEnabled
を true にすれば OK なので手動で実施してください
ポイント説明
まず QueryChangedDiskAreas
を実行するのに必須なのはスナップショットの情報とスナップショットが持つディスクの Key 番号と ChangeID と呼ばれる変更履歴を管理するタイムスタンプ情報です
今回のサンプルでは ChangeID は *
を指定しており *
を指定した場合は元 VM の初めから差分をチェックします
スナップショットは新規で作成し、そのスナップショットの情報と元 VM の情報を比較します
スナップショットの作成と作成したスナップショットの moref の取得は 6 でやっています
あと必要なハードディスクの Key 番号は 5 でやっています
vm.Device(ctx)
で各デバイスの情報を取得しそこから「Hard disk 1」を取得します
今回は VM が持つハードディスクは 1 つしかないので「Hard disk 1」を指定していますがハードディスクが複数ある場合は差分を取りたいハードディスクを取得するようにしてください
あとは device.Key
で参照するだけです
StartOffset
は探索する先頭を指定できますが基本は 0 でいいと思います
コードでやることを減らすには
今回はスナップショットも作成もコードでやっています
QueryChangedDiskAreas
API は単純に差分を取得するだけなのでスナップショットは事前に作成しておいても OK です
moref の情報をハードコードで設定してあげても良いです
あとは device.Key
もハードディスクが決まっているのであれば決め打ちでも OK です
単純な整数番号なので mob などで取得して設定すれば OK です
要するに query := new(types.QueryChangedDiskAreas)
に設定する値をあらかじめ取得してハードコードすればいいだけです
3, 4, 5, 6 の流れをごっそり削除することが可能になります
最後に
govmomi で QueryChangedDiskAreas をコールしてみました
govmomi じゃなくても QueryChangedDiskAreas 自体はコールできます
CBT の概念を理解しないと QueryChangedDiskAreas 自体も何をやっているかよくわからないのでまずは CBT を理解したほうが良いかなと思います
0 件のコメント:
コメントを投稿