Ejemplo n.º 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.
		}
	}
}
Ejemplo n.º 2
0
Archivo: worker.go Proyecto: makyo/juju
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
		}
	}
}