From cfb21a3ea27019e6c68cc41acb61a9db4f37bb96 Mon Sep 17 00:00:00 2001 From: Zhongcheng Lao Date: Fri, 1 Nov 2019 21:44:32 +0800 Subject: [PATCH 1/4] Adds preferable network protocol for Hyper-V driver Signed-off-by: Zhongcheng Lao --- drivers/hyperv/hyperv.go | 62 +++++++++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/drivers/hyperv/hyperv.go b/drivers/hyperv/hyperv.go index e47aca1d71..84953347cc 100644 --- a/drivers/hyperv/hyperv.go +++ b/drivers/hyperv/hyperv.go @@ -16,16 +16,23 @@ import ( "github.com/docker/machine/libmachine/state" ) +const ( + DefaultProtocol = iota + PreferIPv4 + PreferIPv6 +) + type Driver struct { *drivers.BaseDriver - Boot2DockerURL string - VSwitch string - DiskSize int - MemSize int - CPU int - MacAddr string - VLanID int - DisableDynamicMemory bool + Boot2DockerURL string + VSwitch string + DiskSize int + MemSize int + CPU int + MacAddr string + VLanID int + DisableDynamicMemory bool + PreferredNetworkProtocol int } const ( @@ -99,6 +106,11 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag { Usage: "Disable dynamic memory management setting", EnvVar: "HYPERV_DISABLE_DYNAMIC_MEMORY", }, + mcnflag.IntFlag{ + Name: "hyperv-preferred-network-protocol", + Usage: "Preferred network protocol (IPv4/v6)", + EnvVar: "HYPERV_PREFERRED_NETWORK_PROTOCOL", + }, } } @@ -428,6 +440,10 @@ func (d *Driver) Kill() error { return nil } +func isIPv4(address string) bool { + return strings.Count(address, ":") < 2 +} + func (d *Driver) GetIP() (string, error) { s, err := d.GetState() if err != nil { @@ -437,7 +453,7 @@ func (d *Driver) GetIP() (string, error) { return "", drivers.ErrHostIsNotRunning } - stdout, err := cmdOut("((", "Hyper-V\\Get-VM", d.MachineName, ").networkadapters[0]).ipaddresses[0]") + stdout, err := cmdOut("((", "Hyper-V\\Get-VM", d.MachineName, ").networkadapters[0]).ipaddresses") if err != nil { return "", err } @@ -447,7 +463,33 @@ func (d *Driver) GetIP() (string, error) { return "", fmt.Errorf("IP not found") } - return resp[0], nil + switch d.PreferredNetworkProtocol { + case PreferIPv4: + for _, ipStr := range resp { + ip := net.ParseIP(ipStr) + if isIPv4(ipStr) && ip.To4() != nil && ip.IsGlobalUnicast() { + return ipStr, nil + } + } + + case PreferIPv6: + for _, ipStr := range resp { + ip := net.ParseIP(ipStr) + if !isIPv4(ipStr) && ip.IsGlobalUnicast() { + return ipStr, nil + } + } + + default: + for _, ipStr := range resp { + ip := net.ParseIP(ipStr) + if ip.IsGlobalUnicast() { + return ipStr, nil + } + } + } + + return "", nil } func (d *Driver) publicSSHKeyPath() string { From e5b2079617814e754b0f24ffaf731134bce07f3a Mon Sep 17 00:00:00 2001 From: Zhongcheng Lao Date: Mon, 4 Nov 2019 17:18:09 +0800 Subject: [PATCH 2/4] Adds timeout when waiting for IP and stopped Signed-off-by: Zhongcheng Lao --- drivers/hyperv/hyperv.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/hyperv/hyperv.go b/drivers/hyperv/hyperv.go index 84953347cc..4e5db86389 100644 --- a/drivers/hyperv/hyperv.go +++ b/drivers/hyperv/hyperv.go @@ -2,6 +2,7 @@ package hyperv import ( "encoding/json" + "errors" "fmt" "net" "os" @@ -42,6 +43,7 @@ const ( defaultVLanID = 0 defaultDisableDynamicMemory = false defaultSwitchID = "c08cb7b8-9b3c-408e-8e30-5e16a3aeb444" + defaultTimeout = time.Minute * 10 ) // NewDriver creates a new Hyper-v driver with default settings. @@ -340,12 +342,17 @@ func (d *Driver) chooseVirtualSwitch() (string, error) { func (d *Driver) waitForIP() (string, error) { log.Infof("Waiting for host to start...") + start := time.Now() for { ip, _ := d.GetIP() if ip != "" { return ip, nil } + if time.Since(start) >= defaultTimeout { + return "", errors.New("timeout waiting for IP") + } + time.Sleep(1 * time.Second) } } @@ -354,6 +361,7 @@ func (d *Driver) waitForIP() (string, error) { func (d *Driver) waitStopped() error { log.Infof("Waiting for host to stop...") + start := time.Now() for { s, err := d.GetState() if err != nil { @@ -364,6 +372,10 @@ func (d *Driver) waitStopped() error { return nil } + if time.Since(start) >= defaultTimeout { + return errors.New("timeout waiting for stopped") + } + time.Sleep(1 * time.Second) } } From d3b4e7cca9e57c2ecc10c15021adb7c717082774 Mon Sep 17 00:00:00 2001 From: Zhongcheng Lao Date: Thu, 14 Nov 2019 21:06:16 +0800 Subject: [PATCH 3/4] Adds wait timeout option for Hyper-V driver Signed-off-by: Zhongcheng Lao --- drivers/hyperv/hyperv.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/hyperv/hyperv.go b/drivers/hyperv/hyperv.go index 4e5db86389..3ab998620f 100644 --- a/drivers/hyperv/hyperv.go +++ b/drivers/hyperv/hyperv.go @@ -34,6 +34,7 @@ type Driver struct { VLanID int DisableDynamicMemory bool PreferredNetworkProtocol int + WaitTimeoutInSeconds time.Duration } const ( @@ -43,20 +44,22 @@ const ( defaultVLanID = 0 defaultDisableDynamicMemory = false defaultSwitchID = "c08cb7b8-9b3c-408e-8e30-5e16a3aeb444" - defaultTimeout = time.Minute * 10 + defaultWaitTimeoutInSeconds = 3 * 60 ) // NewDriver creates a new Hyper-v driver with default settings. func NewDriver(hostName, storePath string) *Driver { return &Driver{ - DiskSize: defaultDiskSize, - MemSize: defaultMemory, - CPU: defaultCPU, - DisableDynamicMemory: defaultDisableDynamicMemory, BaseDriver: &drivers.BaseDriver{ MachineName: hostName, StorePath: storePath, }, + DiskSize: defaultDiskSize, + MemSize: defaultMemory, + CPU: defaultCPU, + DisableDynamicMemory: defaultDisableDynamicMemory, + PreferredNetworkProtocol: DefaultProtocol, + WaitTimeoutInSeconds: defaultWaitTimeoutInSeconds, } } @@ -113,6 +116,12 @@ func (d *Driver) GetCreateFlags() []mcnflag.Flag { Usage: "Preferred network protocol (IPv4/v6)", EnvVar: "HYPERV_PREFERRED_NETWORK_PROTOCOL", }, + mcnflag.IntFlag{ + Name: "hyperv-wait-timeout", + Usage: "Wait timeout (in seconds)", + Value: defaultWaitTimeoutInSeconds, + EnvVar: "HYPERV_WAIT_TIMEOUT", + }, } } @@ -126,6 +135,8 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error { d.VLanID = flags.Int("hyperv-vlan-id") d.SSHUser = "docker" d.DisableDynamicMemory = flags.Bool("hyperv-disable-dynamic-memory") + d.PreferredNetworkProtocol = flags.Int("hyperv-preferred-network-protocol") + d.WaitTimeoutInSeconds = time.Duration(flags.Int("hyperv-wait-timeout")) d.SetSwarmConfigFromFlags(flags) return nil @@ -349,7 +360,7 @@ func (d *Driver) waitForIP() (string, error) { return ip, nil } - if time.Since(start) >= defaultTimeout { + if time.Since(start) >= d.WaitTimeoutInSeconds*time.Second { return "", errors.New("timeout waiting for IP") } @@ -372,7 +383,7 @@ func (d *Driver) waitStopped() error { return nil } - if time.Since(start) >= defaultTimeout { + if time.Since(start) >= d.WaitTimeoutInSeconds*time.Second { return errors.New("timeout waiting for stopped") } From d615d6216f08b008274452984a3cce7558e2aeff Mon Sep 17 00:00:00 2001 From: Zhongcheng Lao Date: Thu, 14 Nov 2019 21:08:11 +0800 Subject: [PATCH 4/4] Prefer IPv4 over v6 and global unicast IP by default in Hyper-V driver Signed-off-by: Zhongcheng Lao --- drivers/hyperv/hyperv.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/drivers/hyperv/hyperv.go b/drivers/hyperv/hyperv.go index 3ab998620f..8c03985bd7 100644 --- a/drivers/hyperv/hyperv.go +++ b/drivers/hyperv/hyperv.go @@ -18,7 +18,7 @@ import ( ) const ( - DefaultProtocol = iota + Default = iota PreferIPv4 PreferIPv6 ) @@ -58,7 +58,7 @@ func NewDriver(hostName, storePath string) *Driver { MemSize: defaultMemory, CPU: defaultCPU, DisableDynamicMemory: defaultDisableDynamicMemory, - PreferredNetworkProtocol: DefaultProtocol, + PreferredNetworkProtocol: Default, WaitTimeoutInSeconds: defaultWaitTimeoutInSeconds, } } @@ -464,7 +464,7 @@ func (d *Driver) Kill() error { } func isIPv4(address string) bool { - return strings.Count(address, ":") < 2 + return strings.Count(address, ":") < 1 } func (d *Driver) GetIP() (string, error) { @@ -504,12 +504,23 @@ func (d *Driver) GetIP() (string, error) { } default: + var preferredIP string for _, ipStr := range resp { ip := net.ParseIP(ipStr) if ip.IsGlobalUnicast() { - return ipStr, nil + if preferredIP == "" { + preferredIP = ipStr + } + if isIPv4(ipStr) && ip.To4() != nil { + preferredIP = ipStr + break + } } } + + if preferredIP != "" { + return preferredIP, nil + } } return "", nil