Skip to content

Commit

Permalink
Merge pull request #2844 from dougm/issue-2843
Browse files Browse the repository at this point in the history
Add content library VmConfigSpec support
  • Loading branch information
dougm committed May 16, 2022
2 parents 18cdce8 + 9d4ca65 commit ecf7a0b
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 1 deletion.
4 changes: 4 additions & 0 deletions govc/cli/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ var aliases = map[string]string{}
// Setting the env var GOVC_SHOW_UNRELEASED=true enables any commands registered as unreleased.
var hideUnreleased = os.Getenv("GOVC_SHOW_UNRELEASED") != "true"

func ShowUnreleased() bool {
return !hideUnreleased
}

func Register(name string, c Command, unreleased ...bool) {
if len(unreleased) != 0 && unreleased[0] && hideUnreleased {
return
Expand Down
13 changes: 13 additions & 0 deletions govc/library/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type deploy struct {
*importx.OptionsFlag

profile string
config string
}

func init() {
Expand All @@ -61,6 +62,10 @@ func (cmd *deploy) Register(ctx context.Context, f *flag.FlagSet) {
cmd.OptionsFlag.Register(ctx, f)

f.StringVar(&cmd.profile, "profile", "", "Storage profile")

if cli.ShowUnreleased() {
f.StringVar(&cmd.config, "config", "", "VM config spec")
}
}

func (cmd *deploy) Process(ctx context.Context) error {
Expand Down Expand Up @@ -220,6 +225,14 @@ func (cmd *deploy) Run(ctx context.Context, f *flag.FlagSet) error {
FolderID: folder.Reference().Value,
},
}

if cmd.config != "" {
deploy.VmConfigSpec = &vcenter.VmConfigSpec{
Provider: "XML",
XML: cmd.config,
}
}

ref, err = m.DeployLibraryItem(ctx, item.ID, deploy)
if err != nil {
return err
Expand Down
16 changes: 16 additions & 0 deletions govc/test/library.bats
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,29 @@ EOF
run govc vm.info -r ttylinux2
assert_success
assert_matches DC0_DVPG0
assert_matches 32MB
assert_matches "1 vCPU"

run env GOVC_DATASTORE="" govc library.deploy "my-content/$TTYLINUX_NAME" ttylinux3 # datastore is not required
assert_success

run govc vm.destroy ttylinux ttylinux2 ttylinux3
assert_success

config=$(base64 <<<'
<obj xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="vim25:VirtualMachineConfigSpec" xmlns:vim25="urn:vim25">
<numCPUs>4</numCPUs>
<memoryMB>2048</memoryMB>
</obj>')

run env GOVC_SHOW_UNRELEASED=true govc library.deploy -config "$config" "my-content/$TTYLINUX_NAME" ttylinux
assert_success

run govc vm.info -r ttylinux
assert_success
assert_matches 2048MB
assert_matches "4 vCPU"

item_id=$(govc library.info -json "/my-content/$TTYLINUX_NAME" | jq -r .[].id)

run govc datastore.rm "contentlib-$library_id/$item_id" # remove library files out-of-band, forcing a deploy error below
Expand Down
53 changes: 52 additions & 1 deletion vapi/simulator/simulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ package simulator

import (
"archive/tar"
"bytes"
"context"
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -53,6 +55,7 @@ import (
"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/types"
vim "github.com/vmware/govmomi/vim25/types"
"github.com/vmware/govmomi/vim25/xml"
)

type item struct {
Expand Down Expand Up @@ -1675,7 +1678,34 @@ func (i *item) ovf() string {
return ""
}

func vmConfigSpec(ctx context.Context, c *vim25.Client, deploy vcenter.Deploy) (*types.VirtualMachineConfigSpec, error) {
if deploy.VmConfigSpec == nil {
return nil, nil
}

b, err := base64.StdEncoding.DecodeString(deploy.VmConfigSpec.XML)
if err != nil {
return nil, err
}

var spec *types.VirtualMachineConfigSpec

dec := xml.NewDecoder(bytes.NewReader(b))
dec.TypeFunc = c.Types
err = dec.Decode(&spec)
if err != nil {
return nil, err
}

return spec, nil
}

func (s *handler) libraryDeploy(ctx context.Context, c *vim25.Client, lib *library.Library, item *item, deploy vcenter.Deploy) (*nfc.LeaseInfo, error) {
config, err := vmConfigSpec(ctx, c, deploy)
if err != nil {
return nil, err
}

name := item.ovf()
desc, err := ioutil.ReadFile(filepath.Join(libraryPath(lib, item.ID), name))
if err != nil {
Expand Down Expand Up @@ -1769,7 +1799,17 @@ func (s *handler) libraryDeploy(ctx context.Context, c *vim25.Client, lib *libra
return nil, err
}

return info, lease.Complete(ctx)
if err = lease.Complete(ctx); err != nil {
return nil, err
}

if config != nil {
if err = s.reconfigVM(info.Entity, *config); err != nil {
return nil, err
}
}

return info, nil
}

func (s *handler) libraryItemOVF(w http.ResponseWriter, r *http.Request) {
Expand Down Expand Up @@ -1898,6 +1938,17 @@ func (s *handler) deleteVM(ref *types.ManagedObjectReference) {
})
}

func (s *handler) reconfigVM(ref types.ManagedObjectReference, config types.VirtualMachineConfigSpec) error {
return s.withClient(func(ctx context.Context, c *vim25.Client) error {
vm := object.NewVirtualMachine(c, ref)
task, err := vm.Reconfigure(ctx, config)
if err != nil {
return err
}
return task.Wait(ctx)
})
}

func (s *handler) cloneVM(source string, name string, p *library.Placement, storage *vcenter.DiskStorage) (*types.ManagedObjectReference, error) {
var folder, pool, host, ds *types.ManagedObjectReference
if p.Folder != "" {
Expand Down
7 changes: 7 additions & 0 deletions vapi/vcenter/vcenter_ovf.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ type StorageMapping struct {
Value StorageGroupMapping `json:"value"`
}

// VmConfigSpec defines the optional virtual machine configuration settings used when deploying an OVF template
type VmConfigSpec struct {
Provider string `json:"provider"`
XML string `json:"xml"`
}

// DeploymentSpec is the deployment specification for the deployment
type DeploymentSpec struct {
Name string `json:"name,omitempty"`
Expand All @@ -136,6 +142,7 @@ type DeploymentSpec struct {
Flags []string `json:"flags,omitempty"`
AdditionalParams []AdditionalParams `json:"additional_parameters,omitempty"`
DefaultDatastoreID string `json:"default_datastore_id,omitempty"`
VmConfigSpec *VmConfigSpec `json:"vmConfigSpec,omitempty"`
}

// Target is the target for the deployment
Expand Down

0 comments on commit ecf7a0b

Please sign in to comment.