Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add content library VmConfigSpec support #2844

Merged
merged 3 commits into from
May 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: reconfigureVM better?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's ok - unexported and the API method is actually called ReconfigVM_Task.. not sure why chose to spell it out in the wrapper method 🤷

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