func (s *ContainerSetupSuite) setupContainerWorker(c *gc.C, tag names.MachineTag) (watcher.StringsHandler, worker.Runner) { testing.PatchExecutable(c, s, "ubuntu-cloudimg-query", containertesting.FakeLxcURLScript) runner := worker.NewRunner(allFatal, noImportance, worker.RestartDelay) pr := s.st.Provisioner() machine, err := pr.Machine(tag) c.Assert(err, jc.ErrorIsNil) err = machine.SetSupportedContainers(instance.ContainerTypes...) c.Assert(err, jc.ErrorIsNil) cfg := s.AgentConfigForTag(c, tag) watcherName := fmt.Sprintf("%s-container-watcher", machine.Id()) params := provisioner.ContainerSetupParams{ Runner: runner, WorkerName: watcherName, SupportedContainers: instance.ContainerTypes, ImageURLGetter: &containertesting.MockURLGetter{}, Machine: machine, Provisioner: pr, Config: cfg, InitLock: s.initLock, } handler := provisioner.NewContainerSetupHandler(params) runner.StartWorker(watcherName, func() (worker.Worker, error) { return watcher.NewStringsWorker(watcher.StringsConfig{ Handler: handler, }) }) return handler, runner }
// NewMachineActionsWorker returns a worker.Worker that watches for actions // enqueued on this machine and tries to execute them. func NewMachineActionsWorker(config WorkerConfig) (worker.Worker, error) { if err := config.Validate(); err != nil { return nil, errors.Trace(err) } swConfig := watcher.StringsConfig{ Handler: &handler{config}, } return watcher.NewStringsWorker(swConfig) }
// NewDeployer returns a Worker that deploys and recalls unit agents // via ctx, taking a machine id to operate on. func NewDeployer(st *apideployer.State, ctx Context) (worker.Worker, error) { d := &Deployer{ st: st, ctx: ctx, deployed: make(set.Strings), } w, err := watcher.NewStringsWorker(watcher.StringsConfig{ Handler: d, }) if err != nil { return nil, errors.Trace(err) } return w, 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 := apiprovisioner.NewState(st) 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) } // Start the watcher to fire when a container is first requested on the machine. watcherName := fmt.Sprintf("%s-container-watcher", machine.Id()) params := provisioner.ContainerSetupParams{ Runner: runner, WorkerName: watcherName, SupportedContainers: containers, Machine: machine, Provisioner: pr, Config: agentConfig, InitLockName: agent.MachineLockName, } 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 }
func newStringsHandlerWorker(c *gc.C, setupError, handlerError, teardownError error) (*stringsHandler, worker.Worker) { sh := &stringsHandler{ actions: nil, handled: make(chan []string, 1), setupError: setupError, teardownError: teardownError, handlerError: handlerError, watcher: newTestStringsWatcher(), setupDone: make(chan struct{}), } w, err := watcher.NewStringsWorker(watcher.StringsConfig{Handler: sh}) c.Assert(err, jc.ErrorIsNil) select { case <-sh.setupDone: case <-time.After(coretesting.ShortWait): c.Error("Failed waiting for stringsHandler.Setup to be called during SetUpTest") } return sh, w }
// NewWorker returns a worker that keeps track of IP address // lifecycles, releaseing and removing dead addresses. func NewWorker(api *apiaddresser.API) (worker.Worker, error) { ok, err := api.CanDeallocateAddresses() if err != nil { return nil, errors.Annotate(err, "checking address deallocation") } if !ok { // Environment does not support IP address // deallocation. logger.Debugf("address deallocation not supported; not starting worker") return worker.FinishedWorker{}, nil } handler := &addresserHandler{api: api} aw, err := watcher.NewStringsWorker(watcher.StringsConfig{ Handler: handler, }) if err != nil { return nil, errors.Trace(err) } return aw, 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 }
func New(ua UnitAssigner) (worker.Worker, error) { return watcher.NewStringsWorker(watcher.StringsConfig{ Handler: unitAssignerHandler{api: ua}, }) }