Exemple #1
0
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")
}
Exemple #2
0
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)
}
Exemple #3
0
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,
		)
	}
}
Exemple #4
0
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,
		)
	}
}
Exemple #5
0
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
}
Exemple #6
0
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
}