func destroyEnvironment(st *state.State, environTag names.EnvironTag, destroyHostedEnvirons bool) error { var err error if environTag != st.EnvironTag() { if st, err = st.ForEnviron(environTag); err != nil { return errors.Trace(err) } defer st.Close() } if destroyHostedEnvirons { envs, err := st.AllEnvironments() if err != nil { return errors.Trace(err) } for _, env := range envs { envSt, err := st.ForEnviron(env.EnvironTag()) defer envSt.Close() if err != nil { return errors.Trace(err) } check := NewBlockChecker(envSt) if err = check.DestroyAllowed(); err != nil { return errors.Trace(err) } } } else { check := NewBlockChecker(st) if err = check.DestroyAllowed(); err != nil { return errors.Trace(err) } } env, err := st.Environment() if err != nil { return errors.Trace(err) } if destroyHostedEnvirons { if err := env.DestroyIncludingHosted(); err != nil { return err } } else { if err = env.Destroy(); err != nil { return errors.Trace(err) } } err = sendMetrics(st) if err != nil { logger.Warningf("failed to send leftover metrics: %v", err) } // Return to the caller. If it's the CLI, it will finish up by calling the // provider's Destroy method, which will destroy the state servers, any // straggler instances, and other provider-specific resources. Once all // resources are torn down, the Undertaker worker handles the removal of // the environment. return nil }
func assertEnvHasBlock(c *gc.C, st *state.State, t state.BlockType, msg string) { dBlock, found, err := st.GetBlockForType(t) c.Assert(err, jc.ErrorIsNil) c.Assert(found, jc.IsTrue) c.Assert(dBlock, gc.NotNil) c.Assert(dBlock.Type(), gc.DeepEquals, t) tag, err := dBlock.Tag() c.Assert(err, jc.ErrorIsNil) c.Assert(tag, gc.DeepEquals, st.EnvironTag()) c.Assert(dBlock.Message(), gc.DeepEquals, msg) }
// DestroyEnvironment destroys all services and non-manager machine // instances in the specified environment. This function assumes that all // necessary authentication checks have been done. func DestroyEnvironment(st *state.State, environTag names.EnvironTag) error { var err error if environTag != st.EnvironTag() { if st, err = st.ForEnviron(environTag); err != nil { return errors.Trace(err) } defer st.Close() } check := NewBlockChecker(st) if err = check.DestroyAllowed(); err != nil { return errors.Trace(err) } env, err := st.Environment() if err != nil { return errors.Trace(err) } if err = env.Destroy(); err != nil { return errors.Trace(err) } machines, err := st.AllMachines() if err != nil { return errors.Trace(err) } err = sendMetrics(st) if err != nil { logger.Warningf("failed to send leftover metrics: %v", err) } // We must destroy instances server-side to support JES (Juju Environment // Server), as there's no CLI to fall back on. In that case, we only ever // destroy non-state machines; we leave destroying state servers in non- // hosted environments to the CLI, as otherwise the API server may get cut // off. if err := destroyNonManagerMachines(st, machines); err != nil { return errors.Trace(err) } // If this is not the state server environment, remove all documents from // state associated with the environment. if env.EnvironTag() != env.ServerTag() { return errors.Trace(st.RemoveAllEnvironDocs()) } // Return to the caller. If it's the CLI, it will finish up // by calling the provider's Destroy method, which will // destroy the state servers, any straggler instances, and // other provider-specific resources. return nil }
// NewMetricsManagerAPI creates a new API endpoint for calling metrics manager functions. func NewMetricsManagerAPI( st *state.State, resources *common.Resources, authorizer common.Authorizer, ) (*MetricsManagerAPI, error) { if !(authorizer.AuthMachineAgent() && authorizer.AuthEnvironManager()) { return nil, common.ErrPerm } // Allow access only to the current environment. accessEnviron := func() (common.AuthFunc, error) { return func(tag names.Tag) bool { if tag == nil { return false } return tag == st.EnvironTag() }, nil } return &MetricsManagerAPI{ state: st, accessEnviron: accessEnviron, }, nil }
func getBackupDBWrapper(st *state.State) *storageDBWrapper { envUUID := st.EnvironTag().Id() db := st.MongoSession().DB(storageDBName) return newStorageDBWrapper(db, storageMetaName, envUUID) }
// NewStorageProvisionerAPI creates a new server-side StorageProvisionerAPI facade. func NewStorageProvisionerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*StorageProvisionerAPI, error) { if !authorizer.AuthMachineAgent() { return nil, common.ErrPerm } canAccessStorageMachine := func(tag names.MachineTag, allowEnvironManager bool) bool { authEntityTag := authorizer.GetAuthTag() if tag == authEntityTag { // Machine agents can access volumes // scoped to their own machine. return true } parentId := state.ParentId(tag.Id()) if parentId == "" { return allowEnvironManager && authorizer.AuthEnvironManager() } // All containers with the authenticated // machine as a parent are accessible by it. return names.NewMachineTag(parentId) == authEntityTag } getScopeAuthFunc := func() (common.AuthFunc, error) { return func(tag names.Tag) bool { switch tag := tag.(type) { case names.EnvironTag: // Environment managers can access all volumes // and filesystems scoped to the environment. isEnvironManager := authorizer.AuthEnvironManager() return isEnvironManager && tag == st.EnvironTag() case names.MachineTag: return canAccessStorageMachine(tag, false) default: return false } }, nil } canAccessStorageEntity := func(tag names.Tag, allowMachines bool) bool { switch tag := tag.(type) { case names.VolumeTag: machineTag, ok := names.VolumeMachine(tag) if ok { return canAccessStorageMachine(machineTag, false) } return authorizer.AuthEnvironManager() case names.FilesystemTag: machineTag, ok := names.FilesystemMachine(tag) if ok { return canAccessStorageMachine(machineTag, false) } return authorizer.AuthEnvironManager() case names.MachineTag: return allowMachines && canAccessStorageMachine(tag, true) default: return false } } getStorageEntityAuthFunc := func() (common.AuthFunc, error) { return func(tag names.Tag) bool { return canAccessStorageEntity(tag, false) }, nil } getLifeAuthFunc := func() (common.AuthFunc, error) { return func(tag names.Tag) bool { return canAccessStorageEntity(tag, true) }, nil } getAttachmentAuthFunc := func() (func(names.MachineTag, names.Tag) bool, error) { // getAttachmentAuthFunc returns a function that validates // access by the authenticated user to an attachment. return func(machineTag names.MachineTag, attachmentTag names.Tag) bool { // Machine agents can access their own machine, and // machines contained. Environment managers can access // top-level machines. if !canAccessStorageMachine(machineTag, true) { return false } // Environment managers can access environment-scoped // volumes and volumes scoped to their own machines. // Other machine agents can access volumes regardless // of their scope. if !authorizer.AuthEnvironManager() { return true } var machineScope names.MachineTag var hasMachineScope bool switch attachmentTag := attachmentTag.(type) { case names.VolumeTag: machineScope, hasMachineScope = names.VolumeMachine(attachmentTag) case names.FilesystemTag: machineScope, hasMachineScope = names.FilesystemMachine(attachmentTag) } return !hasMachineScope || machineScope == authorizer.GetAuthTag() }, nil } getMachineAuthFunc := func() (common.AuthFunc, error) { return func(tag names.Tag) bool { if tag, ok := tag.(names.MachineTag); ok { return canAccessStorageMachine(tag, true) } return false }, nil } getBlockDevicesAuthFunc := func() (common.AuthFunc, error) { return func(tag names.Tag) bool { if tag, ok := tag.(names.MachineTag); ok { return canAccessStorageMachine(tag, false) } return false }, nil } stateInterface := getState(st) settings := getSettingsManager(st) return &StorageProvisionerAPI{ LifeGetter: common.NewLifeGetter(stateInterface, getLifeAuthFunc), DeadEnsurer: common.NewDeadEnsurer(stateInterface, getStorageEntityAuthFunc), EnvironWatcher: common.NewEnvironWatcher(stateInterface, resources, authorizer), InstanceIdGetter: common.NewInstanceIdGetter(st, getMachineAuthFunc), StatusSetter: common.NewStatusSetter(st, getStorageEntityAuthFunc), st: stateInterface, settings: settings, resources: resources, authorizer: authorizer, getScopeAuthFunc: getScopeAuthFunc, getStorageEntityAuthFunc: getStorageEntityAuthFunc, getAttachmentAuthFunc: getAttachmentAuthFunc, getMachineAuthFunc: getMachineAuthFunc, getBlockDevicesAuthFunc: getBlockDevicesAuthFunc, }, nil }