func logAllSeverities(logger loggo.Logger) { logger.Criticalf("something critical") logger.Errorf("an error") logger.Warningf("a warning message") logger.Infof("an info message") logger.Debugf("a debug message") logger.Tracef("a trace message") }
func (c *Client) sendRateLimitedRequest(method, URL string, headers http.Header, reqData []byte, logger *loggo.Logger) (resp *http.Response, err error) { for i := 0; i < c.maxSendAttempts; i++ { var reqReader io.Reader if reqData != nil { reqReader = bytes.NewReader(reqData) } req, err := http.NewRequest(method, URL, reqReader) if err != nil { err = errors.Newf(err, "failed creating the request %s", URL) return nil, err } // Setting req.Close to true to avoid malformed HTTP version "nullHTTP/1.1" error // See http://stackoverflow.com/questions/17714494/golang-http-request-results-in-eof-errors-when-making-multiple-requests-successi req.Close = true for header, values := range headers { for _, value := range values { req.Header.Add(header, value) } } req.ContentLength = int64(len(reqData)) resp, err = c.Do(req) if err != nil { return nil, errors.Newf(err, "failed executing the request %s", URL) } if resp.StatusCode != http.StatusRequestEntityTooLarge || resp.Header.Get("Retry-After") == "" { return resp, nil } resp.Body.Close() retryAfter, err := strconv.ParseFloat(resp.Header.Get("Retry-After"), 64) if err != nil { return nil, errors.Newf(err, "Invalid Retry-After header %s", URL) } if retryAfter == 0 { return nil, errors.Newf(err, "Resource limit exeeded at URL %s", URL) } if logger != nil { logger.Warningf("Too many requests, retrying in %dms.", int(retryAfter*1000)) } time.Sleep(time.Duration(retryAfter) * time.Second) } return nil, errors.Newf(err, "Maximum number of attempts (%d) reached sending request to %s", c.maxSendAttempts, URL) }
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 releaseContainerAddresses( api APICalls, instanceID instance.Id, namespace instance.Namespace, log loggo.Logger, ) { containerTag, err := namespace.MachineTag(string(instanceID)) 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 prepareOrGetContainerInterfaceInfo( api APICalls, machineID string, bridgeDevice string, allocateOrMaintain bool, enableNAT bool, startingNetworkInfo []network.InterfaceInfo, log loggo.Logger, providerType string, ) ([]network.InterfaceInfo, error) { maintain := !allocateOrMaintain if environs.AddressAllocationEnabled(providerType) { if maintain { log.Debugf("running maintenance for container %q", machineID) } else { log.Debugf("trying to allocate static IP for container %q", machineID) } allocatedInfo, err := configureContainerNetwork( machineID, bridgeDevice, api, startingNetworkInfo, allocateOrMaintain, enableNAT, ) if err != nil && !maintain { log.Infof("not allocating static IP for container %q: %v", machineID, err) } return allocatedInfo, err } if maintain { log.Debugf("address allocation disabled: Not running maintenance for machine %q", machineID) return nil, nil } log.Debugf("address allocation feature flag not enabled; using multi-bridge networking for container %q", machineID) // In case we're running on MAAS 1.8+ with devices support, we'll still // call PrepareContainerInterfaceInfo(), but we'll ignore a NotSupported // error if we get it (which means we're not using MAAS 1.8+). containerTag := names.NewMachineTag(machineID) preparedInfo, err := api.PrepareContainerInterfaceInfo(containerTag) if err != nil && errors.IsNotSupported(err) { log.Warningf("new container %q not registered as device: not running on MAAS 1.8+", machineID) return nil, nil } else if err != nil { return nil, errors.Trace(err) } log.Tracef("PrepareContainerInterfaceInfo returned %+v", preparedInfo) dnsServersFound := false for _, info := range preparedInfo { if len(info.DNSServers) > 0 { dnsServersFound = true break } } if !dnsServersFound { logger.Warningf("no DNS settings found, discovering the host settings") dnsServers, searchDomain, err := localDNSServers() if err != nil { return nil, errors.Trace(err) } // Since the result is sorted, the first entry is the primary NIC. preparedInfo[0].DNSServers = dnsServers preparedInfo[0].DNSSearchDomains = []string{searchDomain} logger.Debugf( "setting DNS servers %+v and domains %+v on container interface %q", preparedInfo[0].DNSServers, preparedInfo[0].DNSSearchDomains, preparedInfo[0].InterfaceName, ) } return preparedInfo, nil }
func prepareOrGetContainerInterfaceInfo( api APICalls, machineID string, bridgeDevice string, allocateOrMaintain bool, enableNAT bool, startingNetworkInfo []network.InterfaceInfo, log loggo.Logger, ) ([]network.InterfaceInfo, error) { maintain := !allocateOrMaintain if environs.AddressAllocationEnabled() { if maintain { log.Debugf("running maintenance for container %q", machineID) } else { log.Debugf("trying to allocate static IP for container %q", machineID) } allocatedInfo, err := configureContainerNetwork( machineID, bridgeDevice, api, startingNetworkInfo, allocateOrMaintain, enableNAT, ) if err != nil && !maintain { log.Infof("not allocating static IP for container %q: %v", machineID, err) } return allocatedInfo, err } if maintain { log.Debugf("address allocation disabled: Not running maintenance for machine %q", machineID) return nil, nil } log.Debugf("address allocation feature flag not enabled; using DHCP for container %q", machineID) // In case we're running on MAAS 1.8+ with devices support, we'll still // call PrepareContainerInterfaceInfo(), but we'll ignore a NotSupported // error if we get it (which means we're not using MAAS 1.8+). containerTag := names.NewMachineTag(machineID) preparedInfo, err := api.PrepareContainerInterfaceInfo(containerTag) if err != nil && errors.IsNotSupported(err) { log.Warningf("new container %q not registered as device: not running on MAAS 1.8+", machineID) return nil, nil } else if err != nil { return nil, errors.Trace(err) } dnsServers, searchDomain, dnsErr := localDNSServers() if dnsErr != nil { return nil, errors.Trace(dnsErr) } for i, _ := range preparedInfo { preparedInfo[i].DNSServers = dnsServers preparedInfo[i].DNSSearch = searchDomain } log.Tracef("PrepareContainerInterfaceInfo returned %#v", preparedInfo) // Most likely there will be only one item in the list, but check // all of them for forward compatibility. macAddresses := set.NewStrings() for _, prepInfo := range preparedInfo { macAddresses.Add(prepInfo.MACAddress) } log.Infof( "new container %q registered as a MAAS device with MAC address(es) %v", machineID, macAddresses.SortedValues(), ) return preparedInfo, nil }