2017年4月18日火曜日

govmomi で VM を削除する方法

概要

govmomi で指定の VM を 1 台削除する方法を紹介します

環境

  • Ubuntu 16.04
  • golang 1.8
  • govmomi 0.14.0

ソースコード

  • vim destroy_vm.go
package main

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

    "github.com/vmware/govmomi"
    "github.com/vmware/govmomi/find"
    "github.com/vmware/govmomi/object"
)

type VCenterAPI struct {
    URL           string
    User          string
    Pass          string
    Insecure      bool
    URLFlag       *string
    InsecureFlag  *bool
    Network       string
    GovmomiClient *govmomi.Client
    Finder        *find.Finder
    DC            *object.Datacenter
}

func NewVCenterAPI() (api *VCenterAPI) {
    api = new(VCenterAPI)
    api.URL = "https://192.168.100.101/sdk"
    api.User = "vcenter-username"
    api.Pass = "vcenter-password"
    api.Insecure = true
    api.URLFlag = flag.String("url", api.URL, "")
    api.InsecureFlag = flag.Bool("insecure", api.Insecure, "")
    api.Network = "VM Network"
    flag.Parse()
    return api
}

func (api *VCenterAPI) Init() (err error) {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    u, err := url.Parse(*api.URLFlag)
    if err != nil {
        return err
    }
    u.User = url.UserPassword(api.User, api.Pass)
    c, err := govmomi.NewClient(ctx, u, *api.InsecureFlag)
    if err != nil {
        return err
    }
    f := find.NewFinder(c.Client, true)
    dc, err := f.DefaultDatacenter(ctx)
    if err != nil {
        return err
    }
    f.SetDatacenter(dc)
    api.GovmomiClient = c
    api.Finder = f
    api.DC = dc
    return nil
}

func (api *VCenterAPI) DestroyVM(path string) (err error) {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    vm, err := api.Finder.VirtualMachine(ctx, path)
    if err != nil {
        return err
    }
    t, err := vm.Destroy(ctx)
    if err != nil {
        return err
    }
    err = t.Wait(ctx)
    if err != nil {
        return err
    }
    return nil
}

func (api *VCenterAPI) PowerOffVM(path string) (err error) {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()
    vm, err := api.Finder.VirtualMachine(ctx, path)
    if err != nil {
        return err
    }
    t, err := vm.PowerOff(ctx)
    if err != nil {
        return err
    }
    err = t.Wait(ctx)
    if err != nil {
        return err
    }
    return nil
}

func main() {
    api := NewVCenterAPI()
    err := api.Init()
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    path := "/dc/vm/folder/vm1"
    err = api.PowerOffVM(path)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    err = api.DestroyVM(path)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}
  • go fmt destroy_vm.go
  • go run destroy_vm.go

解説

削除する前に VM が停止していなければいけません
なので、PowerOffVM という関数を用意しています

DestroyVM も PowerOffVM もロジックはだいたい同じです
ポイントは find.VirtualMachine を使って単一の VM だけ取得している点です
find.Finder.VirtualMachineList を使って VM のインベントリパスを指定しても問題ないのですが、例えばアスタリスクなどを使って複数の VM を指定した場合複数の VM が取得できてしまいます
自分で VM の名前などでフィルタを掛けてもいいですが、そんなことをしないでも良いように準備されている find.VirtualMachine を使っています

あとはそこで取得できた object.VirtualMachine の構造体が用意している Destroy(context) を呼び出すだけで OK です
関数の戻り値にタスクが戻ってくるので Wait することでパワーオフと削除を待つことができます

実行する際に VM へのインベントリパスを指定しています
パスが存在しない場合にはエラーになります
主な発生するエラーは以下の通りです

  • find.VirtualMachine で複数指定すると以下のエラーになる
    • path '/dc/vm/folder/*' resolves to multiple vms
  • Destroy 対象の VM がパワー ON だと以下のエラーになる
    • The attempted operation cannot be performed in the current state (Powered on).
  • 指定した VM のインベントリパスがない場合
    • vm ‘/dc/vm/folder/non-vm’ not found

最後に

govmomi で VM を削除する方法を紹介しました
サンプルコードが見つからなかったのでリファレンスとソースコードを見ながら実装しましたが、慣れれば簡単にできるようになると思います

参考サイト

0 件のコメント:

コメントを投稿