Пример #1
0
func (t *Tests) TestBootstrap(c *gc.C) {
	e := t.Prepare(c)
	err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), e, bootstrap.BootstrapParams{})
	c.Assert(err, jc.ErrorIsNil)

	controllerInstances, err := e.ControllerInstances()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(controllerInstances, gc.Not(gc.HasLen), 0)

	e2 := t.Open(c, e.Config())
	controllerInstances2, err := e2.ControllerInstances()
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(controllerInstances2, gc.Not(gc.HasLen), 0)
	c.Assert(controllerInstances2, jc.SameContents, controllerInstances)

	err = environs.Destroy(e2.Config().Name(), e2, t.ControllerStore)
	c.Assert(err, jc.ErrorIsNil)

	// Prepare again because Destroy invalidates old environments.
	e3 := t.Prepare(c)

	err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), e3, bootstrap.BootstrapParams{})
	c.Assert(err, jc.ErrorIsNil)

	err = environs.Destroy(e3.Config().Name(), e3, t.ControllerStore)
	c.Assert(err, jc.ErrorIsNil)
}
Пример #2
0
// Run implements Command.Run
func (c *killCommand) Run(ctx *cmd.Context) error {
	controllerName := c.ControllerName()
	store := c.ClientStore()
	if !c.assumeYes {
		if err := confirmDestruction(ctx, controllerName); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.
	api, err := c.getControllerAPI()
	switch {
	case err == nil:
		defer api.Close()
	case errors.Cause(err) == common.ErrPerm:
		return errors.Annotate(err, "cannot destroy controller")
	default:
		if errors.Cause(err) != modelcmd.ErrConnTimedOut {
			logger.Debugf("unable to open api: %s", err)
		}
		ctx.Infof("Unable to open API: %s\n", err)
		api = nil
	}

	// Obtain controller environ so we can clean up afterwards.
	controllerEnviron, err := c.getControllerEnviron(ctx, store, controllerName, api)
	if err != nil {
		return errors.Annotate(err, "getting controller environ")
	}
	// If we were unable to connect to the API, just destroy the controller through
	// the environs interface.
	if api == nil {
		ctx.Infof("Unable to connect to the API server. Destroying through provider.")
		return environs.Destroy(controllerName, controllerEnviron, store)
	}

	// Attempt to destroy the controller and all environments.
	err = api.DestroyController(true)
	if err != nil {
		ctx.Infof("Unable to destroy controller through the API: %s.  Destroying through provider.", err)
		return environs.Destroy(controllerName, controllerEnviron, store)
	}

	ctx.Infof("Destroying controller %q\nWaiting for resources to be reclaimed", controllerName)

	updateStatus := newTimedStatusUpdater(ctx, api, controllerEnviron.Config().UUID())
	for ctrStatus, envsStatus := updateStatus(0); hasUnDeadModels(envsStatus); ctrStatus, envsStatus = updateStatus(2 * time.Second) {
		ctx.Infof(fmtCtrStatus(ctrStatus))
		for _, envStatus := range envsStatus {
			ctx.Verbosef(fmtModelStatus(envStatus))
		}
	}

	ctx.Infof("All hosted models reclaimed, cleaning up controller machines")

	return environs.Destroy(controllerName, controllerEnviron, store)
}
Пример #3
0
Файл: tests.go Проект: bac/juju
func (t *Tests) TestBootstrap(c *gc.C) {
	credential := t.Credential
	if credential.AuthType() == "" {
		credential = cloud.NewEmptyCredential()
	}

	var regions []cloud.Region
	if t.CloudRegion != "" {
		regions = []cloud.Region{{
			Name:     t.CloudRegion,
			Endpoint: t.CloudEndpoint,
		}}
	}

	args := bootstrap.BootstrapParams{
		ControllerConfig: coretesting.FakeControllerConfig(),
		CloudName:        t.TestConfig["type"].(string),
		Cloud: cloud.Cloud{
			Type:      t.TestConfig["type"].(string),
			AuthTypes: []cloud.AuthType{credential.AuthType()},
			Regions:   regions,
			Endpoint:  t.CloudEndpoint,
		},
		CloudRegion:         t.CloudRegion,
		CloudCredential:     &credential,
		CloudCredentialName: "credential",
		AdminSecret:         AdminSecret,
		CAPrivateKey:        coretesting.CAKey,
	}

	e := t.Prepare(c)
	err := bootstrap.Bootstrap(envtesting.BootstrapContext(c), e, args)
	c.Assert(err, jc.ErrorIsNil)

	controllerInstances, err := e.ControllerInstances(t.ControllerUUID)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(controllerInstances, gc.Not(gc.HasLen), 0)

	e2 := t.Open(c, e.Config())
	controllerInstances2, err := e2.ControllerInstances(t.ControllerUUID)
	c.Assert(err, jc.ErrorIsNil)
	c.Assert(controllerInstances2, gc.Not(gc.HasLen), 0)
	c.Assert(controllerInstances2, jc.SameContents, controllerInstances)

	err = environs.Destroy(e2.Config().Name(), e2, t.ControllerStore)
	c.Assert(err, jc.ErrorIsNil)

	// Prepare again because Destroy invalidates old environments.
	e3 := t.Prepare(c)

	err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), e3, args)
	c.Assert(err, jc.ErrorIsNil)

	err = environs.Destroy(e3.Config().Name(), e3, t.ControllerStore)
	c.Assert(err, jc.ErrorIsNil)
}
Пример #4
0
Файл: kill.go Проект: bac/juju
// Run implements Command.Run
func (c *killCommand) Run(ctx *cmd.Context) error {
	controllerName := c.ControllerName()
	store := c.ClientStore()
	if !c.assumeYes {
		if err := confirmDestruction(ctx, controllerName); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.
	api, err := c.getControllerAPI()
	switch {
	case err == nil:
		defer api.Close()
	case errors.Cause(err) == common.ErrPerm:
		return errors.Annotate(err, "cannot destroy controller")
	default:
		if errors.Cause(err) != modelcmd.ErrConnTimedOut {
			logger.Debugf("unable to open api: %s", err)
		}
		ctx.Infof("Unable to open API: %s\n", err)
		api = nil
	}

	// Obtain controller environ so we can clean up afterwards.
	controllerEnviron, err := c.getControllerEnviron(ctx, store, controllerName, api)
	if err != nil {
		return errors.Annotate(err, "getting controller environ")
	}
	// If we were unable to connect to the API, just destroy the controller through
	// the environs interface.
	if api == nil {
		ctx.Infof("Unable to connect to the API server, destroying through provider")
		return environs.Destroy(controllerName, controllerEnviron, store)
	}

	// Attempt to destroy the controller and all environments.
	err = api.DestroyController(true)
	if err != nil {
		ctx.Infof("Unable to destroy controller through the API: %s\nDestroying through provider", err)
		return environs.Destroy(controllerName, controllerEnviron, store)
	}

	ctx.Infof("Destroying controller %q\nWaiting for resources to be reclaimed", controllerName)

	uuid := controllerEnviron.Config().UUID()
	if err := c.WaitForModels(ctx, api, uuid); err != nil {
		c.DirectDestroyRemaining(ctx, api)
	}
	return environs.Destroy(controllerName, controllerEnviron, store)
}
Пример #5
0
func (*OpenSuite) TestDestroy(c *gc.C) {
	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(
		testing.Attrs{
			"name": "erewhemos",
		},
	))
	c.Assert(err, jc.ErrorIsNil)

	store := jujuclienttesting.NewMemStore()
	// Prepare the environment and sanity-check that
	// the config storage info has been made.
	controllerCfg := testing.FakeControllerConfig()
	ctx := envtesting.BootstrapContext(c)
	e, err := bootstrap.Prepare(ctx, store, bootstrap.PrepareParams{
		ControllerConfig: controllerCfg,
		ControllerName:   "controller-name",
		ModelConfig:      cfg.AllAttrs(),
		Cloud:            dummy.SampleCloudSpec(),
		AdminSecret:      "admin-secret",
	})
	c.Assert(err, jc.ErrorIsNil)
	_, err = store.ControllerByName("controller-name")
	c.Assert(err, jc.ErrorIsNil)

	err = environs.Destroy("controller-name", e, store)
	c.Assert(err, jc.ErrorIsNil)

	// Check that the environment has actually been destroyed
	// and that the controller details been removed too.
	_, err = e.ControllerInstances(controllerCfg.ControllerUUID())
	c.Assert(err, gc.ErrorMatches, "model is not prepared")
	_, err = store.ControllerByName("controller-name")
	c.Assert(err, jc.Satisfies, errors.IsNotFound)
}
Пример #6
0
func (c *DestroyEnvironmentCommand) Run(ctx *cmd.Context) (result error) {
	store, err := configstore.Default()
	if err != nil {
		return fmt.Errorf("cannot open environment info storage: %v", err)
	}
	environ, err := environs.NewFromName(c.envName, store)
	if err != nil {
		if environs.IsEmptyConfig(err) {
			// Delete the .jenv file and call it done.
			ctx.Infof("removing empty environment file")
			return environs.DestroyInfo(c.envName, store)
		}
		return err
	}
	if !c.assumeYes {
		fmt.Fprintf(ctx.Stdout, destroyEnvMsg, environ.Name(), environ.Config().Type())

		scanner := bufio.NewScanner(ctx.Stdin)
		scanner.Scan()
		err := scanner.Err()
		if err != nil && err != io.EOF {
			return fmt.Errorf("Environment destruction aborted: %s", err)
		}
		answer := strings.ToLower(scanner.Text())
		if answer != "y" && answer != "yes" {
			return errors.New("environment destruction aborted")
		}
	}
	// If --force is supplied, then don't attempt to use the API.
	// This is necessary to destroy broken environments, where the
	// API server is inaccessible or faulty.
	if !c.force {
		defer func() {
			if result == nil {
				return
			}
			logger.Errorf(`failed to destroy environment %q
        
If the environment is unusable, then you may run

    juju destroy-environment --force

to forcefully destroy the environment. Upon doing so, review
your environment provider console for any resources that need
to be cleaned up.

`, c.envName)
		}()
		apiclient, err := juju.NewAPIClientFromName(c.envName)
		if err != nil {
			return fmt.Errorf("cannot connect to API: %v", err)
		}
		defer apiclient.Close()
		err = apiclient.DestroyEnvironment()
		if err != nil && !params.IsCodeNotImplemented(err) {
			return fmt.Errorf("destroying environment: %v", err)
		}
	}
	return environs.Destroy(environ, store)
}
Пример #7
0
func (*OpenSuite) TestDestroy(c *gc.C) {
	cfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(
		testing.Attrs{
			"state-server": false,
			"name":         "erewhemos",
		},
	))
	c.Assert(err, gc.IsNil)

	store := configstore.NewMem()
	// Prepare the environment and sanity-check that
	// the config storage info has been made.
	ctx := testing.Context(c)
	e, err := environs.Prepare(cfg, ctx, store)
	c.Assert(err, gc.IsNil)
	_, err = store.ReadInfo(e.Config().Name())
	c.Assert(err, gc.IsNil)

	err = environs.Destroy(e, store)
	c.Assert(err, gc.IsNil)

	// Check that the environment has actually been destroyed
	// and that the config info has been destroyed too.
	_, err = e.StateServerInstances()
	c.Assert(err, gc.ErrorMatches, "environment has been destroyed")
	_, err = store.ReadInfo(e.Config().Name())
	c.Assert(err, jc.Satisfies, errors.IsNotFound)
}
Пример #8
0
// Run implements Command.Run
func (c *destroyCommand) Run(ctx *cmd.Context) error {
	store, err := configstore.Default()
	if err != nil {
		return errors.Annotate(err, "cannot open controller info storage")
	}

	cfgInfo, err := store.ReadInfo(c.ModelName())
	if err != nil {
		return errors.Annotate(err, "cannot read controller info")
	}

	// Verify that we're destroying a controller
	apiEndpoint := cfgInfo.APIEndpoint()
	if apiEndpoint.ServerUUID != "" && apiEndpoint.ModelUUID != apiEndpoint.ServerUUID {
		return errors.Errorf("%q is not a controller; use juju model destroy to destroy it", c.ModelName())
	}

	if !c.assumeYes {
		if err = confirmDestruction(ctx, c.ModelName()); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.  If we can't, fail the destroy.  Users will
	// need to use the controller kill command if we can't connect.
	api, err := c.getControllerAPI()
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil)
	}
	defer api.Close()

	// Obtain bootstrap / controller environ information
	controllerEnviron, err := c.getControllerEnviron(cfgInfo, api)
	if err != nil {
		return errors.Annotate(err, "cannot obtain bootstrap information")
	}

	// Attempt to destroy the controller.
	err = api.DestroyController(c.destroyEnvs)
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy controller"), ctx, api)
	}

	ctx.Infof("Destroying controller %q", c.ModelName())
	if c.destroyEnvs {
		ctx.Infof("Waiting for hosted model resources to be reclaimed.")

		updateStatus := newTimedStatusUpdater(ctx, api, apiEndpoint.ModelUUID)
		for ctrStatus, envsStatus := updateStatus(0); hasUnDeadEnvirons(envsStatus); ctrStatus, envsStatus = updateStatus(2 * time.Second) {
			ctx.Infof(fmtCtrStatus(ctrStatus))
			for _, envStatus := range envsStatus {
				ctx.Verbosef(fmtEnvStatus(envStatus))
			}
		}

		ctx.Infof("All hosted models reclaimed, cleaning up controller machines")
	}
	return environs.Destroy(controllerEnviron, store)
}
Пример #9
0
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) {
	if !t.HasProvisioner {
		c.Skip("HasProvisioner is false; cannot test deployment")
	}

	current := version.Current
	other := current
	other.Series = "quantal"
	if current == other {
		other.Series = "precise"
	}

	dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{
		"state-server": false,
		"name":         "dummy storage",
	}))
	dummyenv, err := environs.Prepare(dummyCfg, coretesting.Context(c), configstore.NewMem())
	c.Assert(err, gc.IsNil)
	defer dummyenv.Destroy()

	t.Destroy(c)

	attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series})
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, gc.IsNil)
	env, err := environs.Prepare(cfg, coretesting.Context(c), t.ConfigStore)
	c.Assert(err, gc.IsNil)
	defer environs.Destroy(env, t.ConfigStore)

	currentName := envtools.StorageName(current)
	otherName := envtools.StorageName(other)
	envStorage := env.Storage()
	dummyStorage := dummyenv.Storage()

	defer envStorage.Remove(otherName)

	_, err = sync.Upload(dummyStorage, &current.Number)
	c.Assert(err, gc.IsNil)

	// This will only work while cross-compiling across releases is safe,
	// which depends on external elements. Tends to be safe for the last
	// few releases, but we may have to refactor some day.
	err = storageCopy(dummyStorage, currentName, envStorage, otherName)
	c.Assert(err, gc.IsNil)

	err = bootstrap.Bootstrap(coretesting.Context(c), env, environs.BootstrapParams{})
	c.Assert(err, gc.IsNil)

	st := t.Env.(testing.GetStater).GetStateInAPIServer()
	// Wait for machine agent to come up on the bootstrap
	// machine and ensure it deployed the proper series.
	m0, err := st.Machine("0")
	c.Assert(err, gc.IsNil)
	mw0 := newMachineToolWaiter(m0)
	defer mw0.Stop()

	waitAgentTools(c, mw0, other)
}
Пример #10
0
// destroyPreparedEnviron destroys the environment and logs an error if it fails.
func destroyPreparedEnviron(ctx *cmd.Context, env environs.Environ, store configstore.Storage, err *error, action string) {
	if *err == nil {
		return
	}
	ctx.Infof("%s failed, destroying environment", action)
	if err := environs.Destroy(env, store); err != nil {
		logger.Errorf("%s failed, and the environment could not be destroyed: %v", action, err)
	}
}
Пример #11
0
func (t *Tests) TestBootstrap(c *gc.C) {
	e := t.Prepare(c)
	t.UploadFakeTools(c, e.Storage())
	err := bootstrap.EnsureNotBootstrapped(e)
	c.Assert(err, gc.IsNil)
	err = bootstrap.Bootstrap(coretesting.Context(c), e, bootstrap.BootstrapParams{})
	c.Assert(err, gc.IsNil)

	stateServerInstances, err := e.StateServerInstances()
	c.Assert(err, gc.IsNil)
	c.Assert(stateServerInstances, gc.Not(gc.HasLen), 0)

	err = bootstrap.EnsureNotBootstrapped(e)
	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")

	e2 := t.Open(c)
	t.UploadFakeTools(c, e2.Storage())
	err = bootstrap.EnsureNotBootstrapped(e2)
	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")

	stateServerInstances2, err := e2.StateServerInstances()
	c.Assert(err, gc.IsNil)
	c.Assert(stateServerInstances2, gc.Not(gc.HasLen), 0)
	c.Assert(stateServerInstances2, jc.SameContents, stateServerInstances)

	err = environs.Destroy(e2, t.ConfigStore)
	c.Assert(err, gc.IsNil)

	// Prepare again because Destroy invalidates old environments.
	e3 := t.Prepare(c)
	t.UploadFakeTools(c, e3.Storage())

	err = bootstrap.EnsureNotBootstrapped(e3)
	c.Assert(err, gc.IsNil)
	err = bootstrap.Bootstrap(coretesting.Context(c), e3, bootstrap.BootstrapParams{})
	c.Assert(err, gc.IsNil)

	err = bootstrap.EnsureNotBootstrapped(e3)
	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")

	err = environs.Destroy(e3, t.ConfigStore)
	c.Assert(err, gc.IsNil)
}
Пример #12
0
func (t *LiveTests) Destroy(c *gc.C) {
	if t.Env == nil {
		return
	}
	err := environs.Destroy(t.Env, t.ConfigStore)
	c.Assert(err, gc.IsNil)
	t.bootstrapped = false
	t.prepared = false
	t.Env = nil
}
Пример #13
0
func (t *LiveTests) Destroy(c *gc.C) {
	if t.Env == nil {
		return
	}
	err := environs.Destroy(t.Env.Config().Name(), t.Env, t.ControllerStore)
	c.Assert(err, jc.ErrorIsNil)
	t.bootstrapped = false
	t.prepared = false
	t.Env = nil
}
Пример #14
0
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) {
	if !t.HasProvisioner {
		c.Skip("HasProvisioner is false; cannot test deployment")
	}

	current := version.Binary{
		Number: jujuversion.Current,
		Arch:   arch.HostArch(),
		Series: series.HostSeries(),
	}
	other := current
	other.Series = "quantal"
	if current == other {
		other.Series = "precise"
	}

	dummyCfg := dummy.SampleConfig().Merge(coretesting.Attrs{
		"controller": false,
		"name":       "dummy storage",
	})
	args := t.prepareForBootstrapParams(c)
	args.BaseConfig = dummyCfg
	dummyenv, err := environs.Prepare(envtesting.BootstrapContext(c),
		jujuclienttesting.NewMemStore(),
		args,
	)
	c.Assert(err, jc.ErrorIsNil)
	defer dummyenv.Destroy()

	t.Destroy(c)

	attrs := t.TestConfig.Merge(coretesting.Attrs{
		"name":           "livetests",
		"default-series": other.Series,
	})
	args.BaseConfig = attrs
	env, err := environs.Prepare(envtesting.BootstrapContext(c),
		t.ControllerStore,
		args)
	c.Assert(err, jc.ErrorIsNil)
	defer environs.Destroy("livetests", env, t.ControllerStore)

	err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{})
	c.Assert(err, jc.ErrorIsNil)

	st := t.Env.(jujutesting.GetStater).GetStateInAPIServer()
	// Wait for machine agent to come up on the bootstrap
	// machine and ensure it deployed the proper series.
	m0, err := st.Machine("0")
	c.Assert(err, jc.ErrorIsNil)
	mw0 := newMachineToolWaiter(m0)
	defer mw0.Stop()

	waitAgentTools(c, mw0, other)
}
Пример #15
0
func destroyPreparedEnvironProductionFunc(
	ctx *cmd.Context,
	env environs.Environ,
	store configstore.Storage,
	action string,
) {
	ctx.Infof("%s failed, destroying environment", action)
	if err := environs.Destroy(env, store); err != nil {
		logger.Errorf("the environment could not be destroyed: %v", err)
	}
}
Пример #16
0
// Run implements Command.Run
func (c *destroyCommand) Run(ctx *cmd.Context) error {
	store, err := configstore.Default()
	if err != nil {
		return errors.Annotate(err, "cannot open system info storage")
	}

	cfgInfo, err := store.ReadInfo(c.systemName)
	if err != nil {
		return errors.Annotate(err, "cannot read system info")
	}

	// Verify that we're destroying a system
	apiEndpoint := cfgInfo.APIEndpoint()
	if apiEndpoint.ServerUUID != "" && apiEndpoint.EnvironUUID != apiEndpoint.ServerUUID {
		return errors.Errorf("%q is not a system; use juju environment destroy to destroy it", c.systemName)
	}

	if !c.assumeYes {
		if err = confirmDestruction(ctx, c.systemName); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.  If we can't, fail the destroy.  Users will
	// need to use the system kill command if we can't connect.
	api, err := c.getSystemAPI()
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil)
	}
	defer api.Close()

	// Obtain bootstrap / system environ information
	systemEnviron, err := c.getSystemEnviron(cfgInfo, api)
	if err != nil {
		return errors.Annotate(err, "cannot obtain bootstrap information")
	}

	// Attempt to destroy the system.
	err = api.DestroySystem(c.destroyEnvs, false)
	if params.IsCodeNotImplemented(err) {
		// Fall back to using the client endpoint to destroy the system,
		// sending the info we were already able to collect.
		return c.destroySystemViaClient(ctx, cfgInfo, systemEnviron, store)
	}
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy system"), ctx, api)
	}

	return environs.Destroy(systemEnviron, store)
}
Пример #17
0
// destroyControllerViaClient attempts to destroy the controller using the client
// endpoint for older juju controllers which do not implement controller.DestroyController
func (c *destroyCommand) destroyControllerViaClient(ctx *cmd.Context, info configstore.EnvironInfo, controllerEnviron environs.Environ, store configstore.Storage) error {
	api, err := c.getClientAPI()
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil)
	}
	defer api.Close()

	err = api.DestroyEnvironment()
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy controller"), ctx, nil)
	}

	return environs.Destroy(controllerEnviron, store)
}
Пример #18
0
// Run implements Command.Run
func (c *destroyCommand) Run(ctx *cmd.Context) error {
	controllerName := c.ControllerName()
	store := c.ClientStore()
	controllerDetails, err := store.ControllerByName(controllerName)
	if err != nil {
		return errors.Annotate(err, "cannot read controller info")
	}

	if !c.assumeYes {
		if err = confirmDestruction(ctx, c.ControllerName()); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.  If we can't, fail the destroy.  Users will
	// need to use the controller kill command if we can't connect.
	api, err := c.getControllerAPI()
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil)
	}
	defer api.Close()

	// Obtain controller environ so we can clean up afterwards.
	controllerEnviron, err := c.getControllerEnviron(store, controllerName, api)
	if err != nil {
		return errors.Annotate(err, "getting controller environ")
	}

	// Attempt to destroy the controller.
	err = api.DestroyController(c.destroyModels)
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot destroy controller"), ctx, api)
	}

	ctx.Infof("Destroying controller %q", c.ControllerName())
	if c.destroyModels {
		ctx.Infof("Waiting for hosted model resources to be reclaimed.")

		updateStatus := newTimedStatusUpdater(ctx, api, controllerDetails.ControllerUUID)
		for ctrStatus, modelsStatus := updateStatus(0); hasUnDeadModels(modelsStatus); ctrStatus, modelsStatus = updateStatus(2 * time.Second) {
			ctx.Infof(fmtCtrStatus(ctrStatus))
			for _, model := range modelsStatus {
				ctx.Verbosef(fmtModelStatus(model))
			}
		}

		ctx.Infof("All hosted models reclaimed, cleaning up controller machines")
	}
	return environs.Destroy(c.ControllerName(), controllerEnviron, store)
}
Пример #19
0
// killSystemViaClient attempts to kill the system using the client
// endpoint for older juju systems which do not implement systemmanager.DestroySystem
func (c *killCommand) killSystemViaClient(ctx *cmd.Context, info configstore.EnvironInfo, systemEnviron environs.Environ, store configstore.Storage) error {
	api, err := c.getClientAPI()
	if err != nil {
		defer api.Close()
	}

	if api != nil {
		err = api.DestroyEnvironment()
		if err != nil {
			ctx.Infof("Unable to destroy system through the API: %s.  Destroying through provider.", err)
		}
	}

	return environs.Destroy(systemEnviron, store)
}
Пример #20
0
func (t *Tests) TestBootstrap(c *gc.C) {
	e := t.Prepare(c)
	t.UploadFakeTools(c, e.Storage())
	err := bootstrap.EnsureNotBootstrapped(e)
	c.Assert(err, gc.IsNil)
	err = bootstrap.Bootstrap(coretesting.Context(c), e, environs.BootstrapParams{})
	c.Assert(err, gc.IsNil)

	info, apiInfo, err := e.StateInfo()
	c.Check(info.Addrs, gc.Not(gc.HasLen), 0)
	c.Check(apiInfo.Addrs, gc.Not(gc.HasLen), 0)

	err = bootstrap.EnsureNotBootstrapped(e)
	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")

	e2 := t.Open(c)
	t.UploadFakeTools(c, e2.Storage())
	err = bootstrap.EnsureNotBootstrapped(e2)
	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")

	checkSameInfo := func(a, b *state.Info) {
		c.Check(a.Addrs, jc.SameContents, b.Addrs)
		c.Check(a.CACert, gc.DeepEquals, b.CACert)
	}

	info2, apiInfo2, err := e2.StateInfo()
	checkSameInfo(info2, info)

	c.Check(apiInfo2, gc.DeepEquals, apiInfo)

	err = environs.Destroy(e2, t.ConfigStore)
	c.Assert(err, gc.IsNil)

	// Prepare again because Destroy invalidates old environments.
	e3 := t.Prepare(c)
	t.UploadFakeTools(c, e3.Storage())

	err = bootstrap.EnsureNotBootstrapped(e3)
	c.Assert(err, gc.IsNil)
	err = bootstrap.Bootstrap(coretesting.Context(c), e3, environs.BootstrapParams{})
	c.Assert(err, gc.IsNil)

	err = bootstrap.EnsureNotBootstrapped(e3)
	c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
}
Пример #21
0
func (t *LiveTests) TestBootstrapWithDefaultSeries(c *gc.C) {
	if !t.HasProvisioner {
		c.Skip("HasProvisioner is false; cannot test deployment")
	}

	current := version.Current
	other := current
	other.Series = "quantal"
	if current == other {
		other.Series = "precise"
	}

	dummyCfg, err := config.New(config.NoDefaults, dummy.SampleConfig().Merge(coretesting.Attrs{
		"state-server": false,
		"name":         "dummy storage",
	}))
	dummyenv, err := environs.Prepare(dummyCfg, envtesting.BootstrapContext(c), configstore.NewMem())
	c.Assert(err, jc.ErrorIsNil)
	defer dummyenv.Destroy()

	t.Destroy(c)

	attrs := t.TestConfig.Merge(coretesting.Attrs{"default-series": other.Series})
	cfg, err := config.New(config.NoDefaults, attrs)
	c.Assert(err, jc.ErrorIsNil)
	env, err := environs.Prepare(cfg, envtesting.BootstrapContext(c), t.ConfigStore)
	c.Assert(err, jc.ErrorIsNil)
	defer environs.Destroy(env, t.ConfigStore)

	err = bootstrap.Bootstrap(envtesting.BootstrapContext(c), env, bootstrap.BootstrapParams{})
	c.Assert(err, jc.ErrorIsNil)

	st := t.Env.(jujutesting.GetStater).GetStateInAPIServer()
	// Wait for machine agent to come up on the bootstrap
	// machine and ensure it deployed the proper series.
	m0, err := st.Machine("0")
	c.Assert(err, jc.ErrorIsNil)
	mw0 := newMachineToolWaiter(m0)
	defer mw0.Stop()

	waitAgentTools(c, mw0, other)
}
Пример #22
0
// Run implements Command.Run
func (c *destroyCommand) Run(ctx *cmd.Context) error {
	controllerName := c.ControllerName()
	store := c.ClientStore()
	if !c.assumeYes {
		if err := confirmDestruction(ctx, c.ControllerName()); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.  If we can't, fail the destroy.  Users will
	// need to use the controller kill command if we can't connect.
	api, err := c.getControllerAPI()
	if err != nil {
		return c.ensureUserFriendlyErrorLog(errors.Annotate(err, "cannot connect to API"), ctx, nil)
	}
	defer api.Close()

	// Obtain controller environ so we can clean up afterwards.
	controllerEnviron, err := c.getControllerEnviron(ctx, store, controllerName, api)
	if err != nil {
		return errors.Annotate(err, "getting controller environ")
	}

	for {
		// Attempt to destroy the controller.
		ctx.Infof("Destroying controller")
		var hasHostedModels bool
		err = api.DestroyController(c.destroyModels)
		if err != nil {
			if params.IsCodeHasHostedModels(err) {
				hasHostedModels = true
			} else {
				return c.ensureUserFriendlyErrorLog(
					errors.Annotate(err, "cannot destroy controller"),
					ctx, api,
				)
			}
		}

		updateStatus := newTimedStatusUpdater(ctx, api, controllerEnviron.Config().UUID(), clock.WallClock)
		ctrStatus, modelsStatus := updateStatus(0)
		if !c.destroyModels {
			if err := c.checkNoAliveHostedModels(ctx, modelsStatus); err != nil {
				return errors.Trace(err)
			}
			if hasHostedModels && !hasUnDeadModels(modelsStatus) {
				// When we called DestroyController before, we were
				// informed that there were hosted models remaining.
				// When we checked just now, there were none. We should
				// try destroying again.
				continue
			}
		}

		// Even if we've not just requested for hosted models to be destroyed,
		// there may be some being destroyed already. We need to wait for them.
		ctx.Infof("Waiting for hosted model resources to be reclaimed")
		for ; hasUnDeadModels(modelsStatus); ctrStatus, modelsStatus = updateStatus(2 * time.Second) {
			ctx.Infof(fmtCtrStatus(ctrStatus))
			for _, model := range modelsStatus {
				ctx.Verbosef(fmtModelStatus(model))
			}
		}
		ctx.Infof("All hosted models reclaimed, cleaning up controller machines")
		return environs.Destroy(c.ControllerName(), controllerEnviron, store)
	}
}
Пример #23
0
// Run implements Command.Run
func (c *killCommand) Run(ctx *cmd.Context) error {
	store, err := configstore.Default()
	if err != nil {
		return errors.Annotate(err, "cannot open controller info storage")
	}

	cfgInfo, err := store.ReadInfo(c.ModelName())
	if err != nil {
		return errors.Annotate(err, "cannot read controller info")
	}

	// Verify that we're destroying a controller
	apiEndpoint := cfgInfo.APIEndpoint()
	if apiEndpoint.ServerUUID != "" && apiEndpoint.ModelUUID != apiEndpoint.ServerUUID {
		return errors.Errorf("%q is not a controller; use juju model destroy to destroy it", c.ModelName())
	}

	if !c.assumeYes {
		if err = confirmDestruction(ctx, c.ModelName()); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.
	api, err := c.getControllerAPI()
	switch {
	case err == nil:
		defer api.Close()
	case errors.Cause(err) == common.ErrPerm:
		return errors.Annotate(err, "cannot destroy controller")
	default:
		if errors.Cause(err) != modelcmd.ErrConnTimedOut {
			logger.Debugf("unable to open api: %s", err)
		}
		ctx.Infof("Unable to open API: %s\n", err)
		api = nil
	}

	// Obtain bootstrap / controller environ information
	controllerEnviron, err := c.getControllerEnviron(cfgInfo, api)
	if err != nil {
		return errors.Annotate(err, "cannot obtain bootstrap information")
	}

	// If we were unable to connect to the API, just destroy the controller through
	// the environs interface.
	if api == nil {
		ctx.Infof("Unable to connect to the API server. Destroying through provider.")
		return environs.Destroy(controllerEnviron, store)
	}

	// Attempt to destroy the controller and all environments.
	err = api.DestroyController(true)
	if err != nil {
		ctx.Infof("Unable to destroy controller through the API: %s.  Destroying through provider.", err)
		return environs.Destroy(controllerEnviron, store)
	}

	ctx.Infof("Destroying controller %q\nWaiting for resources to be reclaimed", c.ModelName())

	updateStatus := newTimedStatusUpdater(ctx, api, apiEndpoint.ModelUUID)
	for ctrStatus, envsStatus := updateStatus(0); hasUnDeadEnvirons(envsStatus); ctrStatus, envsStatus = updateStatus(2 * time.Second) {
		ctx.Infof(fmtCtrStatus(ctrStatus))
		for _, envStatus := range envsStatus {
			ctx.Verbosef(fmtEnvStatus(envStatus))
		}
	}

	ctx.Infof("All hosted models reclaimed, cleaning up controller machines")

	return environs.Destroy(controllerEnviron, store)
}
Пример #24
0
func (c *destroyEnvironmentCommand) Run(ctx *cmd.Context) (result error) {
	store, err := configstore.Default()
	if err != nil {
		return errors.Annotate(err, "cannot open environment info storage")
	}

	cfgInfo, err := store.ReadInfo(c.EnvName())
	if err != nil {
		return errors.Annotate(err, "cannot read environment info")
	}

	var hasBootstrapCfg bool
	var serverEnviron environs.Environ
	if bootstrapCfg := cfgInfo.BootstrapConfig(); bootstrapCfg != nil {
		hasBootstrapCfg = true
		serverEnviron, err = getServerEnv(bootstrapCfg)
		if err != nil {
			return errors.Trace(err)
		}
	}

	if c.force {
		if hasBootstrapCfg {
			// If --force is supplied on a server environment, then don't
			// attempt to use the API. This is necessary to destroy broken
			// environments, where the API server is inaccessible or faulty.
			return environs.Destroy(serverEnviron, store)
		} else {
			// Force only makes sense on the server environment.
			return errors.Errorf("cannot force destroy environment without bootstrap information")
		}
	}

	apiclient, err := c.NewAPIClient()
	if err != nil {
		if errors.IsNotFound(err) {
			logger.Warningf("environment not found, removing config file")
			ctx.Infof("environment not found, removing config file")
			return environs.DestroyInfo(c.EnvName(), store)
		}
		return errors.Annotate(err, "cannot connect to API")
	}
	defer apiclient.Close()
	info, err := apiclient.EnvironmentInfo()
	if err != nil {
		return errors.Annotate(err, "cannot get information for environment")
	}

	if !c.assumeYes {
		fmt.Fprintf(ctx.Stdout, destroyEnvMsg, c.EnvName(), info.ProviderType)

		scanner := bufio.NewScanner(ctx.Stdin)
		scanner.Scan()
		err := scanner.Err()
		if err != nil && err != io.EOF {
			return errors.Annotate(err, "environment destruction aborted")
		}
		answer := strings.ToLower(scanner.Text())
		if answer != "y" && answer != "yes" {
			return stderrors.New("environment destruction aborted")
		}
	}

	if info.UUID == info.ServerUUID {
		if !hasBootstrapCfg {
			// serverEnviron will be nil as we didn't have the jenv bootstrap
			// config to build it. But we do have a connection to the API
			// server, so get the config from there.
			bootstrapCfg, err := apiclient.EnvironmentGet()
			if err != nil {
				return errors.Annotate(err, "environment destruction failed")
			}
			serverEnviron, err = getServerEnv(bootstrapCfg)
			if err != nil {
				return errors.Annotate(err, "environment destruction failed")
			}
		}

		if err := c.destroyEnv(apiclient); err != nil {
			return errors.Annotate(err, "environment destruction failed")
		}
		if err := environs.Destroy(serverEnviron, store); err != nil {
			return errors.Annotate(err, "environment destruction failed")
		}
		return environs.DestroyInfo(c.EnvName(), store)
	}

	// If this is not the server environment, there is no bootstrap info and
	// we do not call Destroy on the provider. Destroying the environment via
	// the API and cleaning up the jenv file is sufficient.
	if err := c.destroyEnv(apiclient); err != nil {
		errors.Annotate(err, "cannot destroy environment")
	}
	return environs.DestroyInfo(c.EnvName(), store)
}
Пример #25
0
// Run implements Command.Run
func (c *killCommand) Run(ctx *cmd.Context) error {
	if c.apiDialerFunc == nil {
		c.apiDialerFunc = c.NewAPIRoot
	}

	store, err := configstore.Default()
	if err != nil {
		return errors.Annotate(err, "cannot open system info storage")
	}

	cfgInfo, err := store.ReadInfo(c.systemName)
	if err != nil {
		return errors.Annotate(err, "cannot read system info")
	}

	// Verify that we're destroying a system
	apiEndpoint := cfgInfo.APIEndpoint()
	if apiEndpoint.ServerUUID != "" && apiEndpoint.EnvironUUID != apiEndpoint.ServerUUID {
		return errors.Errorf("%q is not a system; use juju environment destroy to destroy it", c.systemName)
	}

	if !c.assumeYes {
		if err = confirmDestruction(ctx, c.systemName); err != nil {
			return err
		}
	}

	// Attempt to connect to the API.
	api, err := c.getSystemAPI(cfgInfo)
	switch {
	case err == nil:
		defer api.Close()
	case errors.Cause(err) == common.ErrPerm:
		return errors.Annotate(err, "cannot destroy system")
	default:
		if err != ErrConnTimedOut {
			logger.Debugf("unable to open api: %s", err)
		}
		ctx.Infof("Unable to open API: %s\n", err)
		api = nil
	}

	// Obtain bootstrap / system environ information
	systemEnviron, err := c.getSystemEnviron(cfgInfo, api)
	if err != nil {
		return errors.Annotate(err, "cannot obtain bootstrap information")
	}

	// If we were unable to connect to the API, just destroy the system through
	// the environs interface.
	if api == nil {
		return environs.Destroy(systemEnviron, store)
	}

	// Attempt to destroy the system with destroyEnvs and ignoreBlocks = true
	err = api.DestroySystem(true, true)
	if params.IsCodeNotImplemented(err) {
		// Fall back to using the client endpoint to destroy the system,
		// sending the info we were already able to collect.
		return c.killSystemViaClient(ctx, cfgInfo, systemEnviron, store)
	}

	if err != nil {
		ctx.Infof("Unable to destroy system through the API: %s.  Destroying through provider.", err)
	}

	return environs.Destroy(systemEnviron, store)
}