// primeAgent writes the configuration file and tools with version vers // for an agent with the given entity name. It returns the agent's // configuration and the current tools. func (s *agentSuite) primeAgent(c *gc.C, tag names.Tag, password string, vers version.Binary) (agent.ConfigSetterWriter, *coretools.Tools) { stor := s.Environ.Storage() agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), vers) err := envtools.MergeAndWriteMetadata(stor, coretools.List{agentTools}, envtools.DoNotWriteMirrors) c.Assert(err, gc.IsNil) tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers) c.Assert(err, gc.IsNil) c.Assert(tools1, gc.DeepEquals, agentTools) stateInfo := s.MongoInfo(c) apiInfo := s.APIInfo(c) conf, err := agent.NewAgentConfig( agent.AgentConfigParams{ DataDir: s.DataDir(), Tag: tag, UpgradedToVersion: vers.Number, Password: password, Nonce: agent.BootstrapNonce, StateAddresses: stateInfo.Addrs, APIAddresses: apiInfo.Addrs, CACert: stateInfo.CACert, }) conf.SetPassword(password) c.Assert(conf.Write(), gc.IsNil) s.primeAPIHostPorts(c) return conf, agentTools }
// PrimeAgentVersion writes the configuration file and tools with version // vers for an agent with the given entity name. It returns the agent's // configuration and the current tools. func (s *AgentSuite) PrimeAgentVersion(c *gc.C, tag names.Tag, password string, vers version.Binary) (agent.ConfigSetterWriter, *coretools.Tools) { c.Logf("priming agent %s", tag.String()) stor, err := filestorage.NewFileStorageWriter(c.MkDir()) c.Assert(err, jc.ErrorIsNil) agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), "released", vers) err = envtools.MergeAndWriteMetadata(stor, "released", "released", coretools.List{agentTools}, envtools.DoNotWriteMirrors) tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers) c.Assert(err, jc.ErrorIsNil) c.Assert(tools1, gc.DeepEquals, agentTools) stateInfo := s.MongoInfo(c) apiInfo := s.APIInfo(c) paths := agent.DefaultPaths paths.DataDir = s.DataDir() conf, err := agent.NewAgentConfig( agent.AgentConfigParams{ Paths: paths, Tag: tag, UpgradedToVersion: vers.Number, Password: password, Nonce: agent.BootstrapNonce, StateAddresses: stateInfo.Addrs, APIAddresses: apiInfo.Addrs, CACert: stateInfo.CACert, Model: apiInfo.ModelTag, }) c.Assert(err, jc.ErrorIsNil) conf.SetPassword(password) c.Assert(conf.Write(), gc.IsNil) s.primeAPIHostPorts(c) return conf, agentTools }
// WriteLogWithOplog writes out a log record to the a (probably fake) // oplog collection and the logs collection. func WriteLogWithOplog( oplog *mgo.Collection, envUUID string, entity names.Tag, t time.Time, module string, location string, level loggo.Level, msg string, ) error { doc := &logDoc{ Id: bson.NewObjectId(), Time: t, EnvUUID: envUUID, Entity: entity.String(), Module: module, Location: location, Level: level, Message: msg, } err := oplog.Insert(bson.D{ {"ts", bson.MongoTimestamp(time.Now().Unix() << 32)}, // an approximation which will do {"h", rand.Int63()}, // again, a suitable fake {"op", "i"}, // this will always be an insert {"ns", "logs.logs"}, {"o", doc}, }) if err != nil { return err } session := oplog.Database.Session logs := session.DB("logs").C("logs") return logs.Insert(doc) }
// SetPassword is part of the ConnFacade interface. func (facade *connFacade) SetPassword(entity names.Tag, password string) error { var results params.ErrorResults args := params.EntityPasswords{ Changes: []params.EntityPassword{{ Tag: entity.String(), Password: password, }}, } err := facade.caller.FacadeCall("SetPasswords", args, &results) if err != nil { return errors.Trace(err) } if len(results.Results) != 1 { return errors.Errorf("expected 1 result, got %d", len(results.Results)) } if err := results.Results[0].Error; err != nil { if params.IsCodeDead(err) { return ErrDenied } else if params.IsCodeNotFoundOrCodeUnauthorized(err) { return ErrDenied } return errors.Trace(err) } return nil }
// Life is part of the ConnFacade interface. func (facade *connFacade) Life(entity names.Tag) (Life, error) { var results params.AgentGetEntitiesResults args := params.Entities{ Entities: []params.Entity{{Tag: entity.String()}}, } err := facade.caller.FacadeCall("GetEntities", args, &results) if err != nil { return "", errors.Trace(err) } if len(results.Entities) != 1 { return "", errors.Errorf("expected 1 result, got %d", len(results.Entities)) } if err := results.Entities[0].Error; err != nil { if params.IsCodeNotFoundOrCodeUnauthorized(err) { return "", ErrDenied } return "", errors.Trace(err) } life := Life(results.Entities[0].Life) switch life { case Alive, Dying, Dead: return life, nil } return "", errors.Errorf("unknown life value %q", life) }
func (fix *SimpleToolsFixture) paths(tag names.Tag) (confPath, agentDir, toolsDir string) { confName := fmt.Sprintf("jujud-%s.conf", tag) confPath = filepath.Join(fix.initDir, confName) agentDir = agent.Dir(fix.dataDir, tag) toolsDir = tools.ToolsDir(fix.dataDir, tag.String()) return }
// Life returns the entity's life value; or ErrNotFound; or some // other error. func (facade *Facade) Life(entity names.Tag) (life.Value, error) { args := params.Entities{ Entities: []params.Entity{{Tag: entity.String()}}, } var results params.LifeResults err := facade.caller.FacadeCall("Life", args, &results) if err != nil { return "", errors.Trace(err) } if count := len(results.Results); count != 1 { return "", errors.Errorf("expected 1 Life result, got %d", count) } result := results.Results[0] if err := result.Error; err != nil { if params.IsCodeNotFound(err) { return "", ErrNotFound } return "", errors.Trace(result.Error) } life := life.Value(result.Life) if err := life.Validate(); err != nil { return "", errors.Trace(err) } return life, nil }
// NewDbLogger returns a DbLogger instance which is used to write logs // to the database. func NewDbLogger(st LoggingState, entity names.Tag) *DbLogger { _, logsColl := initLogsSession(st) return &DbLogger{ logsColl: logsColl, envUUID: st.EnvironUUID(), entity: entity.String(), } }
func (s *dblogSuite) getLogCount(c *gc.C, entity names.Tag) int { // TODO(mjs) - replace this with State's functionality for reading // logs from the DB, once it gets this. This will happen before // the DB logging feature branch is merged. logs := s.Session.DB("logs").C("logs") count, err := logs.Find(bson.M{"n": entity.String()}).Count() c.Assert(err, jc.ErrorIsNil) return count }
func (s *annotationSuite) assertAnnotationsRemoval(c *gc.C, tag names.Tag) { entity := tag.String() entities := params.Entities{[]params.Entity{{entity}}} ann := s.annotationsApi.Get(entities) c.Assert(ann.Results, gc.HasLen, 1) aResult := ann.Results[0] c.Assert(aResult.EntityTag, gc.DeepEquals, entity) c.Assert(aResult.Annotations, gc.HasLen, 0) }
func (f simpleEntityFinder) FindEntity(tag names.Tag) (state.Entity, error) { if utag, ok := tag.(names.UserTag); ok { // It's a user tag which we need to be in canonical form // so we can look it up unambiguously. tag = names.NewUserTag(utag.Canonical()) } if f[tag.String()] { return &simpleEntity{tag}, nil } return nil, errors.NotFoundf("entity %q", tag) }
func newRsyslogConfigHandler(st *apirsyslog.State, mode RsyslogMode, tag names.Tag, namespace string, stateServerAddrs []string, jujuConfigDir string) (*RsyslogConfigHandler, error) { if namespace != "" { jujuConfigDir += "-" + namespace } jujuConfigDir = filepath.Join(jujuConfigDir, "rsyslog") if err := os.MkdirAll(jujuConfigDir, 0755); err != nil { return nil, errors.Trace(err) } syslogConfig := &syslog.SyslogConfig{ LogFileName: tag.String(), LogDir: logDir, JujuConfigDir: jujuConfigDir, Port: 0, Namespace: namespace, StateServerAddresses: stateServerAddrs, } if mode == RsyslogModeAccumulate { syslog.NewAccumulateConfig(syslogConfig) } else { syslog.NewForwardConfig(syslogConfig) } // Historically only machine-0 includes the namespace in the log // dir/file; for backwards compatibility we continue the tradition. if tag != names.NewMachineTag("0") { namespace = "" } switch tag := tag.(type) { case names.MachineTag: if namespace == "" { syslogConfig.ConfigFileName = "25-juju.conf" } else { syslogConfig.ConfigFileName = fmt.Sprintf("25-juju-%s.conf", namespace) } default: syslogConfig.ConfigFileName = fmt.Sprintf("26-juju-%s.conf", tag) } syslogConfig.ConfigDir = rsyslogConfDir syslogConfig.LogDir = logDir if namespace != "" { syslogConfig.LogDir += "-" + namespace } return &RsyslogConfigHandler{ st: st, mode: mode, syslogConfig: syslogConfig, tag: tag, }, nil }
// primeStateAgent writes the configuration file and tools with version vers // for an agent with the given entity name. It returns the agent's configuration // and the current tools. func (s *agentSuite) primeStateAgent( c *gc.C, tag names.Tag, password string, vers version.Binary) (agent.ConfigSetterWriter, *coretools.Tools) { agentTools := envtesting.PrimeTools(c, s.Environ.Storage(), s.DataDir(), vers) tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers) c.Assert(err, gc.IsNil) c.Assert(tools1, gc.DeepEquals, agentTools) stateInfo := s.MongoInfo(c) conf := writeStateAgentConfig(c, stateInfo, s.DataDir(), tag, password, vers) s.primeAPIHostPorts(c) return conf, agentTools }
// PrimeStateAgentVersion writes the configuration file and tools with // version vers for a state agent with the given entity name. It // returns the agent's configuration and the current tools. func (s *AgentSuite) PrimeStateAgentVersion(c *gc.C, tag names.Tag, password string, vers version.Binary) ( agent.ConfigSetterWriter, *coretools.Tools, ) { stor, err := filestorage.NewFileStorageWriter(c.MkDir()) c.Assert(err, jc.ErrorIsNil) agentTools := envtesting.PrimeTools(c, stor, s.DataDir(), "released", vers) tools1, err := agenttools.ChangeAgentTools(s.DataDir(), tag.String(), vers) c.Assert(err, jc.ErrorIsNil) c.Assert(tools1, gc.DeepEquals, agentTools) conf := s.WriteStateAgentConfig(c, tag, password, vers, s.State.ModelTag()) s.primeAPIHostPorts(c) return conf, agentTools }
func (s *annotationSuite) testSetGetEntitiesAnnotations(c *gc.C, tag names.Tag) { entity := tag.String() entities := []string{entity} for i, t := range clientAnnotationsTests { c.Logf("test %d. %s. entity %s", i, t.about, tag.Id()) s.setupEntity(c, entities, t.initial) s.assertSetEntityAnnotations(c, entities, t.input, t.err) if t.err != "" { continue } aResult := s.assertGetEntityAnnotations(c, params.Entities{[]params.Entity{{entity}}}, entity, t.expected) s.cleanupEntityAnnotations(c, entities, aResult) } }
// Life requests the life cycle of the given entity from the given // server-side API facade via the given caller. func Life(caller base.FacadeCaller, tag names.Tag) (params.Life, error) { var result params.LifeResults args := params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, } if err := caller.FacadeCall("Life", args, &result); err != nil { return "", err } if len(result.Results) != 1 { return "", errors.Errorf("expected 1 result, got %d", len(result.Results)) } if err := result.Results[0].Error; err != nil { return "", err } return result.Results[0].Life, nil }
func newUnitsWatcher(st *State, tag names.Tag, getUnits func() ([]string, error), coll, id string) StringsWatcher { w := &unitsWatcher{ commonWatcher: commonWatcher{st: st}, tag: tag.String(), getUnits: getUnits, life: map[string]Life{}, in: make(chan watcher.Change), out: make(chan []string), } go func() { defer w.tomb.Done() defer close(w.out) w.tomb.Kill(w.loop(coll, id)) }() return w }
func (st *State) getEntity(tag names.Tag) (*params.AgentGetEntitiesResult, error) { var results params.AgentGetEntitiesResults args := params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, } err := st.facade.FacadeCall("GetEntities", args, &results) if err != nil { return nil, err } if len(results.Entities) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Entities)) } if err := results.Entities[0].Error; err != nil { return nil, err } return &results.Entities[0], nil }
// MakeActionResult does the actual type conversion from state.Action // to params.ActionResult. func MakeActionResult(actionReceiverTag names.Tag, action state.Action) params.ActionResult { output, message := action.Results() return params.ActionResult{ Action: ¶ms.Action{ Receiver: actionReceiverTag.String(), Tag: action.ActionTag().String(), Name: action.Name(), Parameters: action.Parameters(), }, Status: string(action.Status()), Message: message, Output: output, Enqueued: action.Enqueued(), Started: action.Started(), Completed: action.Completed(), } }
func (st *State) countEntityStorageInstancesForName( tag names.Tag, name string, ) (uint64, error) { storageCollection, closer := st.getCollection(storageInstancesC) defer closer() criteria := bson.D{{ "$and", []bson.D{ bson.D{{"owner", tag.String()}}, bson.D{{"storagename", name}}, }, }} result, err := storageCollection.Find(criteria).Count() if err != nil { return 0, err } return uint64(result), err }
// RetryStrategy returns the configuration for the agent specified by the agentTag. func (c *Client) RetryStrategy(agentTag names.Tag) (params.RetryStrategy, error) { var results params.RetryStrategyResults args := params.Entities{ Entities: []params.Entity{{Tag: agentTag.String()}}, } err := c.facade.FacadeCall("RetryStrategy", args, &results) if err != nil { return params.RetryStrategy{}, errors.Trace(err) } if len(results.Results) != 1 { return params.RetryStrategy{}, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return params.RetryStrategy{}, errors.Trace(result.Error) } return *result.Result, nil }
// Watch starts a NotifyWatcher for the entity with the specified tag. func Watch(facade base.FacadeCaller, tag names.Tag) (watcher.NotifyWatcher, error) { var results params.NotifyWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: tag.String()}}, } err := facade.FacadeCall("Watch", args, &results) if err != nil { return nil, err } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, result.Error } return watcher.NewNotifyWatcher(facade.RawAPICaller(), result), nil }
// updateBackupMachineTag updates the paths that are stored in the backup // to the current machine. This path is tied, among other factors, to the // machine tag. // Eventually this will change: when backups hold relative paths. func updateBackupMachineTag(oldTag, newTag names.Tag) error { oldTagString := oldTag.String() newTagString := newTag.String() if oldTagString == newTagString { return nil } oldTagPath := path.Join(agent.DefaultPaths.DataDir, oldTagString) newTagPath := path.Join(agent.DefaultPaths.DataDir, newTagString) oldToolsDir := tools.ToolsDir(agent.DefaultPaths.DataDir, oldTagString) oldLink, err := filepath.EvalSymlinks(oldToolsDir) os.Rename(oldTagPath, newTagPath) newToolsDir := tools.ToolsDir(agent.DefaultPaths.DataDir, newTagString) newToolsPath := strings.Replace(oldLink, oldTagPath, newTagPath, -1) err = symlink.Replace(newToolsDir, newToolsPath) return errors.Annotatef(err, "cannot set the new tools path") }
// FindEntity implements StateInterface. func (mst *mockState) FindEntity(tag names.Tag) (state.Entity, error) { mst.mu.Lock() defer mst.mu.Unlock() mst.stub.MethodCall(mst, "FindEntity", tag) if err := mst.stub.NextErr(); err != nil { return nil, err } if tag == nil { return nil, errors.NotValidf("nil tag is") // +" not valid" } for _, ipAddress := range mst.ipAddresses { if ipAddress.Tag().String() == tag.String() { return ipAddress, nil } } return nil, errors.NotFoundf("IP address %s", tag) }
// WatchRetryStrategy returns a notify watcher that looks for changes in the // retry strategy config for the agent specified by agentTag // Right now only the boolean that decides whether we retry can be modified. func (c *Client) WatchRetryStrategy(agentTag names.Tag) (watcher.NotifyWatcher, error) { var results params.NotifyWatchResults args := params.Entities{ Entities: []params.Entity{{Tag: agentTag.String()}}, } err := c.facade.FacadeCall("WatchRetryStrategy", args, &results) if err != nil { return nil, errors.Trace(err) } if len(results.Results) != 1 { return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if result.Error != nil { return nil, errors.Trace(result.Error) } w := apiwatcher.NewNotifyWatcher(c.facade.RawAPICaller(), result) return w, nil }
// removeStorageInstancesOps returns the transaction operations to remove all // storage instances owned by the specified entity. func removeStorageInstancesOps(st *State, owner names.Tag) ([]txn.Op, error) { coll, closer := st.getCollection(storageInstancesC) defer closer() var docs []storageInstanceDoc err := coll.Find(bson.D{{"owner", owner.String()}}).Select(bson.D{{"id", true}}).All(&docs) if err != nil { return nil, errors.Annotatef(err, "cannot get storage instances for %s", owner) } ops := make([]txn.Op, len(docs)) for i, doc := range docs { ops[i] = txn.Op{ C: storageInstancesC, Id: doc.Id, Remove: true, } } return ops, nil }
// relation requests relation information from the server. func (st *State) relation(relationTag, unitTag names.Tag) (params.RelationResult, error) { nothing := params.RelationResult{} var result params.RelationResults args := params.RelationUnits{ RelationUnits: []params.RelationUnit{ {Relation: relationTag.String(), Unit: unitTag.String()}, }, } err := st.facade.FacadeCall("Relation", args, &result) if err != nil { return nothing, err } if len(result.Results) != 1 { return nothing, fmt.Errorf("expected 1 result, got %d", len(result.Results)) } if err := result.Results[0].Error; err != nil { return nothing, err } return result.Results[0], nil }
// LoggingConfig returns the loggo configuration string for the agent // specified by agentTag. func (st *State) LoggingConfig(agentTag names.Tag) (string, error) { var results params.StringResults args := params.Entities{ Entities: []params.Entity{{Tag: agentTag.String()}}, } err := st.facade.FacadeCall("LoggingConfig", args, &results) if err != nil { // TODO: Not directly tested return "", err } if len(results.Results) != 1 { // TODO: Not directly tested return "", fmt.Errorf("expected 1 result, got %d", len(results.Results)) } result := results.Results[0] if err := result.Error; err != nil { return "", err } return result.Result, nil }
// MakeLogDoc creates a database document for a single log message. func MakeLogDoc( modelUUID string, entity names.Tag, t time.Time, module string, location string, level loggo.Level, msg string, ) *logDoc { return &logDoc{ Id: bson.NewObjectId(), Time: t, ModelUUID: modelUUID, Entity: entity.String(), Module: module, Location: location, Level: level, Message: msg, } }
// Watch returns a NotifyWatcher that sends a value whenever the // entity's life value may have changed; or ErrNotFound; or some // other error. func (facade *Facade) Watch(entity names.Tag) (watcher.NotifyWatcher, error) { args := params.Entities{ Entities: []params.Entity{{Tag: entity.String()}}, } var results params.NotifyWatchResults err := facade.caller.FacadeCall("Watch", args, &results) if err != nil { return nil, errors.Trace(err) } if count := len(results.Results); count != 1 { return nil, errors.Errorf("expected 1 Watch result, got %d", count) } result := results.Results[0] if err := result.Error; err != nil { if params.IsCodeNotFound(err) { return nil, ErrNotFound } return nil, errors.Trace(result.Error) } w := facade.newWatcher(facade.caller.RawAPICaller(), result) return w, nil }