func (env *maasEnviron) deviceInterfaceInfo(deviceID instance.Id, nameToParentName map[string]string) ([]network.InterfaceInfo, error) { interfaces, err := env.deviceInterfaces(deviceID) if err != nil { return nil, errors.Trace(err) } interfaceInfo := make([]network.InterfaceInfo, 0, len(interfaces)) for _, nic := range interfaces { nicInfo := network.InterfaceInfo{ InterfaceName: nic.Name, InterfaceType: network.EthernetInterface, MACAddress: nic.MACAddress, MTU: nic.EffectveMTU, VLANTag: nic.VLAN.VID, ProviderId: network.Id(strconv.Itoa(nic.ID)), ProviderVLANId: network.Id(strconv.Itoa(nic.VLAN.ID)), Disabled: !nic.Enabled, NoAutoStart: !nic.Enabled, ParentInterfaceName: nameToParentName[nic.Name], } if len(nic.Links) == 0 { logger.Debugf("device %q interface %q has no links", deviceID, nic.Name) interfaceInfo = append(interfaceInfo, nicInfo) continue } for _, link := range nic.Links { nicInfo.ConfigType = maasLinkToInterfaceConfigType(string(link.Mode)) if link.IPAddress == "" { logger.Debugf("device %q interface %q has no address", deviceID, nic.Name) interfaceInfo = append(interfaceInfo, nicInfo) continue } if link.Subnet == nil { logger.Debugf("device %q interface %q link %d missing subnet", deviceID, nic.Name, link.ID) interfaceInfo = append(interfaceInfo, nicInfo) continue } nicInfo.CIDR = link.Subnet.CIDR nicInfo.Address = network.NewAddressOnSpace(link.Subnet.Space, link.IPAddress) nicInfo.ProviderSubnetId = network.Id(strconv.Itoa(link.Subnet.ID)) nicInfo.ProviderAddressId = network.Id(strconv.Itoa(link.ID)) if link.Subnet.GatewayIP != "" { nicInfo.GatewayAddress = network.NewAddressOnSpace(link.Subnet.Space, link.Subnet.GatewayIP) } if len(link.Subnet.DNSServers) > 0 { nicInfo.DNSServers = network.NewAddressesOnSpace(link.Subnet.Space, link.Subnet.DNSServers...) } interfaceInfo = append(interfaceInfo, nicInfo) } } logger.Debugf("device %q has interface info: %+v", deviceID, interfaceInfo) return interfaceInfo, nil }
func (s *AddressSuite) TestNewAddressOnSpace(c *gc.C) { addr1 := network.NewAddressOnSpace("foo", "0.1.2.3") addr2 := network.NewAddressOnSpace("", "2001:db8::123") c.Check(addr1, jc.DeepEquals, network.Address{ Value: "0.1.2.3", Type: "ipv4", Scope: "public", SpaceName: "foo", }) c.Check(addr2, jc.DeepEquals, network.Address{ Value: "2001:db8::123", Type: "ipv6", Scope: "public", SpaceName: "", }) }
func (s *instanceTest) TestAddressesViaInterfaces(c *gc.C) { // We simulate an newer MAAS (1.9+) which returns both ip_addresses and // interface_set for a node. To verify we use interfaces we deliberately put // different items in ip_addresses jsonValue := `{ "hostname": "-testing.invalid", "system_id": "system_id", "interface_set" : [ { "name": "eth0", "links": [ { "subnet": { "space": "bar" }, "ip_address": "8.7.6.5" }, { "subnet": { "space": "bar" }, "ip_address": "8.7.6.6" } ] }, { "name": "eth1", "links": [ { "subnet": { "space": "storage" }, "ip_address": "10.0.1.1" } ] }, { "name": "eth3", "links": [ { "subnet": { "space": "db" }, "ip_address": "fc00::123" } ] }, { "name": "eth4" }, { "name": "eth5", "links": [ { "mode": "link-up" } ] } ], "ip_addresses": [ "anything", "foo", "0.1.2.3" ] }` obj := s.testMAASObject.TestServer.NewNode(jsonValue) inst := maasInstance{&obj} // Since gomaasapi treats "interface_set" specially and the only way to // change it is via SetNodeNetworkLink(), which in turn does not allow you // to specify ip_address, we need to patch the call which gets a fresh copy // of the node details from the test server to avoid manging the // interface_set we used above. s.PatchValue(&refreshMAASObject, func(mo *gomaasapi.MAASObject) (gomaasapi.MAASObject, error) { return *mo, nil }) expected := []network.Address{ network.NewAddressOnSpace("bar", "8.7.6.5"), network.NewAddressOnSpace("bar", "8.7.6.6"), network.NewAddressOnSpace("storage", "10.0.1.1"), network.NewAddressOnSpace("db", "fc00::123"), } addr, err := inst.Addresses() c.Assert(err, jc.ErrorIsNil) c.Check(addr, jc.DeepEquals, expected) }
func (s *relationUnitSuite) TestNetworkConfig(c *gc.C) { // Set some provider addresses bound to both "public" and "internal" // spaces. addresses := []network.Address{ network.NewAddressOnSpace("public", "8.8.8.8"), network.NewAddressOnSpace("", "8.8.4.4"), network.NewAddressOnSpace("internal", "10.0.0.1"), network.NewAddressOnSpace("internal", "10.0.0.2"), network.NewAddressOnSpace("public", "fc00::1"), } err := s.wordpressMachine.SetProviderAddresses(addresses...) c.Assert(err, jc.ErrorIsNil) _, apiRelUnit := s.getRelationUnits(c) netConfig, err := apiRelUnit.NetworkConfig() c.Assert(err, jc.ErrorIsNil) c.Assert(netConfig, jc.DeepEquals, []params.NetworkConfig{ {Address: "10.0.0.1"}, {Address: "10.0.0.2"}, }) }
func (s *unitSuite) TestNetworkConfig(c *gc.C) { c.Skip("dimitern: temporarily disabled to pass a CI run until it can be fixed like its apiserver/uniter counterpart") // Set some provider addresses bound to both "public" and "internal" // spaces. addresses := []network.Address{ network.NewAddressOnSpace("public", "8.8.8.8"), network.NewAddressOnSpace("", "8.8.4.4"), network.NewAddressOnSpace("internal", "10.0.0.1"), network.NewAddressOnSpace("internal", "10.0.0.2"), network.NewAddressOnSpace("public", "fc00::1"), } err := s.wordpressMachine.SetProviderAddresses(addresses...) c.Assert(err, jc.ErrorIsNil) netConfig, err := s.apiUnit.NetworkConfig("db") // relation name, bound to "internal" c.Assert(err, jc.ErrorIsNil) c.Assert(netConfig, jc.DeepEquals, []params.NetworkConfig{ {Address: "10.0.0.1"}, {Address: "10.0.0.2"}, }) netConfig, err = s.apiUnit.NetworkConfig("admin-api") // extra-binding name, bound to "public" c.Assert(err, jc.ErrorIsNil) c.Assert(netConfig, jc.DeepEquals, []params.NetworkConfig{ {Address: "8.8.8.8"}, {Address: "fc00::1"}, }) netConfig, err = s.apiUnit.NetworkConfig("unknown") c.Assert(err, gc.ErrorMatches, `binding name "unknown" not defined by the unit's charm`) c.Assert(netConfig, gc.IsNil) netConfig, err = s.apiUnit.NetworkConfig("") c.Assert(err, gc.ErrorMatches, "binding name cannot be empty") c.Assert(netConfig, gc.IsNil) }
func (suite *maas2EnvironSuite) TestAllocateContainerAddressesSingleNic(c *gc.C) { vlan1 := fakeVLAN{ id: 5001, mtu: 1500, } vlan2 := fakeVLAN{ id: 5002, mtu: 1500, } subnet1 := fakeSubnet{ id: 3, space: "default", vlan: vlan1, gateway: "10.20.19.2", cidr: "10.20.19.0/24", dnsServers: []string{"10.20.19.2", "10.20.19.3"}, } subnet2 := fakeSubnet{ id: 4, space: "freckles", vlan: vlan2, gateway: "192.168.1.1", cidr: "192.168.1.0/24", dnsServers: []string{"10.20.19.2", "10.20.19.3"}, } interfaces := []gomaasapi.Interface{ &fakeInterface{ id: 91, name: "eth0", type_: "physical", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan1, links: []gomaasapi.Link{ &fakeLink{ id: 436, subnet: &subnet1, ipAddress: "10.20.19.103", mode: "static", }, }, parents: []string{}, children: []string{"eth0.100", "eth0.250", "eth0.50"}, }, } deviceInterfaces := []gomaasapi.Interface{ &fakeInterface{ id: 93, name: "eth1", type_: "physical", enabled: true, macAddress: "53:54:00:70:9b:ff", vlan: vlan2, links: []gomaasapi.Link{ &fakeLink{ id: 480, subnet: &subnet2, ipAddress: "192.168.1.127", mode: "static", }, }, parents: []string{}, children: []string{"eth0.100", "eth0.250", "eth0.50"}, }, } var env *maasEnviron device := &fakeDevice{ interfaceSet: deviceInterfaces, systemID: "foo", } controller := &fakeController{ machines: []gomaasapi.Machine{&fakeMachine{ systemID: "1", architecture: arch.HostArch(), interfaceSet: interfaces, createDevice: device, }}, spaces: []gomaasapi.Space{ fakeSpace{ name: "freckles", id: 4567, subnets: []gomaasapi.Subnet{subnet1, subnet2}, }, }, devices: []gomaasapi.Device{device}, } suite.injectController(controller) suite.setupFakeTools(c) env = suite.makeEnviron(c, nil) prepared := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", ProviderVLANId: "5001", ProviderAddressId: "436", InterfaceName: "eth0", InterfaceType: "ethernet", ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }} result, err := env.AllocateContainerAddresses(instance.Id("1"), prepared) c.Assert(err, jc.ErrorIsNil) expected := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "53:54:00:70:9b:ff", CIDR: "192.168.1.0/24", ProviderId: "93", ProviderSubnetId: "4", VLANTag: 0, ProviderVLANId: "5002", ProviderAddressId: "480", InterfaceName: "eth1", InterfaceType: "ethernet", ConfigType: "static", Address: network.NewAddressOnSpace("freckles", "192.168.1.127"), DNSServers: network.NewAddressesOnSpace("freckles", "10.20.19.2", "10.20.19.3"), MTU: 1500, GatewayAddress: network.NewAddressOnSpace("freckles", "192.168.1.1"), }} c.Assert(result, jc.DeepEquals, expected) }
func (suite *maas2EnvironSuite) TestStartInstanceNetworkInterfaces(c *gc.C) { vlan0 := fakeVLAN{ id: 5001, vid: 0, mtu: 1500, } vlan50 := fakeVLAN{ id: 5004, vid: 50, mtu: 1500, } subnetPXE := fakeSubnet{ id: 3, space: "default", vlan: vlan0, gateway: "10.20.19.2", cidr: "10.20.19.0/24", dnsServers: []string{"10.20.19.2", "10.20.19.3"}, } exampleInterfaces := []gomaasapi.Interface{ &fakeInterface{ id: 91, name: "eth0", type_: "physical", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan0, links: []gomaasapi.Link{ &fakeLink{ id: 436, subnet: &subnetPXE, ipAddress: "10.20.19.103", mode: "static", }, &fakeLink{ id: 437, subnet: &subnetPXE, ipAddress: "10.20.19.104", mode: "static", }, }, parents: []string{}, children: []string{"eth0.100", "eth0.250", "eth0.50"}, }, &fakeInterface{ id: 150, name: "eth0.50", type_: "vlan", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan50, links: []gomaasapi.Link{ &fakeLink{ id: 517, subnet: &fakeSubnet{ id: 5, space: "admin", vlan: vlan50, gateway: "10.50.19.2", cidr: "10.50.19.0/24", dnsServers: []string{}, }, ipAddress: "10.50.19.103", mode: "static", }, }, parents: []string{"eth0"}, children: []string{}, }, } var env *maasEnviron machine := newFakeMachine("Bruce Sterling", arch.HostArch(), "") machine.interfaceSet = exampleInterfaces controller := &fakeController{ allocateMachine: machine, allocateMachineMatches: gomaasapi.ConstraintMatches{ Storage: map[string][]gomaasapi.BlockDevice{}, }, } suite.injectController(controller) suite.setupFakeTools(c) env = suite.makeEnviron(c, nil) params := environs.StartInstanceParams{} result, err := testing.StartInstanceWithParams(env, "1", params) c.Assert(err, jc.ErrorIsNil) expected := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "436", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "437", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.104"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 1, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.50.19.0/24", ProviderId: "150", ProviderSubnetId: "5", AvailabilityZones: nil, VLANTag: 50, ProviderVLANId: "5004", ProviderAddressId: "517", InterfaceName: "eth0.50", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("admin", "10.50.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("admin", "10.50.19.2"), }, } c.Assert(result.NetworkInfo, jc.DeepEquals, expected) }
func (s *interfacesSuite) TestMAAS2InterfacesNilVLAN(c *gc.C) { vlan0 := fakeVLAN{ id: 5001, vid: 0, mtu: 1500, } subnetPXE := fakeSubnet{ id: 3, space: "default", vlan: vlan0, gateway: "10.20.19.2", cidr: "10.20.19.0/24", dnsServers: []string{"10.20.19.2", "10.20.19.3"}, } exampleInterfaces := []gomaasapi.Interface{ &fakeInterface{ id: 91, name: "eth0", type_: "physical", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: nil, links: []gomaasapi.Link{&fakeLink{ id: 436, subnet: &subnetPXE, ipAddress: "10.20.19.103", mode: "static", }}, parents: []string{}, children: []string{"eth0.100", "eth0.250", "eth0.50"}, }, } machine := &fakeMachine{interfaceSet: exampleInterfaces} instance := &maas2Instance{machine: machine} expected := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "436", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }} infos, err := maas2NetworkInterfaces(instance, map[string]network.Id{}) c.Assert(err, jc.ErrorIsNil) c.Check(infos, jc.DeepEquals, expected) }
func (s *interfacesSuite) TestMAAS2NetworkInterfaces(c *gc.C) { vlan0 := fakeVLAN{ id: 5001, vid: 0, mtu: 1500, } vlan50 := fakeVLAN{ id: 5004, vid: 50, mtu: 1500, } vlan100 := fakeVLAN{ id: 5005, vid: 100, mtu: 1500, } vlan250 := fakeVLAN{ id: 5008, vid: 250, mtu: 1500, } subnetPXE := fakeSubnet{ id: 3, space: "default", vlan: vlan0, gateway: "10.20.19.2", cidr: "10.20.19.0/24", dnsServers: []string{"10.20.19.2", "10.20.19.3"}, } exampleInterfaces := []gomaasapi.Interface{ &fakeInterface{ id: 91, name: "eth0", type_: "physical", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan0, links: []gomaasapi.Link{ &fakeLink{ id: 436, subnet: &subnetPXE, ipAddress: "10.20.19.103", mode: "static", }, &fakeLink{ id: 437, subnet: &subnetPXE, ipAddress: "10.20.19.104", mode: "static", }, }, parents: []string{}, children: []string{"eth0.100", "eth0.250", "eth0.50"}, }, &fakeInterface{ id: 150, name: "eth0.50", type_: "vlan", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan50, links: []gomaasapi.Link{ &fakeLink{ id: 517, subnet: &fakeSubnet{ id: 5, space: "admin", vlan: vlan50, gateway: "10.50.19.2", cidr: "10.50.19.0/24", dnsServers: []string{}, }, ipAddress: "10.50.19.103", mode: "static", }, }, parents: []string{"eth0"}, children: []string{}, }, &fakeInterface{ id: 151, name: "eth0.100", type_: "vlan", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan100, links: []gomaasapi.Link{ &fakeLink{ id: 519, subnet: &fakeSubnet{ id: 6, space: "public", vlan: vlan100, gateway: "10.100.19.2", cidr: "10.100.19.0/24", dnsServers: []string{}, }, ipAddress: "10.100.19.103", mode: "static", }, }, parents: []string{"eth0"}, children: []string{}, }, &fakeInterface{ id: 152, name: "eth0.250", type_: "vlan", enabled: true, macAddress: "52:54:00:70:9b:fe", vlan: vlan250, links: []gomaasapi.Link{ &fakeLink{ id: 523, subnet: &fakeSubnet{ id: 8, space: "storage", vlan: vlan250, gateway: "10.250.19.2", cidr: "10.250.19.0/24", dnsServers: []string{}, }, ipAddress: "10.250.19.103", mode: "static", }, }, parents: []string{"eth0"}, children: []string{}, }, } subnetsMap := make(map[string]network.Id) subnetsMap["10.250.19.0/24"] = network.Id("3") subnetsMap["192.168.1.0/24"] = network.Id("0") expected := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "436", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "437", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.104"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 1, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.50.19.0/24", ProviderId: "150", ProviderSubnetId: "5", AvailabilityZones: nil, VLANTag: 50, ProviderVLANId: "5004", ProviderAddressId: "517", InterfaceName: "eth0.50", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("admin", "10.50.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("admin", "10.50.19.2"), }, { DeviceIndex: 2, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.100.19.0/24", ProviderId: "151", ProviderSubnetId: "6", AvailabilityZones: nil, VLANTag: 100, ProviderVLANId: "5005", ProviderAddressId: "519", InterfaceName: "eth0.100", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("public", "10.100.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("public", "10.100.19.2"), }, { DeviceIndex: 3, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.250.19.0/24", ProviderId: "152", ProviderSubnetId: "8", AvailabilityZones: nil, VLANTag: 250, ProviderVLANId: "5008", ProviderAddressId: "523", ProviderSpaceId: "3", InterfaceName: "eth0.250", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: newAddressOnSpaceWithId("storage", network.Id("3"), "10.250.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: newAddressOnSpaceWithId("storage", network.Id("3"), "10.250.19.2"), }} machine := &fakeMachine{interfaceSet: exampleInterfaces} instance := &maas2Instance{machine: machine} infos, err := maas2NetworkInterfaces(instance, subnetsMap) c.Assert(err, jc.ErrorIsNil) c.Check(infos, jc.DeepEquals, expected) }
func (s *interfacesSuite) TestMAASObjectNetworkInterfaces(c *gc.C) { nodeJSON := fmt.Sprintf(`{ "system_id": "foo", "interface_set": %s }`, exampleInterfaceSetJSON) obj := s.testMAASObject.TestServer.NewNode(nodeJSON) subnetsMap := make(map[string]network.Id) subnetsMap["10.250.19.0/24"] = network.Id("3") subnetsMap["192.168.1.0/24"] = network.Id("0") expected := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "436", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "437", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.104"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 1, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.50.19.0/24", ProviderId: "150", ProviderSubnetId: "5", AvailabilityZones: nil, VLANTag: 50, ProviderVLANId: "5004", ProviderAddressId: "517", InterfaceName: "eth0.50", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("admin", "10.50.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("admin", "10.50.19.2"), }, { DeviceIndex: 2, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.100.19.0/24", ProviderId: "151", ProviderSubnetId: "6", AvailabilityZones: nil, VLANTag: 100, ProviderVLANId: "5005", ProviderAddressId: "519", InterfaceName: "eth0.100", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("public", "10.100.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("public", "10.100.19.2"), }, { DeviceIndex: 3, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.250.19.0/24", ProviderId: "152", ProviderSubnetId: "8", AvailabilityZones: nil, VLANTag: 250, ProviderVLANId: "5008", ProviderAddressId: "523", ProviderSpaceId: "3", InterfaceName: "eth0.250", ParentInterfaceName: "eth0", InterfaceType: "802.1q", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: newAddressOnSpaceWithId("storage", network.Id("3"), "10.250.19.103"), DNSServers: nil, DNSSearchDomains: nil, MTU: 1500, GatewayAddress: newAddressOnSpaceWithId("storage", network.Id("3"), "10.250.19.2"), }} infos, err := maasObjectNetworkInterfaces(&obj, subnetsMap) c.Assert(err, jc.ErrorIsNil) c.Check(infos, jc.DeepEquals, expected) }
var exampleParsedInterfaceSetJSON = []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "436", InterfaceName: "eth0", InterfaceType: "ethernet", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearchDomains: nil, MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), }, { DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, ProviderVLANId: "5001", ProviderAddressId: "437", InterfaceName: "eth0",
// maasObjectNetworkInterfaces implements environs.NetworkInterfaces() using the // new (1.9+) MAAS API, parsing the node details JSON embedded into the given // maasObject to extract all the relevant InterfaceInfo fields. It returns an // error satisfying errors.IsNotSupported() if it cannot find the required // "interface_set" node details field. func maasObjectNetworkInterfaces(maasObject *gomaasapi.MAASObject, subnetsMap map[string]network.Id) ([]network.InterfaceInfo, error) { interfaceSet, ok := maasObject.GetMap()["interface_set"] if !ok || interfaceSet.IsNil() { // This means we're using an older MAAS API. return nil, errors.NotSupportedf("interface_set") } // TODO(dimitern): Change gomaasapi JSONObject to give access to the raw // JSON bytes directly, rather than having to do call MarshalJSON just so // the result can be unmarshaled from it. // // LKK Card: https://canonical.leankit.com/Boards/View/101652562/119311323 rawBytes, err := interfaceSet.MarshalJSON() if err != nil { return nil, errors.Annotate(err, "cannot get interface_set JSON bytes") } interfaces, err := parseInterfaces(rawBytes) if err != nil { return nil, errors.Trace(err) } infos := make([]network.InterfaceInfo, 0, len(interfaces)) for i, iface := range interfaces { // The below works for all types except bonds and their members. parentName := strings.Join(iface.Parents, "") var nicType network.InterfaceType switch iface.Type { case typePhysical: nicType = network.EthernetInterface children := strings.Join(iface.Children, "") if parentName == "" && len(iface.Children) == 1 && strings.HasPrefix(children, "bond") { // FIXME: Verify the bond exists, regardless of its name. // This is a bond member, set the parent correctly (from // Juju's perspective) - to the bond itself. parentName = children } case typeBond: parentName = "" nicType = network.BondInterface case typeVLAN: nicType = network.VLAN_8021QInterface } nicInfo := network.InterfaceInfo{ DeviceIndex: i, MACAddress: iface.MACAddress, ProviderId: network.Id(fmt.Sprintf("%v", iface.ID)), VLANTag: iface.VLAN.VID, InterfaceName: iface.Name, InterfaceType: nicType, ParentInterfaceName: parentName, Disabled: !iface.Enabled, NoAutoStart: !iface.Enabled, } for _, link := range iface.Links { switch link.Mode { case modeUnknown: nicInfo.ConfigType = network.ConfigUnknown case modeDHCP: nicInfo.ConfigType = network.ConfigDHCP case modeStatic, modeLinkUp: nicInfo.ConfigType = network.ConfigStatic default: nicInfo.ConfigType = network.ConfigManual } if link.IPAddress == "" { logger.Debugf("interface %q has no address", iface.Name) } else { // We set it here initially without a space, just so we don't // lose it when we have no linked subnet below. nicInfo.Address = network.NewAddress(link.IPAddress) nicInfo.ProviderAddressId = network.Id(fmt.Sprintf("%v", link.ID)) } if link.Subnet == nil { logger.Debugf("interface %q link %d missing subnet", iface.Name, link.ID) infos = append(infos, nicInfo) continue } sub := link.Subnet nicInfo.CIDR = sub.CIDR nicInfo.ProviderSubnetId = network.Id(fmt.Sprintf("%v", sub.ID)) nicInfo.ProviderVLANId = network.Id(fmt.Sprintf("%v", sub.VLAN.ID)) // Now we know the subnet and space, we can update the address to // store the space with it. nicInfo.Address = network.NewAddressOnSpace(sub.Space, link.IPAddress) spaceId, ok := subnetsMap[string(sub.CIDR)] if !ok { // The space we found is not recognised, no // provider id available. logger.Warningf("interface %q link %d has unrecognised space %q", iface.Name, link.ID, sub.Space) } else { nicInfo.Address.SpaceProviderId = spaceId nicInfo.ProviderSpaceId = spaceId } gwAddr := network.NewAddressOnSpace(sub.Space, sub.GatewayIP) nicInfo.DNSServers = network.NewAddressesOnSpace(sub.Space, sub.DNSServers...) if ok { gwAddr.SpaceProviderId = spaceId for i := range nicInfo.DNSServers { nicInfo.DNSServers[i].SpaceProviderId = spaceId } } nicInfo.GatewayAddress = gwAddr nicInfo.MTU = sub.VLAN.MTU // Each link we represent as a separate InterfaceInfo, but with the // same name and device index, just different addres, subnet, etc. infos = append(infos, nicInfo) } } return infos, nil }
func maas2NetworkInterfaces(instance *maas2Instance, subnetsMap map[string]network.Id) ([]network.InterfaceInfo, error) { interfaces := instance.machine.InterfaceSet() infos := make([]network.InterfaceInfo, 0, len(interfaces)) for i, iface := range interfaces { // The below works for all types except bonds and their members. parentName := strings.Join(iface.Parents(), "") var nicType network.InterfaceType switch maasInterfaceType(iface.Type()) { case typePhysical: nicType = network.EthernetInterface children := strings.Join(iface.Children(), "") if parentName == "" && len(iface.Children()) == 1 && strings.HasPrefix(children, "bond") { // FIXME: Verify the bond exists, regardless of its name. // This is a bond member, set the parent correctly (from // Juju's perspective) - to the bond itself. parentName = children } case typeBond: parentName = "" nicType = network.BondInterface case typeVLAN: nicType = network.VLAN_8021QInterface } vlanTag := 0 if iface.VLAN() != nil { vlanTag = iface.VLAN().VID() } nicInfo := network.InterfaceInfo{ DeviceIndex: i, MACAddress: iface.MACAddress(), ProviderId: network.Id(fmt.Sprintf("%v", iface.ID())), VLANTag: vlanTag, InterfaceName: iface.Name(), InterfaceType: nicType, ParentInterfaceName: parentName, Disabled: !iface.Enabled(), NoAutoStart: !iface.Enabled(), } for _, link := range iface.Links() { switch maasLinkMode(link.Mode()) { case modeUnknown: nicInfo.ConfigType = network.ConfigUnknown case modeDHCP: nicInfo.ConfigType = network.ConfigDHCP case modeStatic, modeLinkUp: nicInfo.ConfigType = network.ConfigStatic default: nicInfo.ConfigType = network.ConfigManual } if link.IPAddress() == "" { logger.Debugf("interface %q has no address", iface.Name()) } else { // We set it here initially without a space, just so we don't // lose it when we have no linked subnet below. nicInfo.Address = network.NewAddress(link.IPAddress()) nicInfo.ProviderAddressId = network.Id(fmt.Sprintf("%v", link.ID())) } if link.Subnet() == nil { logger.Debugf("interface %q link %d missing subnet", iface.Name(), link.ID()) infos = append(infos, nicInfo) continue } sub := link.Subnet() nicInfo.CIDR = sub.CIDR() nicInfo.ProviderSubnetId = network.Id(fmt.Sprintf("%v", sub.ID())) nicInfo.ProviderVLANId = network.Id(fmt.Sprintf("%v", sub.VLAN().ID())) // Now we know the subnet and space, we can update the address to // store the space with it. nicInfo.Address = network.NewAddressOnSpace(sub.Space(), link.IPAddress()) spaceId, ok := subnetsMap[string(sub.CIDR())] if !ok { // The space we found is not recognised, no // provider id available. logger.Warningf("interface %q link %d has unrecognised space %q", iface.Name(), link.ID(), sub.Space()) } else { nicInfo.Address.SpaceProviderId = spaceId nicInfo.ProviderSpaceId = spaceId } gwAddr := network.NewAddressOnSpace(sub.Space(), sub.Gateway()) nicInfo.DNSServers = network.NewAddressesOnSpace(sub.Space(), sub.DNSServers()...) if ok { gwAddr.SpaceProviderId = spaceId for i := range nicInfo.DNSServers { nicInfo.DNSServers[i].SpaceProviderId = spaceId } } nicInfo.GatewayAddress = gwAddr nicInfo.MTU = sub.VLAN().MTU() // Each link we represent as a separate InterfaceInfo, but with the // same name and device index, just different addres, subnet, etc. infos = append(infos, nicInfo) } } return infos, nil }
func (env *maasEnviron) deviceInterfaceInfo2(deviceID string, nameToParentName map[string]string) ([]network.InterfaceInfo, error) { args := gomaasapi.DevicesArgs{SystemIDs: []string{deviceID}} devices, err := env.maasController.Devices(args) if err != nil { return nil, errors.Trace(err) } if len(devices) != 1 { return nil, errors.Errorf("unexpected response requesting device %v: %v", deviceID, devices) } interfaces := devices[0].InterfaceSet() interfaceInfo := make([]network.InterfaceInfo, 0, len(interfaces)) for _, nic := range interfaces { vlanId := 0 vlanVid := 0 vlan := nic.VLAN() if vlan != nil { vlanId = vlan.ID() vlanVid = vlan.VID() } nicInfo := network.InterfaceInfo{ InterfaceName: nic.Name(), InterfaceType: network.EthernetInterface, MACAddress: nic.MACAddress(), MTU: nic.EffectiveMTU(), VLANTag: vlanVid, ProviderId: network.Id(strconv.Itoa(nic.ID())), ProviderVLANId: network.Id(strconv.Itoa(vlanId)), Disabled: !nic.Enabled(), NoAutoStart: !nic.Enabled(), ParentInterfaceName: nameToParentName[nic.Name()], } if len(nic.Links()) == 0 { logger.Debugf("device %q interface %q has no links", deviceID, nic.Name()) interfaceInfo = append(interfaceInfo, nicInfo) continue } for _, link := range nic.Links() { nicInfo.ConfigType = maasLinkToInterfaceConfigType(link.Mode()) subnet := link.Subnet() if link.IPAddress() == "" || subnet == nil { logger.Debugf("device %q interface %q has no address", deviceID, nic.Name()) interfaceInfo = append(interfaceInfo, nicInfo) continue } nicInfo.CIDR = subnet.CIDR() nicInfo.Address = network.NewAddressOnSpace(subnet.Space(), link.IPAddress()) nicInfo.ProviderSubnetId = network.Id(strconv.Itoa(subnet.ID())) nicInfo.ProviderAddressId = network.Id(strconv.Itoa(link.ID())) if subnet.Gateway() != "" { nicInfo.GatewayAddress = network.NewAddressOnSpace(subnet.Space(), subnet.Gateway()) } if len(subnet.DNSServers()) > 0 { nicInfo.DNSServers = network.NewAddressesOnSpace(subnet.Space(), subnet.DNSServers()...) } interfaceInfo = append(interfaceInfo, nicInfo) } } logger.Debugf("device %q has interface info: %+v", deviceID, interfaceInfo) return interfaceInfo, nil }
func newAddressOnSpaceWithId(space string, id network.Id, address string) network.Address { newAddress := network.NewAddressOnSpace(space, address) newAddress.SpaceProviderId = id return newAddress }
func (s *interfacesSuite) TestMAASObjectNetworkInterfaces(c *gc.C) { nodeJSON := fmt.Sprintf(`{ "system_id": "foo", "interface_set": %s }`, exampleInterfaceSetJSON) obj := s.testMAASObject.TestServer.NewNode(nodeJSON) expected := []network.InterfaceInfo{{ DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", NetworkName: "juju-private", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, InterfaceName: "eth0", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.103"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearch: "", MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), ExtraConfig: nil, }, { DeviceIndex: 0, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.20.19.0/24", NetworkName: "juju-private", ProviderId: "91", ProviderSubnetId: "3", AvailabilityZones: nil, VLANTag: 0, InterfaceName: "eth0", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("default", "10.20.19.104"), DNSServers: network.NewAddressesOnSpace("default", "10.20.19.2", "10.20.19.3"), DNSSearch: "", MTU: 1500, GatewayAddress: network.NewAddressOnSpace("default", "10.20.19.2"), ExtraConfig: nil, }, { DeviceIndex: 1, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.50.19.0/24", NetworkName: "juju-private", ProviderId: "150", ProviderSubnetId: "5", AvailabilityZones: nil, VLANTag: 50, InterfaceName: "eth0.50", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("admin", "10.50.19.103"), DNSServers: nil, DNSSearch: "", MTU: 1500, GatewayAddress: network.NewAddressOnSpace("admin", "10.50.19.2"), ExtraConfig: nil, }, { DeviceIndex: 2, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.100.19.0/24", NetworkName: "juju-private", ProviderId: "151", ProviderSubnetId: "6", AvailabilityZones: nil, VLANTag: 100, InterfaceName: "eth0.100", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("public", "10.100.19.103"), DNSServers: nil, DNSSearch: "", MTU: 1500, GatewayAddress: network.NewAddressOnSpace("public", "10.100.19.2"), ExtraConfig: nil, }, { DeviceIndex: 3, MACAddress: "52:54:00:70:9b:fe", CIDR: "10.250.19.0/24", NetworkName: "juju-private", ProviderId: "152", ProviderSubnetId: "8", AvailabilityZones: nil, VLANTag: 250, InterfaceName: "eth0.250", Disabled: false, NoAutoStart: false, ConfigType: "static", Address: network.NewAddressOnSpace("storage", "10.250.19.103"), DNSServers: nil, DNSSearch: "", MTU: 1500, GatewayAddress: network.NewAddressOnSpace("storage", "10.250.19.2"), ExtraConfig: nil, }} infos, err := maasObjectNetworkInterfaces(&obj) c.Assert(err, jc.ErrorIsNil) c.Check(infos, jc.DeepEquals, expected) }
// maasObjectNetworkInterfaces implements environs.NetworkInterfaces() using the // new (1.9+) MAAS API, parsing the node details JSON embedded into the given // maasObject to extract all the relevant InterfaceInfo fields. It returns an // error satisfying errors.IsNotSupported() if it cannot find the required // "interface_set" node details field. func maasObjectNetworkInterfaces(maasObject *gomaasapi.MAASObject) ([]network.InterfaceInfo, error) { interfaceSet, ok := maasObject.GetMap()["interface_set"] if !ok || interfaceSet.IsNil() { // This means we're using an older MAAS API. return nil, errors.NotSupportedf("interface_set") } // TODO(dimitern): Change gomaasapi JSONObject to give access to the raw // JSON bytes directly, rather than having to do call MarshalJSON just so // the result can be unmarshaled from it. // // LKK Card: https://canonical.leankit.com/Boards/View/101652562/119311323 rawBytes, err := interfaceSet.MarshalJSON() if err != nil { return nil, errors.Annotate(err, "cannot get interface_set JSON bytes") } interfaces, err := parseInterfaces(rawBytes) if err != nil { return nil, errors.Trace(err) } infos := make([]network.InterfaceInfo, 0, len(interfaces)) for i, iface := range interfaces { nicInfo := network.InterfaceInfo{ DeviceIndex: i, MACAddress: iface.MACAddress, ProviderId: network.Id(fmt.Sprintf("%v", iface.ID)), VLANTag: iface.VLAN.VID, InterfaceName: iface.Name, Disabled: !iface.Enabled, NoAutoStart: !iface.Enabled, // This is not needed anymore, but the provisioner still validates it's set. NetworkName: network.DefaultPrivate, } for _, link := range iface.Links { switch link.Mode { case modeUnknown: nicInfo.ConfigType = network.ConfigUnknown case modeDHCP: nicInfo.ConfigType = network.ConfigDHCP case modeStatic, modeLinkUp: nicInfo.ConfigType = network.ConfigStatic default: nicInfo.ConfigType = network.ConfigManual } if link.IPAddress == "" { logger.Warningf("interface %q has no address", iface.Name) } else { // We set it here initially without a space, just so we don't // lose it when we have no linked subnet below. nicInfo.Address = network.NewAddress(link.IPAddress) } if link.Subnet == nil { logger.Warningf("interface %q link %d missing subnet", iface.Name, link.ID) infos = append(infos, nicInfo) continue } sub := link.Subnet nicInfo.CIDR = sub.CIDR nicInfo.ProviderSubnetId = network.Id(fmt.Sprintf("%v", sub.ID)) // Now we know the subnet and space, we can update the address to // store the space with it. nicInfo.Address = network.NewAddressOnSpace(sub.Space, link.IPAddress) gwAddr := network.NewAddressOnSpace(sub.Space, sub.GatewayIP) nicInfo.GatewayAddress = gwAddr nicInfo.DNSServers = network.NewAddressesOnSpace(sub.Space, sub.DNSServers...) nicInfo.MTU = sub.VLAN.MTU // Each link we represent as a separate InterfaceInfo, but with the // same name and device index, just different addres, subnet, etc. infos = append(infos, nicInfo) } } return infos, nil }