github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/cmd/jujud/unit.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "fmt" 8 "runtime" 9 10 "github.com/juju/loggo" 11 "github.com/juju/names" 12 "launchpad.net/gnuflag" 13 "launchpad.net/tomb" 14 15 "github.com/juju/juju/cmd" 16 "github.com/juju/juju/version" 17 "github.com/juju/juju/worker" 18 "github.com/juju/juju/worker/apiaddressupdater" 19 workerlogger "github.com/juju/juju/worker/logger" 20 "github.com/juju/juju/worker/rsyslog" 21 "github.com/juju/juju/worker/uniter" 22 "github.com/juju/juju/worker/upgrader" 23 ) 24 25 var agentLogger = loggo.GetLogger("juju.jujud") 26 27 // UnitAgent is a cmd.Command responsible for running a unit agent. 28 type UnitAgent struct { 29 cmd.CommandBase 30 tomb tomb.Tomb 31 AgentConf 32 UnitName string 33 runner worker.Runner 34 } 35 36 // Info returns usage information for the command. 37 func (a *UnitAgent) Info() *cmd.Info { 38 return &cmd.Info{ 39 Name: "unit", 40 Purpose: "run a juju unit agent", 41 } 42 } 43 44 func (a *UnitAgent) SetFlags(f *gnuflag.FlagSet) { 45 a.AgentConf.AddFlags(f) 46 f.StringVar(&a.UnitName, "unit-name", "", "name of the unit to run") 47 } 48 49 // Init initializes the command for running. 50 func (a *UnitAgent) Init(args []string) error { 51 if a.UnitName == "" { 52 return requiredError("unit-name") 53 } 54 if !names.IsUnit(a.UnitName) { 55 return fmt.Errorf(`--unit-name option expects "<service>/<n>" argument`) 56 } 57 if err := a.AgentConf.CheckArgs(args); err != nil { 58 return err 59 } 60 a.runner = worker.NewRunner(isFatal, moreImportant) 61 return nil 62 } 63 64 // Stop stops the unit agent. 65 func (a *UnitAgent) Stop() error { 66 a.runner.Kill() 67 return a.tomb.Wait() 68 } 69 70 // Run runs a unit agent. 71 func (a *UnitAgent) Run(ctx *cmd.Context) error { 72 defer a.tomb.Done() 73 if err := a.ReadConfig(a.Tag()); err != nil { 74 return err 75 } 76 agentLogger.Infof("unit agent %v start (%s [%s])", a.Tag(), version.Current, runtime.Compiler) 77 a.runner.StartWorker("api", a.APIWorkers) 78 err := agentDone(a.runner.Wait()) 79 a.tomb.Kill(err) 80 return err 81 } 82 83 func (a *UnitAgent) APIWorkers() (worker.Worker, error) { 84 agentConfig := a.CurrentConfig() 85 dataDir := agentConfig.DataDir() 86 hookLock, err := hookExecutionLock(dataDir) 87 if err != nil { 88 return nil, err 89 } 90 st, entity, err := openAPIState(agentConfig, a) 91 if err != nil { 92 return nil, err 93 } 94 runner := worker.NewRunner(connectionIsFatal(st), moreImportant) 95 runner.StartWorker("upgrader", func() (worker.Worker, error) { 96 return upgrader.NewUpgrader(st.Upgrader(), agentConfig), nil 97 }) 98 runner.StartWorker("logger", func() (worker.Worker, error) { 99 return workerlogger.NewLogger(st.Logger(), agentConfig), nil 100 }) 101 runner.StartWorker("uniter", func() (worker.Worker, error) { 102 return uniter.NewUniter(st.Uniter(), entity.Tag(), dataDir, hookLock), nil 103 }) 104 runner.StartWorker("apiaddressupdater", func() (worker.Worker, error) { 105 return apiaddressupdater.NewAPIAddressUpdater(st.Uniter(), a), nil 106 }) 107 runner.StartWorker("rsyslog", func() (worker.Worker, error) { 108 return newRsyslogConfigWorker(st.Rsyslog(), agentConfig, rsyslog.RsyslogModeForwarding) 109 }) 110 return newCloseWorker(runner, st), nil 111 } 112 113 func (a *UnitAgent) Tag() string { 114 return names.UnitTag(a.UnitName) 115 }