// OpenedPorts returns a map of network.PortRange to unit tag for all opened // port ranges on the machine for the subnet matching given subnetTag. func (m *Machine) OpenedPorts(subnetTag names.SubnetTag) (map[network.PortRange]names.UnitTag, error) { var results params.MachinePortsResults var subnetTagAsString string if subnetTag.Id() != "" { subnetTagAsString = subnetTag.String() } args := params.MachinePortsParams{ Params: []params.MachinePorts{ {MachineTag: m.tag.String(), SubnetTag: subnetTagAsString}, }, } err := m.st.facade.FacadeCall("GetMachinePorts", 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 } // Convert string tags to names.UnitTag before returning. endResult := make(map[network.PortRange]names.UnitTag) for _, ports := range result.Ports { unitTag, err := names.ParseUnitTag(ports.UnitTag) if err != nil { return nil, err } endResult[ports.PortRange.NetworkPortRange()] = unitTag } return endResult, nil }
// 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 }
// validateSubnet ensures either subnetTag or providerId is valid (not both), // then uses the cache to validate and lookup the provider SubnetInfo for the // subnet, if found. func (cache *addSubnetsCache) validateSubnet(subnetTag, providerId string) (*network.SubnetInfo, error) { haveTag := subnetTag != "" haveProviderId := providerId != "" if !haveTag && !haveProviderId { return nil, errors.Errorf("either SubnetTag or SubnetProviderId is required") } else if haveTag && haveProviderId { return nil, errors.Errorf("SubnetTag and SubnetProviderId cannot be both set") } var tag names.SubnetTag if haveTag { var err error tag, err = names.ParseSubnetTag(subnetTag) if err != nil { return nil, errors.Annotate(err, "given SubnetTag is invalid") } } // Otherwise we need the cache to validate. if err := cache.cacheSubnets(); err != nil { return nil, errors.Trace(err) } if haveTag { providerIds, ok := cache.providerIdsByCIDR[tag.Id()] if !ok || providerIds.IsEmpty() { return nil, errors.NotFoundf("subnet with CIDR %q", tag.Id()) } if providerIds.Size() > 1 { ids := `"` + strings.Join(providerIds.SortedValues(), `", "`) + `"` return nil, errors.Errorf( "multiple subnets with CIDR %q: retry using ProviderId from: %s", tag.Id(), ids, ) } // A single CIDR matched. providerId = providerIds.Values()[0] } info, ok := cache.subnetsByProviderId[providerId] if !ok || info == nil { return nil, errors.NotFoundf( "subnet with CIDR %q and ProviderId %q", tag.Id(), providerId, ) } // Do last-call validation. if !names.IsValidSubnet(info.CIDR) { _, ipnet, err := net.ParseCIDR(info.CIDR) if err != nil && info.CIDR != "" { // The underlying error is not important here, just that // the CIDR is invalid. return nil, errors.Errorf( "subnet with CIDR %q and ProviderId %q: invalid CIDR", info.CIDR, providerId, ) } if info.CIDR == "" { return nil, errors.Errorf( "subnet with ProviderId %q: empty CIDR", providerId, ) } return nil, errors.Errorf( "subnet with ProviderId %q: incorrect CIDR format %q, expected %q", providerId, info.CIDR, ipnet.String(), ) } return info, nil }