func (s *configFilesSuite) TestRenderManaged(c *gc.C) { info := network.InterfaceInfo{ InterfaceName: "ethX", VLANTag: 42, } cf := networker.NewConfigFile("ethX", "/some/path", info, nil) data := cf.RenderManaged() expectedVLAN := ` # Managed by Juju, please don't change. auto ethX.42 iface ethX.42 inet dhcp vlan-raw-device ethX `[1:] c.Assert(string(data), jc.DeepEquals, expectedVLAN) expectedNormal := ` # Managed by Juju, please don't change. auto ethX iface ethX inet dhcp `[1:] info.VLANTag = 0 cf = networker.NewConfigFile("ethX", "/some/path", info, nil) data = cf.RenderManaged() c.Assert(string(data), jc.DeepEquals, expectedNormal) }
func (p *ProvisionerAPI) prepareOrGetContainerInterfaceInfo(args params.Entities, maintain bool) (params.MachineNetworkConfigResults, error) { result := params.MachineNetworkConfigResults{ Results: make([]params.MachineNetworkConfigResult, len(args.Entities)), } netEnviron, hostMachine, canAccess, err := p.prepareContainerAccessEnvironment() if err != nil { return result, errors.Trace(err) } instId, err := hostMachine.InstanceId() if errors.IsNotProvisioned(err) { err = errors.NotProvisionedf("cannot prepare container network config: host machine %q", hostMachine) return result, err } else if err != nil { return result, errors.Trace(err) } for i, entity := range args.Entities { machineTag, err := names.ParseMachineTag(entity.Tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } // The auth function (canAccess) checks that the machine is a // top level machine (we filter those out next) or that the // machine has the host as a parent. container, err := p.getMachine(canAccess, machineTag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } else if !container.IsContainer() { err = errors.Errorf("cannot prepare network config for %q: not a container", machineTag) result.Results[i].Error = common.ServerError(err) continue } else if ciid, cerr := container.InstanceId(); maintain == true && cerr == nil { // Since we want to configure and create NICs on the // container before it starts, it must also be not // provisioned yet. err = errors.Errorf("container %q already provisioned as %q", container, ciid) result.Results[i].Error = common.ServerError(err) continue } else if cerr != nil && !errors.IsNotProvisioned(cerr) { // Any other error needs to be reported. result.Results[i].Error = common.ServerError(cerr) continue } if err := hostMachine.SetContainerLinkLayerDevices(container); err != nil { result.Results[i].Error = common.ServerError(err) continue } containerDevices, err := container.AllLinkLayerDevices() if err != nil { result.Results[i].Error = common.ServerError(err) continue } preparedInfo := make([]network.InterfaceInfo, len(containerDevices)) preparedOK := true for j, device := range containerDevices { parentDevice, err := device.ParentDevice() if err != nil || parentDevice == nil { err = errors.Errorf( "cannot get parent %q of container device %q: %v", device.ParentName(), device.Name(), err, ) result.Results[i].Error = common.ServerError(err) preparedOK = false break } parentAddrs, err := parentDevice.Addresses() if err != nil { result.Results[i].Error = common.ServerError(err) preparedOK = false break } info := network.InterfaceInfo{ InterfaceName: device.Name(), MACAddress: device.MACAddress(), ConfigType: network.ConfigManual, InterfaceType: network.InterfaceType(device.Type()), NoAutoStart: !device.IsAutoStart(), Disabled: !device.IsUp(), MTU: int(device.MTU()), ParentInterfaceName: parentDevice.Name(), } if len(parentAddrs) > 0 { logger.Infof("host machine device %q has addresses %v", parentDevice.Name(), parentAddrs) firstAddress := parentAddrs[0] parentDeviceSubnet, err := firstAddress.Subnet() if err != nil { err = errors.Annotatef(err, "cannot get subnet %q used by address %q of host machine device %q", firstAddress.SubnetCIDR(), firstAddress.Value(), parentDevice.Name(), ) result.Results[i].Error = common.ServerError(err) preparedOK = false break } info.ConfigType = network.ConfigStatic info.CIDR = parentDeviceSubnet.CIDR() info.ProviderSubnetId = parentDeviceSubnet.ProviderId() info.VLANTag = parentDeviceSubnet.VLANTag() } else { logger.Infof("host machine device %q has no addresses %v", parentDevice.Name(), parentAddrs) } logger.Tracef("prepared info for container interface %q: %+v", info.InterfaceName, info) preparedOK = true preparedInfo[j] = info } if !preparedOK { // Error result is already set. continue } allocatedInfo, err := netEnviron.AllocateContainerAddresses(instId, machineTag, preparedInfo) if err != nil { result.Results[i].Error = common.ServerError(err) continue } logger.Debugf("got allocated info from provider: %+v", allocatedInfo) allocatedConfig := networkingcommon.NetworkConfigFromInterfaceInfo(allocatedInfo) logger.Tracef("allocated network config: %+v", allocatedConfig) result.Results[i].Config = allocatedConfig } return result, nil }
// legacyNetworkInterfaces implements Environ.NetworkInterfaces() on MAAS 1.8 and earlier. func (environ *maasEnviron) legacyNetworkInterfaces(instId instance.Id) ([]network.InterfaceInfo, error) { instances, err := environ.acquiredInstances([]instance.Id{instId}) if err != nil { return nil, errors.Annotatef(err, "could not find instance %q", instId) } if len(instances) == 0 { return nil, errors.NotFoundf("instance %q", instId) } inst := instances[0] interfaces, err := environ.getInstanceNetworkInterfaces(inst) if err != nil { return nil, errors.Annotatef(err, "failed to get instance %q network interfaces", instId) } networks, err := environ.getInstanceNetworks(inst) if err != nil { return nil, errors.Annotatef(err, "failed to get instance %q subnets", instId) } macToNetworksMap := make(map[string][]networkDetails) for _, network := range networks { macs, err := environ.listConnectedMacs(network) if err != nil { return nil, errors.Trace(err) } for _, mac := range macs { if networks, found := macToNetworksMap[mac]; found { macToNetworksMap[mac] = append(networks, network) } else { macToNetworksMap[mac] = append([]networkDetails(nil), network) } } } result := []network.InterfaceInfo{} for serial, iface := range interfaces { deviceIndex := iface.DeviceIndex interfaceName := iface.InterfaceName disabled := iface.Disabled ifaceInfo := network.InterfaceInfo{ DeviceIndex: deviceIndex, InterfaceName: interfaceName, Disabled: disabled, NoAutoStart: disabled, MACAddress: serial, ConfigType: network.ConfigDHCP, } allDetails, ok := macToNetworksMap[serial] if !ok { logger.Debugf("no subnet information for MAC address %q, instance %q", serial, instId) continue } for _, details := range allDetails { ifaceInfo.VLANTag = details.VLANTag ifaceInfo.ProviderSubnetId = network.Id(details.Name) mask := net.IPMask(net.ParseIP(details.Mask)) cidr := net.IPNet{ IP: net.ParseIP(details.IP), Mask: mask, } ifaceInfo.CIDR = cidr.String() ifaceInfo.Address = network.NewAddress(cidr.IP.String()) if details.DefaultGateway != "" { ifaceInfo.GatewayAddress = network.NewAddress(details.DefaultGateway) } result = append(result, ifaceInfo) } } return result, nil }