Exemple #1
0
func (s *MachineSuite) TestMachineIdFromTag(c *C) {
	c.Assert(state.MachineIdFromTag("machine-10"), Equals, "10")
	// Check a container id.
	c.Assert(state.MachineIdFromTag("machine-10-lxc-1"), Equals, "10/lxc/1")
	// Check reversability.
	nested := "2/kvm/0/lxc/3"
	c.Assert(state.MachineIdFromTag(state.MachineTag(nested)), Equals, nested)
	// Try with an invalid tag format.
	c.Assert(state.MachineIdFromTag("foo"), Equals, "")
}
Exemple #2
0
// Watch starts an NotifyWatcher for each given machine.
func (m *MachinerAPI) Watch(args params.Entities) (params.NotifyWatchResults, error) {
	result := params.NotifyWatchResults{
		Results: make([]params.NotifyWatchResult, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	for i, entity := range args.Entities {
		err := common.ErrPerm
		if m.auth.AuthOwner(entity.Tag) {
			var machine *state.Machine
			machine, err = m.st.Machine(state.MachineIdFromTag(entity.Tag))
			if err == nil {
				watch := machine.Watch()
				// Consume the initial event. Technically, API
				// calls to Watch 'transmit' the initial event
				// in the Watch response. But NotifyWatchers
				// have no state to transmit.
				if _, ok := <-watch.Changes(); ok {
					result.Results[i].NotifyWatcherId = m.resources.Register(watch)
				} else {
					err = watcher.MustErr(watch)
				}
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}
Exemple #3
0
// getAllUnits returns a list of all principal and subordinate units
// assigned to the given machine.
func getAllUnits(st *state.State, machineTag string) ([]string, error) {
	machine, err := st.Machine(state.MachineIdFromTag(machineTag))
	if err != nil {
		return nil, err
	}
	// Start a watcher on machine's units, read the initial event and stop it.
	watch := machine.WatchUnits()
	defer watch.Stop()
	if units, ok := <-watch.Changes(); ok {
		return units, nil
	}
	return nil, fmt.Errorf("cannot obtain units of machine %q: %v", machineTag, watch.Err())
}
Exemple #4
0
func (api *AgentAPI) getMachine(tag string) (result params.MachineAgentGetMachinesResult, err error) {
	// Allow only for the owner agent.
	// Note: having a bulk API call for this is utter madness, given that
	// this check means we can only ever return a single object.
	if !api.auth.AuthOwner(tag) {
		err = common.ErrPerm
		return
	}
	machine, err := api.st.Machine(state.MachineIdFromTag(tag))
	if err != nil {
		return
	}
	result.Life = params.Life(machine.Life().String())
	result.Jobs = stateJobsToAPIParamsJobs(machine.Jobs())
	return
}
Exemple #5
0
// EnsureDead changes the lifecycle of each given machine to Dead if
// it's Alive or Dying. It does nothing otherwise.
func (m *MachinerAPI) EnsureDead(args params.Entities) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Errors: make([]*params.Error, len(args.Entities)),
	}
	if len(args.Entities) == 0 {
		return result, nil
	}
	for i, entity := range args.Entities {
		err := common.ErrPerm
		if m.auth.AuthOwner(entity.Tag) {
			var machine *state.Machine
			machine, err = m.st.Machine(state.MachineIdFromTag(entity.Tag))
			if err == nil {
				err = machine.EnsureDead()
			}
		}
		result.Errors[i] = common.ServerError(err)
	}
	return result, nil
}
Exemple #6
0
// SetStatus sets the status of each given machine.
func (m *MachinerAPI) SetStatus(args params.MachinesSetStatus) (params.ErrorResults, error) {
	result := params.ErrorResults{
		Errors: make([]*params.Error, len(args.Machines)),
	}
	if len(args.Machines) == 0 {
		return result, nil
	}
	for i, arg := range args.Machines {
		err := common.ErrPerm
		if m.auth.AuthOwner(arg.Tag) {
			var machine *state.Machine
			machine, err = m.st.Machine(state.MachineIdFromTag(arg.Tag))
			if err == nil {
				err = machine.SetStatus(arg.Status, arg.Info)
			}
		}
		result.Errors[i] = common.ServerError(err)
	}
	return result, nil
}
// EnsureWeHaveLXC checks if we have lxc installed, and installs it if we
// don't. Juju 1.11 added the ability to deploy into LXC containers, and uses
// functionality from the lxc package in order to do so. Juju 1.10 did not
// install lxc, so we ensure it is installed.
// See http://bugs.launchpad.net/bug/1199913
// dataDir is the root location where data files are put. It is used to grab
// the uniter-hook-execution lock so that we don't try run to apt-get at the
// same time that a hook might want to run it.
func EnsureWeHaveLXC(dataDir, machineTag string) error {
	// We need to short circuit this in two places:
	//   1. if we are running a local provider, then the machines are lxc
	//     containers, and if we install lxc on them, it adds an lxc bridge
	//     network device with the same ip address as the hosts bridge.  This
	//     screws up all the networking routes.
	//   2. if the machine is an lxc container, we need to avoid installing lxc
	//     package for exactly the same reasons.
	// Later, post-precise LTS, when we have updated lxc, we can bring this
	// back in to have nested lxc, but until then, we have to avoid it.
	containerType := state.ContainerTypeFromId(state.MachineIdFromTag(machineTag))
	providerType := os.Getenv("JUJU_PROVIDER_TYPE")
	if providerType == provider.Local || containerType == instance.LXC {
		return nil
	}
	manager := lxc.NewContainerManager(lxc.ManagerConfig{Name: "lxc-test"})
	if _, err := manager.ListContainers(); err == nil {
		validationLogger.Debugf("found lxc, not installing")
		// We already have it, nothing more to do
		return nil
	}
	validationLogger.Debugf("got error looking for lxc, attempting to install")
	if dataDir != "" {
		lock, err := getUniterLock(dataDir, "apt-get install lxc for juju 1.11 upgrade")
		if err == nil {
			defer lock.Unlock()
		} else {
			validationLogger.Warningf("Failed to acquire lock: %v, will try to install lxc anyway", lock)
		}
		// If we got an error trying to acquire the lock, we try to install
		// lxc anyway. Worst case the install will fail, which is where we
		// are already
	}
	// TODO: This is not platform independent. If jujud is running on
	//       something other than a debian-based Linux, and we are missing
	//       lxc, this call will always fail. However, in juju 1.11+ we
	//       install lxc via cloud-init or whatever bootstrap code we use.
	//       So this is really only upgrade compatibility and juju 1.10
	//       only supports debian-based anyway
	return utils.AptGetInstall("lxc")
}
Exemple #8
0
func (u *UpgraderAPI) oneAgentTools(entity params.Entity, agentVersion version.Number, env environs.Environ) (params.AgentTools, error) {
	if !u.authorizer.AuthOwner(entity.Tag) {
		return nilTools, common.ErrPerm
	}
	machine, err := u.st.Machine(state.MachineIdFromTag(entity.Tag))
	if err != nil {
		return nilTools, err
	}
	// TODO: Support Unit as well as Machine
	existingTools, err := machine.AgentTools()
	if err != nil {
		return nilTools, err
	}
	requested := version.Binary{
		Number: agentVersion,
		Series: existingTools.Series,
		Arch:   existingTools.Arch,
	}
	// Note: (jam) We shouldn't have to search the provider
	//       for every machine that wants to upgrade. The
	//       information could just be cached in state, or
	//       even in the API servers
	tools, err := environs.FindExactTools(env, requested)
	if err != nil {
		return nilTools, err
	}
	return params.AgentTools{
		Tag:    entity.Tag,
		Arch:   tools.Arch,
		Series: tools.Series,
		URL:    tools.URL,
		Major:  tools.Major,
		Minor:  tools.Minor,
		Patch:  tools.Patch,
		Build:  tools.Build,
	}, nil
}
Exemple #9
0
// SetTools updates the recorded tools version for the agents.
func (u *UpgraderAPI) SetTools(args params.SetAgentTools) (params.SetAgentToolsResults, error) {
	results := params.SetAgentToolsResults{
		Results: make([]params.SetAgentToolsResult, len(args.AgentTools)),
	}
	for i, tools := range args.AgentTools {
		var err error
		results.Results[i].Tag = tools.Tag
		if !u.authorizer.AuthOwner(tools.Tag) {
			err = common.ErrPerm
		} else {
			// TODO: When we get there, we should support setting
			//       Unit agent tools as well as Machine tools. We
			//       can use something like the "AgentState"
			//       interface that cmd/jujud/agent.go had.
			machine, err := u.st.Machine(state.MachineIdFromTag(tools.Tag))
			if err == nil {
				stTools := state.Tools{
					Binary: version.Binary{
						Number: version.Number{
							Major: tools.Major,
							Minor: tools.Minor,
							Patch: tools.Patch,
							Build: tools.Build,
						},
						Arch:   tools.Arch,
						Series: tools.Series,
					},
					URL: tools.URL,
				}
				err = machine.SetAgentTools(&stTools)
			}
		}
		results.Results[i].Error = common.ServerError(err)
	}
	return results, nil
}
Exemple #10
0
// WatchUnits starts a StringsWatcher to watch all units deployed to
// any machine passed in args, in order to track which ones should be
// deployed or recalled.
func (d *DeployerAPI) WatchUnits(args params.Entities) (params.StringsWatchResults, error) {
	result := params.StringsWatchResults{
		Results: make([]params.StringsWatchResult, len(args.Entities)),
	}
	for i, entity := range args.Entities {
		err := common.ErrPerm
		if d.authorizer.AuthOwner(entity.Tag) {
			var machine *state.Machine
			machine, err = d.st.Machine(state.MachineIdFromTag(entity.Tag))
			if err == nil {
				watch := machine.WatchUnits()
				// Consume the initial event and forward it to the result.
				if changes, ok := <-watch.Changes(); ok {
					result.Results[i].StringsWatcherId = d.resources.Register(watch)
					result.Results[i].Changes = changes
				} else {
					err = watcher.MustErr(watch)
				}
			}
		}
		result.Results[i].Error = common.ServerError(err)
	}
	return result, nil
}