Skip to content

Commit

Permalink
Support network alias
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardstudy committed Dec 1, 2017
1 parent 854ccbb commit f342568
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 3 deletions.
2 changes: 2 additions & 0 deletions factory/factory.go
Expand Up @@ -14,6 +14,8 @@ type Network struct {
Default []string
DNS *[]string

Alias string

Mac string
}

Expand Down
14 changes: 13 additions & 1 deletion platform/net/interface_configuration_creator.go
Expand Up @@ -169,7 +169,7 @@ func (creator interfaceConfigurationCreator) CreateInterfaceConfigurations(netwo
}

func (creator interfaceConfigurationCreator) createMultipleInterfaceConfigurations(networks boshsettings.Networks, interfacesByMAC map[string]string) ([]StaticInterfaceConfiguration, []DHCPInterfaceConfiguration, error) {
if len(interfacesByMAC) < len(networks) {
if !networks.HasInterfaceAlias() && len(interfacesByMAC) < len(networks) {
return nil, nil, bosherr.Errorf("Number of network settings '%d' is greater than the number of network devices '%d'", len(networks), len(interfacesByMAC))
}

Expand All @@ -196,6 +196,18 @@ func (creator interfaceConfigurationCreator) createMultipleInterfaceConfiguratio
}
}

for _, networkSettings = range networks {
if networkSettings.Mac != "" {
continue
}
if networkSettings.Alias != "" {
staticConfigs, dhcpConfigs, err = creator.createInterfaceConfiguration(staticConfigs, dhcpConfigs, networkSettings.Alias, networkSettings)
if err != nil {
return nil, nil, bosherr.WrapError(err, "Creating interface configuration using alias")
}
}
}

return staticConfigs, dhcpConfigs, nil
}

Expand Down
69 changes: 69 additions & 0 deletions platform/net/interface_configuration_creator_test.go
Expand Up @@ -151,6 +151,34 @@ func describeInterfaceConfigurationCreator() {
})
})
})

Context("And the network has a alias", func() {
BeforeEach(func() {
staticNetwork.Alias = "static-interface-name"
networks["foo"] = staticNetwork
interfacesByMAC["fake-static-mac-address"] = "any-interface-name"
})

It("creates an interface configuration when matching interface exists", func() {
staticInterfaceConfigurations, dhcpInterfaceConfigurations, err := interfaceConfigurationCreator.CreateInterfaceConfigurations(networks, interfacesByMAC)
Expect(err).ToNot(HaveOccurred())

Expect(staticInterfaceConfigurations).To(Equal([]StaticInterfaceConfiguration{
StaticInterfaceConfiguration{
Name: "any-interface-name",
Address: "1.2.3.4",
Netmask: "255.255.255.0",
Network: "1.2.3.0",
IsDefaultForGateway: false,
Broadcast: "1.2.3.255",
Mac: "fake-static-mac-address",
Gateway: "3.4.5.6",
},
}))

Expect(len(dhcpInterfaceConfigurations)).To(Equal(0))
})
})
})

Context("Multiple networks", func() {
Expand Down Expand Up @@ -239,6 +267,47 @@ func describeInterfaceConfigurationCreator() {
})
})
})

Context("when static network has alias, dhcp network is not allowd to have alias", func() {
BeforeEach(func() {
staticNetwork.Alias = "static-interface-name"
staticNetworkWithoutMAC.Alias = "static-interface-name:1"
staticNetworkWithoutMAC.IP = "1.2.3.5"
networks["foo"] = staticNetwork
networks["bar"] = dhcpNetwork
networks["baz"] = staticNetworkWithoutMAC
interfacesByMAC[staticNetwork.Mac] = "static-interface-name"
interfacesByMAC[dhcpNetwork.Mac] = "dhcp-interface-name"
})

It("creates interface configurations for each network when matching interfaces exist", func() {
staticInterfaceConfigurations, _, err := interfaceConfigurationCreator.CreateInterfaceConfigurations(networks, interfacesByMAC)
Expect(err).ToNot(HaveOccurred())

Expect(staticInterfaceConfigurations).To(ConsistOf([]StaticInterfaceConfiguration{
{
Name: "static-interface-name",
Address: "1.2.3.4",
Netmask: "255.255.255.0",
Network: "1.2.3.0",
Broadcast: "1.2.3.255",
IsDefaultForGateway: false,
Mac: "fake-static-mac-address",
Gateway: "3.4.5.6",
},
{
Name: "static-interface-name:1",
Address: "1.2.3.5",
Netmask: "255.255.255.0",
Network: "1.2.3.0",
Broadcast: "1.2.3.255",
IsDefaultForGateway: false,
Gateway: "3.4.5.6",
},
}))
})
})

})

