// GetMachineActiveNetworks returns the tags of the all networks the // each given machine has open ports on. func (f *FirewallerAPI) GetMachineActiveNetworks(args params.Entities) (params.StringsResults, error) { result := params.StringsResults{ Results: make([]params.StringsResult, len(args.Entities)), } canAccess, err := f.accessMachine() if err != nil { return params.StringsResults{}, err } for i, entity := range args.Entities { machineTag, err := names.ParseMachineTag(entity.Tag) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } machine, err := f.getMachine(canAccess, machineTag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } ports, err := machine.AllPorts() if err != nil { result.Results[i].Error = common.ServerError(err) continue } for _, port := range ports { networkTag := names.NewNetworkTag(port.NetworkName()).String() result.Results[i].Result = append(result.Results[i].Result, networkTag) } } return result, nil }
// SetInstanceInfo sets the provider specific machine id, nonce, // metadata and network info for each given machine. Once set, the // instance id cannot be changed. func (p *ProvisionerAPI) SetInstanceInfo(args params.InstancesInfo) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Machines)), } canAccess, err := p.getAuthFunc() if err != nil { return result, err } for i, arg := range args.Machines { tag, err := names.ParseMachineTag(arg.Tag) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } machine, err := p.getMachine(canAccess, tag) if err == nil { var networks []state.NetworkInfo var interfaces []state.NetworkInterfaceInfo networks, interfaces, err = networkParamsToStateParams(arg.Networks, arg.Interfaces) if err == nil { err = machine.SetInstanceInfo( arg.InstanceId, arg.Nonce, arg.Characteristics, networks, interfaces) } if err != nil { // Give the user more context about the error. err = fmt.Errorf("aborted instance %q: %v", arg.InstanceId, err) } } result.Results[i].Error = common.ServerError(err) } return result, nil }
func (d *DiskManagerAPI) SetMachineBlockDevices(args params.SetMachineBlockDevices) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.MachineBlockDevices)), } canAccess, err := d.getAuthFunc() if err != nil { return result, err } for i, arg := range args.MachineBlockDevices { tag, err := names.ParseMachineTag(arg.Machine) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } if !canAccess(tag) { err = common.ErrPerm } else { // TODO(axw) create volumes for block devices without matching // volumes, if and only if the block device has a serial. Under // the assumption of unique (to a machine) serial IDs, this // gives us a guaranteed *persistently* unique way of identifying // the volume. // // NOTE: we must predicate the above on there being no unprovisioned // volume attachments for the machine, otherwise we would have // a race between the volume attachment info being recorded and // the diskmanager publishing block devices and erroneously creating // volumes. err = d.st.SetMachineBlockDevices(tag.Id(), stateBlockDeviceInfo(arg.BlockDevices)) // TODO(axw) set volume/filesystem attachment info. } result.Results[i].Error = common.ServerError(err) } return result, nil }
func (api *MachinerAPI) getMachineForSettingNetworkConfig(machineTag string) (*state.Machine, error) { canModify, err := api.getCanModify() if err != nil { return nil, errors.Trace(err) } tag, err := names.ParseMachineTag(machineTag) if err != nil { return nil, errors.Trace(err) } if !canModify(tag) { return nil, errors.Trace(common.ErrPerm) } m, err := api.getMachine(tag) if errors.IsNotFound(err) { return nil, errors.Trace(common.ErrPerm) } else if err != nil { return nil, errors.Trace(err) } if m.IsContainer() { logger.Warningf("not updating network config for container %q", m.Id()) } return m, nil }
// SetSupportedContainers updates the list of containers supported by the machines passed in args. func (p *ProvisionerAPI) SetSupportedContainers(args params.MachineContainersParams) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Params)), } canAccess, err := p.getAuthFunc() if err != nil { return result, err } for i, arg := range args.Params { tag, err := names.ParseMachineTag(arg.MachineTag) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } machine, err := p.getMachine(canAccess, tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } if len(arg.ContainerTypes) == 0 { err = machine.SupportsNoContainers() } else { err = machine.SetSupportedContainers(arg.ContainerTypes) } if err != nil { result.Results[i].Error = common.ServerError(err) } } return result, nil }
// InstanceStatus returns the instance status for each given entity. // Only machine tags are accepted. func (p *ProvisionerAPI) InstanceStatus(args params.Entities) (params.StatusResults, error) { result := params.StatusResults{ Results: make([]params.StatusResult, len(args.Entities)), } canAccess, err := p.getAuthFunc() if err != nil { logger.Errorf("failed to get an authorisation function: %v", err) return result, errors.Trace(err) } for i, arg := range args.Entities { mTag, err := names.ParseMachineTag(arg.Tag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } machine, err := p.getMachine(canAccess, mTag) if err == nil { var statusInfo status.StatusInfo statusInfo, err = machine.InstanceStatus() result.Results[i].Status = statusInfo.Status result.Results[i].Info = statusInfo.Message result.Results[i].Data = statusInfo.Data result.Results[i].Since = statusInfo.Since } result.Results[i].Error = common.ServerError(err) } return result, nil }
// Constraints returns the constraints for each given machine entity. func (p *ProvisionerAPI) Constraints(args params.Entities) (params.ConstraintsResults, error) { result := params.ConstraintsResults{ Results: make([]params.ConstraintsResult, len(args.Entities)), } canAccess, err := p.getAuthFunc() if err != nil { return result, err } for i, entity := range args.Entities { tag, err := names.ParseMachineTag(entity.Tag) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } machine, err := p.getMachine(canAccess, tag) if err == nil { var cons constraints.Value cons, err = machine.Constraints() if err == nil { result.Results[i].Constraints = cons } } result.Results[i].Error = common.ServerError(err) } return result, nil }
// DistributionGroup returns, for each given machine entity, // a slice of instance.Ids that belong to the same distribution // group as that machine. This information may be used to // distribute instances for high availability. func (p *ProvisionerAPI) DistributionGroup(args params.Entities) (params.DistributionGroupResults, error) { result := params.DistributionGroupResults{ Results: make([]params.DistributionGroupResult, len(args.Entities)), } canAccess, err := p.getAuthFunc() if err != nil { return result, err } for i, entity := range args.Entities { tag, err := names.ParseMachineTag(entity.Tag) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } machine, err := p.getMachine(canAccess, tag) if err == nil { // If the machine is an environment manager, return // environment manager instances. Otherwise, return // instances with services in common with the machine // being provisioned. if machine.IsManager() { result.Results[i].Result, err = environManagerInstances(p.st) } else { result.Results[i].Result, err = commonServiceInstances(p.st, machine) } } result.Results[i].Error = common.ServerError(err) } return result, nil }
// API2Payload converts an API Payload info struct into // a payload.FullPayloadInfo struct. func API2Payload(apiInfo Payload) (payload.FullPayloadInfo, error) { labels := make([]string, len(apiInfo.Labels)) copy(labels, apiInfo.Labels) var unit, machine string var empty payload.FullPayloadInfo if apiInfo.Unit != "" { tag, err := names.ParseUnitTag(apiInfo.Unit) if err != nil { return empty, errors.Trace(err) } unit = tag.Id() } if apiInfo.Machine != "" { tag, err := names.ParseMachineTag(apiInfo.Machine) if err != nil { return empty, errors.Trace(err) } machine = tag.Id() } return payload.FullPayloadInfo{ Payload: payload.Payload{ PayloadClass: charm.PayloadClass{ Name: apiInfo.Class, Type: apiInfo.Type, }, ID: apiInfo.ID, Status: apiInfo.Status, Labels: labels, Unit: unit, }, Machine: machine, }, nil }
// RequestedNetworks returns the requested networks for each given // machine entity. Each entry in both lists is returned with its // provider specific id. func (p *ProvisionerAPI) RequestedNetworks(args params.Entities) (params.RequestedNetworksResults, error) { result := params.RequestedNetworksResults{ Results: make([]params.RequestedNetworkResult, len(args.Entities)), } canAccess, err := p.getAuthFunc() if err != nil { return result, err } for i, entity := range args.Entities { tag, err := names.ParseMachineTag(entity.Tag) if err != nil { result.Results[i].Error = common.ServerError(common.ErrPerm) continue } machine, err := p.getMachine(canAccess, tag) if err == nil { var networks []string networks, err = machine.RequestedNetworks() if err == nil { // TODO(dimitern) For now, since network names and // provider ids are the same, we return what we got // from state. In the future, when networks can be // added before provisioning, we should convert both // slices from juju network names to provider-specific // ids before returning them. result.Results[i].Networks = networks } } result.Results[i].Error = common.ServerError(err) } return result, nil }
// WatchBlockDevices watches for changes to the specified machines' block devices. func (s *StorageProvisionerAPI) WatchBlockDevices(args params.Entities) (params.NotifyWatchResults, error) { canAccess, err := s.getBlockDevicesAuthFunc() if err != nil { return params.NotifyWatchResults{}, common.ServerError(common.ErrPerm) } results := params.NotifyWatchResults{ Results: make([]params.NotifyWatchResult, len(args.Entities)), } one := func(arg params.Entity) (string, error) { machineTag, err := names.ParseMachineTag(arg.Tag) if err != nil { return "", err } if !canAccess(machineTag) { return "", common.ErrPerm } w := s.st.WatchBlockDevices(machineTag) if _, ok := <-w.Changes(); ok { return s.resources.Register(w), nil } return "", watcher.EnsureErr(w) } for i, arg := range args.Entities { var result params.NotifyWatchResult id, err := one(arg) if err != nil { result.Error = common.ServerError(err) } else { result.NotifyWatcherId = id } results.Results[i] = result } return results, nil }
func maybeReleaseContainerAddresses( api APICalls, instanceID instance.Id, namespace string, log loggo.Logger, ) { if environs.AddressAllocationEnabled() { // The addresser worker will take care of the addresses. return } // If we're not using addressable containers, we might still have used MAAS // 1.8+ device to register the container when provisioning. In that case we // need to attempt releasing the device, but ignore a NotSupported error // (when we're not using MAAS 1.8+). namespacePrefix := fmt.Sprintf("%s-", namespace) tagString := strings.TrimPrefix(string(instanceID), namespacePrefix) containerTag, err := names.ParseMachineTag(tagString) if err != nil { // Not a reason to cause StopInstances to fail though.. log.Warningf("unexpected container tag %q: %v", instanceID, err) return } err = api.ReleaseContainerAddresses(containerTag) switch { case err == nil: log.Infof("released all addresses for container %q", containerTag.Id()) case errors.IsNotSupported(err): log.Warningf("not releasing all addresses for container %q: %v", containerTag.Id(), err) default: log.Warningf( "unexpected error trying to release container %q addreses: %v", containerTag.Id(), err, ) } }
func (api *MachinerAPI) SetMachineAddresses(args params.SetMachinesAddresses) (params.ErrorResults, error) { results := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.MachineAddresses)), } canModify, err := api.getCanModify() if err != nil { return results, err } for i, arg := range args.MachineAddresses { tag, err := names.ParseMachineTag(arg.Tag) if err != nil { results.Results[i].Error = common.ServerError(common.ErrPerm) continue } err = common.ErrPerm if canModify(tag) { var m *state.Machine m, err = api.getMachine(tag) if err == nil { err = m.SetMachineAddresses(arg.Addresses...) } else if errors.IsNotFound(err) { err = common.ErrPerm } } results.Results[i].Error = common.ServerError(err) } return results, nil }
// prepareContainerAccessEnvironment retrieves the environment, host machine, and access // for working with containers. func (p *ProvisionerAPI) prepareContainerAccessEnvironment() (environs.NetworkingEnviron, *state.Machine, common.AuthFunc, error) { cfg, err := p.st.EnvironConfig() if err != nil { return nil, nil, nil, errors.Annotate(err, "failed to get environment config") } environ, err := environs.New(cfg) if err != nil { return nil, nil, nil, errors.Annotate(err, "failed to construct an environment from config") } netEnviron, supported := environs.SupportsNetworking(environ) if !supported { // " not supported" will be appended to the message below. return nil, nil, nil, errors.NotSupportedf("environment %q networking", cfg.Name()) } canAccess, err := p.getAuthFunc() if err != nil { return nil, nil, nil, errors.Annotate(err, "cannot authenticate request") } hostAuthTag := p.authorizer.GetAuthTag() if hostAuthTag == nil { return nil, nil, nil, errors.Errorf("authenticated entity tag is nil") } hostTag, err := names.ParseMachineTag(hostAuthTag.String()) if err != nil { return nil, nil, nil, errors.Trace(err) } host, err := p.getMachine(canAccess, hostTag) if err != nil { return nil, nil, nil, errors.Trace(err) } return netEnviron, host, canAccess, nil }
func constructStartInstanceParams( machine *apiprovisioner.Machine, instanceConfig *instancecfg.InstanceConfig, provisioningInfo *params.ProvisioningInfo, possibleTools coretools.List, ) (environs.StartInstanceParams, error) { volumes := make([]storage.VolumeParams, len(provisioningInfo.Volumes)) for i, v := range provisioningInfo.Volumes { volumeTag, err := names.ParseVolumeTag(v.VolumeTag) if err != nil { return environs.StartInstanceParams{}, errors.Trace(err) } if v.Attachment == nil { return environs.StartInstanceParams{}, errors.Errorf("volume params missing attachment") } machineTag, err := names.ParseMachineTag(v.Attachment.MachineTag) if err != nil { return environs.StartInstanceParams{}, errors.Trace(err) } if machineTag != machine.Tag() { return environs.StartInstanceParams{}, errors.Errorf("volume attachment params has invalid machine tag") } if v.Attachment.InstanceId != "" { return environs.StartInstanceParams{}, errors.Errorf("volume attachment params specifies instance ID") } volumes[i] = storage.VolumeParams{ volumeTag, v.Size, storage.ProviderType(v.Provider), v.Attributes, v.Tags, &storage.VolumeAttachmentParams{ AttachmentParams: storage.AttachmentParams{ Machine: machineTag, ReadOnly: v.Attachment.ReadOnly, }, Volume: volumeTag, }, } } var subnetsToZones map[network.Id][]string if provisioningInfo.SubnetsToZones != nil { // Convert subnet provider ids from string to network.Id. subnetsToZones = make(map[network.Id][]string, len(provisioningInfo.SubnetsToZones)) for providerId, zones := range provisioningInfo.SubnetsToZones { subnetsToZones[network.Id(providerId)] = zones } } return environs.StartInstanceParams{ Constraints: provisioningInfo.Constraints, Tools: possibleTools, InstanceConfig: instanceConfig, Placement: provisioningInfo.Placement, DistributionGroup: machine.DistributionGroup, Volumes: volumes, SubnetsToZones: subnetsToZones, }, nil }
func (mr *Machiner) SetUp() (watcher.NotifyWatcher, error) { // Find which machine we're responsible for. tag, err := names.ParseMachineTag(mr.tag) if err != nil { return nil, err } m, err := mr.st.Machine(tag) if params.IsCodeNotFoundOrCodeUnauthorized(err) { return nil, worker.ErrTerminateAgent } else if err != nil { return nil, err } mr.machine = m // Set the addresses in state to the host's addresses. if err := setMachineAddresses(m); err != nil { return nil, err } // Mark the machine as started and log it. if err := m.SetStatus(params.StatusStarted, "", nil); err != nil { return nil, fmt.Errorf("%s failed to set status started: %v", mr.tag, err) } logger.Infof("%q started", mr.tag) return m.Watch() }
func (p *ProvisionerAPI) watchOneMachineContainers(arg params.WatchContainer) (params.StringsWatchResult, error) { nothing := params.StringsWatchResult{} canAccess, err := p.getAuthFunc() if err != nil { return nothing, common.ErrPerm } tag, err := names.ParseMachineTag(arg.MachineTag) if err != nil { return nothing, common.ErrPerm } if !canAccess(tag) { return nothing, common.ErrPerm } machine, err := p.st.Machine(tag.Id()) if err != nil { return nothing, err } var watch state.StringsWatcher if arg.ContainerType != "" { watch = machine.WatchContainers(instance.ContainerType(arg.ContainerType)) } else { watch = machine.WatchAllContainers() } // Consume the initial event and forward it to the result. if changes, ok := <-watch.Changes(); ok { return params.StringsWatchResult{ StringsWatcherId: p.resources.Register(watch), Changes: changes, }, nil } return nothing, watcher.EnsureErr(watch) }
func (d *Deployer) SetUp() (watcher.StringsWatcher, error) { machineTag := d.ctx.AgentConfig().Tag() tag, err := names.ParseMachineTag(machineTag) if err != nil { return nil, err } machine, err := d.st.Machine(tag) if err != nil { return nil, err } machineUnitsWatcher, err := machine.WatchUnits() if err != nil { return nil, err } deployed, err := d.ctx.DeployedUnits() if err != nil { return nil, err } for _, unitName := range deployed { d.deployed.Add(unitName) if err := d.changed(unitName); err != nil { return nil, err } } return machineUnitsWatcher, nil }
// ReleaseContainerAddresses finds addresses allocated to a container // and marks them as Dead, to be released and removed. It accepts // container tags as arguments. If address allocation feature flag is // not enabled, it will return a NotSupported error. func (p *ProvisionerAPI) ReleaseContainerAddresses(args params.Entities) (params.ErrorResults, error) { result := params.ErrorResults{ Results: make([]params.ErrorResult, len(args.Entities)), } canAccess, err := p.getAuthFunc() if err != nil { logger.Errorf("failed to get an authorisation function: %v", err) return result, errors.Trace(err) } // Loop over the passed container tags. for i, entity := range args.Entities { tag, err := names.ParseMachineTag(entity.Tag) if err != nil { logger.Warningf("failed to parse machine tag %q: %v", entity.Tag, err) result.Results[i].Error = common.ServerError(common.ErrPerm) continue } // The auth function (canAccess) checks that the machine is a // top level machine (we filter those out next) or that the // machine has the host as a parent. container, err := p.getMachine(canAccess, tag) if err != nil { logger.Warningf("failed to get machine %q: %v", tag, err) result.Results[i].Error = common.ServerError(err) continue } else if !container.IsContainer() { err = errors.Errorf("cannot mark addresses for removal for %q: not a container", tag) result.Results[i].Error = common.ServerError(err) continue } id := container.Id() addresses, err := p.st.AllocatedIPAddresses(id) if err != nil { logger.Warningf("failed to get Id for container %q: %v", tag, err) result.Results[i].Error = common.ServerError(err) continue } deadErrors := []error{} logger.Debugf("for container %q found addresses %v", tag, addresses) for _, addr := range addresses { err = addr.EnsureDead() if err != nil { deadErrors = append(deadErrors, err) continue } } if len(deadErrors) != 0 { err = errors.Errorf("failed to mark all addresses for removal for %q: %v", tag, deadErrors) result.Results[i].Error = common.ServerError(err) } } return result, nil }
// NewProvisionerAPI creates a new server-side ProvisionerAPI facade. func NewProvisionerAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*ProvisionerAPI, error) { if !authorizer.AuthMachineAgent() && !authorizer.AuthEnvironManager() { return nil, common.ErrPerm } getAuthFunc := func() (common.AuthFunc, error) { isEnvironManager := authorizer.AuthEnvironManager() isMachineAgent := authorizer.AuthMachineAgent() authEntityTag := authorizer.GetAuthTag() // TODO(dfc) this func should take a Tag return func(tag string) bool { if isMachineAgent && tag == authEntityTag.String() { // A machine agent can always access its own machine. return true } t, err := names.ParseMachineTag(tag) if err != nil { return false } parentId := state.ParentId(t.Id()) if parentId == "" { // All top-level machines are accessible by the // environment manager. return isEnvironManager } // All containers with the authenticated machine as a // parent are accessible by it. // TODO(dfc) sometimes authEntity tag is nil, which is fine because nil is // only equal to nil, but it suggests someone is passing an authorizer // with a nil tag. return isMachineAgent && names.NewMachineTag(parentId) == authEntityTag }, nil } // Both provisioner types can watch the environment. getCanWatch := common.AuthAlways(true) // Only the environment provisioner can read secrets. getCanReadSecrets := common.AuthAlways(authorizer.AuthEnvironManager()) return &ProvisionerAPI{ Remover: common.NewRemover(st, false, getAuthFunc), StatusSetter: common.NewStatusSetter(st, getAuthFunc), DeadEnsurer: common.NewDeadEnsurer(st, getAuthFunc), PasswordChanger: common.NewPasswordChanger(st, getAuthFunc), LifeGetter: common.NewLifeGetter(st, getAuthFunc), StateAddresser: common.NewStateAddresser(st), APIAddresser: common.NewAPIAddresser(st, resources), ToolsGetter: common.NewToolsGetter(st, getAuthFunc), EnvironWatcher: common.NewEnvironWatcher(st, resources, getCanWatch, getCanReadSecrets), EnvironMachinesWatcher: common.NewEnvironMachinesWatcher(st, resources, getCanReadSecrets), InstanceIdGetter: common.NewInstanceIdGetter(st, getAuthFunc), st: st, resources: resources, authorizer: authorizer, getAuthFunc: getAuthFunc, getCanWatchMachines: getCanReadSecrets, }, nil }
func (s *MachineSuite) TestManageEnvironServesAPI(c *gc.C) { s.assertJobWithState(c, state.JobManageEnviron, func(conf agent.Config, agentState *state.State) { st, err := api.Open(conf.APIInfo(), fastDialOpts) c.Assert(err, gc.IsNil) defer st.Close() tag, err := names.ParseMachineTag(conf.Tag()) c.Assert(err, gc.IsNil) m, err := st.Machiner().Machine(tag) c.Assert(err, gc.IsNil) c.Assert(m.Life(), gc.Equals, params.Alive) }) }
// VolumeAttachmentToState converts a params.VolumeAttachment // to a state.VolumeAttachmentInfo and tags. func VolumeAttachmentToState(in params.VolumeAttachment) (names.MachineTag, names.VolumeTag, state.VolumeAttachmentInfo, error) { machineTag, err := names.ParseMachineTag(in.MachineTag) if err != nil { return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err } volumeTag, err := names.ParseVolumeTag(in.VolumeTag) if err != nil { return names.MachineTag{}, names.VolumeTag{}, state.VolumeAttachmentInfo{}, err } info := VolumeAttachmentInfoToState(in.Info) return machineTag, volumeTag, info, nil }
func (s *machineSuite) TestParseMachineTag(c *gc.C) { for i, t := range parseMachineTagTests { c.Logf("test %d: %s", i, t.tag) got, err := names.ParseMachineTag(t.tag) if err != nil || t.err != nil { c.Check(err, gc.DeepEquals, t.err) continue } c.Check(got, gc.FitsTypeOf, t.expected) c.Check(got, gc.Equals, t.expected) } }
// GetMachinePorts returns the port ranges opened on a machine for the specified // subnet as a map mapping port ranges to the tags of the units that opened // them. func (f *FirewallerAPI) GetMachinePorts(args params.MachinePortsParams) (params.MachinePortsResults, error) { result := params.MachinePortsResults{ Results: make([]params.MachinePortsResult, len(args.Params)), } canAccess, err := f.accessMachine() if err != nil { return params.MachinePortsResults{}, err } for i, param := range args.Params { machineTag, err := names.ParseMachineTag(param.MachineTag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } var subnetTag names.SubnetTag if param.SubnetTag != "" { subnetTag, err = names.ParseSubnetTag(param.SubnetTag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } } machine, err := f.getMachine(canAccess, machineTag) if err != nil { result.Results[i].Error = common.ServerError(err) continue } ports, err := machine.OpenedPorts(subnetTag.Id()) if err != nil { result.Results[i].Error = common.ServerError(err) continue } if ports != nil { portRangeMap := ports.AllPortRanges() var portRanges []network.PortRange for portRange := range portRangeMap { portRanges = append(portRanges, portRange) } network.SortPortRanges(portRanges) for _, portRange := range portRanges { unitTag := names.NewUnitTag(portRangeMap[portRange]).String() result.Results[i].Ports = append(result.Results[i].Ports, params.MachinePortRange{ UnitTag: unitTag, PortRange: params.FromNetworkPortRange(portRange), }) } } } return result, nil }
func (p *containerProvisioner) getMachine() (*apiprovisioner.Machine, error) { if p.machine == nil { tag, err := names.ParseMachineTag(p.agentConfig.Tag()) if err != nil { return nil, err } if p.machine, err = p.st.Machine(tag); err != nil { logger.Errorf("%s is not in state", p.agentConfig.Tag()) return nil, err } } return p.machine, nil }
func filterVolumes( st storageAccess, f params.VolumeFilter, ) ([]state.Volume, map[names.VolumeTag][]state.VolumeAttachment, error) { if f.IsEmpty() { // No filter was specified: get all volumes, and all attachments. volumes, err := st.AllVolumes() if err != nil { return nil, nil, errors.Trace(err) } volumeAttachments := make(map[names.VolumeTag][]state.VolumeAttachment) for _, v := range volumes { attachments, err := st.VolumeAttachments(v.VolumeTag()) if err != nil { return nil, nil, errors.Trace(err) } volumeAttachments[v.VolumeTag()] = attachments } return volumes, volumeAttachments, nil } volumesByTag := make(map[names.VolumeTag]state.Volume) volumeAttachments := make(map[names.VolumeTag][]state.VolumeAttachment) for _, machine := range f.Machines { machineTag, err := names.ParseMachineTag(machine) if err != nil { return nil, nil, errors.Trace(err) } attachments, err := st.MachineVolumeAttachments(machineTag) if err != nil { return nil, nil, errors.Trace(err) } for _, attachment := range attachments { volumeTag := attachment.Volume() volumesByTag[volumeTag] = nil volumeAttachments[volumeTag] = append(volumeAttachments[volumeTag], attachment) } } for volumeTag := range volumesByTag { volume, err := st.Volume(volumeTag) if err != nil { return nil, nil, errors.Trace(err) } volumesByTag[volumeTag] = volume } volumes := make([]state.Volume, 0, len(volumesByTag)) for _, volume := range volumesByTag { volumes = append(volumes, volume) } return volumes, volumeAttachments, nil }
func filterFilesystems( st storageAccess, f params.FilesystemFilter, ) ([]state.Filesystem, map[names.FilesystemTag][]state.FilesystemAttachment, error) { if f.IsEmpty() { // No filter was specified: get all filesystems, and all attachments. filesystems, err := st.AllFilesystems() if err != nil { return nil, nil, errors.Trace(err) } filesystemAttachments := make(map[names.FilesystemTag][]state.FilesystemAttachment) for _, f := range filesystems { attachments, err := st.FilesystemAttachments(f.FilesystemTag()) if err != nil { return nil, nil, errors.Trace(err) } filesystemAttachments[f.FilesystemTag()] = attachments } return filesystems, filesystemAttachments, nil } filesystemsByTag := make(map[names.FilesystemTag]state.Filesystem) filesystemAttachments := make(map[names.FilesystemTag][]state.FilesystemAttachment) for _, machine := range f.Machines { machineTag, err := names.ParseMachineTag(machine) if err != nil { return nil, nil, errors.Trace(err) } attachments, err := st.MachineFilesystemAttachments(machineTag) if err != nil { return nil, nil, errors.Trace(err) } for _, attachment := range attachments { filesystemTag := attachment.Filesystem() filesystemsByTag[filesystemTag] = nil filesystemAttachments[filesystemTag] = append(filesystemAttachments[filesystemTag], attachment) } } for filesystemTag := range filesystemsByTag { filesystem, err := st.Filesystem(filesystemTag) if err != nil { return nil, nil, errors.Trace(err) } filesystemsByTag[filesystemTag] = filesystem } filesystems := make([]state.Filesystem, 0, len(filesystemsByTag)) for _, filesystem := range filesystemsByTag { filesystems = append(filesystems, filesystem) } return filesystems, filesystemAttachments, nil }
// FilesystemAttachmentToState converts a storage.FilesystemAttachment // to a state.FilesystemAttachmentInfo. func FilesystemAttachmentToState(in params.FilesystemAttachment) (names.MachineTag, names.FilesystemTag, state.FilesystemAttachmentInfo, error) { machineTag, err := names.ParseMachineTag(in.MachineTag) if err != nil { return names.MachineTag{}, names.FilesystemTag{}, state.FilesystemAttachmentInfo{}, err } filesystemTag, err := names.ParseFilesystemTag(in.FilesystemTag) if err != nil { return names.MachineTag{}, names.FilesystemTag{}, state.FilesystemAttachmentInfo{}, err } info := state.FilesystemAttachmentInfo{ in.Info.MountPoint, in.Info.ReadOnly, } return machineTag, filesystemTag, info, nil }
func (c *dumpLogsCommand) findMachineId(dataDir string) (string, error) { entries, err := ioutil.ReadDir(agent.BaseDir(dataDir)) if err != nil { return "", errors.Annotate(err, "failed to read agent configuration base directory") } for _, entry := range entries { if entry.IsDir() { tag, err := names.ParseMachineTag(entry.Name()) if err == nil { return tag.Id(), nil } } } return "", errors.New("no machine agent configuration found") }
// updateSupportedContainers records in state that a machine can run the specified containers. // It starts a watcher and when a container of a given type is first added to the machine, // the watcher is killed, the machine is set up to be able to start containers of the given type, // and a suitable provisioner is started. func (a *MachineAgent) updateSupportedContainers( runner worker.Runner, st *api.State, machineTag string, containers []instance.ContainerType, agentConfig agent.Config, ) error { pr := st.Provisioner() tag, err := names.ParseMachineTag(machineTag) if err != nil { return err } machine, err := pr.Machine(tag) if errors.IsNotFound(err) || err == nil && machine.Life() == params.Dead { return worker.ErrTerminateAgent } if err != nil { return errors.Annotatef(err, "cannot load machine %s from state", tag) } if len(containers) == 0 { if err := machine.SupportsNoContainers(); err != nil { return errors.Annotatef(err, "clearing supported containers for %s", tag) } return nil } if err := machine.SetSupportedContainers(containers...); err != nil { return errors.Annotatef(err, "setting supported containers for %s", tag) } initLock, err := hookExecutionLock(agentConfig.DataDir()) if err != nil { return err } // Start the watcher to fire when a container is first requested on the machine. watcherName := fmt.Sprintf("%s-container-watcher", machine.Id()) handler := provisioner.NewContainerSetupHandler( runner, watcherName, containers, machine, pr, agentConfig, initLock, ) a.startWorkerAfterUpgrade(runner, watcherName, func() (worker.Worker, error) { return worker.NewStringsWorker(handler), nil }) return nil }