Skip to content

Commit e61ad35

Browse files
author
Pradeep Ramachandra
committed
api: Update folder.PlaceVMsXCluster to filter clusters based on candidate networks availability
- Add GoVmomi Bindings to CandidateNetworks - Made changes suggested by Shengjie Signed-off-by: Pradeep Ramachandra <[email protected]>
1 parent 39c6f0f commit e61ad35

File tree

4 files changed

+119
-17
lines changed

4 files changed

+119
-17
lines changed

cli/folder/place.go

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,13 @@ type place struct {
8686
*flags.VirtualMachineFlag
8787
*flags.OutputFlag
8888

89-
pool flags.StringList
90-
Type typeFlag
89+
pool flags.StringList
90+
Type typeFlag
91+
CandidateNetworks flags.StringList
9192
}
9293

9394
func init() {
94-
cli.Register("folder.place", &place{}, true)
95+
cli.Register("folder.place", &place{}, false)
9596
}
9697

9798
func (cmd *place) Register(ctx context.Context, f *flag.FlagSet) {
@@ -106,6 +107,7 @@ func (cmd *place) Register(ctx context.Context, f *flag.FlagSet) {
106107

107108
f.Var(&cmd.pool, "pool", "Resource Pools to use for placement.")
108109
f.Var(&cmd.Type, "type", fmt.Sprintf("Placement type (%s)", strings.Join(allTypes, "|")))
110+
f.Var(&cmd.CandidateNetworks, "candidate-networks", "Candidate network names (repeat for multiple nics)")
109111
}
110112

111113
func (cmd *place) Usage() string {
@@ -116,7 +118,13 @@ func (cmd *place) Description() string {
116118
return `Get a placement recommendation for an existing VM
117119
118120
Examples:
119-
govc folder.place -rp $rp1Name -rp $rp2Name -rp $rp3Name-vm $vmName`
121+
govc folder.place -rp $rp1Name -rp $rp2Name -rp $rp3Name -vm $vmName -type relocate -candidate-networks "netA|netB" -candidate-networks "netC"
122+
Each use of the "-candidate-networks" flag represents a different NIC.
123+
Within each value, "|" separates multiple candidate networks for that NIC.
124+
For example:
125+
-candidate-networks "netA|netB" → NIC 0 can connect to netA or netB
126+
-candidate-networks "netC" → NIC 1 can connect only to netC
127+
`
120128
}
121129

122130
func (cmd *place) Process(ctx context.Context) error {
@@ -136,13 +144,12 @@ func (cmd *place) Process(ctx context.Context) error {
136144
}
137145

138146
func (cmd *place) Run(ctx context.Context, f *flag.FlagSet) error {
139-
c, err := cmd.Client()
147+
client, err := cmd.Client()
140148
if err != nil {
141149
return err
142150
}
143-
144151
// Use latest version to pick up latest PlaceVmsXCluster API.
145-
err = c.UseServiceVersion()
152+
err = client.UseServiceVersion()
146153
if err != nil {
147154
return err
148155
}
@@ -175,9 +182,41 @@ func (cmd *place) Run(ctx context.Context, f *flag.FlagSet) error {
175182
default:
176183
return errors.New("please specify a valid type")
177184
}
185+
var candidateNetworks []types.PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks
186+
if len(cmd.CandidateNetworks) > 0 {
187+
client, err := cmd.Client()
188+
if err != nil {
189+
return err
190+
}
191+
finder := find.NewFinder(client, false)
192+
193+
dc, err := cmd.Datacenter()
194+
if err != nil {
195+
return err
196+
}
197+
finder.SetDatacenter(dc)
198+
199+
for _, nic := range cmd.CandidateNetworks {
200+
// Each 'nic' string is like "netA|netB"
201+
netNames := strings.Split(nic, "|")
202+
var refs []types.ManagedObjectReference
203+
204+
for _, name := range netNames {
205+
fmt.Printf(">>> Looking up network: %q\n", name)
206+
netObj, err := finder.Network(ctx, name)
207+
if err != nil {
208+
return fmt.Errorf("network %q not found: %w", name, err)
209+
}
210+
refs = append(refs, netObj.Reference())
211+
}
212+
candidateNetworks = append(candidateNetworks, types.PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks{
213+
Networks: refs,
214+
})
215+
}
216+
}
178217

179218
// PlaceVMsXCluster is only valid against the root folder.
180-
folder := object.NewRootFolder(c)
219+
folder := object.NewRootFolder(client)
181220

182221
refs := make([]types.ManagedObjectReference, 0, len(cmd.pool))
183222

@@ -191,9 +230,10 @@ func (cmd *place) Run(ctx context.Context, f *flag.FlagSet) error {
191230
}
192231

193232
vmPlacementSpecs := []types.PlaceVmsXClusterSpecVmPlacementSpec{{
194-
Vm: types.NewReference(vm.Reference()),
195-
ConfigSpec: types.VirtualMachineConfigSpec{},
196-
RelocateSpec: relocateSpec,
233+
Vm: types.NewReference(vm.Reference()),
234+
ConfigSpec: types.VirtualMachineConfigSpec{},
235+
RelocateSpec: relocateSpec,
236+
CandidateNetworks: candidateNetworks,
197237
}}
198238

199239
placementSpec := types.PlaceVmsXClusterSpec{

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ require (
2121
github.com/pmezard/go-difflib v1.0.0 // indirect
2222
gopkg.in/yaml.v3 v3.0.1 // indirect
2323
)
24+
25+
replace github.com/vmware/govmomi => .

simulator/folder_test.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,33 @@ func TestPlaceVmsXClusterCreateAndPowerOn(t *testing.T) {
632632

633633
Test(func(ctx context.Context, c *vim25.Client) {
634634
finder := find.NewFinder(c, false)
635+
datacenter, err := finder.DefaultDatacenter(ctx)
636+
if err != nil {
637+
t.Fatalf("failed to get default datacenter: %v", err)
638+
}
639+
finder.SetDatacenter(datacenter)
635640

641+
netA, err := finder.Network(ctx, "VM Network")
642+
if err != nil {
643+
t.Fatalf("unexpected error while getting network reference: %v", err)
644+
}
645+
netB, err := finder.Network(ctx, "DC0_DVPG0")
646+
if err != nil {
647+
t.Fatalf("unexpected error while getting network reference: %v", err)
648+
}
649+
650+
candidateNetworks := []types.PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks{
651+
{
652+
Networks: []types.ManagedObjectReference{
653+
netA.Reference(), netB.Reference(),
654+
},
655+
},
656+
{
657+
Networks: []types.ManagedObjectReference{
658+
netA.Reference(),
659+
},
660+
},
661+
}
636662
spec := types.PlaceVmsXClusterSpec{}
637663

638664
pools, err := finder.ResourcePoolList(ctx, "/DC0/host/DC0_C*/*")
@@ -648,6 +674,7 @@ func TestPlaceVmsXClusterCreateAndPowerOn(t *testing.T) {
648674
ConfigSpec: types.VirtualMachineConfigSpec{
649675
Name: "test-vm",
650676
},
677+
CandidateNetworks: candidateNetworks,
651678
}}
652679

653680
folder := object.NewRootFolder(c)
@@ -686,6 +713,19 @@ func TestPlaceVmsXClusterRelocate(t *testing.T) {
686713

687714
vmMoRef := Map(ctx).Any("VirtualMachine").(*VirtualMachine).Reference()
688715

716+
netA, err := finder.Network(context.Background(), "VM Network")
717+
if err != nil {
718+
t.Fatalf("unexpected error while getting network reference: %v", err)
719+
}
720+
netB, err := finder.Network(context.Background(), "DC0_DVPG0")
721+
if err != nil {
722+
t.Fatalf("unexpected error while getting network reference: %v", err)
723+
}
724+
725+
candidateNetworks := []types.PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks{
726+
{Networks: []types.ManagedObjectReference{netA.Reference(), netB.Reference()}}, // NIC 0
727+
{Networks: []types.ManagedObjectReference{netA.Reference()}}, // NIC 1
728+
}
689729
cfgSpec := types.VirtualMachineConfigSpec{}
690730

691731
tests := []struct {
@@ -754,9 +794,10 @@ func TestPlaceVmsXClusterRelocate(t *testing.T) {
754794
}
755795

756796
placeVmsXClusterSpec.VmPlacementSpecs = []types.PlaceVmsXClusterSpecVmPlacementSpec{{
757-
ConfigSpec: test.configSpec,
758-
Vm: test.vmMoRef,
759-
RelocateSpec: test.relocateSpec,
797+
ConfigSpec: test.configSpec,
798+
Vm: test.vmMoRef,
799+
RelocateSpec: test.relocateSpec,
800+
CandidateNetworks: candidateNetworks,
760801
}}
761802

762803
folder := object.NewRootFolder(c)

vim25/types/unreleased.go

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ func init() {
3030
t["ArrayOfPlaceVmsXClusterSpecVmPlacementSpec"] = reflect.TypeOf((*ArrayOfPlaceVmsXClusterSpecVmPlacementSpec)(nil)).Elem()
3131
}
3232

33+
type ArrayOfPlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks struct {
34+
PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks []PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks `xml:"PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks,omitempty"`
35+
}
36+
37+
func init() {
38+
t["ArrayOfPlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks"] = reflect.TypeOf((*ArrayOfPlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks)(nil)).Elem()
39+
}
40+
3341
type PlaceVmsXCluster PlaceVmsXClusterRequestType
3442

3543
func init() {
@@ -102,15 +110,26 @@ func init() {
102110
type PlaceVmsXClusterSpecVmPlacementSpec struct {
103111
DynamicData
104112

105-
Vm *ManagedObjectReference `xml:"vm,omitempty"`
106-
ConfigSpec VirtualMachineConfigSpec `xml:"configSpec"`
107-
RelocateSpec *VirtualMachineRelocateSpec `xml:"relocateSpec,omitempty"`
113+
Vm *ManagedObjectReference `xml:"vm,omitempty"`
114+
ConfigSpec VirtualMachineConfigSpec `xml:"configSpec"`
115+
RelocateSpec *VirtualMachineRelocateSpec `xml:"relocateSpec,omitempty"`
116+
CandidateNetworks []PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks `xml:"candidateNetworks,omitempty"`
108117
}
109118

110119
func init() {
111120
t["PlaceVmsXClusterSpecVmPlacementSpec"] = reflect.TypeOf((*PlaceVmsXClusterSpecVmPlacementSpec)(nil)).Elem()
112121
}
113122

123+
type PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks struct {
124+
DynamicData
125+
126+
Networks []ManagedObjectReference `xml:"networks,omitempty"`
127+
}
128+
129+
func init() {
130+
t["PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks"] = reflect.TypeOf((*PlaceVmsXClusterSpecVmPlacementSpecCandidateNetworks)(nil)).Elem()
131+
}
132+
114133
const RecommendationReasonCodeXClusterPlacement = RecommendationReasonCode("xClusterPlacement")
115134

116135
type ClusterClusterReconfigurePlacementAction struct {

0 commit comments

Comments
 (0)