github.com/vmware/govmomi@v0.43.0/govc/vm/ip.go (about) 1 /* 2 Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package vm 18 19 import ( 20 "context" 21 "flag" 22 "fmt" 23 "strings" 24 "time" 25 26 "github.com/vmware/govmomi/govc/cli" 27 "github.com/vmware/govmomi/govc/flags" 28 "github.com/vmware/govmomi/govc/host/esxcli" 29 "github.com/vmware/govmomi/object" 30 ) 31 32 type ip struct { 33 *flags.OutputFlag 34 *flags.SearchFlag 35 36 esx bool 37 all bool 38 v4 bool 39 wait time.Duration 40 nic string 41 } 42 43 func init() { 44 cli.Register("vm.ip", &ip{}) 45 } 46 47 func (cmd *ip) Register(ctx context.Context, f *flag.FlagSet) { 48 cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) 49 cmd.OutputFlag.Register(ctx, f) 50 51 cmd.SearchFlag, ctx = flags.NewSearchFlag(ctx, flags.SearchVirtualMachines) 52 cmd.SearchFlag.Register(ctx, f) 53 54 f.BoolVar(&cmd.esx, "esxcli", false, "Use esxcli instead of guest tools") 55 f.BoolVar(&cmd.all, "a", false, "Wait for an IP address on all NICs") 56 f.StringVar(&cmd.nic, "n", "", "Wait for IP address on NIC, specified by device name or MAC") 57 f.BoolVar(&cmd.v4, "v4", false, "Only report IPv4 addresses") 58 f.DurationVar(&cmd.wait, "wait", time.Hour, "Wait time for the VM obtain an IP address") 59 } 60 61 func (cmd *ip) Usage() string { 62 return "VM..." 63 } 64 65 func (cmd *ip) Description() string { 66 return `List IPs for VM. 67 68 By default the vm.ip command depends on vmware-tools to report the 'guest.ipAddress' field and will 69 wait until it has done so. This value can also be obtained using: 70 71 govc vm.info -json $vm | jq -r .virtualMachines[].guest.ipAddress 72 73 When given the '-a' flag, only IP addresses for which there is a corresponding virtual nic are listed. 74 If there are multiple nics, the listed addresses will be comma delimited. The '-a' flag depends on 75 vmware-tools to report the 'guest.net' field and will wait until it has done so for all nics. 76 Note that this list includes IPv6 addresses if any, use '-v4' to filter them out. IP addresses reported 77 by tools for which there is no virtual nic are not included, for example that of the 'docker0' interface. 78 79 These values can also be obtained using: 80 81 govc vm.info -json $vm | jq -r .virtualMachines[].guest.net[].ipConfig.ipAddress[].ipAddress 82 83 When given the '-n' flag, filters '-a' behavior to the nic specified by MAC address or device name. 84 85 The 'esxcli' flag does not require vmware-tools to be installed, but does require the ESX host to 86 have the /Net/GuestIPHack setting enabled. 87 88 The 'wait' flag default to 1hr (original default was infinite). If a VM does not obtain an IP within 89 the wait time, the command will still exit with status 0. 90 91 Examples: 92 govc vm.ip $vm 93 govc vm.ip -wait 5m $vm 94 govc vm.ip -a -v4 $vm 95 govc vm.ip -n 00:0c:29:57:7b:c3 $vm 96 govc vm.ip -n ethernet-0 $vm 97 govc host.esxcli system settings advanced set -o /Net/GuestIPHack -i 1 98 govc vm.ip -esxcli $vm` 99 } 100 101 func (cmd *ip) Process(ctx context.Context) error { 102 if err := cmd.OutputFlag.Process(ctx); err != nil { 103 return err 104 } 105 if err := cmd.SearchFlag.Process(ctx); err != nil { 106 return err 107 } 108 return nil 109 } 110 111 func (cmd *ip) Run(ctx context.Context, f *flag.FlagSet) error { 112 c, err := cmd.Client() 113 if err != nil { 114 return err 115 } 116 117 vms, err := cmd.VirtualMachines(f.Args()) 118 if err != nil { 119 return err 120 } 121 122 var get func(*object.VirtualMachine, context.Context) (string, error) 123 124 if cmd.esx { 125 get = func(vm *object.VirtualMachine, deadline context.Context) (string, error) { 126 guest := esxcli.NewGuestInfo(c) 127 128 ticker := time.NewTicker(time.Millisecond * 500) 129 defer ticker.Stop() 130 131 for { 132 select { 133 case <-ticker.C: 134 ip, err := guest.IpAddress(vm) 135 if err != nil { 136 return "", err 137 } 138 139 if ip != "0.0.0.0" { 140 return ip, nil 141 } 142 case <-deadline.Done(): 143 return "", nil 144 } 145 } 146 } 147 } else { 148 var hwaddr []string 149 if cmd.nic != "" { 150 hwaddr = strings.Split(cmd.nic, ",") 151 } 152 153 get = func(vm *object.VirtualMachine, deadline context.Context) (string, error) { 154 if cmd.all || hwaddr != nil { 155 macs, err := vm.WaitForNetIP(deadline, cmd.v4, hwaddr...) 156 if err != nil { 157 return "", err 158 } 159 160 var ips []string 161 for _, addrs := range macs { 162 ips = append(ips, addrs...) 163 } 164 return strings.Join(ips, ","), nil 165 } 166 return vm.WaitForIP(deadline, cmd.v4) 167 } 168 } 169 170 for _, vm := range vms { 171 deadline, cancel := context.WithDeadline(ctx, time.Now().Add(cmd.wait)) 172 173 ip, err := get(vm, deadline) 174 if err != nil { 175 if deadline.Err() != context.DeadlineExceeded { 176 cancel() 177 return err 178 } 179 } 180 181 cancel() 182 183 if ip == "" { 184 continue 185 } 186 187 // TODO(PN): Display inventory path to VM 188 fmt.Fprintf(cmd, "%s\n", ip) 189 } 190 191 return nil 192 }