// Phase implements ModelMigration. func (mig *modelMigration) Phase() (migration.Phase, error) { phase, ok := migration.ParsePhase(mig.statusDoc.Phase) if !ok { return phase, errors.Errorf("invalid phase in DB: %v", mig.statusDoc.Phase) } return phase, nil }
// MinionReports returns details of the reports made by migration // minions to the controller for the current migration phase. func (c *Client) MinionReports() (migration.MinionReports, error) { var in params.MinionReports var out migration.MinionReports err := c.caller.FacadeCall("MinionReports", nil, &in) if err != nil { return out, errors.Trace(err) } out.MigrationId = in.MigrationId phase, ok := migration.ParsePhase(in.Phase) if !ok { return out, errors.Errorf("invalid phase: %q", in.Phase) } out.Phase = phase out.SuccessCount = in.SuccessCount out.UnknownCount = in.UnknownCount out.SomeUnknownMachines, out.SomeUnknownUnits, err = groupTagIds(in.UnknownSample) if err != nil { return out, errors.Annotate(err, "processing unknown agents") } out.FailedMachines, out.FailedUnits, err = groupTagIds(in.Failed) if err != nil { return out, errors.Annotate(err, "processing failed agents") } return out, nil }
// MigrationStatus returns the details and progress of the latest // model migration. func (c *Client) MigrationStatus() (migration.MigrationStatus, error) { var empty migration.MigrationStatus var status params.MasterMigrationStatus err := c.caller.FacadeCall("MigrationStatus", nil, &status) if err != nil { return empty, errors.Trace(err) } modelTag, err := names.ParseModelTag(status.Spec.ModelTag) if err != nil { return empty, errors.Annotatef(err, "parsing model tag") } phase, ok := migration.ParsePhase(status.Phase) if !ok { return empty, errors.New("unable to parse phase") } target := status.Spec.TargetInfo controllerTag, err := names.ParseControllerTag(target.ControllerTag) if err != nil { return empty, errors.Annotatef(err, "parsing controller tag") } authTag, err := names.ParseUserTag(target.AuthTag) if err != nil { return empty, errors.Annotatef(err, "unable to parse auth tag") } var macs []macaroon.Slice if target.Macaroons != "" { if err := json.Unmarshal([]byte(target.Macaroons), &macs); err != nil { return empty, errors.Annotatef(err, "unmarshalling macaroon") } } return migration.MigrationStatus{ MigrationId: status.MigrationId, ModelUUID: modelTag.Id(), ExternalControl: status.Spec.ExternalControl, Phase: phase, PhaseChangedTime: status.PhaseChangedTime, TargetInfo: migration.TargetInfo{ ControllerTag: controllerTag, Addrs: target.Addrs, CACert: target.CACert, AuthTag: authTag, Password: target.Password, Macaroons: macs, }, }, nil }
// SetPhase sets the phase of the active model migration. The provided // phase must be a valid phase value, for example QUIESCE" or // "ABORT". See the core/migration package for the complete list. func (api *API) SetPhase(args params.SetMigrationPhaseArgs) error { mig, err := api.backend.GetModelMigration() if err != nil { return errors.Annotate(err, "could not get migration") } phase, ok := coremigration.ParsePhase(args.Phase) if !ok { return errors.Errorf("invalid phase: %q", args.Phase) } err = mig.SetPhase(phase) return errors.Annotate(err, "failed to set phase") }
// Report allows a migration minion to submit whether it succeeded or // failed for a specific migration phase. func (api *API) Report(info params.MinionReport) error { phase, ok := migration.ParsePhase(info.Phase) if !ok { return errors.New("unable to parse phase") } mig, err := api.backend.Migration(info.MigrationId) if err != nil { return errors.Trace(err) } err = mig.SubmitMinionReport(api.authorizer.GetAuthTag(), phase, info.Success) return errors.Trace(err) }
func (w *migrationStatusWatcher) loop() error { w.newResult = func() interface{} { return new(params.MigrationStatus) } w.call = makeWatcherAPICaller(w.caller, "MigrationStatusWatcher", w.id) w.commonWatcher.init() go w.commonLoop() for { var data interface{} var ok bool select { case data, ok = <-w.in: if !ok { // The tomb is already killed with the correct error // at this point, so just return. return nil } case <-w.tomb.Dying(): return nil } inStatus := *data.(*params.MigrationStatus) phase, ok := migration.ParsePhase(inStatus.Phase) if !ok { return errors.Errorf("invalid phase %q", inStatus.Phase) } outStatus := watcher.MigrationStatus{ MigrationId: inStatus.MigrationId, Attempt: inStatus.Attempt, Phase: phase, SourceAPIAddrs: inStatus.SourceAPIAddrs, SourceCACert: inStatus.SourceCACert, TargetAPIAddrs: inStatus.TargetAPIAddrs, TargetCACert: inStatus.TargetCACert, } select { case w.out <- outStatus: case <-w.tomb.Dying(): return nil } } }
// GetMigrationStatus implements Client. func (c *client) GetMigrationStatus() (MigrationStatus, error) { var empty MigrationStatus var status params.FullMigrationStatus err := c.caller.FacadeCall("GetMigrationStatus", nil, &status) if err != nil { return empty, errors.Trace(err) } modelTag, err := names.ParseModelTag(status.Spec.ModelTag) if err != nil { return empty, errors.Annotatef(err, "parsing model tag") } phase, ok := migration.ParsePhase(status.Phase) if !ok { return empty, errors.New("unable to parse phase") } target := status.Spec.TargetInfo controllerTag, err := names.ParseModelTag(target.ControllerTag) if err != nil { return empty, errors.Annotatef(err, "parsing controller tag") } authTag, err := names.ParseUserTag(target.AuthTag) if err != nil { return empty, errors.Annotatef(err, "unable to parse auth tag") } return MigrationStatus{ ModelUUID: modelTag.Id(), Attempt: status.Attempt, Phase: phase, TargetInfo: migration.TargetInfo{ ControllerTag: controllerTag, Addrs: target.Addrs, CACert: target.CACert, AuthTag: authTag, Password: target.Password, }, }, nil }
// Phase returns the current migration.Phase for the supplied model UUID. func (facade *Facade) Phase(uuid string) (migration.Phase, error) { results := params.PhaseResults{} err := facade.call("Phase", uuid, &results) if err != nil { return migration.UNKNOWN, errors.Trace(err) } if count := len(results.Results); count != 1 { return migration.UNKNOWN, countError(count) } result := results.Results[0] if result.Error != nil { return migration.UNKNOWN, errors.Trace(result.Error) } phase, ok := migration.ParsePhase(result.Phase) if !ok { err := errors.Errorf("unknown phase %q", result.Phase) return migration.UNKNOWN, err } return phase, nil }
func (s *PhaseSuite) TestParseInvalid(c *gc.C) { phase, ok := migration.ParsePhase("foo") c.Check(phase, gc.Equals, migration.UNKNOWN) c.Check(ok, jc.IsFalse) }
func (s *PhaseSuite) TestParseValid(c *gc.C) { phase, ok := migration.ParsePhase("REAP") c.Check(phase, gc.Equals, migration.REAP) c.Check(ok, jc.IsTrue) }