Skip to content

Commit

Permalink
govc: support raw object references in import.ova NetworkMapping
Browse files Browse the repository at this point in the history
vCenter doesn't allow duplicate port group names within the network folder when creating via the UI
or the AddDVPortgroupTask() API. However, NSXt 3.0 can do so via other (unknown) means. With this
condition, govc would fail to map the given network name to its managed object reference.
To workaround this, a raw MO ref can now be used in the NetworkMapping, instead of the Network name
or inventory path.

Related history:
223168f * Add NetworkMapping section to importx options.
e3c3cd0 * Populate network mapping from ovf envelope (vmware#546)

Fixes vmware#1996
  • Loading branch information
dougm committed May 29, 2020
1 parent 776bf25 commit 10c22fd
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 23 deletions.
52 changes: 33 additions & 19 deletions govc/importx/ovf.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"fmt"
"path"

"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/nfc"
Expand Down Expand Up @@ -163,34 +164,42 @@ func (cmd *ovfx) Map(op []Property) (p []types.KeyValue) {
return
}

func (cmd *ovfx) NetworkMap(e *ovf.Envelope) (p []types.OvfNetworkMapping) {
func (cmd *ovfx) NetworkMap(e *ovf.Envelope) ([]types.OvfNetworkMapping, error) {
ctx := context.TODO()
finder, err := cmd.DatastoreFlag.Finder()
if err != nil {
return
return nil, err
}

networks := map[string]string{}

if e.Network != nil {
for _, net := range e.Network.Networks {
networks[net.Name] = net.Name
var nmap []types.OvfNetworkMapping
for _, m := range cmd.Options.NetworkMapping {
if m.Network == "" {
continue // Not set, let vSphere choose the default network
}
}

for _, net := range cmd.Options.NetworkMapping {
networks[net.Name] = net.Network
}
var ref types.ManagedObjectReference

for src, dst := range networks {
if net, err := finder.Network(ctx, dst); err == nil {
p = append(p, types.OvfNetworkMapping{
Name: src,
Network: net.Reference(),
})
net, err := finder.Network(ctx, m.Network)
if err != nil {
switch err.(type) {
case *find.NotFoundError:
if !ref.FromString(m.Network) {
return nil, err
} // else this is a raw MO ref
default:
return nil, err
}
} else {
ref = net.Reference()
}

nmap = append(nmap, types.OvfNetworkMapping{
Name: m.Name,
Network: ref,
})
}
return

return nmap, err
}

func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
Expand Down Expand Up @@ -224,6 +233,11 @@ func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
name = cmd.Name
}

nmap, err := cmd.NetworkMap(e)
if err != nil {
return nil, err
}

cisp := types.OvfCreateImportSpecParams{
DiskProvisioning: cmd.Options.DiskProvisioning,
EntityName: name,
Expand All @@ -233,7 +247,7 @@ func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) {
DeploymentOption: cmd.Options.Deployment,
Locale: "US"},
PropertyMapping: cmd.Map(cmd.Options.PropertyMapping),
NetworkMapping: cmd.NetworkMap(e),
NetworkMapping: nmap,
}

host, err := cmd.HostSystemIfSpecified()
Expand Down
37 changes: 37 additions & 0 deletions govc/test/import.bats
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,40 @@ load test_helper
run govc import.vmdk -force "$GOVC_TEST_VMDK_SRC" "$name"
assert_success # exists, but -force was used
}

@test "import duplicate dvpg names" {
vcsim_env

run govc dvs.create DVS1 # DVS0 already exists
assert_success

run govc dvs.portgroup.add -dvs DVS0 -type ephemeral NSX-dvpg
assert_success

run govc dvs.portgroup.add -dvs DVS1 -type ephemeral NSX-dvpg
assert_success

ovf="$GOVC_IMAGES/$TTYLINUX_NAME.ovf"

spec=$(govc import.spec "$GOVC_IMAGES/$TTYLINUX_NAME.ovf")

run govc import.ovf -name ttylinux -options - "$ovf" <<<"$spec"
assert_success # no network specified

options=$(jq ".NetworkMapping[].Network = \"enoent\"" <<<"$spec")

run govc import.ovf -options - "$ovf" <<<"$options"
assert_failure # network not found

options=$(jq ".NetworkMapping[].Network = \"NSX-dvpg\"" <<<"$spec")

run govc import.ovf -options - "$ovf" <<<"$options"
assert_failure # 2 networks have the same name

switch=$(govc find -i network -name DVS0)
id=$(govc find -i network -config.distributedVirtualSwitch "$switch" -name NSX-dvpg)
options=$(jq ".NetworkMapping[].Network = \"$id\"" <<<"$spec")

run govc import.ovf -options - "$ovf" <<<"$options"
assert_success # using raw MO id
}
13 changes: 9 additions & 4 deletions simulator/dvs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package simulator

import (
"strconv"
"strings"

"github.com/vmware/govmomi/vim25/methods"
"github.com/vmware/govmomi/vim25/mo"
Expand All @@ -41,10 +42,14 @@ func (s *DistributedVirtualSwitch) AddDVPortgroupTask(ctx *Context, c *types.Add
pg.Name = spec.Name
pg.Entity().Name = pg.Name

if obj := Map.FindByName(pg.Name, f.ChildEntity); obj != nil {
return nil, &types.DuplicateName{
Name: pg.Name,
Object: obj.Reference(),
// Standard AddDVPortgroupTask() doesn't allow duplicate names, but NSX 3.0 does create some DVPGs with the same name.
// Allow duplicate names using this prefix so we can reproduce and test this condition.
if !strings.HasPrefix(pg.Name, "NSX-") {
if obj := Map.FindByName(pg.Name, f.ChildEntity); obj != nil {
return nil, &types.DuplicateName{
Name: pg.Name,
Object: obj.Reference(),
}
}
}

Expand Down

0 comments on commit 10c22fd

Please sign in to comment.