// newDialInfo returns mgo.DialInfo with the given address using the minimal // possible setup. func newDialInfo(privateAddr string, conf agent.Config) (*mgo.DialInfo, error) { dialOpts := mongo.DialOpts{Direct: true} ssi, ok := conf.StateServingInfo() if !ok { return nil, errors.Errorf("cannot get state serving info to dial") } info := mongo.Info{ Addrs: []string{net.JoinHostPort(privateAddr, strconv.Itoa(ssi.StatePort))}, CACert: conf.CACert(), } dialInfo, err := mongo.DialInfo(info, dialOpts) if err != nil { return nil, errors.Annotate(err, "cannot produce a dial info") } oldPassword := conf.OldPassword() if oldPassword != "" { dialInfo.Username = "******" dialInfo.Password = conf.OldPassword() } else { dialInfo.Username, dialInfo.Password, err = tagUserCredentials(conf) if err != nil { return nil, errors.Trace(err) } } return dialInfo, nil }
// newDialInfo returns mgo.DialInfo with the given address using the minimal // possible setup. func newDialInfo(privateAddr string, conf agent.Config) (*mgo.DialInfo, error) { dialOpts := mongo.DialOpts{Direct: true} ssi, ok := conf.StateServingInfo() if !ok { return nil, errors.Errorf("cannot get state serving info to dial") } info := mongo.Info{ Addrs: []string{fmt.Sprintf("%s:%d", privateAddr, ssi.StatePort)}, CACert: conf.CACert(), } dialInfo, err := mongo.DialInfo(info, dialOpts) if err != nil { return nil, errors.Annotate(err, "cannot produce a dial info") } dialInfo.Username = "******" dialInfo.Password = conf.OldPassword() return dialInfo, nil }
// newDialInfo returns mgo.DialInfo with the given address using the minimal // possible setup. func newDialInfo(privateAddr string, conf agent.Config) (*mgo.DialInfo, error) { dialOpts := mongo.DialOpts{Direct: true} ssi, ok := conf.StateServingInfo() if !ok { return nil, errors.Errorf("cannot get state serving info to dial") } info := mongo.Info{ Addrs: []string{net.JoinHostPort(privateAddr, strconv.Itoa(ssi.StatePort))}, CACert: conf.CACert(), } dialInfo, err := mongo.DialInfo(info, dialOpts) if err != nil { return nil, errors.Annotate(err, "cannot produce a dial info") } oldPassword := conf.OldPassword() if oldPassword != "" { dialInfo.Username = "******" dialInfo.Password = conf.OldPassword() } else { dialInfo.Username = conf.Tag().String() // TODO(perrito) we might need an accessor for the actual state password // just in case it ever changes from the same as api password. apiInfo, ok := conf.APIInfo() if ok { dialInfo.Password = apiInfo.Password logger.Infof("using API password to access state server.") } else { // There seems to be no way to reach this inconsistence other than making a // backup on a machine where these fields are corrupted and even so I find // no reasonable way to reach this state, yet since APIInfo has it as a // possibility I prefer to handle it, we cannot recover from this since // it would mean that the agent.conf is corrupted. return nil, errors.New("cannot obtain password to access the state server") } } return dialInfo, nil }
// updateSupportedContainers records in state that a machine can run the specified containers. // It starts a watcher and when a container of a given type is first added to the machine, // the watcher is killed, the machine is set up to be able to start containers of the given type, // and a suitable provisioner is started. func (a *MachineAgent) updateSupportedContainers( runner worker.Runner, st api.Connection, containers []instance.ContainerType, agentConfig agent.Config, ) error { pr := st.Provisioner() tag := agentConfig.Tag().(names.MachineTag) machine, err := pr.Machine(tag) if errors.IsNotFound(err) || err == nil && machine.Life() == params.Dead { return worker.ErrTerminateAgent } if err != nil { return errors.Annotatef(err, "cannot load machine %s from state", tag) } if len(containers) == 0 { if err := machine.SupportsNoContainers(); err != nil { return errors.Annotatef(err, "clearing supported containers for %s", tag) } return nil } if err := machine.SetSupportedContainers(containers...); err != nil { return errors.Annotatef(err, "setting supported containers for %s", tag) } initLock, err := cmdutil.HookExecutionLock(agentConfig.DataDir()) if err != nil { return err } // Start the watcher to fire when a container is first requested on the machine. modelUUID, err := st.ModelTag() if err != nil { return err } watcherName := fmt.Sprintf("%s-container-watcher", machine.Id()) // There may not be a CA certificate private key available, and without // it we can't ensure that other Juju nodes can connect securely, so only // use an image URL getter if there's a private key. var imageURLGetter container.ImageURLGetter if agentConfig.Value(agent.AllowsSecureConnection) == "true" { cfg, err := pr.ModelConfig() if err != nil { return errors.Annotate(err, "unable to get environ config") } imageURLGetter = container.NewImageURLGetter( // Explicitly call the non-named constructor so if anyone // adds additional fields, this fails. container.ImageURLGetterConfig{ ServerRoot: st.Addr(), ModelUUID: modelUUID.Id(), CACert: []byte(agentConfig.CACert()), CloudimgBaseUrl: cfg.CloudImageBaseURL(), Stream: cfg.ImageStream(), ImageDownloadFunc: container.ImageDownloadURL, }) } params := provisioner.ContainerSetupParams{ Runner: runner, WorkerName: watcherName, SupportedContainers: containers, ImageURLGetter: imageURLGetter, Machine: machine, Provisioner: pr, Config: agentConfig, InitLock: initLock, } handler := provisioner.NewContainerSetupHandler(params) a.startWorkerAfterUpgrade(runner, watcherName, func() (worker.Worker, error) { w, err := watcher.NewStringsWorker(watcher.StringsConfig{ Handler: handler, }) if err != nil { return nil, errors.Annotatef(err, "cannot start %s worker", watcherName) } return w, nil }) return nil }