Skip to content

Instantly share code, notes, and snippets.

@mjm
Created March 21, 2019 21:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjm/f7e198546dffedee34f7a3f508b0c14d to your computer and use it in GitHub Desktop.
Save mjm/f7e198546dffedee34f7a3f508b0c14d to your computer and use it in GitHub Desktop.
Instant clone a vSphere VM
package main
import (
"context"
"flag"
"fmt"
"net"
"net/url"
"os"
"path"
"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/mo"
"github.com/vmware/govmomi/vim25/types"
)
func main() {
ctx := context.Background()
flag.Parse()
srcPath := flag.Arg(0)
destPath := flag.Arg(1)
u, err := url.Parse(os.Getenv("VSPHERE_URL"))
checkError(err)
client, err := govmomi.NewClient(ctx, u, true)
checkError(err)
finder := find.NewFinder(client.Client, false)
srcVM, err := finder.VirtualMachine(ctx, srcPath)
checkError(err)
destFolder, err := finder.Folder(ctx, path.Dir(destPath))
checkError(err)
destFolderRef := destFolder.Reference()
req := types.InstantClone_Task{
This: srcVM.Reference(),
Spec: types.VirtualMachineInstantCloneSpec{
Name: path.Base(destPath),
Location: types.VirtualMachineRelocateSpec{
Folder: &destFolderRef,
},
},
}
start := time.Now()
fmt.Println("Cloning VM...")
res, err := methods.InstantClone_Task(ctx, client.Client, &req)
checkError(err)
task := object.NewTask(client.Client, res.Returnval)
err = task.Wait(ctx)
checkError(err)
elapsed := time.Since(start)
fmt.Println("Clone succeeded. Took ", elapsed)
start = time.Now()
fmt.Println("Waiting for IP...")
clonedVM, err := finder.VirtualMachine(ctx, destPath)
checkError(err)
/* ips, err := clonedVM.WaitForNetIP(ctx, true)
checkError(err)
for k, v := range ips {
fmt.Println(k, "\t", v)
}
*/
var ip string
var vmInfo mo.VirtualMachine
for ip == "" {
err = clonedVM.Properties(ctx, clonedVM.Reference(), []string{"guest.net"}, &vmInfo)
checkError(err)
nics := vmInfo.Guest.Net
for _, nic := range nics {
if ip != "" {
break
}
if mac := nic.MacAddress; mac == "" {
continue
}
if nic.IpConfig == nil {
continue
}
for _, vmIP := range nic.IpAddress {
if net.ParseIP(vmIP).To4() == nil {
continue
}
ip = vmIP
break
}
}
// No IP found on the VM yet
time.Sleep(500 * time.Millisecond)
}
fmt.Println("IP:", ip)
elapsed = time.Since(start)
fmt.Println("Waiting for IP took ", elapsed)
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment