예제 #1
0
파일: usermanager.go 프로젝트: bac/juju
func NewUserManagerAPI(
	st *state.State,
	resources facade.Resources,
	authorizer facade.Authorizer,
) (*UserManagerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, common.ErrPerm
	}

	// Since we know this is a user tag (because AuthClient is true),
	// we just do the type assertion to the UserTag.
	apiUser, _ := authorizer.GetAuthTag().(names.UserTag)
	// Pretty much all of the user manager methods have special casing for admin
	// users, so look once when we start and remember if the user is an admin.
	isAdmin, err := authorizer.HasPermission(permission.SuperuserAccess, st.ControllerTag())
	if err != nil {
		return nil, errors.Trace(err)
	}

	return &UserManagerAPI{
		state:      st,
		authorizer: authorizer,
		check:      common.NewBlockChecker(st),
		apiUser:    apiUser,
		isAdmin:    isAdmin,
	}, nil
}
예제 #2
0
// populateGUIArchive stores the uploaded Juju GUI archive in provider storage,
// updates the GUI metadata and set the current Juju GUI version.
func (c *BootstrapCommand) populateGUIArchive(st *state.State, env environs.Environ) error {
	agentConfig := c.CurrentConfig()
	dataDir := agentConfig.DataDir()
	guistorage, err := st.GUIStorage()
	if err != nil {
		return errors.Trace(err)
	}
	defer guistorage.Close()
	gui, err := agenttools.ReadGUIArchive(dataDir)
	if err != nil {
		return errors.Annotate(err, "cannot fetch GUI info")
	}
	f, err := os.Open(filepath.Join(agenttools.SharedGUIDir(dataDir), "gui.tar.bz2"))
	if err != nil {
		return errors.Annotate(err, "cannot read GUI archive")
	}
	defer f.Close()
	if err := guistorage.Add(f, binarystorage.Metadata{
		Version: gui.Version.String(),
		Size:    gui.Size,
		SHA256:  gui.SHA256,
	}); err != nil {
		return errors.Annotate(err, "cannot store GUI archive")
	}
	if err = st.GUISetVersion(gui.Version); err != nil {
		return errors.Annotate(err, "cannot set current GUI version")
	}
	return nil
}
예제 #3
0
// ImportModel deserializes a model description from the bytes, transforms
// the model config based on information from the controller model, and then
// imports that as a new database model.
func ImportModel(st *state.State, bytes []byte) (*state.Model, *state.State, error) {
	model, err := description.Deserialize(bytes)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	controllerModel, err := st.ControllerModel()
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	controllerConfig, err := controllerModel.Config()
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	model.UpdateConfig(controllerValues(controllerConfig))

	if err := updateConfigFromProvider(model, controllerConfig); err != nil {
		return nil, nil, errors.Trace(err)
	}

	dbModel, dbState, err := st.Import(model)
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	return dbModel, dbState, nil
}
예제 #4
0
파일: model_test.go 프로젝트: makyo/juju
func (s *ModelSuite) assertDyingEnvironTransitionDyingToDead(c *gc.C, st *state.State) {
	// Add a service to prevent the model from transitioning directly to Dead.
	// Add the service before getting the Model, otherwise we'll have to run
	// the transaction twice, and hit the hook point too early.
	svc := factory.NewFactory(st).MakeService(c, nil)
	env, err := st.Model()
	c.Assert(err, jc.ErrorIsNil)

	// ProcessDyingModel is called by a worker after Destroy is called. To
	// avoid a race, we jump the gun here and test immediately after the
	// environement was set to dead.
	defer state.SetAfterHooks(c, st, func() {
		c.Assert(env.Refresh(), jc.ErrorIsNil)
		c.Assert(env.Life(), gc.Equals, state.Dying)

		err := svc.Destroy()
		c.Assert(err, jc.ErrorIsNil)

		c.Assert(st.ProcessDyingModel(), jc.ErrorIsNil)

		c.Assert(env.Refresh(), jc.ErrorIsNil)
		c.Assert(env.Life(), gc.Equals, state.Dead)
	}).Check()

	c.Assert(env.Destroy(), jc.ErrorIsNil)
}
예제 #5
0
파일: client.go 프로젝트: mhilton/juju
// addServiceUnits adds a given number of units to a service.
func addServiceUnits(state *state.State, args params.AddServiceUnits) ([]*state.Unit, error) {
	service, err := state.Service(args.ServiceName)
	if err != nil {
		return nil, err
	}
	if args.NumUnits < 1 {
		return nil, fmt.Errorf("must add at least one unit")
	}

	// New API uses placement directives.
	if len(args.Placement) > 0 {
		return jjj.AddUnitsWithPlacement(state, service, args.NumUnits, args.Placement)
	}

	// Otherwise we use the older machine spec.
	if args.NumUnits > 1 && args.ToMachineSpec != "" {
		return nil, fmt.Errorf("cannot use NumUnits with ToMachineSpec")
	}

	if args.ToMachineSpec != "" && names.IsValidMachine(args.ToMachineSpec) {
		_, err = state.Machine(args.ToMachineSpec)
		if err != nil {
			return nil, errors.Annotatef(err, `cannot add units for service "%v" to machine %v`, args.ServiceName, args.ToMachineSpec)
		}
	}
	return jjj.AddUnits(state, service, args.NumUnits, args.ToMachineSpec)
}
예제 #6
0
파일: storage_test.go 프로젝트: kat-co/juju
// assertMachineStorageRefs ensures that the specified machine's set of volume
// and filesystem references corresponds exactly to the volume and filesystem
// attachments that relate to the machine.
func assertMachineStorageRefs(c *gc.C, st *state.State, m names.MachineTag) {
	machines, closer := state.GetRawCollection(st, state.MachinesC)
	defer closer()

	var doc struct {
		Volumes     []string `bson:"volumes,omitempty"`
		Filesystems []string `bson:"filesystems,omitempty"`
	}
	err := machines.FindId(state.DocID(st, m.Id())).One(&doc)
	c.Assert(err, jc.ErrorIsNil)

	have := make(set.Tags)
	for _, v := range doc.Volumes {
		have.Add(names.NewVolumeTag(v))
	}
	for _, f := range doc.Filesystems {
		have.Add(names.NewFilesystemTag(f))
	}

	expect := make(set.Tags)
	volumeAttachments, err := st.MachineVolumeAttachments(m)
	c.Assert(err, jc.ErrorIsNil)
	for _, a := range volumeAttachments {
		expect.Add(a.Volume())
	}
	filesystemAttachments, err := st.MachineFilesystemAttachments(m)
	c.Assert(err, jc.ErrorIsNil)
	for _, a := range filesystemAttachments {
		expect.Add(a.Filesystem())
	}

	c.Assert(have, jc.DeepEquals, expect)
}
예제 #7
0
func currentInfo(st *state.State, db *mgo.Database) (*serverInfo, error) {
	var doc stateServersDoc
	err := db.C("stateServers").Find(bson.D{{"_id", "e"}}).One(&doc)
	if err != nil {
		return nil, fmt.Errorf("cannot get state server info: %v", err)
	}
	ms := make(map[string]*state.Machine)
	var all []string
	all = append(all, doc.MachineIds...)
	all = append(all, doc.VotingMachineIds...)
	for _, id := range all {
		if _, ok := ms[id]; ok {
			continue
		}
		m, err := st.Machine(id)
		if err != nil {
			return nil, fmt.Errorf("cannot get info on machine %s: %v", id, err)
		}
		ms[id] = m
	}
	return &serverInfo{
		servers:  &doc,
		machines: ms,
	}, nil
}
예제 #8
0
파일: payload.go 프로젝트: imoapps/juju
func (payloads) newPublicFacade(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*server.PublicAPI, error) {
	up, err := st.EnvPayloads()
	if err != nil {
		return nil, errors.Trace(err)
	}
	return server.NewPublicAPI(up), nil
}
예제 #9
0
func (c *MigrateCommand) exportModel(ctx *cmd.Context, st *state.State) error {
	ctx.Infof("\nexport %s", c.modelUUID)

	// first make sure the uuid is good enough
	tag := names.NewModelTag(c.modelUUID)
	_, err := st.GetModel(tag)
	if err != nil {
		return errors.Trace(err)
	}

	modelState, err := st.ForModel(tag)
	if err != nil {
		return errors.Trace(err)
	}
	defer modelState.Close()

	model, err := modelState.Export()
	if err != nil {
		return errors.Trace(err)
	}

	bytes, err := yaml.Marshal(model)
	if err != nil {
		return errors.Trace(err)
	}

	ctx.Stdout.Write(bytes)
	return nil
}
예제 #10
0
func (s *MachineRemovalSuite) createRemovalWatcher(c *gc.C, st *state.State) (
	state.NotifyWatcher, testing.NotifyWatcherC,
) {
	w := st.WatchMachineRemovals()
	s.AddCleanup(func(c *gc.C) { workertest.CleanKill(c, w) })
	return w, testing.NewNotifyWatcherC(c, st, w)
}
예제 #11
0
파일: payload.go 프로젝트: imoapps/juju
func (payloads) newHookContextFacade(st *state.State, unit *state.Unit) (interface{}, error) {
	up, err := st.UnitPayloads(unit)
	if err != nil {
		return nil, errors.Trace(err)
	}
	return internalserver.NewUnitFacade(up), nil
}
예제 #12
0
파일: run.go 프로젝트: imoapps/juju
// getAllUnitNames returns a sequence of valid Unit objects from state. If any
// of the service names or unit names are not found, an error is returned.
func getAllUnitNames(st *state.State, units, services []string) (result []*state.Unit, err error) {
	unitsSet := set.NewStrings(units...)
	for _, name := range services {
		service, err := st.Service(name)
		if err != nil {
			return nil, err
		}
		units, err := service.AllUnits()
		if err != nil {
			return nil, err
		}
		for _, unit := range units {
			unitsSet.Add(unit.Name())
		}
	}
	for _, unitName := range unitsSet.Values() {
		unit, err := st.Unit(unitName)
		if err != nil {
			return nil, err
		}
		// We only operate on units that have an assigned machine.
		if _, err := unit.AssignedMachineId(); err != nil {
			return nil, err
		}
		result = append(result, unit)
	}
	return result, nil
}
예제 #13
0
func (s *MigrationSuite) createStatusWatcher(c *gc.C, st *state.State) (
	state.NotifyWatcher, statetesting.NotifyWatcherC,
) {
	w := st.WatchMigrationStatus()
	s.AddCleanup(func(c *gc.C) { statetesting.AssertStop(c, w) })
	return w, statetesting.NewNotifyWatcherC(c, st, w)
}
예제 #14
0
func handleResponse(mm *state.MetricsManager, st *state.State, response wireformat.Response) {
	for _, envResp := range response.EnvResponses {
		err := st.SetMetricBatchesSent(envResp.AcknowledgedBatches)
		if err != nil {
			logger.Errorf("failed to set sent on metrics %v", err)
		}
		for unitName, status := range envResp.UnitStatuses {
			unit, err := st.Unit(unitName)
			if err != nil {
				logger.Errorf("failed to retrieve unit %q: %v", unitName, err)
				continue
			}
			err = unit.SetMeterStatus(status.Status, status.Info)
			if err != nil {
				logger.Errorf("failed to set unit %q meter status to %v: %v", unitName, status, err)
			}
		}
	}
	if response.NewGracePeriod > 0 {
		err := mm.SetGracePeriod(response.NewGracePeriod)
		if err != nil {
			logger.Errorf("failed to set new grace period %v", err)
		}
	}
}
예제 #15
0
파일: tools.go 프로젝트: bac/juju
// processGet handles a tools GET request.
func (h *toolsDownloadHandler) processGet(r *http.Request, st *state.State) ([]byte, error) {
	version, err := version.ParseBinary(r.URL.Query().Get(":version"))
	if err != nil {
		return nil, errors.Annotate(err, "error parsing version")
	}
	storage, err := st.ToolsStorage()
	if err != nil {
		return nil, errors.Annotate(err, "error getting tools storage")
	}
	defer storage.Close()
	_, reader, err := storage.Open(version.String())
	if errors.IsNotFound(err) {
		// Tools could not be found in tools storage,
		// so look for them in simplestreams, fetch
		// them and cache in tools storage.
		logger.Infof("%v tools not found locally, fetching", version)
		reader, err = h.fetchAndCacheTools(version, storage, st)
		if err != nil {
			err = errors.Annotate(err, "error fetching tools")
		}
	}
	if err != nil {
		return nil, err
	}
	defer reader.Close()
	data, err := ioutil.ReadAll(reader)
	if err != nil {
		return nil, errors.Annotate(err, "failed to read tools tarball")
	}
	return data, nil
}
예제 #16
0
파일: images.go 프로젝트: imoapps/juju
// loadImage loads an os image from the blobstore,
// downloading and caching it if necessary.
func (h *imagesDownloadHandler) loadImage(st *state.State, envuuid, kind, series, arch string) (
	*imagestorage.Metadata, io.ReadCloser, error,
) {
	// We want to ensure that if an image needs to be downloaded and cached,
	// this only happens once.
	imageIdent := fmt.Sprintf("image-%s-%s-%s-%s", envuuid, kind, series, arch)
	lockDir := filepath.Join(h.dataDir, "locks")
	lock, err := fslock.NewLock(lockDir, imageIdent, fslock.Defaults())
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	lock.Lock("fetch and cache image " + imageIdent)
	defer lock.Unlock()
	storage := st.ImageStorage()
	metadata, imageReader, err := storage.Image(kind, series, arch)
	// Not in storage, so go fetch it.
	if errors.IsNotFound(err) {
		if err := h.fetchAndCacheLxcImage(storage, envuuid, series, arch); err != nil {
			return nil, nil, errors.Annotate(err, "error fetching and caching image")
		}
		err = networkOperationWitDefaultRetries(func() error {
			metadata, imageReader, err = storage.Image(string(instance.LXC), series, arch)
			return err
		}, "streaming os image from blobstore")()
	}
	if err != nil {
		return nil, nil, errors.Trace(err)
	}
	return metadata, imageReader, nil
}
예제 #17
0
// AddSubnetsWithTemplate adds numSubnets subnets, using the given
// infoTemplate. Any string field in the infoTemplate can be specified
// as a text/template string containing {{.}}, which is the current
// index of the subnet-to-add (between 0 and numSubnets-1).
//
// Example:
//
// AddSubnetsWithTemplate(c, st, 2, state.SubnetInfo{
//     CIDR: "10.10.{{.}}.0/24",
//     ProviderId: "subnet-{{.}}",
//     SpaceName: "space1",
//     AvailabilityZone: "zone-{{.}}",
//     AllocatableIPLow: "{{if (gt . 0)}}10.10.{{.}}.5{{end}}",
//     AllocatableIPHigh: "{{if (gt . 0)}}10.10.{{.}}.254{{end}}",
//     VLANTag: 42,
// })
//
// This is equivalent to the following calls:
//
// _, err := st.AddSubnet(state.SubnetInfo{
//     CIDR: "10.10.0.0/24",
//     ProviderId: "subnet-0",
//     SpaceName: "space1",
//     AvailabilityZone: "zone-0",
//     VLANTag: 42,
// })
// c.Assert(err, jc.ErrorIsNil)
// _, err = st.AddSubnet(state.SubnetInfo{
//     CIDR: "10.10.1.0/24",
//     ProviderId: "subnet-1",
//     SpaceName: "space1",
//     AvailabilityZone: "zone-1",
//     AllocatableIPLow: "10.10.1.5",
//     AllocatableIPHigh: "10.10.1.254",
//     VLANTag: 42,
// })
func AddSubnetsWithTemplate(c *gc.C, st *state.State, numSubnets uint, infoTemplate state.SubnetInfo) {
	for subnetIndex := 0; subnetIndex < int(numSubnets); subnetIndex++ {
		info := infoTemplate // make a copy each time.

		// permute replaces the contents of *s with the result of interpreting
		// *s as a template.
		permute := func(s string) string {
			t, err := template.New("").Parse(s)
			c.Assert(err, jc.ErrorIsNil)

			var buf bytes.Buffer
			err = t.Execute(&buf, subnetIndex)
			c.Assert(err, jc.ErrorIsNil)
			return buf.String()
		}

		info.ProviderId = network.Id(permute(string(info.ProviderId)))
		info.CIDR = permute(info.CIDR)
		info.AllocatableIPHigh = permute(info.AllocatableIPHigh)
		info.AllocatableIPLow = permute(info.AllocatableIPLow)
		info.AvailabilityZone = permute(info.AvailabilityZone)
		info.SpaceName = permute(info.SpaceName)

		_, err := st.AddSubnet(info)
		c.Assert(err, jc.ErrorIsNil)
	}
}
예제 #18
0
파일: admin.go 프로젝트: kakamessi99/juju
// checkCreds validates the entities credentials in the current environment.
// If the entity is a user, and lookForEnvUser is true, an env user must exist
// for the environment.  In the case of a user logging in to the server, but
// not an environment, there is no env user needed.  While we have the env
// user, if we do have it, update the last login time.
func checkCreds(st *state.State, req params.LoginRequest, lookForEnvUser bool) (state.Entity, *time.Time, error) {
	tag, err := names.ParseTag(req.AuthTag)
	if err != nil {
		return nil, nil, err
	}
	entity, err := st.FindEntity(tag)
	if errors.IsNotFound(err) {
		// We return the same error when an entity does not exist as for a bad
		// password, so that we don't allow unauthenticated users to find
		// information about existing entities.
		logger.Debugf("entity %q not found", tag)
		return nil, nil, common.ErrBadCreds
	}
	if err != nil {
		return nil, nil, errors.Trace(err)
	}

	authenticator, err := authentication.FindEntityAuthenticator(entity)
	if err != nil {
		return nil, nil, err
	}

	if err = authenticator.Authenticate(entity, req.Credentials, req.Nonce); err != nil {
		logger.Debugf("bad credentials")
		return nil, nil, err
	}

	// For user logins, update the last login time.
	// NOTE: this code path is only for local users. When we support remote
	// user logins with bearer tokens, we will need to make sure that we also
	// update the last connection times for the environment users there.
	var lastLogin *time.Time
	if user, ok := entity.(*state.User); ok {
		userLastLogin, err := user.LastLogin()
		if err != nil && !state.IsNeverLoggedInError(err) {
			return nil, nil, errors.Trace(err)
		}
		if lookForEnvUser {
			envUser, err := st.EnvironmentUser(user.UserTag())
			if err != nil {
				return nil, nil, errors.Wrap(err, common.ErrBadCreds)
			}
			// The last connection for the environment takes precedence over
			// the local user last login time.
			userLastLogin, err = envUser.LastConnection()
			if err != nil && !state.IsNeverConnectedError(err) {
				return nil, nil, errors.Trace(err)
			}
			envUser.UpdateLastConnection()
		}
		// Only update the user's last login time if it is a successful
		// login, meaning that if we are logging into an environment, make
		// sure that there is an environment user in that environment for
		// this user.
		user.UpdateLastLogin()
		lastLogin = &userLastLogin
	}

	return entity, lastLogin, nil
}
예제 #19
0
// fetchMachines returns a map from top level machine id to machines, where machines[0] is the host
// machine and machines[1..n] are any containers (including nested ones).
//
// If machineIds is non-nil, only machines whose IDs are in the set are returned.
func fetchMachines(st *state.State, machineIds *set.Strings) (map[string][]*state.Machine, error) {
	v := make(map[string][]*state.Machine)
	machines, err := st.AllMachines()
	if err != nil {
		return nil, err
	}
	// AllMachines gives us machines sorted by id.
	for _, m := range machines {
		if machineIds != nil && !machineIds.Contains(m.Id()) {
			continue
		}
		parentId, ok := m.ParentId()
		if !ok {
			// Only top level host machines go directly into the machine map.
			v[m.Id()] = []*state.Machine{m}
		} else {
			topParentId := state.TopParentId(m.Id())
			machines, ok := v[topParentId]
			if !ok {
				panic(fmt.Errorf("unexpected machine id %q", parentId))
			}
			machines = append(machines, m)
			v[topParentId] = machines
		}
	}
	return v, nil
}
예제 #20
0
func getMachine(st *state.State, tag names.Tag) (*state.Machine, error) {
	m0, err := st.FindEntity(tag)
	if err != nil {
		return nil, err
	}
	return m0.(*state.Machine), nil
}
예제 #21
0
func (r resources) newHookContextFacade(st *corestate.State, unit *corestate.Unit) (interface{}, error) {
	res, err := st.Resources()
	if err != nil {
		return nil, errors.Trace(err)
	}
	return internalserver.NewUnitFacade(&resourcesUnitDataStore{res, unit}), nil
}
예제 #22
0
파일: charms.go 프로젝트: bac/juju
func modelIsImporting(st *state.State) (bool, error) {
	model, err := st.Model()
	if err != nil {
		return false, errors.Trace(err)
	}
	return model.MigrationMode() == state.MigrationModeImporting, nil
}
예제 #23
0
파일: uniter_v1.go 프로젝트: imoapps/juju
// NewUniterAPIV1 creates a new instance of the Uniter API, version 1.
func NewUniterAPIV1(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*UniterAPIV1, error) {
	baseAPI, err := newUniterBaseAPI(st, resources, authorizer)
	if err != nil {
		return nil, err
	}
	accessMachine := func() (common.AuthFunc, error) {
		switch tag := authorizer.GetAuthTag().(type) {
		case names.UnitTag:
			entity, err := st.Unit(tag.Id())
			if err != nil {
				return nil, errors.Trace(err)
			}
			machineId, err := entity.AssignedMachineId()
			if err != nil {
				return nil, errors.Trace(err)
			}
			machineTag := names.NewMachineTag(machineId)
			return func(tag names.Tag) bool {
				return tag == machineTag
			}, nil
		default:
			return nil, errors.Errorf("expected names.UnitTag, got %T", tag)
		}
	}
	return &UniterAPIV1{
		uniterBaseAPI: *baseAPI,

		accessMachine: accessMachine,
	}, nil
}
예제 #24
0
파일: destroy.go 프로젝트: jiasir/juju
// destroyInstances directly destroys all non-manager,
// non-manual machine instances.
func destroyInstances(st *state.State, machines []*state.Machine) error {
	var ids []instance.Id
	for _, m := range machines {
		if m.IsManager() {
			continue
		}
		if _, isContainer := m.ParentId(); isContainer {
			continue
		}
		manual, err := m.IsManual()
		if manual {
			continue
		} else if err != nil {
			return err
		}
		id, err := m.InstanceId()
		if err != nil {
			continue
		}
		ids = append(ids, id)
	}
	if len(ids) == 0 {
		return nil
	}
	envcfg, err := st.EnvironConfig()
	if err != nil {
		return err
	}
	env, err := environs.New(envcfg)
	if err != nil {
		return err
	}
	return env.StopInstances(ids...)
}
예제 #25
0
파일: reboot.go 프로젝트: pmatulis/juju
// NewRebootAPI creates a new server-side RebootAPI facade.
func NewRebootAPI(st *state.State, resources *common.Resources, auth common.Authorizer) (*RebootAPI, error) {
	if !auth.AuthMachineAgent() {
		return nil, common.ErrPerm
	}

	tag, ok := auth.GetAuthTag().(names.MachineTag)
	if !ok {
		return nil, errors.Errorf("Expected names.MachineTag, got %T", auth.GetAuthTag())
	}
	machine, err := st.Machine(tag.Id())
	if err != nil {
		return nil, errors.Trace(err)
	}

	canAccess := func() (common.AuthFunc, error) {
		return auth.AuthOwner, nil
	}

	return &RebootAPI{
		RebootActionGetter: common.NewRebootActionGetter(st, canAccess),
		RebootRequester:    common.NewRebootRequester(st, canAccess),
		RebootFlagClearer:  common.NewRebootFlagClearer(st, canAccess),
		st:                 st,
		machine:            machine,
		resources:          resources,
		auth:               auth,
	}, nil
}
예제 #26
0
파일: conn.go 프로젝트: mhilton/juju
// PutCharm uploads the given charm to provider storage, and adds a
// state.Charm to the state.  The charm is not uploaded if a charm with
// the same URL already exists in the state.
// If bumpRevision is true, the charm must be a local directory,
// and the revision number will be incremented before pushing.
func PutCharm(st *state.State, curl *charm.URL, repo charmrepo.Interface, bumpRevision bool) (*state.Charm, error) {
	if curl.Revision == -1 {
		rev, err := charmrepo.Latest(repo, curl)
		if err != nil {
			return nil, fmt.Errorf("cannot get latest charm revision: %v", err)
		}
		curl = curl.WithRevision(rev)
	}
	ch, err := repo.Get(curl)
	if err != nil {
		return nil, fmt.Errorf("cannot get charm: %v", err)
	}
	if bumpRevision {
		chd, ok := ch.(*charm.CharmDir)
		if !ok {
			return nil, fmt.Errorf("cannot increment revision of charm %q: not a directory", curl)
		}
		if err = chd.SetDiskRevision(chd.Revision() + 1); err != nil {
			return nil, fmt.Errorf("cannot increment revision of charm %q: %v", curl, err)
		}
		curl = curl.WithRevision(chd.Revision())
	}
	if sch, err := st.Charm(curl); err == nil {
		return sch, nil
	}
	return addCharm(st, curl, ch)
}
예제 #27
0
파일: controller.go 프로젝트: imoapps/juju
// NewControllerAPI creates a new api server endpoint for managing
// environments.
func NewControllerAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*ControllerAPI, error) {
	if !authorizer.AuthClient() {
		return nil, errors.Trace(common.ErrPerm)
	}

	// Since we know this is a user tag (because AuthClient is true),
	// we just do the type assertion to the UserTag.
	apiUser, _ := authorizer.GetAuthTag().(names.UserTag)
	isAdmin, err := st.IsControllerAdministrator(apiUser)
	if err != nil {
		return nil, errors.Trace(err)
	}
	// The entire end point is only accessible to controller administrators.
	if !isAdmin {
		return nil, errors.Trace(common.ErrPerm)
	}

	return &ControllerAPI{
		state:      st,
		authorizer: authorizer,
		apiUser:    apiUser,
		resources:  resources,
	}, nil
}
예제 #28
0
파일: deploy.go 프로젝트: pmatulis/juju
// AddUnits starts n units of the given service using the specified placement
// directives to allocate the machines.
func AddUnits(st *state.State, svc *state.Service, n int, placement []*instance.Placement) ([]*state.Unit, error) {
	units := make([]*state.Unit, n)
	// Hard code for now till we implement a different approach.
	policy := state.AssignCleanEmpty
	// All units should have the same networks as the service.
	networks, err := svc.Networks()
	if err != nil {
		return nil, errors.Errorf("cannot get service %q networks", svc.Name())
	}
	// TODO what do we do if we fail half-way through this process?
	for i := 0; i < n; i++ {
		unit, err := svc.AddUnit()
		if err != nil {
			return nil, errors.Annotatef(err, "cannot add unit %d/%d to service %q", i+1, n, svc.Name())
		}
		// Are there still placement directives to use?
		if i > len(placement)-1 {
			if err := st.AssignUnit(unit, policy); err != nil {
				return nil, errors.Trace(err)
			}
			units[i] = unit
			continue
		}
		if err := st.AssignUnitWithPlacement(unit, placement[i], networks); err != nil {
			return nil, errors.Annotatef(err, "adding new machine to host unit %q", unit.Name())
		}
		units[i] = unit
	}
	return units, nil
}
예제 #29
0
파일: upgrader.go 프로젝트: bac/juju
// NewUpgraderAPI creates a new server-side UpgraderAPI facade.
func NewUpgraderAPI(
	st *state.State,
	resources facade.Resources,
	authorizer facade.Authorizer,
) (*UpgraderAPI, error) {
	if !authorizer.AuthMachineAgent() {
		return nil, common.ErrPerm
	}
	getCanReadWrite := func() (common.AuthFunc, error) {
		return authorizer.AuthOwner, nil
	}
	env, err := st.Model()
	if err != nil {
		return nil, err
	}
	urlGetter := common.NewToolsURLGetter(env.UUID(), st)
	configGetter := stateenvirons.EnvironConfigGetter{st}
	return &UpgraderAPI{
		ToolsGetter: common.NewToolsGetter(st, configGetter, st, urlGetter, getCanReadWrite),
		ToolsSetter: common.NewToolsSetter(st, getCanReadWrite),
		st:          st,
		resources:   resources,
		authorizer:  authorizer,
	}, nil
}
예제 #30
0
파일: authcontext.go 프로젝트: bac/juju
// newAuthContext creates a new authentication context for st.
func newAuthContext(st *state.State) (*authContext, error) {
	ctxt := &authContext{
		st: st,
		// TODO(fwereade) 2016-07-21 there should be a clock parameter
		clock: clock.WallClock,
		localUserInteractions: authentication.NewInteractions(),
	}

	// Create a bakery service for discharging third-party caveats for
	// local user authentication. This service does not persist keys;
	// its macaroons should be very short-lived.
	localUserThirdPartyBakeryService, _, err := newBakeryService(st, nil, nil)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ctxt.localUserThirdPartyBakeryService = localUserThirdPartyBakeryService

	// Create a bakery service for local user authentication. This service
	// persists keys into MongoDB in a TTL collection.
	store, err := st.NewBakeryStorage()
	if err != nil {
		return nil, errors.Trace(err)
	}
	locator := bakeryServicePublicKeyLocator{ctxt.localUserThirdPartyBakeryService}
	localUserBakeryService, localUserBakeryServiceKey, err := newBakeryService(
		st, store, locator,
	)
	if err != nil {
		return nil, errors.Trace(err)
	}
	ctxt.localUserBakeryService = &expirableStorageBakeryService{
		localUserBakeryService, localUserBakeryServiceKey, store, locator,
	}
	return ctxt, nil
}