Example #1
0
func newEnviron(cloud environs.CloudSpec, cfg *config.Config) (*environ, error) {
	ecfg, err := newValidConfig(cfg, configDefaults)
	if err != nil {
		return nil, errors.Annotate(err, "invalid config")
	}

	client, err := newClient(cloud)
	if err != nil {
		return nil, errors.Annotatef(err, "failed to create new client")
	}

	namespace, err := instance.NewNamespace(cfg.UUID())
	if err != nil {
		return nil, errors.Trace(err)
	}

	env := &environ{
		name:      ecfg.Name(),
		cloud:     cloud,
		ecfg:      ecfg,
		client:    client,
		namespace: namespace,
	}
	return env, nil
}
Example #2
0
func newEnviron(spec environs.CloudSpec, cfg *config.Config, newRawProvider newRawProviderFunc) (*environ, error) {
	ecfg, err := newValidConfig(cfg)
	if err != nil {
		return nil, errors.Annotate(err, "invalid config")
	}

	namespace, err := instance.NewNamespace(cfg.UUID())
	if err != nil {
		return nil, errors.Trace(err)
	}

	raw, err := newRawProvider(spec)
	if err != nil {
		return nil, errors.Trace(err)
	}

	env := &environ{
		name:      ecfg.Name(),
		uuid:      ecfg.UUID(),
		raw:       raw,
		namespace: namespace,
		ecfg:      ecfg,
	}
	env.base = common.DefaultProvider{Env: env}

	//TODO(wwitzel3) make sure we are also cleaning up profiles during destroy
	if err := env.initProfile(); err != nil {
		return nil, errors.Trace(err)
	}

	return env, nil
}
Example #3
0
// decorateAndWriteInfo decorates the info struct with information
// from the given cfg, and the writes that out to the filesystem.
func decorateAndWriteInfo(info configstore.EnvironInfo, cfg *config.Config) error {

	// Sanity check our config.
	var endpoint configstore.APIEndpoint
	if cert, ok := cfg.CACert(); !ok {
		return errors.Errorf("CACert is not set")
	} else if uuid, ok := cfg.UUID(); !ok {
		return errors.Errorf("UUID is not set")
	} else if adminSecret := cfg.AdminSecret(); adminSecret == "" {
		return errors.Errorf("admin-secret is not set")
	} else {
		endpoint = configstore.APIEndpoint{
			CACert:    cert,
			ModelUUID: uuid,
		}
	}

	creds := configstore.APICredentials{
		User:     configstore.DefaultAdminUsername,
		Password: cfg.AdminSecret(),
	}
	endpoint.ServerUUID = endpoint.ModelUUID
	info.SetAPICredentials(creds)
	info.SetAPIEndpoint(endpoint)
	info.SetBootstrapConfig(cfg.AllAttrs())

	if err := info.Write(); err != nil {
		return errors.Annotatef(err, "cannot create model info %q", cfg.Name())
	}

	return nil
}
Example #4
0
File: open.go Project: zhouqt/juju
// decorateAndWriteInfo decorates the info struct with information
// from the given cfg, and the writes that out to the filesystem.
func decorateAndWriteInfo(info configstore.EnvironInfo, cfg *config.Config) error {

	// Sanity check our config.
	var endpoint configstore.APIEndpoint
	if cert, ok := cfg.CACert(); !ok {
		return errors.Errorf("CACert is not set")
	} else if uuid, ok := cfg.UUID(); !ok {
		return errors.Errorf("UUID is not set")
	} else if adminSecret := cfg.AdminSecret(); adminSecret == "" {
		return errors.Errorf("admin-secret is not set")
	} else {
		endpoint = configstore.APIEndpoint{
			CACert:      cert,
			EnvironUUID: uuid,
		}
	}

	creds := configstore.APICredentials{
		User:     "******", // TODO(waigani) admin@local once we have that set
		Password: cfg.AdminSecret(),
	}
	info.SetAPICredentials(creds)
	info.SetAPIEndpoint(endpoint)
	info.SetBootstrapConfig(cfg.AllAttrs())

	if err := info.Write(); err != nil {
		return errors.Annotatef(err, "cannot create environment info %q", cfg.Name())
	}

	return nil
}
Example #5
0
// InstanceTags returns the minimum set of tags that should be set on a
// machine instance, if the provider supports them.
func InstanceTags(cfg *config.Config, jobs []multiwatcher.MachineJob) map[string]string {
	instanceTags := tags.ResourceTags(names.NewModelTag(cfg.UUID()), cfg)
	if multiwatcher.AnyJobNeedsState(jobs...) {
		instanceTags[tags.JujuController] = "true"
	}
	return instanceTags
}
Example #6
0
// NewModel creates a new model with its own UUID and
// prepares it for use. Model and State instances for the new
// model are returned.
//
// The controller model's UUID is attached to the new
// model's document. Having the server UUIDs stored with each
// model document means that we have a way to represent external
// models, perhaps for future use around cross model
// relations.
func (st *State) NewModel(cfg *config.Config, owner names.UserTag) (_ *Model, _ *State, err error) {
	if owner.IsLocal() {
		if _, err := st.User(owner); err != nil {
			return nil, nil, errors.Annotate(err, "cannot create model")
		}
	}

	ssEnv, err := st.ControllerModel()
	if err != nil {
		return nil, nil, errors.Annotate(err, "could not load controller model")
	}

	uuid := cfg.UUID()
	newState, err := st.ForModel(names.NewModelTag(uuid))
	if err != nil {
		return nil, nil, errors.Annotate(err, "could not create state for new model")
	}
	defer func() {
		if err != nil {
			newState.Close()
		}
	}()

	ops, err := newState.envSetupOps(cfg, uuid, ssEnv.UUID(), owner)
	if err != nil {
		return nil, nil, errors.Annotate(err, "failed to create new model")
	}
	err = newState.runTransaction(ops)
	if err == txn.ErrAborted {

		// We have a  unique key restriction on the "owner" and "name" fields,
		// which will cause the insert to fail if there is another record with
		// the same "owner" and "name" in the collection. If the txn is
		// aborted, check if it is due to the unique key restriction.
		models, closer := st.getCollection(modelsC)
		defer closer()
		envCount, countErr := models.Find(bson.D{
			{"owner", owner.Canonical()},
			{"name", cfg.Name()}},
		).Count()
		if countErr != nil {
			err = errors.Trace(countErr)
		} else if envCount > 0 {
			err = errors.AlreadyExistsf("model %q for %s", cfg.Name(), owner.Canonical())
		} else {
			err = errors.New("model already exists")
		}
	}
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	newEnv, err := newState.Model()
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return newEnv, newState, nil
}
Example #7
0
// InstanceTags returns the minimum set of tags that should be set on a
// machine instance, if the provider supports them.
func InstanceTags(cfg *config.Config, jobs []multiwatcher.MachineJob) map[string]string {
	uuid, _ := cfg.UUID()
	instanceTags := tags.ResourceTags(names.NewEnvironTag(uuid), cfg)
	if multiwatcher.AnyJobNeedsState(jobs...) {
		instanceTags[tags.JujuStateServer] = "true"
	}
	return instanceTags
}
Example #8
0
File: open.go Project: kapilt/juju
// Initialize sets up an initial empty state and returns it.
// This needs to be performed only once for a given environment.
// It returns unauthorizedError if access is unauthorized.
func Initialize(info *mongo.MongoInfo, cfg *config.Config, opts mongo.DialOpts, policy Policy) (rst *State, err error) {
	st, err := open(info, opts, policy)
	if err != nil {
		return nil, err
	}
	defer func() {
		if err != nil {
			st.Close()
		}
	}()
	// A valid environment is used as a signal that the
	// state has already been initalized. If this is the case
	// do nothing.
	if _, err := st.Environment(); err == nil {
		return st, nil
	} else if !errors.IsNotFound(err) {
		return nil, err
	}
	logger.Infof("initializing environment")
	if err := checkEnvironConfig(cfg); err != nil {
		return nil, err
	}
	uuid, ok := cfg.UUID()
	if !ok {
		return nil, errors.Errorf("environment uuid was not supplied")
	}
	st.environTag = names.NewEnvironTag(uuid)
	ops := []txn.Op{
		createConstraintsOp(st, environGlobalKey, constraints.Value{}),
		createSettingsOp(st, environGlobalKey, cfg.AllAttrs()),
		createEnvironmentOp(st, cfg.Name(), uuid),
		{
			C:      stateServersC,
			Id:     environGlobalKey,
			Assert: txn.DocMissing,
			Insert: &stateServersDoc{
				EnvUUID: uuid,
			},
		}, {
			C:      stateServersC,
			Id:     apiHostPortsKey,
			Assert: txn.DocMissing,
			Insert: &apiHostPortsDoc{},
		}, {
			C:      stateServersC,
			Id:     stateServingInfoKey,
			Assert: txn.DocMissing,
			Insert: &params.StateServingInfo{},
		},
	}
	if err := st.runTransaction(ops); err == txn.ErrAborted {
		// The config was created in the meantime.
		return st, nil
	} else if err != nil {
		return nil, err
	}
	return st, nil
}
Example #9
0
// PrepareForCreateEnvironment is specified in the EnvironProvider interface.
func (p maasEnvironProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) {
	attrs := cfg.UnknownAttrs()
	oldName, found := attrs["maas-agent-name"]
	if found && oldName != "" {
		return nil, errAgentNameAlreadySet
	}
	attrs["maas-agent-name"] = cfg.UUID()
	return cfg.Apply(attrs)
}
Example #10
0
func (s *BaseSuiteUnpatched) setConfig(c *gc.C, cfg *config.Config) {
	s.Config = cfg
	ecfg, err := newValidConfig(cfg, configDefaults)
	c.Assert(err, jc.ErrorIsNil)
	s.EnvConfig = ecfg
	uuid, _ := cfg.UUID()
	s.Env.uuid = uuid
	s.Env.ecfg = s.EnvConfig
	s.Prefix = "juju-" + uuid + "-"
}
Example #11
0
// resourceGroupName returns the name of the environment's resource group.
func resourceGroupName(cfg *config.Config) string {
	uuid, _ := cfg.UUID()
	// UUID is always available for azure environments, since the (new)
	// provider was introduced after environment UUIDs.
	modelTag := names.NewModelTag(uuid)
	return fmt.Sprintf(
		"juju-%s-%s", cfg.Name(),
		resourceName(modelTag),
	)
}
Example #12
0
// storageTags returns the tags that should be set on a volume or filesystem,
// if the provider supports them.
func storageTags(
	storageInstance state.StorageInstance,
	cfg *config.Config,
) (map[string]string, error) {
	storageTags := tags.ResourceTags(names.NewModelTag(cfg.UUID()), cfg)
	if storageInstance != nil {
		storageTags[tags.JujuStorageInstance] = storageInstance.Tag().Id()
		storageTags[tags.JujuStorageOwner] = storageInstance.Owner().Id()
	}
	return storageTags, nil
}
Example #13
0
// newEnviron creates a new azureEnviron.
func newEnviron(provider *azureEnvironProvider, cfg *config.Config) (*azureEnviron, error) {
	env := azureEnviron{provider: provider}
	err := env.SetConfig(cfg)
	if err != nil {
		return nil, err
	}
	modelTag := names.NewModelTag(cfg.UUID())
	env.resourceGroup = resourceGroupName(modelTag, cfg.Name())
	env.envName = cfg.Name()
	return &env, nil
}
Example #14
0
File: ebs.go Project: xushiwei/juju
// VolumeSource is defined on the Provider interface.
func (e *ebsProvider) VolumeSource(environConfig *config.Config, cfg *storage.Config) (storage.VolumeSource, error) {
	ec2, _, _, err := awsClients(environConfig)
	if err != nil {
		return nil, errors.Annotate(err, "creating AWS clients")
	}
	source := &ebsVolumeSource{
		ec2:       ec2,
		envName:   environConfig.Name(),
		modelUUID: environConfig.UUID(),
	}
	return source, nil
}
Example #15
0
File: open.go Project: kapilt/juju
// Prepare prepares a new environment based on the provided configuration.
// If the environment is already prepared, it behaves like New.
func Prepare(cfg *config.Config, ctx BootstrapContext, store configstore.Storage) (Environ, error) {
	p, err := Provider(cfg.Type())
	if err != nil {
		return nil, err
	}
	info, err := store.ReadInfo(cfg.Name())
	if errors.IsNotFound(errors.Cause(err)) {
		info = store.CreateInfo(cfg.Name())
		env, err := prepare(ctx, cfg, info, p)
		if err != nil {
			if err := info.Destroy(); err != nil {
				logger.Warningf("cannot destroy newly created environment info: %v", err)
			}
			return nil, err
		}
		cfg = env.Config()
		creds := configstore.APICredentials{
			User:     "******", // TODO(waigani) admin@local once we have that set
			Password: cfg.AdminSecret(),
		}
		info.SetAPICredentials(creds)
		endpoint := configstore.APIEndpoint{}
		var ok bool
		endpoint.CACert, ok = cfg.CACert()
		if !ok {
			return nil, errors.Errorf("CACert is not set")
		}
		endpoint.EnvironUUID, ok = cfg.UUID()
		if !ok {
			return nil, errors.Errorf("CACert is not set")
		}
		info.SetAPIEndpoint(endpoint)
		info.SetBootstrapConfig(env.Config().AllAttrs())
		if err := info.Write(); err != nil {
			return nil, errors.Annotatef(err, "cannot create environment info %q", env.Config().Name())
		}
		return env, nil
	}
	if err != nil {
		return nil, errors.Annotatef(err, "error reading environment info %q", cfg.Name())
	}
	if !info.Initialized() {
		return nil, errors.Errorf("found uninitialized environment info for %q; environment preparation probably in progress or interrupted", cfg.Name())
	}
	if len(info.BootstrapConfig()) == 0 {
		return nil, errors.New("found environment info but no bootstrap config")
	}
	cfg, err = config.New(config.NoDefaults, info.BootstrapConfig())
	if err != nil {
		return nil, errors.Annotate(err, "cannot parse bootstrap config")
	}
	return New(cfg)
}
Example #16
0
func (s *BaseSuiteUnpatched) setConfig(c *gc.C, cfg *config.Config) {
	s.Config = cfg
	ecfg, err := newConfig(cfg, nil)
	c.Assert(err, jc.ErrorIsNil)
	s.EnvConfig = ecfg
	uuid := cfg.UUID()
	s.Env.uuid = uuid
	s.Env.ecfg = s.EnvConfig
	namespace, err := instance.NewNamespace(uuid)
	c.Assert(err, jc.ErrorIsNil)
	s.Env.namespace = namespace
}
Example #17
0
File: open.go Project: zhouqt/juju
// ensureUUID generates a new uuid and attaches it to
// the given environment configuration, unless the
// configuration already has one.
func ensureUUID(cfg *config.Config) (*config.Config, error) {
	_, hasUUID := cfg.UUID()
	if hasUUID {
		return cfg, nil
	}
	uuid, err := utils.NewUUID()
	if err != nil {
		return nil, errors.Trace(err)
	}
	return cfg.Apply(map[string]interface{}{
		"uuid": uuid.String(),
	})
}
Example #18
0
func (g *storageProvider) VolumeSource(environConfig *config.Config, cfg *storage.Config) (storage.VolumeSource, error) {
	// Connect and authenticate.
	env, err := newEnviron(environConfig)
	if err != nil {
		return nil, errors.Annotate(err, "cannot create an environ with this config")
	}

	source := &volumeSource{
		gce:       env.gce,
		envName:   environConfig.Name(),
		modelUUID: environConfig.UUID(),
	}
	return source, nil
}
Example #19
0
// VolumeSource implements storage.Provider.
func (p *cinderProvider) VolumeSource(environConfig *config.Config, providerConfig *storage.Config) (storage.VolumeSource, error) {
	if err := p.ValidateConfig(providerConfig); err != nil {
		return nil, err
	}
	storageAdapter, err := p.newStorageAdapter(environConfig)
	if err != nil {
		return nil, err
	}
	source := &cinderVolumeSource{
		storageAdapter: storageAdapter,
		envName:        environConfig.Name(),
		modelUUID:      environConfig.UUID(),
	}
	return source, nil
}
Example #20
0
// VolumeSource is defined on the Provider interface.
func (e *ebsProvider) VolumeSource(environConfig *config.Config, cfg *storage.Config) (storage.VolumeSource, error) {
	ec2, _, _, err := awsClients(environConfig)
	if err != nil {
		return nil, errors.Annotate(err, "creating AWS clients")
	}
	uuid, ok := environConfig.UUID()
	if !ok {
		return nil, errors.NotFoundf("environment UUID")
	}
	source := &ebsVolumeSource{
		ec2:     ec2,
		envName: environConfig.Name(),
		envUUID: uuid,
	}
	return source, nil
}
Example #21
0
// VolumeSource is defined on the Provider interface.
func (e *azureStorageProvider) VolumeSource(environConfig *config.Config, cfg *storage.Config) (storage.VolumeSource, error) {
	env, err := NewEnviron(environConfig)
	if err != nil {
		return nil, errors.Trace(err)
	}
	uuid, ok := environConfig.UUID()
	if !ok {
		return nil, errors.NotFoundf("environment UUID")
	}
	source := &azureVolumeSource{
		env:     env,
		envName: environConfig.Name(),
		envUUID: uuid,
	}
	return source, nil
}
Example #22
0
func newEnviron(cloud environs.CloudSpec, cfg *config.Config) (*environ, error) {
	ecfg, err := newConfig(cfg, nil)
	if err != nil {
		return nil, errors.Annotate(err, "invalid config")
	}

	credAttrs := cloud.Credential.Attributes()
	if cloud.Credential.AuthType() == jujucloud.JSONFileAuthType {
		contents := credAttrs[credAttrFile]
		credential, err := parseJSONAuthFile(strings.NewReader(contents))
		if err != nil {
			return nil, errors.Trace(err)
		}
		credAttrs = credential.Attributes()
	}

	credential := &google.Credentials{
		ClientID:    credAttrs[credAttrClientID],
		ProjectID:   credAttrs[credAttrProjectID],
		ClientEmail: credAttrs[credAttrClientEmail],
		PrivateKey:  []byte(credAttrs[credAttrPrivateKey]),
	}
	connectionConfig := google.ConnectionConfig{
		Region:    cloud.Region,
		ProjectID: credential.ProjectID,
	}

	// Connect and authenticate.
	conn, err := newConnection(connectionConfig, credential)
	if err != nil {
		return nil, errors.Trace(err)
	}
	namespace, err := instance.NewNamespace(cfg.UUID())
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &environ{
		name:      ecfg.config.Name(),
		uuid:      ecfg.config.UUID(),
		cloud:     cloud,
		ecfg:      ecfg,
		gce:       conn,
		namespace: namespace,
	}, nil
}
Example #23
0
File: environ.go Project: bac/juju
// newEnviron creates a new azureEnviron.
func newEnviron(
	provider *azureEnvironProvider,
	cloud environs.CloudSpec,
	cfg *config.Config,
) (*azureEnviron, error) {

	// The Azure storage code wants the endpoint host only, not the URL.
	storageEndpointURL, err := url.Parse(cloud.StorageEndpoint)
	if err != nil {
		return nil, errors.Annotate(err, "parsing storage endpoint URL")
	}

	env := azureEnviron{
		provider:        provider,
		cloud:           cloud,
		location:        canonicalLocation(cloud.Region),
		storageEndpoint: storageEndpointURL.Host,
	}
	if err := env.initEnviron(); err != nil {
		return nil, errors.Trace(err)
	}

	if err := env.SetConfig(cfg); err != nil {
		return nil, errors.Trace(err)
	}

	modelTag := names.NewModelTag(cfg.UUID())
	env.resourceGroup = resourceGroupName(modelTag, cfg.Name())
	env.envName = cfg.Name()

	// We need a deterministic storage account name, so that we can
	// defer creation of the storage account to the VM deployment,
	// and retain the ability to create multiple deployments in
	// parallel.
	//
	// We use the last 20 non-hyphen hex characters of the model's
	// UUID as the storage account name, prefixed with "juju". The
	// probability of clashing with another storage account should
	// be negligible.
	uuidAlphaNumeric := strings.Replace(env.config.Config.UUID(), "-", "", -1)
	env.storageAccountName = "juju" + uuidAlphaNumeric[len(uuidAlphaNumeric)-20:]

	return &env, nil
}
Example #24
0
// VolumeSource implements storage.Provider.
func (p *cinderProvider) VolumeSource(environConfig *config.Config, providerConfig *storage.Config) (storage.VolumeSource, error) {
	if err := p.ValidateConfig(providerConfig); err != nil {
		return nil, err
	}
	storageAdapter, err := p.newStorageAdapter(environConfig)
	if err != nil {
		return nil, err
	}
	uuid, ok := environConfig.UUID()
	if !ok {
		return nil, errors.NotFoundf("environment UUID")
	}
	source := &cinderVolumeSource{
		storageAdapter: storageAdapter,
		envName:        environConfig.Name(),
		envUUID:        uuid,
	}
	return source, nil
}
Example #25
0
func (g *storageProvider) VolumeSource(environConfig *config.Config, cfg *storage.Config) (storage.VolumeSource, error) {
	uuid, ok := environConfig.UUID()
	if !ok {
		return nil, errors.NotFoundf("environment UUID")
	}

	// Connect and authenticate.
	env, err := newEnviron(environConfig)
	if err != nil {
		return nil, errors.Annotate(err, "cannot create an environ with this config")
	}

	source := &volumeSource{
		gce:     env.gce,
		envName: environConfig.Name(),
		envUUID: uuid,
	}
	return source, nil
}
Example #26
0
// ensureCertificate generates a new CA certificate and
// attaches it to the given controller configuration,
// unless the configuration already has one.
func ensureCertificate(cfg *config.Config) (*config.Config, string, error) {
	caCert, hasCACert := cfg.CACert()
	_, hasCAKey := cfg.CAPrivateKey()
	if hasCACert && hasCAKey {
		return cfg, caCert, nil
	}
	if hasCACert && !hasCAKey {
		return nil, "", errors.Errorf("controller configuration with a certificate but no CA private key")
	}

	caCert, caKey, err := cert.NewCA(cfg.Name(), cfg.UUID(), time.Now().UTC().AddDate(10, 0, 0))
	if err != nil {
		return nil, "", errors.Trace(err)
	}
	cfg, err = cfg.Apply(map[string]interface{}{
		config.CACertKey: string(caCert),
		"ca-private-key": string(caKey),
	})
	if err != nil {
		return nil, "", errors.Trace(err)
	}
	return cfg, string(caCert), nil
}
Example #27
0
// FinishInstanceConfig sets fields on a InstanceConfig that can be determined by
// inspecting a plain config.Config and the machine constraints at the last
// moment before bootstrapping. It assumes that the supplied Config comes from
// an environment that has passed through all the validation checks in the
// Bootstrap func, and that has set an agent-version (via finding the tools to,
// use for bootstrap, or otherwise).
// TODO(fwereade) This function is not meant to be "good" in any serious way:
// it is better that this functionality be collected in one place here than
// that it be spread out across 3 or 4 providers, but this is its only
// redeeming feature.
func FinishInstanceConfig(icfg *InstanceConfig, cfg *config.Config) (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot complete machine configuration")

	if err := PopulateInstanceConfig(
		icfg,
		cfg.Type(),
		cfg.AuthorizedKeys(),
		cfg.SSLHostnameVerification(),
		cfg.ProxySettings(),
		cfg.AptProxySettings(),
		cfg.AptMirror(),
		cfg.PreferIPv6(),
		cfg.EnableOSRefreshUpdate(),
		cfg.EnableOSUpgrade(),
	); err != nil {
		return errors.Trace(err)
	}

	if isStateInstanceConfig(icfg) {
		// Add NUMACTL preference. Needed to work for both bootstrap and high availability
		// Only makes sense for controller
		logger.Debugf("Setting numa ctl preference to %v", cfg.NumaCtlPreference())
		// Unfortunately, AgentEnvironment can only take strings as values
		icfg.AgentEnvironment[agent.NumaCtlPreference] = fmt.Sprintf("%v", cfg.NumaCtlPreference())
	}
	// The following settings are only appropriate at bootstrap time. At the
	// moment, the only controller is the bootstrap node, but this
	// will probably change.
	if !icfg.Bootstrap {
		return nil
	}
	if icfg.APIInfo != nil || icfg.MongoInfo != nil {
		return errors.New("machine configuration already has api/state info")
	}
	caCert, hasCACert := cfg.CACert()
	if !hasCACert {
		return errors.New("model configuration has no ca-cert")
	}
	password := cfg.AdminSecret()
	if password == "" {
		return errors.New("model configuration has no admin-secret")
	}
	icfg.APIInfo = &api.Info{
		Password: password,
		CACert:   caCert,
		ModelTag: names.NewModelTag(cfg.UUID()),
	}
	icfg.MongoInfo = &mongo.MongoInfo{Password: password, Info: mongo.Info{CACert: caCert}}

	// These really are directly relevant to running a controller.
	// Initially, generate a controller certificate with no host IP
	// addresses in the SAN field. Once the controller is up and the
	// NIC addresses become known, the certificate can be regenerated.
	cert, key, err := cfg.GenerateControllerCertAndKey(nil)
	if err != nil {
		return errors.Annotate(err, "cannot generate controller certificate")
	}
	caPrivateKey, hasCAPrivateKey := cfg.CAPrivateKey()
	if !hasCAPrivateKey {
		return errors.New("model configuration has no ca-private-key")
	}
	srvInfo := params.StateServingInfo{
		StatePort:    cfg.StatePort(),
		APIPort:      cfg.APIPort(),
		Cert:         string(cert),
		PrivateKey:   string(key),
		CAPrivateKey: caPrivateKey,
	}
	icfg.StateServingInfo = &srvInfo
	if icfg.Config, err = bootstrapConfig(cfg); err != nil {
		return errors.Trace(err)
	}

	return nil
}
Example #28
0
// NewEnvironment creates a new environment with its own UUID and
// prepares it for use. Environment and State instances for the new
// environment are returned.
//
// The state server environment's UUID is attached to the new
// environment's document. Having the server UUIDs stored with each
// environment document means that we have a way to represent external
// environments, perhaps for future use around cross environment
// relations.
func (st *State) NewEnvironment(cfg *config.Config, owner names.UserTag) (_ *Environment, _ *State, err error) {
	if owner.IsLocal() {
		if _, err := st.User(owner); err != nil {
			return nil, nil, errors.Annotate(err, "cannot create environment")
		}
	}

	ssEnv, err := st.StateServerEnvironment()
	if err != nil {
		return nil, nil, errors.Annotate(err, "could not load state server environment")
	}

	uuid, ok := cfg.UUID()
	if !ok {
		return nil, nil, errors.Errorf("environment uuid was not supplied")
	}
	newState, err := st.ForEnviron(names.NewEnvironTag(uuid))
	if err != nil {
		return nil, nil, errors.Annotate(err, "could not create state for new environment")
	}
	defer func() {
		if err != nil {
			newState.Close()
		}
	}()

	ops, err := newState.envSetupOps(cfg, uuid, ssEnv.UUID(), owner)
	if err != nil {
		return nil, nil, errors.Annotate(err, "failed to create new environment")
	}
	err = newState.runTransactionNoEnvAliveAssert(ops)
	if err == txn.ErrAborted {

		// We have a  unique key restriction on the "owner" and "name" fields,
		// which will cause the insert to fail if there is another record with
		// the same "owner" and "name" in the collection. If the txn is
		// aborted, check if it is due to the unique key restriction.
		environments, closer := st.getCollection(environmentsC)
		defer closer()
		envCount, countErr := environments.Find(bson.D{
			{"owner", owner.Username()},
			{"name", cfg.Name()}},
		).Count()
		if countErr != nil {
			err = errors.Trace(countErr)
		} else if envCount > 0 {
			err = errors.AlreadyExistsf("environment %q for %s", cfg.Name(), owner.Username())
		} else {
			err = errors.New("environment already exists")
		}
	}
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	newEnv, err := newState.Environment()
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	return newEnv, newState, nil
}
Example #29
0
File: open.go Project: imoapps/juju
// Initialize sets up an initial empty state and returns it.
// This needs to be performed only once for the initial state server environment.
// It returns unauthorizedError if access is unauthorized.
func Initialize(owner names.UserTag, info *mongo.MongoInfo, cfg *config.Config, opts mongo.DialOpts, policy Policy) (_ *State, err error) {
	uuid, ok := cfg.UUID()
	if !ok {
		return nil, errors.Errorf("environment uuid was not supplied")
	}
	envTag := names.NewEnvironTag(uuid)
	st, err := open(envTag, info, opts, policy)
	if err != nil {
		return nil, errors.Trace(err)
	}
	defer func() {
		if err != nil {
			if closeErr := st.Close(); closeErr != nil {
				logger.Errorf("error closing state while aborting Initialize: %v", closeErr)
			}
		}
	}()

	// A valid environment is used as a signal that the
	// state has already been initalized. If this is the case
	// do nothing.
	if _, err := st.Environment(); err == nil {
		return nil, errors.New("already initialized")
	} else if !errors.IsNotFound(err) {
		return nil, errors.Trace(err)
	}

	// When creating the state server environment, the new environment
	// UUID is also used as the state server UUID.
	logger.Infof("initializing state server environment %s", uuid)
	ops, err := st.envSetupOps(cfg, uuid, uuid, owner)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ops = append(ops,
		createInitialUserOp(st, owner, info.Password),
		txn.Op{
			C:      stateServersC,
			Id:     environGlobalKey,
			Assert: txn.DocMissing,
			Insert: &stateServersDoc{
				EnvUUID: st.EnvironUUID(),
			},
		},
		txn.Op{
			C:      stateServersC,
			Id:     apiHostPortsKey,
			Assert: txn.DocMissing,
			Insert: &apiHostPortsDoc{},
		},
		txn.Op{
			C:      stateServersC,
			Id:     stateServingInfoKey,
			Assert: txn.DocMissing,
			Insert: &StateServingInfo{},
		},
		txn.Op{
			C:      stateServersC,
			Id:     hostedEnvCountKey,
			Assert: txn.DocMissing,
			Insert: &hostedEnvCountDoc{},
		},
	)

	if err := st.runTransaction(ops); err != nil {
		return nil, errors.Trace(err)
	}
	if err := st.start(envTag); err != nil {
		return nil, errors.Trace(err)
	}
	return st, nil
}
Example #30
0
// MigrationConfigUpdate implements MigrationConfigUpdater.
func (*environ) MigrationConfigUpdate(controllerConfig *config.Config) map[string]interface{} {
	return map[string]interface{}{
		"controller-uuid": controllerConfig.UUID(),
	}
}