Example #1
0
// NewWatcher returns a new Watcher.
func NewWatcher(base *mgo.Collection, envTag names.EnvironTag) *Watcher {
	w := &Watcher{
		envUUID:  envTag.Id(),
		base:     base,
		pings:    pingsC(base),
		beings:   beingsC(base),
		beingKey: make(map[int64]string),
		beingSeq: make(map[string]int64),
		watches:  make(map[string][]chan<- Change),
		request:  make(chan interface{}),
	}
	go func() {
		err := w.loop()
		cause := errors.Cause(err)
		// tomb expects ErrDying or ErrStillAlive as
		// exact values, so we need to log and unwrap
		// the error first.
		if err != nil && cause != tomb.ErrDying {
			logger.Infof("watcher loop failed: %v", err)
		}
		w.tomb.Kill(cause)
		w.tomb.Done()
	}()
	return w
}
Example #2
0
File: open.go Project: tych0/juju
func open(tag names.EnvironTag, info *mongo.MongoInfo, opts mongo.DialOpts, policy Policy) (*State, error) {
	logger.Infof("opening state, mongo addresses: %q; entity %v", info.Addrs, info.Tag)
	logger.Debugf("dialing mongo")
	session, err := mongo.DialWithInfo(info.Info, opts)
	if err != nil {
		return nil, maybeUnauthorized(err, "cannot connect to mongodb")
	}
	logger.Debugf("connection established")

	// In rare circumstances, we may be upgrading from pre-1.23, and not have the
	// environment UUID available. In that case we need to infer what it might be;
	// we depend on the assumption that this is the only circumstance in which
	// the the UUID might not be known.
	if tag.Id() == "" {
		logger.Warningf("creating state without environment tag; inferring bootstrap environment")
		ssInfo, err := readRawStateServerInfo(session)
		if err != nil {
			return nil, errors.Trace(err)
		}
		tag = ssInfo.EnvironmentTag
	}

	st, err := newState(tag, session, info, policy)
	if err != nil {
		session.Close()
		return nil, errors.Trace(err)
	}
	return st, nil
}
Example #3
0
File: open.go Project: tych0/juju
// newState creates an incomplete *State, with a configured watcher but no
// pwatcher, leadershipManager, or serverTag. You must start() the returned
// *State before it will function correctly.
func newState(environTag names.EnvironTag, session *mgo.Session, mongoInfo *mongo.MongoInfo, policy Policy) (_ *State, resultErr error) {
	admin := session.DB("admin")
	if mongoInfo.Tag != nil {
		if err := admin.Login(mongoInfo.Tag.String(), mongoInfo.Password); err != nil {
			return nil, maybeUnauthorized(err, fmt.Sprintf("cannot log in to admin database as %q", mongoInfo.Tag))
		}
	} else if mongoInfo.Password != "" {
		if err := admin.Login(mongo.AdminUser, mongoInfo.Password); err != nil {
			return nil, maybeUnauthorized(err, "cannot log in to admin database")
		}
	}

	// Set up database.
	rawDB := session.DB(jujuDB)
	database, err := allCollections().Load(rawDB, environTag.Id())
	if err != nil {
		return nil, errors.Trace(err)
	}
	if err := InitDbLogs(session); err != nil {
		return nil, errors.Trace(err)
	}

	// Create State.
	st := &State{
		environTag: environTag,
		mongoInfo:  mongoInfo,
		session:    session,
		database:   database,
		policy:     policy,
		watcher:    watcher.New(rawDB.C(txnLogC)),
	}
	st.LeasePersistor = NewLeasePersistor(leaseC, st.run, st.getCollection)
	return st, nil
}
Example #4
0
// NewPinger returns a new Pinger to report that key is alive.
// It starts reporting after Start is called.
func NewPinger(base *mgo.Collection, envTag names.EnvironTag, key string) *Pinger {
	return &Pinger{
		base:     base,
		pings:    pingsC(base),
		beingKey: key,
		envUUID:  envTag.Id(),
	}
}
Example #5
0
func (m *envWorkerManager) envIsDead(envTag names.EnvironTag) error {
	uuid := envTag.Id()
	err := m.runner.StopWorker(uuid)
	if err != nil {
		return errors.Trace(err)
	}

	return nil
}
Example #6
0
func (m *envWorkerManager) isEnvAlive(tag names.EnvironTag) (bool, error) {
	env, err := m.st.GetEnvironment(tag)
	if errors.IsNotFound(err) {
		return false, nil
	} else if err != nil {
		return false, errors.Annotatef(err, "error loading environment %s", tag.Id())
	}
	return env.Life() == state.Alive, nil
}
Example #7
0
// GetEnvironment looks for the environment identified by the uuid passed in.
func (st *State) GetEnvironment(tag names.EnvironTag) (*Environment, error) {
	environments, closer := st.getCollection(environmentsC)
	defer closer()

	env := &Environment{st: st}
	if err := env.refresh(environments.FindId(tag.Id())); err != nil {
		return nil, errors.Trace(err)
	}
	return env, nil
}
Example #8
0
// envNotFound stops all workers for that environment.
func (m *envWorkerManager) envNotFound(envTag names.EnvironTag) error {
	uuid := envTag.Id()
	if err := m.runner.StopWorker(uuid); err != nil {
		return errors.Trace(err)
	}
	if err := m.runner.StopWorker(dyingEnvWorkerId(uuid)); err != nil {
		return errors.Trace(err)
	}
	return nil
}
Example #9
0
// apiPath returns the given API endpoint path relative
// to the given environment tag. The caller is responsible
// for ensuring that the environment tag is valid and
// that the path is slash-prefixed.
func apiPath(envTag names.EnvironTag, path string) string {
	if !strings.HasPrefix(path, "/") {
		panic(fmt.Sprintf("apiPath called with non-slash-prefixed path %q", path))
	}
	if envTag.Id() == "" {
		panic("apiPath called with empty environment tag")
	}
	if envUUID := envTag.Id(); envUUID != "" {
		return "/environment/" + envUUID + path
	}
	return path
}
Example #10
0
// ResourceTags returns tags to set on an infrastructure resource
// for the specified Juju environment.
func ResourceTags(e names.EnvironTag, taggers ...ResourceTagger) map[string]string {
	allTags := make(map[string]string)
	for _, tagger := range taggers {
		tags, ok := tagger.ResourceTags()
		if !ok {
			continue
		}
		for k, v := range tags {
			allTags[k] = v
		}
	}
	allTags[JujuEnv] = e.Id()
	return allTags
}
Example #11
0
func (s *loginSuite) assertRemoteEnvironment(c *gc.C, st api.Connection, expected names.EnvironTag) {
	// Look at what the api thinks it has.
	tag, err := st.EnvironTag()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(tag, gc.Equals, expected)
	// Look at what the api Client thinks it has.
	client := st.Client()

	// EnvironmentUUID looks at the env tag on the api state connection.
	c.Assert(client.EnvironmentUUID(), gc.Equals, expected.Id())

	// EnvironmentInfo calls a remote method that looks up the environment.
	info, err := client.EnvironmentInfo()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(info.UUID, gc.Equals, expected.Id())
}
Example #12
0
File: open.go Project: imoapps/juju
// Open connects to the server described by the given
// info, waits for it to be initialized, and returns a new State
// representing the environment connected to.
//
// A policy may be provided, which will be used to validate and
// modify behaviour of certain operations in state. A nil policy
// may be provided.
//
// Open returns unauthorizedError if access is unauthorized.
func Open(tag names.EnvironTag, info *mongo.MongoInfo, opts mongo.DialOpts, policy Policy) (*State, error) {
	st, err := open(tag, info, opts, policy)
	if err != nil {
		return nil, errors.Trace(err)
	}
	if _, err := st.Environment(); err != nil {
		if err := st.Close(); err != nil {
			logger.Errorf("error closing state for unreadable environment %s: %v", tag.Id(), err)
		}
		return nil, errors.Annotatef(err, "cannot read environment %s", tag.Id())
	}

	// State should only be Opened on behalf of a state server environ; all
	// other *States should be created via ForEnviron.
	if err := st.start(tag); err != nil {
		return nil, errors.Trace(err)
	}
	return st, nil
}
Example #13
0
File: open.go Project: imoapps/juju
// newState creates an incomplete *State, with a configured watcher but no
// pwatcher, leadershipManager, or controllerTag. You must start() the returned
// *State before it will function correctly.
func newState(environTag names.EnvironTag, session *mgo.Session, mongoInfo *mongo.MongoInfo, policy Policy) (_ *State, resultErr error) {
	// Set up database.
	rawDB := session.DB(jujuDB)
	database, err := allCollections().Load(rawDB, environTag.Id())
	if err != nil {
		return nil, errors.Trace(err)
	}
	if err := InitDbLogs(session); err != nil {
		return nil, errors.Trace(err)
	}

	// Create State.
	return &State{
		environTag: environTag,
		mongoInfo:  mongoInfo,
		session:    session,
		database:   database,
		policy:     policy,
		watcher:    watcher.New(rawDB.C(txnLogC)),
	}, nil
}
Example #14
0
func (m *envWorkerManager) envIsDying(envTag names.EnvironTag) error {
	id := dyingEnvWorkerId(envTag.Id())
	return m.runner.StartWorker(id, func() (worker.Worker, error) {
		st, err := m.st.ForEnviron(envTag)
		if err != nil {
			return nil, errors.Annotatef(err, "failed to open state for environment %s", envTag.Id())
		}
		closeState := func() {
			err := st.Close()
			if err != nil {
				logger.Errorf("error closing state for env %s: %v", envTag.Id(), err)
			}
		}

		dyingRunner, err := m.dyingEnvWorker(m.st, st)
		if err != nil {
			closeState()
			return nil, errors.Trace(err)
		}

		// Close State when the runner for the environment is done.
		go func() {
			dyingRunner.Wait()
			closeState()
		}()

		return dyingRunner, nil
	})
}
Example #15
0
func (c *dumpLogsCommand) dumpLogsForEnv(ctx *cmd.Context, st0 *state.State, tag names.EnvironTag) error {
	st, err := st0.ForEnviron(tag)
	if err != nil {
		return errors.Annotate(err, "failed open environment")
	}
	defer st.Close()

	logName := ctx.AbsPath(filepath.Join(c.outDir, fmt.Sprintf("%s.log", tag.Id())))
	ctx.Infof("writing to %s", logName)

	file, err := os.Create(logName)
	if err != nil {
		return errors.Annotate(err, "failed to open output file")
	}
	defer file.Close()

	writer := bufio.NewWriter(file)
	defer writer.Flush()

	tailer := state.NewLogTailer(st, &state.LogTailerParams{NoTail: true})
	logs := tailer.Logs()
	for {
		rec, ok := <-logs
		if !ok {
			break
		}
		writer.WriteString(c.format(
			rec.Time,
			rec.Level,
			rec.Entity,
			rec.Module,
			rec.Message,
		) + "\n")
	}

	return nil
}
Example #16
0
func (m *envWorkerManager) envIsDead(envTag names.EnvironTag) error {
	err := m.runner.StopWorker(envTag.Id())
	return errors.Trace(err)
}