github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/api/provisioner/provisioner.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package provisioner
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"github.com/juju/names"
     9  	"github.com/juju/version"
    10  
    11  	"github.com/juju/juju/api/base"
    12  	"github.com/juju/juju/api/common"
    13  	apiwatcher "github.com/juju/juju/api/watcher"
    14  	"github.com/juju/juju/apiserver/params"
    15  	"github.com/juju/juju/network"
    16  	"github.com/juju/juju/tools"
    17  	"github.com/juju/juju/watcher"
    18  )
    19  
    20  // State provides access to the Machiner API facade.
    21  type State struct {
    22  	*common.ModelWatcher
    23  	*common.APIAddresser
    24  
    25  	facade base.FacadeCaller
    26  }
    27  
    28  const provisionerFacade = "Provisioner"
    29  
    30  // NewState creates a new client-side Machiner facade.
    31  func NewState(caller base.APICaller) *State {
    32  	facadeCaller := base.NewFacadeCaller(caller, provisionerFacade)
    33  	return &State{
    34  		ModelWatcher: common.NewModelWatcher(facadeCaller),
    35  		APIAddresser: common.NewAPIAddresser(facadeCaller),
    36  		facade:       facadeCaller}
    37  }
    38  
    39  // machineLife requests the lifecycle of the given machine from the server.
    40  func (st *State) machineLife(tag names.MachineTag) (params.Life, error) {
    41  	return common.Life(st.facade, tag)
    42  }
    43  
    44  // Machine provides access to methods of a state.Machine through the facade.
    45  func (st *State) Machine(tag names.MachineTag) (*Machine, error) {
    46  	life, err := st.machineLife(tag)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	return &Machine{
    51  		tag:  tag,
    52  		life: life,
    53  		st:   st,
    54  	}, nil
    55  }
    56  
    57  // WatchModelMachines returns a StringsWatcher that notifies of
    58  // changes to the lifecycles of the machines (but not containers) in
    59  // the current model.
    60  func (st *State) WatchModelMachines() (watcher.StringsWatcher, error) {
    61  	var result params.StringsWatchResult
    62  	err := st.facade.FacadeCall("WatchModelMachines", nil, &result)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	if err := result.Error; err != nil {
    67  		return nil, result.Error
    68  	}
    69  	w := apiwatcher.NewStringsWatcher(st.facade.RawAPICaller(), result)
    70  	return w, nil
    71  }
    72  
    73  func (st *State) WatchMachineErrorRetry() (watcher.NotifyWatcher, error) {
    74  	var result params.NotifyWatchResult
    75  	err := st.facade.FacadeCall("WatchMachineErrorRetry", nil, &result)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	if err := result.Error; err != nil {
    80  		return nil, result.Error
    81  	}
    82  	w := apiwatcher.NewNotifyWatcher(st.facade.RawAPICaller(), result)
    83  	return w, nil
    84  }
    85  
    86  // StateAddresses returns the list of addresses used to connect to the state.
    87  func (st *State) StateAddresses() ([]string, error) {
    88  	var result params.StringsResult
    89  	err := st.facade.FacadeCall("StateAddresses", nil, &result)
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	return result.Result, nil
    94  }
    95  
    96  // ContainerManagerConfig returns information from the model config that is
    97  // needed for configuring the container manager.
    98  func (st *State) ContainerManagerConfig(args params.ContainerManagerConfigParams) (result params.ContainerManagerConfig, err error) {
    99  	err = st.facade.FacadeCall("ContainerManagerConfig", args, &result)
   100  	return result, err
   101  }
   102  
   103  // ContainerConfig returns information from the model config that is
   104  // needed for container cloud-init.
   105  func (st *State) ContainerConfig() (result params.ContainerConfig, err error) {
   106  	err = st.facade.FacadeCall("ContainerConfig", nil, &result)
   107  	return result, err
   108  }
   109  
   110  // MachinesWithTransientErrors returns a slice of machines and corresponding status information
   111  // for those machines which have transient provisioning errors.
   112  func (st *State) MachinesWithTransientErrors() ([]*Machine, []params.StatusResult, error) {
   113  	var results params.StatusResults
   114  	err := st.facade.FacadeCall("MachinesWithTransientErrors", nil, &results)
   115  	if err != nil {
   116  		return nil, nil, err
   117  	}
   118  	machines := make([]*Machine, len(results.Results))
   119  	for i, status := range results.Results {
   120  		if status.Error != nil {
   121  			continue
   122  		}
   123  		machines[i] = &Machine{
   124  			tag:  names.NewMachineTag(status.Id),
   125  			life: status.Life,
   126  			st:   st,
   127  		}
   128  	}
   129  	return machines, results.Results, nil
   130  }
   131  
   132  // FindTools returns al ist of tools matching the specified version number and
   133  // series, and, arch. If arch is blank, a default will be used.
   134  func (st *State) FindTools(v version.Number, series string, arch string) (tools.List, error) {
   135  	args := params.FindToolsParams{
   136  		Number:       v,
   137  		Series:       series,
   138  		MajorVersion: -1,
   139  		MinorVersion: -1,
   140  	}
   141  	if arch != "" {
   142  		args.Arch = arch
   143  	}
   144  	var result params.FindToolsResult
   145  	if err := st.facade.FacadeCall("FindTools", args, &result); err != nil {
   146  		return nil, err
   147  	}
   148  	if result.Error != nil {
   149  		return nil, result.Error
   150  	}
   151  	return result.List, nil
   152  }
   153  
   154  // ReleaseContainerAddresses releases a static IP address allocated to a
   155  // container.
   156  func (st *State) ReleaseContainerAddresses(containerTag names.MachineTag) (err error) {
   157  	defer errors.DeferredAnnotatef(&err, "cannot release static addresses for %q", containerTag.Id())
   158  	var result params.ErrorResults
   159  	args := params.Entities{
   160  		Entities: []params.Entity{{Tag: containerTag.String()}},
   161  	}
   162  	if err := st.facade.FacadeCall("ReleaseContainerAddresses", args, &result); err != nil {
   163  		return err
   164  	}
   165  	return result.OneError()
   166  }
   167  
   168  // PrepareContainerInterfaceInfo allocates an address and returns
   169  // information to configure networking for a container. It accepts
   170  // container tags as arguments. If the address allocation feature flag
   171  // is not enabled, it returns a NotSupported error.
   172  func (st *State) PrepareContainerInterfaceInfo(containerTag names.MachineTag) ([]network.InterfaceInfo, error) {
   173  	return st.prepareOrGetContainerInterfaceInfo(containerTag, true)
   174  }
   175  
   176  // GetContainerInterfaceInfo returns information to configure networking
   177  // for a container. It accepts container tags as arguments. If the address
   178  // allocation feature flag is not enabled, it returns a NotSupported error.
   179  func (st *State) GetContainerInterfaceInfo(containerTag names.MachineTag) ([]network.InterfaceInfo, error) {
   180  	return st.prepareOrGetContainerInterfaceInfo(containerTag, false)
   181  }
   182  
   183  // prepareOrGetContainerInterfaceInfo returns the necessary information to
   184  // configure network interfaces of a container with allocated static
   185  // IP addresses.
   186  //
   187  // TODO(dimitern): Before we start using this, we need to rename both
   188  // the method and the network.InterfaceInfo type to be called
   189  // InterfaceConfig.
   190  func (st *State) prepareOrGetContainerInterfaceInfo(
   191  	containerTag names.MachineTag, allocateNewAddress bool) (
   192  	[]network.InterfaceInfo, error) {
   193  	var result params.MachineNetworkConfigResults
   194  	args := params.Entities{
   195  		Entities: []params.Entity{{Tag: containerTag.String()}},
   196  	}
   197  	facadeName := ""
   198  	if allocateNewAddress {
   199  		facadeName = "PrepareContainerInterfaceInfo"
   200  	} else {
   201  		facadeName = "GetContainerInterfaceInfo"
   202  	}
   203  	if err := st.facade.FacadeCall(facadeName, args, &result); err != nil {
   204  		return nil, err
   205  	}
   206  	if len(result.Results) != 1 {
   207  		return nil, errors.Errorf("expected 1 result, got %d", len(result.Results))
   208  	}
   209  	if err := result.Results[0].Error; err != nil {
   210  		return nil, err
   211  	}
   212  	ifaceInfo := make([]network.InterfaceInfo, len(result.Results[0].Config))
   213  	for i, cfg := range result.Results[0].Config {
   214  		ifaceInfo[i] = network.InterfaceInfo{
   215  			DeviceIndex:         cfg.DeviceIndex,
   216  			MACAddress:          cfg.MACAddress,
   217  			CIDR:                cfg.CIDR,
   218  			MTU:                 cfg.MTU,
   219  			ProviderId:          network.Id(cfg.ProviderId),
   220  			ProviderSubnetId:    network.Id(cfg.ProviderSubnetId),
   221  			ProviderSpaceId:     network.Id(cfg.ProviderSpaceId),
   222  			ProviderVLANId:      network.Id(cfg.ProviderVLANId),
   223  			ProviderAddressId:   network.Id(cfg.ProviderAddressId),
   224  			VLANTag:             cfg.VLANTag,
   225  			InterfaceName:       cfg.InterfaceName,
   226  			ParentInterfaceName: cfg.ParentInterfaceName,
   227  			InterfaceType:       network.InterfaceType(cfg.InterfaceType),
   228  			Disabled:            cfg.Disabled,
   229  			NoAutoStart:         cfg.NoAutoStart,
   230  			ConfigType:          network.InterfaceConfigType(cfg.ConfigType),
   231  			Address:             network.NewAddress(cfg.Address),
   232  			DNSServers:          network.NewAddresses(cfg.DNSServers...),
   233  			DNSSearchDomains:    cfg.DNSSearchDomains,
   234  			GatewayAddress:      network.NewAddress(cfg.GatewayAddress),
   235  		}
   236  	}
   237  	return ifaceInfo, nil
   238  }