<commit_before>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package addresser

import (
	"github.com/juju/errors"
	"github.com/juju/loggo"

	"github.com/juju/juju/apiserver/common"
	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/environs"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/network"
	"github.com/juju/juju/state"
	"github.com/juju/juju/state/watcher"
)

func init() {
	common.RegisterStandardFacade("Addresser", 1, NewAddresserAPI)
}

var logger = loggo.GetLogger("juju.apiserver.addresser")

// AddresserAPI provides access to the Addresser API facade.
type AddresserAPI struct {
	st            StateInterface
	resources     *common.Resources
	authorizer    common.Authorizer
	netEnv        environs.NetworkingEnviron
	canDeallocate bool
}

// NewAddresserAPI creates a new server-side Addresser API facade.
func NewAddresserAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*AddresserAPI, error) {
	isEnvironManager := authorizer.AuthEnvironManager()
	if !isEnvironManager {
		// Addresser must run as environment manager.
		return nil, common.ErrPerm
	}
	sti := getState(st)
	return &AddresserAPI{
		st:         sti,
		resources:  resources,
		authorizer: authorizer,
	}, nil
}

// CanDeallocateAddresses checks if the current environment can
// deallocate IP addresses.
func (api *AddresserAPI) CanDeallocateAddresses() params.BoolResult {
	result := params.BoolResult{}
	// Create an environment to verify networking support.
	config, err := api.st.EnvironConfig()
	if err != nil {
		err = errors.Annotate(err, "getting environment config")
		result.Error = common.ServerError(err)
		return result
	}
	env, err := environs.New(config)
	if err != nil {
		err = errors.Annotate(err, "validating environment config")
		result.Error = common.ServerError(err)
		return result
	}
	netEnv, ok := environs.SupportsNetworking(env)
	if !ok {
		result.Error = common.ServerError(errors.NotSupportedf("IP address deallocation"))
		return result
	}
	api.netEnv = netEnv
	api.canDeallocate, err = api.netEnv.SupportsAddressAllocation(network.AnySubnet)
	if err != nil {
		err = errors.Annotate(err, "checking allocation support")
		result.Error = common.ServerError(err)
		return result
	}
	result.Result = api.canDeallocate
	return result
}

// CleanupIPAddresses releases and removes the dead IP addresses.
func (api *AddresserAPI) CleanupIPAddresses() params.ErrorResult {
	result := params.ErrorResult{}
	// Lazy setting of the networking environment, so only
	// has to be done once.
	if api.netEnv == nil {
		checkResult := api.CanDeallocateAddresses()
		if checkResult.Error != nil {
			result.Error = checkResult.Error<commit_msg>Set correct error if environment does not support allocation.<commit_after>// Copyright 2015 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package addresser

import (
	"github.com/juju/errors"
	"github.com/juju/loggo"

	"github.com/juju/juju/apiserver/common"
	"github.com/juju/juju/apiserver/params"
	"github.com/juju/juju/environs"
	"github.com/juju/juju/instance"
	"github.com/juju/juju/network"
	"github.com/juju/juju/state"
	"github.com/juju/juju/state/watcher"
)

func init() {
	common.RegisterStandardFacade("Addresser", 1, NewAddresserAPI)
}

var logger = loggo.GetLogger("juju.apiserver.addresser")

// AddresserAPI provides access to the Addresser API facade.
type AddresserAPI struct {
	st            StateInterface
	resources     *common.Resources
	authorizer    common.Authorizer
	netEnv        environs.NetworkingEnviron
	canDeallocate bool
}

// NewAddresserAPI creates a new server-side Addresser API facade.
func NewAddresserAPI(
	st *state.State,
	resources *common.Resources,
	authorizer common.Authorizer,
) (*AddresserAPI, error) {
	isEnvironManager := authorizer.AuthEnvironManager()
	if !isEnvironManager {
		// Addresser must run as environment manager.
		return nil, common.ErrPerm
	}
	sti := getState(st)
	return &AddresserAPI{
		st:         sti,
		resources:  resources,
		authorizer: authorizer,
	}, nil
}

// CanDeallocateAddresses checks if the current environment can
// deallocate IP addresses.
func (api *AddresserAPI) CanDeallocateAddresses() params.BoolResult {
	result := params.BoolResult{}
	// Create an environment to verify networking support.
	config, err := api.st.EnvironConfig()
	if err != nil {
		err = errors.Annotate(err, "getting environment config")
		result.Error = common.ServerError(err)
		return result
	}
	env, err := environs.New(config)
	if err != nil {
		err = errors.Annotate(err, "validating environment config")
		result.Error = common.ServerError(err)
		return result
	}
	netEnv, ok := environs.SupportsNetworking(env)
	if !ok {
		result.Error = common.ServerError(errors.NotSupportedf("IP address deallocation"))
		return result
	}
	api.netEnv = netEnv
	api.canDeallocate, err = api.netEnv.SupportsAddressAllocation(network.AnySubnet)
	if err != nil {
		err = errors.Annotate(err, "checking allocation support")
		result.Error = common.ServerError(err)
		return result
	}
	if !api.canDeallocate {
		result.Error = common.ServerError(errors.NotSupportedf("IP address deallocation"))
		return result
	}
	result.Result = api.canDeallocate
	return result
}

// CleanupIPAddresses releases and removes the dead IP addresses.
func (api *AddresserAPI) CleanupIPAddresses() params.ErrorResult {
	result := params.ErrorResult{}
	// Lazy setting of the networking environment, so only
	// has to be done once.
	if api.netEnv == nil {
		checkResult := api.CanDeallocateAddresses()
		if checkResult.Error != nil {
			result.Error = checkResult.Error
{'fraction_non_alphanumeric': 0.10579123393768702, 'fraction_numerical': 0.002112304171800739, 'mean_word_length': 4.30532212885154, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2740560', 'n_tokens_mistral': 1980, 'n_tokens_neox': 1836, 'n_words': 457}