Context("when the number of networks does not match the number of devices", func() {
Expand Down
22 changes: 20 additions & 2 deletions platform/net/ubuntu_net_manager.go
Expand Up @@ -102,6 +102,11 @@ func (net UbuntuNetManager) SetupNetworking(networks boshsettings.Networks, errC
return net.writeResolvConf(networks)
}

// Specific for softlayer networking
if networks.HasInterfaceAlias() {
net.writeResolvConf(networks)
}

staticConfigs, dhcpConfigs, dnsServers, err := net.ComputeNetworkConfig(networks)
if err != nil {
return bosherr.WrapError(err, "Computing network configuration")
Expand Down Expand Up @@ -137,7 +142,20 @@ func (net UbuntuNetManager) SetupNetworking(networks boshsettings.Networks, errC

staticAddresses, dynamicAddresses := net.ifaceAddresses(staticConfigs, dhcpConfigs)

err = net.interfaceAddressesValidator.Validate(staticAddresses)
// Skip the validation of virtual interfaces(like eth0:0, eth0:1... )
staticAddressesWithoutVirtual := []boship.InterfaceAddress{}
r, err := regexp.Compile(`:\d+`)
if err != nil {
return bosherr.WrapError(err, "There is a problem with your regexp.")
}
for _, addr := range staticAddresses {
if r.MatchString(addr.GetInterfaceName()) == true {
continue
} else {
staticAddressesWithoutVirtual = append(staticAddressesWithoutVirtual, addr)
}
}
err = net.interfaceAddressesValidator.Validate(staticAddressesWithoutVirtual)
if err != nil {
return bosherr.WrapError(err, "Validating static network configuration")
}
Expand All @@ -147,7 +165,7 @@ func (net UbuntuNetManager) SetupNetworking(networks boshsettings.Networks, errC
return bosherr.WrapError(err, "Validating dns configuration")
}

net.broadcastIps(append(staticAddresses, dynamicAddresses...), errCh)
net.broadcastIps(append(staticAddressesWithoutVirtual, dynamicAddresses...), errCh)

return nil
}
Expand Down
136 changes: 136 additions & 0 deletions platform/net/ubuntu_net_manager_test.go
Expand Up @@ -155,6 +155,40 @@ func describeUbuntuNetManager() {
Expect(dnsServers).To(Equal([]string{"54.209.78.6", "127.0.0.5"}))
})
})

Context("when interface alias exists in network settings", func() {
It("static interface configuration should be construted by alias name", func() {
networks := boshsettings.Networks{
"default": factory.Network{
IP: "10.10.0.32",
Netmask: "255.255.255.0",
Mac: "aa::bb::cc",
Default: []string{"dns", "gateway"},
DNS: &[]string{"54.209.78.6", "127.0.0.5"},
Gateway: "10.10.0.1",
Alias: "eth0:0",
}.Build(),
}
stubInterfaces(networks)
staticInterfaceConfigurations, dhcpInterfaceConfigurations, dnsServers, err := netManager.ComputeNetworkConfig(networks)
Expect(err).ToNot(HaveOccurred())

Expect(staticInterfaceConfigurations).To(Equal([]StaticInterfaceConfiguration{
{
Name: "default",
Address: "10.10.0.32",
Netmask: "255.255.255.0",
Network: "10.10.0.0",
IsDefaultForGateway: true,
Broadcast: "10.10.0.255",
Mac: "aa::bb::cc",
Gateway: "10.10.0.1",
},
}))
Expect(dhcpInterfaceConfigurations).To(BeEmpty())
Expect(dnsServers).To(Equal([]string{"54.209.78.6", "127.0.0.5"}))
})
})
})

Describe("SetupNetworking", func() {
Expand Down Expand Up @@ -904,6 +938,108 @@ iface ethstatic inet static
Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfiguration))
})
})

