Beispiel #1
0
func (u *Undertaker) processDyingModel() error {

	watcher, err := u.config.Facade.WatchModelResources()
	if err != nil {
		return errors.Trace(err)
	}
	if err := u.catacomb.Add(watcher); err != nil {
		return errors.Trace(err)
	}
	defer watcher.Kill() // The watcher is not needed once this func returns.

	for {
		select {
		case <-u.catacomb.Dying():
			return u.catacomb.ErrDying()
		case <-watcher.Changes():
			// TODO(fwereade): this is wrong. If there's a time
			// it's ok to ignore an error, it's when we know
			// exactly what an error is/means. If there's a
			// specific code for "not done yet", *that* is what
			// we should be ignoring. But unknown errors are
			// *unknown*, and we can't just assume that it's
			// safe to continue.
			err := u.config.Facade.ProcessDyingModel()
			if err == nil {
				// ProcessDyingModel succeeded. We're free to
				// destroy any remaining environ resources.
				return nil
			}
			// Yes, we ignore the error. See comment above.
		}
	}
}
Beispiel #2
0
func (w *Worker) loop() error {
	model := w.config.Model
	facade := w.config.Facade
	watcher, err := facade.Watch(model)
	if err != nil {
		return errors.Trace(err)
	}
	if err := w.catacomb.Add(watcher); err != nil {
		return errors.Trace(err)
	}
	for {
		select {
		case <-w.catacomb.Dying():
			return w.catacomb.ErrDying()
		case <-watcher.Changes():
			phase, err := facade.Phase(model)
			if err != nil {
				return errors.Trace(err)
			}
			if w.Check() != w.config.Check(phase) {
				return ErrChanged
			}
		}
	}
}
Beispiel #3
0
func (w *Worker) loop() error {
	watcher, err := w.config.Facade.Watch(w.config.Entity)
	if err != nil {
		return errors.Trace(err)
	}
	if err := w.catacomb.Add(watcher); err != nil {
		return errors.Trace(err)
	}
	for {
		select {
		case <-w.catacomb.Dying():
			return w.catacomb.ErrDying()
		case <-watcher.Changes():
			life, err := w.config.Facade.Life(w.config.Entity)
			if err != nil {
				return errors.Trace(err)
			}
			if w.config.Result(life) != w.Check() {
				return ErrValueChanged
			}
		}
	}
}
Beispiel #4
0
func (w *Worker) loop() error {
	watcher, err := w.config.Facade.Watch()
	if err != nil {
		return errors.Annotate(err, "setting up watcher")
	}
	if err := w.catacomb.Add(watcher); err != nil {
		return errors.Trace(err)
	}

	for {
		select {
		case <-w.catacomb.Dying():
			return w.catacomb.ErrDying()
		case status, ok := <-watcher.Changes():
			if !ok {
				return errors.New("watcher channel closed")
			}
			if err := w.handle(status); err != nil {
				return errors.Trace(err)
			}
		}
	}
}
Beispiel #5
0
func (w *Worker) waitForActiveMigration() (migrationmaster.MigrationStatus, error) {
	var empty migrationmaster.MigrationStatus

	watcher, err := w.config.Facade.Watch()
	if err != nil {
		return empty, errors.Annotate(err, "watching for migration")
	}
	if err := w.catacomb.Add(watcher); err != nil {
		return empty, errors.Trace(err)
	}
	defer watcher.Kill()

	for {
		select {
		case <-w.catacomb.Dying():
			return empty, w.catacomb.ErrDying()
		case <-watcher.Changes():
		}
		status, err := w.config.Facade.GetMigrationStatus()
		switch {
		case params.IsCodeNotFound(err):
			if err := w.config.Guard.Unlock(); err != nil {
				return empty, errors.Trace(err)
			}
			continue
		case err != nil:
			return empty, errors.Annotate(err, "retrieving migration status")
		}
		if modelHasMigrated(status.Phase) {
			return empty, dependency.ErrUninstall
		}
		if !status.Phase.IsTerminal() {
			return status, nil
		}
	}
}