func (c *APIAddressUpdater) Handle(_ <-chan struct{}) error { addresses, err := c.addresser.APIHostPorts() if err != nil { return fmt.Errorf("error getting addresses: %v", err) } // Filter out any LXC bridge addresses. See LP bug #1416928. hpsToSet := make([][]network.HostPort, 0, len(addresses)) for _, hostPorts := range addresses { // Strip ports, filter, then add ports again. filtered := network.FilterLXCAddresses(network.HostsWithoutPort(hostPorts)) hps := make([]network.HostPort, 0, len(filtered)) for _, hostPort := range hostPorts { for _, addr := range filtered { if addr.Value == hostPort.Address.Value { hps = append(hps, hostPort) } } } if len(hps) > 0 { hpsToSet = append(hpsToSet, hps) } } if err := c.setter.SetAPIHostPorts(hpsToSet); err != nil { return fmt.Errorf("error setting addresses: %v", err) } return nil }
// 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 bridge addresses. hostAddresses = network.FilterLXCAddresses(hostAddresses) logger.Infof("setting addresses for %v to %q", tag, hostAddresses) return m.SetMachineAddresses(hostAddresses) }
// InitializeState should be called on the bootstrap machine's agent // configuration. It uses that information to create the state server, dial the // state server, and initialize it. It also generates a new password for the // bootstrap machine and calls Write to save the the configuration. // // The envCfg values will be stored in the state's EnvironConfig; the // machineCfg values will be used to configure the bootstrap Machine, // and its constraints will be also be used for the environment-level // constraints. The connection to the state server 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 ConfigSetter, envCfg *config.Config, machineCfg BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy) (_ *state.State, _ *state.Machine, resultErr error) { if c.Tag() != names.NewMachineTag(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") } logger.Debugf("initializing address %v", info.Addrs) st, err := state.Initialize(adminUser, info, envCfg, dialOpts, policy) 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 = machineCfg.SharedSecret c.SetStateServingInfo(servingInfo) // Filter out any LXC bridge addresses from the machine addresses, // except for local environments. See LP bug #1416928. if !isLocalEnv(envCfg) { machineCfg.Addresses = network.FilterLXCAddresses(machineCfg.Addresses) } else { logger.Debugf("local environment - not filtering addresses from %v", machineCfg.Addresses) } if err = initAPIHostPorts(c, st, machineCfg.Addresses, 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 := initConstraintsAndBootstrapMachine(c, st, machineCfg) if err != nil { return nil, nil, err } return st, m, nil }
func (s *NetworkSuite) TestFilterLXCAddresses(c *gc.C) { lxcFakeNetConfig := filepath.Join(c.MkDir(), "lxc-net") 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) { c.Assert(name, gc.Equals, "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 }) 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) "192.168.123.42", ) filteredAddresses := network.NewAddresses( "127.0.0.1", "2001:db8::1", "10.0.0.1", "192.168.123.42", ) c.Assert(network.FilterLXCAddresses(inputAddresses), jc.DeepEquals, filteredAddresses) }
// Handle is part of the watcher.NotifyHandler interface. func (c *APIAddressUpdater) Handle(_ <-chan struct{}) error { addresses, err := c.addresser.APIHostPorts() if err != nil { return fmt.Errorf("error getting addresses: %v", err) } // Filter out any LXC bridge addresses. See LP bug #1416928. hpsToSet := make([][]network.HostPort, 0, len(addresses)) for _, hostPorts := range addresses { // First try to keep only addresses in the default space where all API servers are on. defaultSpaceHP, ok := network.SelectHostPortBySpace(hostPorts, network.DefaultSpace) if ok { hpsToSet = append(hpsToSet, []network.HostPort{defaultSpaceHP}) continue } else { // As a fallback, use the old behavior. logger.Warningf("cannot determine API addresses by space %q (using all as fallback)", network.DefaultSpace) } // Strip ports, filter, then add ports again. filtered := network.FilterLXCAddresses(network.HostsWithoutPort(hostPorts)) hps := make([]network.HostPort, 0, len(filtered)) for _, hostPort := range hostPorts { for _, addr := range filtered { if addr.Value == hostPort.Address.Value { hps = append(hps, hostPort) } } } if len(hps) > 0 { hpsToSet = append(hpsToSet, hps) } } logger.Debugf("updating API hostPorts to %+v", hpsToSet) if err := c.setter.SetAPIHostPorts(hpsToSet); err != nil { return fmt.Errorf("error setting addresses: %v", err) } return nil }
// 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, cfg *config.Config, hostedModelConfigAttrs map[string]interface{}, machineCfg BootstrapMachineConfig, dialOpts mongo.DialOpts, policy state.Policy, ) (_ *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") } logger.Debugf("initializing address %v", info.Addrs) st, err := state.Initialize(adminUser, info, cfg, dialOpts, policy) 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 = machineCfg.SharedSecret c.SetStateServingInfo(servingInfo) // Filter out any LXC bridge addresses from the machine addresses. machineCfg.Addresses = network.FilterLXCAddresses(machineCfg.Addresses) if err = initAPIHostPorts(c, st, machineCfg.Addresses, 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 := initConstraintsAndBootstrapMachine(c, st, machineCfg) if err != nil { return nil, nil, err } // 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. attrs := make(map[string]interface{}) for k, v := range hostedModelConfigAttrs { attrs[k] = v } hostedModelConfig, err := modelmanager.ModelConfigCreator{}.NewModelConfig(modelmanager.IsAdmin, cfg, attrs) if err != nil { return nil, nil, errors.Annotate(err, "creating hosted model config") } _, hostedModelState, err := st.NewModel(hostedModelConfig, adminUser) if err != nil { return nil, nil, errors.Annotate(err, "creating hosted model") } if err := hostedModelState.SetModelConstraints(machineCfg.ModelConstraints); err != nil { return nil, nil, errors.Annotate(err, "cannot set initial hosted model constraints") } hostedModelState.Close() return st, m, nil }