Context("when manual networks were configured with portal IP", func() {
var (
portalNetwork boshsettings.Network
staticNetwork boshsettings.Network
staticNetwork1 boshsettings.Network
)
BeforeEach(func() {
interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("ethstatic", "1.2.3.5"),
}
portalNetwork = boshsettings.Network{
Type: "manual",
IP: "10.112.166.136",
Netmask: "255.255.255.192",
Resolved: false,
UseDHCP: false,
DNS: []string{"8.8.8.8"},
Alias: "eth0:0",
}
staticNetwork = boshsettings.Network{
Type: "dynamic",
IP: "169.50.68.75",
Netmask: "255.255.255.224",
Gateway: "169.50.68.65",
Default: []string{"gateway", "dns"},
Resolved: false,
UseDHCP: false,
DNS: []string{"8.8.8.8", "10.0.80.11", "10.0.80.12"},
Mac: "06:64:d4:7d:63:71",
Alias: "eth1",
}
staticNetwork1 = boshsettings.Network{
Type: "dynamic",
IP: "10.112.39.113",
Netmask: "255.255.255.128",
Resolved: false,
UseDHCP: false,
DNS: []string{"8.8.8.8", "10.0.80.11", "10.0.80.12"},
Mac: "06:b7:e8:0c:38:d8",
Alias: "eth0",
}
interfaceAddrsProvider.GetInterfaceAddresses = []boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "10.112.39.113"),
boship.NewSimpleInterfaceAddress("eth1", "169.50.68.75"),
}
fs.WriteFileString("/etc/resolv.conf", `
nameserver 8.8.8.8
nameserver 10.0.80.11
nameserver 10.0.80.12
`)
})

It("succeeds", func() {
stubInterfaces(map[string]boshsettings.Network{
"eth1": staticNetwork,
"eth0": staticNetwork1,
})

errCh := make(chan error)
err := netManager.SetupNetworking(boshsettings.Networks{"default": portalNetwork, "dynamic": staticNetwork, "dynamic_1": staticNetwork1}, errCh)
Expect(err).NotTo(HaveOccurred())

broadcastErr := <-errCh // wait for all arpings
Expect(broadcastErr).ToNot(HaveOccurred())

Expect(addressBroadcaster.BroadcastMACAddressesAddresses).To(Equal([]boship.InterfaceAddress{
boship.NewSimpleInterfaceAddress("eth0", "10.112.39.113"),
boship.NewSimpleInterfaceAddress("eth1", "169.50.68.75"),
}))

networkConfig := fs.GetFileTestStat("/etc/network/interfaces")
Expect(networkConfig).ToNot(BeNil())

expectedNetworkConfigurationForStaticAndDhcp = `# Generated by bosh-agent
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 10.112.39.113
network 10.112.39.0
netmask 255.255.255.128
auto eth0:0
iface eth0:0 inet static
address 10.112.166.136
network 10.112.166.128
netmask 255.255.255.192
auto eth1
iface eth1 inet static
address 169.50.68.75
network 169.50.68.64
netmask 255.255.255.224
broadcast 169.50.68.95
gateway 169.50.68.65
dns-nameservers 8.8.8.8 10.0.80.11 10.0.80.12`
Expect(networkConfig.StringContents()).To(Equal(expectedNetworkConfigurationForStaticAndDhcp))
})
})
})

Describe("GetConfiguredNetworkInterfaces", func() {
Expand Down
17 changes: 17 additions & 0 deletions settings/settings.go
Expand Up @@ -266,6 +266,8 @@ type Network struct {
Mac string `json:"mac"`

Preconfigured bool `json:"preconfigured"`

Alias string `json:"alias,omitempty"`
}

type Networks map[string]Network
Expand Down Expand Up @@ -334,6 +336,21 @@ func (n Networks) IPs() (ips []string) {
return
}

func (n Networks) HasInterfaceAlias() bool {
for _, network := range n {
if network.IsVIP() {
// Skip VIP networks since we do not configure interfaces for them
continue
}

if network.Alias != "" {
return true
}
}

return false
}

func (n Networks) IsPreconfigured() bool {
for _, network := range n {
if network.IsVIP() {
Expand Down

0 comments on commit f342568

Please sign in to comment.