2018年12月17日月曜日

govmomi で Task の Wait を行う方法

概要

govmomi の methods で API を呼び出した場合、レスポンスが object.Task でないためいきなり Wait が呼べません
レスポンスから object.Task を作成して Wait する必要があります

環境

  • CentOS 7.5.1804
  • golang 1.11.2
  • govmomi 6712f991d8852a25ae4304a720463301c1ac4c64

サンプルコード

今回はスナップショットの作成 (methods.CreateSnapshot_Task) を Wait する方法を紹介します

  • mkdir go/src/github.com/hawksnowlog/h
  • vim go/src/github.com/hawksnowlog/h/main.go
package main

import (
    "context"
    "flag"
    "fmt"
    "net/url"
    "os"

    "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 = "xxxxxxxxxx"
var vmname = "vm01"
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)
    }
    u.User = url.UserPassword(user, pass)
    c, err := govmomi.NewClient(ctx, u, *insecureFlag)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    f := find.NewFinder(c.Client, true)
    dc, err := f.DefaultDatacenter(ctx)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    f.SetDatacenter(dc)
    // vm list
    vss, err := f.VirtualMachineList(ctx, "*")
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    ref := types.ManagedObjectReference{}
    for _, vm := range vss {
        name := vm.Name()
        if name == vmname {
            ref = vm.Common.Reference()
            break
        }
    }
    // snapshot from vm
    fmt.Println(ref.Type)
    fmt.Println(ref.Value)
    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
    res, err := methods.CreateSnapshot_Task(ctx, c.RoundTripper, ssreq)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    task := object.NewTask(c.Client, res.Returnval)
    err = task.Wait(ctx)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println("created snapshot")
}
  • go build github.com/hawksnowlog/h
  • go install github.com/hawksnowlog/h
  • $GOPATH/bin/h

解説

res, err := methods.CreateSnapshot_Task(ctx, c.RoundTripper, ssreq) で取得できる res は types.CreateSnapshot_TaskResponse になっています
これだと .Wait(ctx) 関数を呼び出せません

なので res を元に task := object.NewTask(c.Client, res.Returnval)object.Task を作成してから .Wait(ctx) を呼び出してあげます

ssreq.This.Type = ref.Typessreq.This.Value = ref.Value はただの文字列になっています
例えばそれぞれ「VirtualMachine」「vm-20」という文字列です
今回のサンプルでは VM を取得してそこから moref を参照していますが決め打ちで決まっている場合は VM を検索するロジックは削除できます

最後に

govmomi で Task を Wait する方法を紹介しました
govmomi は基本は非同期なので、この Wait のやり方を覚えておかないとまだリソースが作成されていない状態で次に行ってしまったりするので注意が必要です
簡単な方法なので覚えておくと良いと思います

参考サイト

0 件のコメント:

コメントを投稿