// 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 }
// 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() }
// 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 }
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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }
// 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 }