Example #1
0
// AllMachinePorts returns all port ranges currently open on the given
// machine, mapped to the tags of the unit that opened them and the
// relation that applies.
func (st *State) AllMachinePorts(machineTag names.MachineTag) (map[network.PortRange]params.RelationUnit, error) {
	if st.BestAPIVersion() < 1 {
		// AllMachinePorts() was introduced in UniterAPIV1.
		return nil, errors.NotImplementedf("AllMachinePorts() (need V1+)")
	}
	var results params.MachinePortsResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: machineTag.String()}},
	}
	err := st.facade.FacadeCall("AllMachinePorts", args, &results)
	if err != nil {
		return nil, err
	}
	if len(results.Results) != 1 {
		return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, result.Error
	}
	portsMap := make(map[network.PortRange]params.RelationUnit)
	for _, ports := range result.Ports {
		portRange := ports.PortRange.NetworkPortRange()
		portsMap[portRange] = params.RelationUnit{
			Unit:     ports.UnitTag,
			Relation: ports.RelationTag,
		}
	}
	return portsMap, nil
}
Example #2
0
// ReleaseContainerAddresses releases a static IP address allocated to a
// container.
func (st *State) ReleaseContainerAddresses(containerTag names.MachineTag) (err error) {
	defer errors.DeferredAnnotatef(&err, "cannot release static addresses for %q", containerTag.Id())
	var result params.ErrorResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: containerTag.String()}},
	}
	if err := st.facade.FacadeCall("ReleaseContainerAddresses", args, &result); err != nil {
		return err
	}
	return result.OneError()
}
Example #3
0
// prepareOrGetContainerInterfaceInfo returns the necessary information to
// configure network interfaces of a container with allocated static
// IP addresses.
//
// TODO(dimitern): Before we start using this, we need to rename both
// the method and the network.InterfaceInfo type to be called
// InterfaceConfig.
func (st *State) prepareOrGetContainerInterfaceInfo(
	containerTag names.MachineTag, allocateNewAddress bool) (
	[]network.InterfaceInfo, error) {
	var result params.MachineNetworkConfigResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: containerTag.String()}},
	}
	facadeName := ""
	if allocateNewAddress {
		facadeName = "PrepareContainerInterfaceInfo"
	} else {
		facadeName = "GetContainerInterfaceInfo"
	}
	if err := st.facade.FacadeCall(facadeName, args, &result); err != nil {
		return nil, err
	}
	if len(result.Results) != 1 {
		return nil, errors.Errorf("expected 1 result, got %d", len(result.Results))
	}
	if err := result.Results[0].Error; err != nil {
		return nil, err
	}
	ifaceInfo := make([]network.InterfaceInfo, len(result.Results[0].Config))
	for i, cfg := range result.Results[0].Config {
		ifaceInfo[i] = network.InterfaceInfo{
			DeviceIndex:         cfg.DeviceIndex,
			MACAddress:          cfg.MACAddress,
			CIDR:                cfg.CIDR,
			MTU:                 cfg.MTU,
			ProviderId:          network.Id(cfg.ProviderId),
			ProviderSubnetId:    network.Id(cfg.ProviderSubnetId),
			ProviderSpaceId:     network.Id(cfg.ProviderSpaceId),
			ProviderVLANId:      network.Id(cfg.ProviderVLANId),
			ProviderAddressId:   network.Id(cfg.ProviderAddressId),
			VLANTag:             cfg.VLANTag,
			InterfaceName:       cfg.InterfaceName,
			ParentInterfaceName: cfg.ParentInterfaceName,
			InterfaceType:       network.InterfaceType(cfg.InterfaceType),
			Disabled:            cfg.Disabled,
			NoAutoStart:         cfg.NoAutoStart,
			ConfigType:          network.InterfaceConfigType(cfg.ConfigType),
			Address:             network.NewAddress(cfg.Address),
			DNSServers:          network.NewAddresses(cfg.DNSServers...),
			DNSSearchDomains:    cfg.DNSSearchDomains,
			GatewayAddress:      network.NewAddress(cfg.GatewayAddress),
		}
	}
	return ifaceInfo, nil
}
Example #4
0
func (s *ContainerSetupSuite) setupContainerWorker(c *gc.C, tag names.MachineTag) (worker.StringsWatchHandler, worker.Runner) {
	runner := worker.NewRunner(allFatal, noImportance)
	pr := s.st.Provisioner()
	machine, err := pr.Machine(tag)
	c.Assert(err, gc.IsNil)
	err = machine.SetSupportedContainers(instance.ContainerTypes...)
	c.Assert(err, gc.IsNil)
	cfg := s.AgentConfigForTag(c, tag.String())

	watcherName := fmt.Sprintf("%s-container-watcher", machine.Id())
	handler := provisioner.NewContainerSetupHandler(runner, watcherName, instance.ContainerTypes, machine, pr, cfg, s.initLock)
	runner.StartWorker(watcherName, func() (worker.Worker, error) {
		return worker.NewStringsWorker(handler), nil
	})
	return handler, runner
}
Example #5
0
// WatchMachine watches for changes to the specified machine.
func (st *State) WatchMachine(m names.MachineTag) (watcher.NotifyWatcher, error) {
	var results params.NotifyWatchResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: m.String()}},
	}
	err := st.facade.FacadeCall("WatchMachines", args, &results)
	if err != nil {
		return nil, err
	}
	if len(results.Results) != 1 {
		panic(errors.Errorf("expected 1 result, got %d", len(results.Results)))
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, result.Error
	}
	w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result)
	return w, nil
}
Example #6
0
// MachineNetworkConfig returns information about network interfaces to
// setup only for a single machine.
func (st *state) MachineNetworkConfig(tag names.MachineTag) ([]network.InterfaceInfo, error) {
	args := params.Entities{
		Entities: []params.Entity{{Tag: tag.String()}},
	}
	var results params.MachineNetworkConfigResults
	err := st.facade.FacadeCall("MachineNetworkConfig", args, &results)
	if err != nil {
		if params.IsCodeNotImplemented(err) {
			// Fallback to former name.
			err = st.facade.FacadeCall("MachineNetworkInfo", args, &results)
		}
		if err != nil {
			// TODO: Not directly tested.
			return nil, err
		}
	}
	if len(results.Results) != 1 {
		// TODO: Not directly tested
		err = errors.Errorf("expected one result, got %d", len(results.Results))
		return nil, err
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, result.Error
	}
	interfaceInfo := make([]network.InterfaceInfo, len(result.Config))
	for i, ifaceInfo := range result.Config {
		interfaceInfo[i].DeviceIndex = ifaceInfo.DeviceIndex
		interfaceInfo[i].MACAddress = ifaceInfo.MACAddress
		interfaceInfo[i].CIDR = ifaceInfo.CIDR
		interfaceInfo[i].NetworkName = ifaceInfo.NetworkName
		interfaceInfo[i].ProviderId = network.Id(ifaceInfo.ProviderId)
		interfaceInfo[i].VLANTag = ifaceInfo.VLANTag
		interfaceInfo[i].InterfaceName = ifaceInfo.InterfaceName
		interfaceInfo[i].Disabled = ifaceInfo.Disabled
		// TODO(dimitern) Once we store all the information from
		// network.InterfaceInfo in state, change this as needed to
		// return it.
	}

	return interfaceInfo, nil
}
Example #7
0
// AuthorisedKeys returns the authorised ssh keys for the machine specified by machineTag.
func (st *State) AuthorisedKeys(tag names.MachineTag) ([]string, error) {
	var results params.StringsResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: tag.String()}},
	}
	err := st.facade.FacadeCall("AuthorisedKeys", args, &results)
	if err != nil {
		// TODO: Not directly tested
		return nil, err
	}
	if len(results.Results) != 1 {
		// TODO: Not directly tested
		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if err := result.Error; err != nil {
		return nil, err
	}
	return result.Result, nil
}
Example #8
0
// Tools returns the agent tools for the given entity.
func (st *State) Tools(tag names.MachineTag) (*tools.Tools, error) {
	var results params.ToolsResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: tag.String()}},
	}
	err := st.call("Tools", args, &results)
	if err != nil {
		// TODO: Not directly tested
		return nil, err
	}
	if len(results.Results) != 1 {
		// TODO: Not directly tested
		return nil, fmt.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if err := result.Error; err != nil {
		return nil, err
	}
	return result.Tools, nil
}
Example #9
0
// MachineNetworkInfo returns information about networks to setup only for a single machine.
func (st *State) MachineNetworkInfo(tag names.MachineTag) ([]network.Info, error) {
	args := params.Entities{
		Entities: []params.Entity{{Tag: tag.String()}},
	}
	var results params.MachineNetworkInfoResults
	err := st.facade.FacadeCall("MachineNetworkInfo", args, &results)
	if err != nil {
		// TODO: Not directly tested
		return nil, err
	}
	if len(results.Results) != 1 {
		// TODO: Not directly tested
		err = errors.Errorf("expected one result, got %d", len(results.Results))
		return nil, err
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, result.Error
	}
	return results.Results[0].Info, nil
}
Example #10
0
// WatchAuthorisedKeys returns a notify watcher that looks for changes in the
// authorised ssh keys for the machine specified by machineTag.
func (st *State) WatchAuthorisedKeys(tag names.MachineTag) (watcher.NotifyWatcher, error) {
	var results params.NotifyWatchResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: tag.String()}},
	}
	err := st.facade.FacadeCall("WatchAuthorisedKeys", args, &results)
	if err != nil {
		// TODO: Not directly tested
		return nil, err
	}
	if len(results.Results) != 1 {
		// TODO: Not directly tested
		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
	}
	result := results.Results[0]
	if result.Error != nil {
		//  TODO: Not directly tested
		return nil, result.Error
	}
	w := watcher.NewNotifyWatcher(st.facade.RawAPICaller(), result)
	return w, nil
}
Example #11
0
// WatchInterfaces returns a NotifyWatcher that notifies of changes to network
// interfaces on the machine.
func (st *state) WatchInterfaces(tag names.MachineTag) (watcher.NotifyWatcher, error) {
	args := params.Entities{
		Entities: []params.Entity{{Tag: tag.String()}},
	}
	var results params.NotifyWatchResults
	err := st.facade.FacadeCall("WatchInterfaces", args, &results)
	if err != nil {
		// TODO: Not directly tested
		return nil, err
	}
	if len(results.Results) != 1 {
		// TODO: Not directly tested
		err = errors.Errorf("expected one result, got %d", len(results.Results))
		return nil, err
	}
	result := results.Results[0]
	if result.Error != nil {
		return nil, result.Error
	}
	w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result)
	return w, nil
}
Example #12
0
// WatchActionNotifications returns a StringsWatcher for observing the
// IDs of Actions added to the Machine. The initial event will contain the
// IDs of any Actions pending at the time the Watcher is made.
func (c *Client) WatchActionNotifications(agent names.MachineTag) (watcher.StringsWatcher, error) {
	var results params.StringsWatchResults
	args := params.Entities{
		Entities: []params.Entity{{Tag: agent.String()}},
	}

	err := c.facade.FacadeCall("WatchActionNotifications", args, &results)
	if err != nil {
		return nil, errors.Trace(err)
	}

	if len(results.Results) != 1 {
		return nil, errors.Errorf("expected 1 result, got %d", len(results.Results))
	}

	result := results.Results[0]
	if result.Error != nil {
		return nil, errors.Trace(result.Error)
	}
	w := apiwatcher.NewStringsWatcher(c.facade.RawAPICaller(), result)
	return w, nil
}
Example #13
0
// RunningActions returns a list of actions running for the given machine tag.
func (c *Client) RunningActions(agent names.MachineTag) ([]params.ActionResult, error) {
	var results params.ActionsByReceivers

	args := params.Entities{
		Entities: []params.Entity{{Tag: agent.String()}},
	}

	err := c.facade.FacadeCall("RunningActions", args, &results)
	if err != nil {
		return nil, errors.Trace(err)
	}

	if len(results.Actions) != 1 {
		return nil, errors.Errorf("expected 1 result, got %d", len(results.Actions))
	}

	result := results.Actions[0]
	if result.Error != nil {
		return nil, result.Error
	}

	return result.Actions, nil
}
Example #14
0
// machineStorageDecrefOp returns a txn.Op that will decrement the attachment
// count for a given machine storage entity (volume or filesystem), given its
// current attachment count and lifecycle state. If the attachment count goes
// to zero, then the entity should become Dead.
func machineStorageDecrefOp(
	collection, id string,
	attachmentCount int, life Life,
	machine names.MachineTag,
	binding string,
) txn.Op {
	op := txn.Op{
		C:  collection,
		Id: id,
	}
	if life == Dying {
		if attachmentCount == 1 {
			// This is the last attachment: the volume can be
			// marked Dead. There can be no concurrent attachments
			// since it is Dying.
			op.Assert = bson.D{
				{"life", Dying},
				{"attachmentcount", 1},
			}
			op.Update = bson.D{
				{"$inc", bson.D{{"attachmentcount", -1}}},
				{"$set", bson.D{{"life", Dead}}},
			}
		} else {
			// This is not the last attachment; just decref,
			// allowing for concurrent attachment removals but
			// ensuring we don't drop to zero without marking
			// the volume Dead.
			op.Assert = bson.D{
				{"life", Dying},
				{"attachmentcount", bson.D{{"$gt", 1}}},
			}
			op.Update = bson.D{
				{"$inc", bson.D{{"attachmentcount", -1}}},
			}
		}
	} else {
		// The volume is still Alive: decref, retrying if the
		// volume is destroyed concurrently or the binding changes.
		// If the volume is bound to the machine, advance it to
		// Dead; binding storage to a machine and attaching the
		// storage to multiple machines will be mutually exclusive.
		//
		// Otherwise, when DestroyVolume is called, the volume will
		// be marked Dead if it has no attachments.
		update := bson.D{
			{"$inc", bson.D{{"attachmentcount", -1}}},
		}
		if binding == machine.String() {
			update = append(update, bson.DocElem{
				"$set", bson.D{{"life", Dead}},
			})
		}
		op.Assert = bson.D{
			{"life", Alive},
			{"binding", binding},
			{"attachmentcount", bson.D{{"$gt", 0}}},
		}
		op.Update = update
	}
	return op
}