Merge pull request #2625 from dgageot/2624-reject-duplicate-hostonlyifs

FIX #2624 reject duplicate hostonlyifs name/IP
This commit is contained in:
David Gageot 2015-12-21 09:29:25 +01:00
commit c584b8e641
3 changed files with 51 additions and 26 deletions

View File

@ -13,9 +13,8 @@ const (
)
var (
reHostonlyInterfaceCreated = regexp.MustCompile(`Interface '(.+)' was successfully created`)
errDuplicateHostOnlyInterfaceNetworks = errors.New("VirtualBox is configured with multiple host-only interfaces with the same IP. Please remove all of them but one.")
errNewHostOnlyInterfaceNotVisible = errors.New("The host-only interface we just created is not visible. This is a well known bug of VirtualBox. You might want to uninstall it and reinstall the version listed here: https://www.virtualbox.org/ticket/14437?cversion=0&cnum_hist=42")
reHostonlyInterfaceCreated = regexp.MustCompile(`Interface '(.+)' was successfully created`)
errNewHostOnlyInterfaceNotVisible = errors.New("The host-only interface we just created is not visible. This is a well known bug of VirtualBox. You might want to uninstall it and reinstall the version listed here: https://www.virtualbox.org/ticket/14437?cversion=0&cnum_hist=42")
)
// Host-only network.
@ -75,7 +74,8 @@ func listHostOnlyNetworks(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
return nil, err
}
m := map[string]*hostOnlyNetwork{}
byName := map[string]*hostOnlyNetwork{}
byIP := map[string]*hostOnlyNetwork{}
n := &hostOnlyNetwork{}
err = parseKeyValues(out, reColonLine, func(key, val string) error {
@ -110,7 +110,19 @@ func listHostOnlyNetworks(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
n.Status = val
case "VBoxNetworkName":
n.NetworkName = val
m[val] = n
if _, present := byName[n.NetworkName]; present {
return fmt.Errorf("VirtualBox is configured with multiple host-only interfaces with the same name %q. Please remove one.", n.NetworkName)
}
byName[n.NetworkName] = n
if len(n.IPv4.IP) != 0 {
if _, present := byIP[n.IPv4.IP.String()]; present {
return fmt.Errorf("VirtualBox is configured with multiple host-only interfaces with the same IP %q. Please remove one.", n.IPv4.IP)
}
byIP[n.IPv4.IP.String()] = n
}
n = &hostOnlyNetwork{}
}
@ -120,7 +132,7 @@ func listHostOnlyNetworks(vbox VBoxManager) (map[string]*hostOnlyNetwork, error)
return nil, err
}
return m, nil
return byName, nil
}
func getHostOnlyNetwork(nets map[string]*hostOnlyNetwork, hostIP net.IP, netmask net.IPMask) *hostOnlyNetwork {
@ -143,10 +155,6 @@ func getOrCreateHostOnlyNetwork(hostIP net.IP, netmask net.IPMask, dhcpIP net.IP
return nil, err
}
if len(nets) != countUniqueIps(nets) {
return nil, errDuplicateHostOnlyInterfaceNetworks
}
hostOnlyNet := getHostOnlyNetwork(nets, hostIP, netmask)
if hostOnlyNet != nil {
return hostOnlyNet, nil
@ -188,16 +196,6 @@ func getOrCreateHostOnlyNetwork(hostIP net.IP, netmask net.IPMask, dhcpIP net.IP
return hostOnlyNet, nil
}
func countUniqueIps(nets map[string]*hostOnlyNetwork) int {
ips := map[string]bool{}
for _, n := range nets {
ips[n.IPv4.IP.String()] = true
}
return len(ips)
}
// DHCP server info.
type dhcpServer struct {
NetworkName string

View File

@ -39,7 +39,7 @@ VBoxNetworkName: HostInterfaceNetworking-vboxnet0
Name: vboxnet1
GUID: 786f6276-656e-4174-8000-0a0027000001
DHCP: Disabled
IPAddress: 192.168.99.1
IPAddress: 169.254.37.187
NetworkMask: 255.255.255.0
IPV6Address:
IPV6NetworkMaskPrefixLength: 0
@ -185,7 +185,7 @@ func TestListTwoHostOnlyNetworks(t *testing.T) {
assert.Equal(t, "vboxnet1", net.Name)
assert.Equal(t, "786f6276-656e-4174-8000-0a0027000001", net.GUID)
assert.False(t, net.DHCP)
assert.Equal(t, "192.168.99.1", net.IPv4.IP.String())
assert.Equal(t, "169.254.37.187", net.IPv4.IP.String())
assert.Equal(t, "ffffff00", net.IPv4.Mask.String())
assert.Empty(t, net.IPv6.IP)
assert.Equal(t, "0a:00:27:00:00:01", net.HwAddr.String())
@ -230,16 +230,38 @@ func TestGetHostOnlyNetwork(t *testing.T) {
assert.NoError(t, err)
}
func TestFailWithDuplicateHostOnlyNetworks(t *testing.T) {
func TestFailIfTwoNetworksHaveSameIP(t *testing.T) {
vbox := &VBoxManagerMock{
args: "list hostonlyifs",
stdOut: stdOutTwoHostOnlyNetwork,
args: "list hostonlyifs",
stdOut: `Name: vboxnet0
IPAddress: 192.168.99.1
NetworkMask: 255.255.255.0
VBoxNetworkName: HostInterfaceNetworking-vboxnet0
Name: vboxnet1
IPAddress: 192.168.99.1
NetworkMask: 255.255.255.0
VBoxNetworkName: HostInterfaceNetworking-vboxnet1`,
}
net, err := getOrCreateHostOnlyNetwork(net.ParseIP("192.168.99.1"), parseIPv4Mask("255.255.255.0"), nil, nil, nil, vbox)
assert.Nil(t, net)
assert.Equal(t, errDuplicateHostOnlyInterfaceNetworks, err)
assert.EqualError(t, err, `VirtualBox is configured with multiple host-only interfaces with the same IP "192.168.99.1". Please remove one.`)
}
func TestFailIfTwoNetworksHaveSameName(t *testing.T) {
vbox := &VBoxManagerMock{
args: "list hostonlyifs",
stdOut: `Name: vboxnet0
VBoxNetworkName: HostInterfaceNetworking-vboxnet0
Name: vboxnet0
VBoxNetworkName: HostInterfaceNetworking-vboxnet0`,
}
net, err := getOrCreateHostOnlyNetwork(net.ParseIP("192.168.99.1"), parseIPv4Mask("255.255.255.0"), nil, nil, nil, vbox)
assert.Nil(t, net)
assert.EqualError(t, err, `VirtualBox is configured with multiple host-only interfaces with the same name "HostInterfaceNetworking-vboxnet0". Please remove one.`)
}
func TestGetDHCPServers(t *testing.T) {

View File

@ -226,6 +226,11 @@ func (d *Driver) PreCreateCheck() error {
return err
}
// Check that Host-only interfaces are ok
if _, err = listHostOnlyNetworks(d.VBoxManager); err != nil {
return err
}
return nil
}