// setMachineAddresses sets the addresses for this machine to all of the // host's non-loopback interface IP addresses. func setMachineAddresses(tag names.MachineTag, m Machine) error { addrs, err := interfaceAddrs() if err != nil { return err } var hostAddresses []network.Address for _, addr := range addrs { var ip net.IP switch addr := addr.(type) { case *net.IPAddr: ip = addr.IP case *net.IPNet: ip = addr.IP default: continue } address := network.NewAddress(ip.String()) // Filter out link-local addresses as we cannot reliably use them. if address.Scope == network.ScopeLinkLocal { continue } hostAddresses = append(hostAddresses, address) } if len(hostAddresses) == 0 { return nil } // Filter out any LXC or LXD bridge addresses. hostAddresses = network.FilterBridgeAddresses(hostAddresses) logger.Infof("setting addresses for %v to %q", tag, hostAddresses) return m.SetMachineAddresses(hostAddresses) }
func (s *NetworkSuite) TestFilterBridgeAddresses(c *gc.C) { lxcFakeNetConfig := filepath.Join(c.MkDir(), "lxc-net") // We create an LXC bridge named "foobar", and then put 10.0.3.1, // 10.0.3.4 and 10.0.3.5/24 on that bridge. // We also put 10.0.4.1 and 10.0.5.1/24 onto whatever bridge LXD is // configured to use. netConf := []byte(` # comments ignored LXC_BR= ignored LXC_ADDR = "fooo" LXC_BRIDGE = " foobar " # detected, spaces stripped anything else ignored LXC_BRIDGE="ignored"`[1:]) err := ioutil.WriteFile(lxcFakeNetConfig, netConf, 0644) c.Assert(err, jc.ErrorIsNil) s.PatchValue(&network.InterfaceByNameAddrs, func(name string) ([]net.Addr, error) { if name == "foobar" { return []net.Addr{ &net.IPAddr{IP: net.IPv4(10, 0, 3, 1)}, &net.IPAddr{IP: net.IPv4(10, 0, 3, 4)}, // Try a CIDR 10.0.3.5/24 as well. &net.IPNet{IP: net.IPv4(10, 0, 3, 5), Mask: net.IPv4Mask(255, 255, 255, 0)}, }, nil } else if name == network.DefaultLXDBridge { return []net.Addr{ &net.IPAddr{IP: net.IPv4(10, 0, 4, 1)}, // Try a CIDR 10.0.5.1/24 as well. &net.IPNet{IP: net.IPv4(10, 0, 5, 1), Mask: net.IPv4Mask(255, 255, 255, 0)}, }, nil } c.Fatalf("unknown bridge name: %q", name) return nil, nil }) s.PatchValue(&network.LXCNetDefaultConfig, lxcFakeNetConfig) inputAddresses := network.NewAddresses( "127.0.0.1", "2001:db8::1", "10.0.0.1", "10.0.3.1", // filtered (directly as IP) "10.0.3.3", // filtered (by the 10.0.3.5/24 CIDR) "10.0.3.5", // filtered (directly) "10.0.3.4", // filtered (directly) "10.0.4.1", // filtered (directly from LXD bridge) "10.0.5.10", // filtered (from LXD bridge, 10.0.5.1/24) "10.0.6.10", // unfiltered "192.168.123.42", ) filteredAddresses := network.NewAddresses( "127.0.0.1", "2001:db8::1", "10.0.0.1", "10.0.6.10", "192.168.123.42", ) c.Assert(network.FilterBridgeAddresses(inputAddresses), jc.DeepEquals, filteredAddresses) }
// InitializeState should be called on the bootstrap machine's agent // configuration. It uses that information to create the controller, dial the // controller, and initialize it. It also generates a new password for the // bootstrap machine and calls Write to save the the configuration. // // The cfg values will be stored in the state's ModelConfig; the // machineCfg values will be used to configure the bootstrap Machine, // and its constraints will be also be used for the model-level // constraints. The connection to the controller will respect the // given timeout parameter. // // InitializeState returns the newly initialized state and bootstrap // machine. If it fails, the state may well be irredeemably compromised. func InitializeState( adminUser names.UserTag, c agent.ConfigSetter, args InitializeStateParams, dialOpts mongo.DialOpts, newPolicy state.NewPolicyFunc, ) (_ *state.State, _ *state.Machine, resultErr error) { if c.Tag() != names.NewMachineTag(agent.BootstrapMachineId) { return nil, nil, errors.Errorf("InitializeState not called with bootstrap machine's configuration") } servingInfo, ok := c.StateServingInfo() if !ok { return nil, nil, errors.Errorf("state serving information not available") } // N.B. no users are set up when we're initializing the state, // so don't use any tag or password when opening it. info, ok := c.MongoInfo() if !ok { return nil, nil, errors.Errorf("stateinfo not available") } info.Tag = nil info.Password = c.OldPassword() if err := initMongoAdminUser(info.Info, dialOpts, info.Password); err != nil { return nil, nil, errors.Annotate(err, "failed to initialize mongo admin user") } cloudCredentials := make(map[names.CloudCredentialTag]cloud.Credential) var cloudCredentialTag names.CloudCredentialTag if args.ControllerCloudCredential != nil && args.ControllerCloudCredentialName != "" { cloudCredentialTag = names.NewCloudCredentialTag(fmt.Sprintf( "%s/%s/%s", args.ControllerCloudName, adminUser.Canonical(), args.ControllerCloudCredentialName, )) cloudCredentials[cloudCredentialTag] = *args.ControllerCloudCredential } logger.Debugf("initializing address %v", info.Addrs) st, err := state.Initialize(state.InitializeParams{ Clock: clock.WallClock, ControllerModelArgs: state.ModelArgs{ Owner: adminUser, Config: args.ControllerModelConfig, Constraints: args.ModelConstraints, CloudName: args.ControllerCloudName, CloudRegion: args.ControllerCloudRegion, CloudCredential: cloudCredentialTag, StorageProviderRegistry: args.StorageProviderRegistry, }, CloudName: args.ControllerCloudName, Cloud: args.ControllerCloud, CloudCredentials: cloudCredentials, ControllerConfig: args.ControllerConfig, ControllerInheritedConfig: args.ControllerInheritedConfig, RegionInheritedConfig: args.RegionInheritedConfig, MongoInfo: info, MongoDialOpts: dialOpts, NewPolicy: newPolicy, }) if err != nil { return nil, nil, errors.Errorf("failed to initialize state: %v", err) } logger.Debugf("connected to initial state") defer func() { if resultErr != nil { st.Close() } }() servingInfo.SharedSecret = args.SharedSecret c.SetStateServingInfo(servingInfo) // Filter out any LXC or LXD bridge addresses from the machine addresses. args.BootstrapMachineAddresses = network.FilterBridgeAddresses(args.BootstrapMachineAddresses) if err = initAPIHostPorts(c, st, args.BootstrapMachineAddresses, servingInfo.APIPort); err != nil { return nil, nil, err } ssi := paramsStateServingInfoToStateStateServingInfo(servingInfo) if err := st.SetStateServingInfo(ssi); err != nil { return nil, nil, errors.Errorf("cannot set state serving info: %v", err) } m, err := initBootstrapMachine(c, st, args) if err != nil { return nil, nil, errors.Annotate(err, "cannot initialize bootstrap machine") } // Create the initial hosted model, with the model config passed to // bootstrap, which contains the UUID, name for the hosted model, // and any user supplied config. We also copy the authorized-keys // from the controller model. attrs := make(map[string]interface{}) for k, v := range args.HostedModelConfig { attrs[k] = v } attrs[config.AuthorizedKeysKey] = args.ControllerModelConfig.AuthorizedKeys() // Construct a CloudSpec to pass on to NewModelConfig below. cloudSpec, err := environs.MakeCloudSpec( args.ControllerCloud, args.ControllerCloudName, args.ControllerCloudRegion, args.ControllerCloudCredential, ) if err != nil { return nil, nil, errors.Trace(err) } controllerUUID := args.ControllerConfig.ControllerUUID() creator := modelmanager.ModelConfigCreator{Provider: args.Provider} hostedModelConfig, err := creator.NewModelConfig( cloudSpec, args.ControllerModelConfig, attrs, ) if err != nil { return nil, nil, errors.Annotate(err, "creating hosted model config") } provider, err := args.Provider(cloudSpec.Type) if err != nil { return nil, nil, errors.Annotate(err, "getting environ provider") } hostedModelEnv, err := provider.Open(environs.OpenParams{ Cloud: cloudSpec, Config: hostedModelConfig, }) if err != nil { return nil, nil, errors.Annotate(err, "opening hosted model environment") } if err := hostedModelEnv.Create(environs.CreateParams{ ControllerUUID: controllerUUID, }); err != nil { return nil, nil, errors.Annotate(err, "creating hosted model environment") } _, hostedModelState, err := st.NewModel(state.ModelArgs{ Owner: adminUser, Config: hostedModelConfig, Constraints: args.ModelConstraints, CloudName: args.ControllerCloudName, CloudRegion: args.ControllerCloudRegion, CloudCredential: cloudCredentialTag, StorageProviderRegistry: args.StorageProviderRegistry, }) if err != nil { return nil, nil, errors.Annotate(err, "creating hosted model") } hostedModelState.Close() return st, m, nil }