// DestroyController will attempt to destroy the controller. If the args // specify the removal of blocks or the destruction of the models, this // method will attempt to do so. // // If the controller has any non-Dead hosted models, then an error with // the code params.CodeHasHostedModels will be transmitted, regardless of // the value of the DestroyModels parameter. This is to inform the client // that it should wait for hosted models to be completely cleaned up // before proceeding. func (s *ControllerAPI) DestroyController(args params.DestroyControllerArgs) error { hasPermission, err := s.authorizer.HasPermission(permission.SuperuserAccess, s.state.ControllerTag()) if err != nil { return errors.Trace(err) } if !hasPermission { return errors.Trace(common.ErrPerm) } st := common.NewModelManagerBackend(s.state) controllerModel, err := st.ControllerModel() if err != nil { return errors.Trace(err) } systemTag := controllerModel.ModelTag() if err = s.ensureNotBlocked(args); err != nil { return errors.Trace(err) } // If we are destroying models, we need to tolerate living // models but set the controller to dying to prevent new // models sneaking in. If we are not destroying hosted models, // this will fail if any hosted models are found. if args.DestroyModels { return errors.Trace(common.DestroyModelIncludingHosted(st, systemTag)) } if err := common.DestroyModel(st, systemTag); err != nil { return errors.Trace(err) } return nil }
func (s *destroyModelSuite) TestBlockDestroyDestroyHostedModel(c *gc.C) { otherSt := s.Factory.MakeModel(c, nil) defer otherSt.Close() info := s.APIInfo(c) info.ModelTag = otherSt.ModelTag() apiState, err := api.Open(info, api.DefaultDialOpts()) block := commontesting.NewBlockHelper(apiState) defer block.Close() block.BlockDestroyModel(c, "TestBlockDestroyDestroyModel") err = common.DestroyModelIncludingHosted(s.State, s.State.ModelTag()) s.AssertBlocked(c, err, "TestBlockDestroyDestroyModel") }
func (s *destroyTwoModelsSuite) TestDestroyControllerAndNonController(c *gc.C) { otherFactory := factory.NewFactory(s.otherState) otherFactory.MakeMachine(c, nil) m := otherFactory.MakeMachine(c, nil) otherFactory.MakeMachineNested(c, m.Id(), nil) err := common.DestroyModelIncludingHosted(s.State, s.State.ModelTag()) c.Assert(err, jc.ErrorIsNil) runAllCleanups(c, s.State) runAllCleanups(c, s.otherState) assertAllMachinesDeadAndRemove(c, s.otherState) // Make sure we can continue to take the hosted model down while the // controller model is dying. c.Assert(s.otherState.ProcessDyingModel(), jc.ErrorIsNil) }
// DestroyController will attempt to destroy the controller. If the args // specify the removal of blocks or the destruction of the models, this // method will attempt to do so. // // If the controller has any non-Dead hosted models, then an error with // the code params.CodeHasHostedModels will be transmitted, regardless of // the value of the DestroyModels parameter. This is to inform the client // that it should wait for hosted models to be completely cleaned up // before proceeding. func (s *ControllerAPI) DestroyController(args params.DestroyControllerArgs) error { controllerEnv, err := s.state.ControllerModel() if err != nil { return errors.Trace(err) } systemTag := controllerEnv.ModelTag() if err = s.ensureNotBlocked(args); err != nil { return errors.Trace(err) } // If we are destroying models, we need to tolerate living // models but set the controller to dying to prevent new // models sneaking in. If we are not destroying hosted models, // this will fail if any hosted models are found. if args.DestroyModels { return errors.Trace(common.DestroyModelIncludingHosted(s.state, systemTag)) } if err := common.DestroyModel(s.state, systemTag); err != nil { return errors.Trace(err) } return nil }