Skip to content

Commit

Permalink
govc: add vm.create '-profile' and '-place' flags
Browse files Browse the repository at this point in the history
  • Loading branch information
dougm committed Jun 12, 2024
1 parent 748043c commit e7d54f9
Showing 1 changed file with 88 additions and 2 deletions.
90 changes: 88 additions & 2 deletions govc/vm/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ import (
"context"
"flag"
"fmt"
"io"
"strings"
"text/tabwriter"

"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/object"
Expand Down Expand Up @@ -60,6 +63,8 @@ type create struct {
annotation string
firmware string
version string
place bool
profile string

iso string
isoDatastoreFlag *flags.DatastoreFlag
Expand Down Expand Up @@ -122,8 +127,11 @@ func (cmd *create) Register(ctx context.Context, f *flag.FlagSet) {
f.BoolVar(&cmd.force, "force", false, "Create VM if vmx already exists")
f.StringVar(&cmd.controller, "disk.controller", "scsi", "Disk controller type")
f.StringVar(&cmd.annotation, "annotation", "", "VM description")

f.StringVar(&cmd.firmware, "firmware", FirmwareTypes[0], FirmwareUsage)
f.StringVar(&cmd.profile, "profile", "", "Storage profile name or ID")
if cli.ShowUnreleased() {
f.BoolVar(&cmd.place, "place", false, "Place VM without creating")
}

esxiVersions := types.GetESXiVersions()
esxiVersionStrings := make([]string, len(esxiVersions))
Expand Down Expand Up @@ -299,7 +307,9 @@ func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
if err != nil {
return err
}

if cmd.place {
return nil
}
info, err := task.WaitForResult(ctx, nil)
if err != nil {
return err
Expand All @@ -322,6 +332,61 @@ func (cmd *create) Run(ctx context.Context, f *flag.FlagSet) error {
return nil
}

type place struct {
Spec types.PlacementSpec `json:"spec"`
Recommendations []types.ClusterRecommendation `json:"recommendations"`

ctx context.Context
cmd *create
}

func (p *place) Dump() interface{} {
return p.Recommendations
}

func (p *place) action(w io.Writer, r types.ClusterRecommendation, a *types.PlacementAction) error {
spec := a.RelocateSpec
if spec == nil {
return nil
}

fields := []struct {
name string
moid *types.ManagedObjectReference
}{
{"Target", r.Target},
{" Folder", spec.Folder},
{" Datastore", spec.Datastore},
{" Pool", spec.Pool},
{" Host", spec.Host},
}

for _, f := range fields {
if f.moid == nil {
continue
}
path, err := find.InventoryPath(p.ctx, p.cmd.Client, *f.moid)
if err != nil {
return err
}
fmt.Fprintf(w, "%s:\t%s\n", f.name, path)
}

return nil
}

func (p *place) Write(w io.Writer) error {
tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0)

for _, r := range p.Recommendations {
for _, a := range r.Action {
p.action(tw, r, a.(*types.PlacementAction))
}
}

return tw.Flush()
}

func (cmd *create) createVM(ctx context.Context) (*object.Task, error) {
var devices object.VirtualDeviceList
var err error
Expand All @@ -346,6 +411,24 @@ func (cmd *create) createVM(ctx context.Context) (*object.Task, error) {
Version: cmd.version,
}

if cmd.profile != "" {
c, err := cmd.PbmClient()
if err != nil {
return nil, err
}
m, err := c.ProfileMap(ctx)
if err != nil {
return nil, err
}
p, ok := m.Name[cmd.profile]
if !ok {
return nil, fmt.Errorf("profile %q not found", cmd.profile)
}
spec.VmProfile = []types.BaseVirtualMachineProfileSpec{&types.VirtualMachineDefinedProfileSpec{
ProfileId: p.GetPbmProfile().ProfileId.UniqueId,
}}
}

devices, err = cmd.addStorage(nil)
if err != nil {
return nil, err
Expand Down Expand Up @@ -384,6 +467,9 @@ func (cmd *create) createVM(ctx context.Context) (*object.Task, error) {
}

recs := result.Recommendations
if cmd.place {
return nil, cmd.WriteResult(&place{pspec, recs, ctx, cmd})
}
if len(recs) == 0 {
return nil, fmt.Errorf("no cluster recommendations")
}
Expand Down

0 comments on commit e7d54f9

Please sign in to comment.