Skip to content

Commit

Permalink
Add device option to WaitForNetIP (#660)
Browse files Browse the repository at this point in the history
With this option, WaitForNetIP can specify NIC(s) by MAC address or device name.

Fixes #653
  • Loading branch information
dougm authored Jan 27, 2017
1 parent ba9e3f4 commit 17e6545
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 6 deletions.
7 changes: 7 additions & 0 deletions govc/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2169,6 +2169,7 @@ Examples:
govc vm.clone -vm template-vm new-vm
Options:
-annotation= VM description
-c=0 Number of CPUs
-customization= Customization Specification Name
-datastore-cluster= Datastore cluster [GOVC_DATASTORE_CLUSTER]
Expand All @@ -2193,6 +2194,7 @@ Options:
Usage: govc vm.create [OPTIONS]
Options:
-annotation= VM description
-c=1 Number of CPUs
-datastore-cluster= Datastore cluster [GOVC_DATASTORE_CLUSTER]
-disk= Disk path (to use existing) OR size (to create new, e.g. 20GB)
Expand Down Expand Up @@ -2287,18 +2289,23 @@ These values can also be obtained using:
govc vm.info -json $vm | jq -r .VirtualMachines[].Guest.Net[].IpConfig.IpAddress[].IpAddress
When given the '-n' flag, filters '-a' behavior to the nic specified by MAC address or device name.
The 'esxcli' flag does not require vmware-tools to be installed, but does require the ESX host to
have the /Net/GuestIPHack setting enabled.
Examples:
govc vm.ip $vm
govc vm.ip -a -v4 $vm
govc vm.ip -n 00:0c:29:57:7b:c3 $vm
govc vm.ip -n ethernet-0 $vm
govc host.esxcli system settings advanced set -o /Net/GuestIPHack -i 1
govc vm.ip -esxcli $vm
Options:
-a=false Wait for an IP address on all NICs
-esxcli=false Use esxcli instead of guest tools
-n= Wait for IP address on NIC, specified by device name or MAC
-v4=false Only report IPv4 addresses
```

Expand Down
15 changes: 15 additions & 0 deletions govc/test/vm.bats
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,21 @@ load test_helper

run govc vm.ip -a -v4 $id
assert_success

run govc vm.ip -n $(vm_mac $id) $id
assert_success

run govc vm.ip -n ethernet-0 $id
assert_success

ip=$(govc vm.ip $id)

# add a second nic
run govc vm.network.add -vm $id "VM Network"
assert_success

res=$(govc vm.ip -n ethernet-0 $id)
assert_equal $ip $res
}

@test "vm.ip -esxcli" {
Expand Down
15 changes: 13 additions & 2 deletions govc/vm/ip.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type ip struct {
esx bool
all bool
v4 bool
nic string
}

func init() {
Expand All @@ -51,6 +52,7 @@ func (cmd *ip) Register(ctx context.Context, f *flag.FlagSet) {

f.BoolVar(&cmd.esx, "esxcli", false, "Use esxcli instead of guest tools")
f.BoolVar(&cmd.all, "a", false, "Wait for an IP address on all NICs")
f.StringVar(&cmd.nic, "n", "", "Wait for IP address on NIC, specified by device name or MAC")
f.BoolVar(&cmd.v4, "v4", false, "Only report IPv4 addresses")
}

Expand All @@ -76,12 +78,16 @@ These values can also be obtained using:
govc vm.info -json $vm | jq -r .VirtualMachines[].Guest.Net[].IpConfig.IpAddress[].IpAddress
When given the '-n' flag, filters '-a' behavior to the nic specified by MAC address or device name.
The 'esxcli' flag does not require vmware-tools to be installed, but does require the ESX host to
have the /Net/GuestIPHack setting enabled.
Examples:
govc vm.ip $vm
govc vm.ip -a -v4 $vm
govc vm.ip -n 00:0c:29:57:7b:c3 $vm
govc vm.ip -n ethernet-0 $vm
govc host.esxcli system settings advanced set -o /Net/GuestIPHack -i 1
govc vm.ip -esxcli $vm`
}
Expand Down Expand Up @@ -131,9 +137,14 @@ func (cmd *ip) Run(ctx context.Context, f *flag.FlagSet) error {
}
}
} else {
var hwaddr []string
if cmd.nic != "" {
hwaddr = strings.Split(cmd.nic, ",")
}

get = func(vm *object.VirtualMachine) (string, error) {
if cmd.all {
macs, err := vm.WaitForNetIP(ctx, cmd.v4)
if cmd.all || hwaddr != nil {
macs, err := vm.WaitForNetIP(ctx, cmd.v4, hwaddr...)
if err != nil {
return "", err
}
Expand Down
23 changes: 19 additions & 4 deletions object/virtual_machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,12 @@ func (v VirtualMachine) WaitForIP(ctx context.Context) (string, error) {

// WaitForNetIP waits for the VM guest.net property to report an IP address for all VM NICs.
// Only consider IPv4 addresses if the v4 param is true.
// By default, wait for all NICs to get an IP address, unless 1 or more device is given.
// A device can be specified by the MAC address or the device name, e.g. "ethernet-0".
// Returns a map with MAC address as the key and IP address list as the value.
func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool) (map[string][]string, error) {
func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool, device ...string) (map[string][]string, error) {
macs := make(map[string][]string)
eths := make(map[string]string)

p := property.DefaultCollector(v.c)

Expand All @@ -242,21 +245,33 @@ func (v VirtualMachine) WaitForNetIP(ctx context.Context, v4 bool) (map[string][
continue
}

devices := c.Val.(types.ArrayOfVirtualDevice).VirtualDevice
for _, device := range devices {
if nic, ok := device.(types.BaseVirtualEthernetCard); ok {
devices := VirtualDeviceList(c.Val.(types.ArrayOfVirtualDevice).VirtualDevice)
for _, d := range devices {
if nic, ok := d.(types.BaseVirtualEthernetCard); ok {
mac := nic.GetVirtualEthernetCard().MacAddress
if mac == "" {
return false
}
macs[mac] = nil
eths[devices.Name(d)] = mac
}
}
}

return true
})

if len(device) != 0 {
// Only wait for specific NIC(s)
macs = make(map[string][]string)
for _, mac := range device {
if eth, ok := eths[mac]; ok {
mac = eth // device name, e.g. "ethernet-0"
}
macs[mac] = nil
}
}

err = property.Wait(ctx, p, v.Reference(), []string{"guest.net"}, func(pc []types.PropertyChange) bool {
for _, c := range pc {
if c.Op != types.PropertyChangeOpAssign {
Expand Down

0 comments on commit 17e6545

Please sign in to comment.