github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/maas/environprovider.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package maas
     5  
     6  import (
     7  	"fmt"
     8  	"net/http"
     9  
    10  	"github.com/juju/errors"
    11  	"github.com/juju/gomaasapi"
    12  	"github.com/juju/loggo"
    13  
    14  	"github.com/juju/juju/cloud"
    15  	"github.com/juju/juju/environs"
    16  	"github.com/juju/juju/environs/config"
    17  )
    18  
    19  // Logger for the MAAS provider.
    20  var logger = loggo.GetLogger("juju.provider.maas")
    21  
    22  type maasEnvironProvider struct {
    23  	environProviderCredentials
    24  }
    25  
    26  var _ environs.EnvironProvider = (*maasEnvironProvider)(nil)
    27  
    28  var providerInstance maasEnvironProvider
    29  
    30  func (maasEnvironProvider) Open(cfg *config.Config) (environs.Environ, error) {
    31  	logger.Debugf("opening model %q.", cfg.Name())
    32  	env, err := NewEnviron(cfg)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	return env, nil
    37  }
    38  
    39  var errAgentNameAlreadySet = errors.New(
    40  	"maas-agent-name is already set; this should not be set by hand")
    41  
    42  // RestrictedConfigAttributes is specified in the EnvironProvider interface.
    43  func (p maasEnvironProvider) RestrictedConfigAttributes() []string {
    44  	return []string{"maas-server"}
    45  }
    46  
    47  // PrepareForCreateEnvironment is specified in the EnvironProvider interface.
    48  func (p maasEnvironProvider) PrepareForCreateEnvironment(cfg *config.Config) (*config.Config, error) {
    49  	attrs := cfg.UnknownAttrs()
    50  	oldName, found := attrs["maas-agent-name"]
    51  	if found && oldName != "" {
    52  		return nil, errAgentNameAlreadySet
    53  	}
    54  	attrs["maas-agent-name"] = cfg.UUID()
    55  	return cfg.Apply(attrs)
    56  }
    57  
    58  // BootstrapConfig is specified in the EnvironProvider interface.
    59  func (p maasEnvironProvider) BootstrapConfig(args environs.BootstrapConfigParams) (*config.Config, error) {
    60  	// For MAAS, either:
    61  	// 1. the endpoint from the cloud definition defines the MAAS server URL
    62  	//    (if a full cloud definition had been set up)
    63  	// 2. the region defines the MAAS server ip/host
    64  	//    (if the bootstrap shortcut is used)
    65  	server := args.CloudEndpoint
    66  	if server == "" && args.CloudRegion != "" {
    67  		server = fmt.Sprintf("http://%s/MAAS", args.CloudRegion)
    68  	}
    69  	if server == "" {
    70  		return nil, errors.New("MAAS server not specified")
    71  	}
    72  	attrs := map[string]interface{}{
    73  		"maas-server": server,
    74  	}
    75  	// Add the credentials.
    76  	switch authType := args.Credentials.AuthType(); authType {
    77  	case cloud.OAuth1AuthType:
    78  		credentialAttrs := args.Credentials.Attributes()
    79  		for k, v := range credentialAttrs {
    80  			attrs[k] = v
    81  		}
    82  	default:
    83  		return nil, errors.NotSupportedf("%q auth-type", authType)
    84  	}
    85  	cfg, err := args.Config.Apply(attrs)
    86  	if err != nil {
    87  		return nil, errors.Trace(err)
    88  	}
    89  	return p.PrepareForCreateEnvironment(cfg)
    90  }
    91  
    92  // PrepareForBootstrap is specified in the EnvironProvider interface.
    93  func (p maasEnvironProvider) PrepareForBootstrap(ctx environs.BootstrapContext, cfg *config.Config) (environs.Environ, error) {
    94  	env, err := p.Open(cfg)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	if ctx.ShouldVerifyCredentials() {
    99  		if err := verifyCredentials(env.(*maasEnviron)); err != nil {
   100  			return nil, err
   101  		}
   102  	}
   103  	return env, nil
   104  }
   105  
   106  func verifyCredentials(env *maasEnviron) error {
   107  	// Verify we can connect to the server and authenticate.
   108  	if env.usingMAAS2() {
   109  		// The maas2 controller verifies credentials at creation time.
   110  		return nil
   111  	}
   112  	_, err := env.getMAASClient().GetSubObject("maas").CallGet("get_config", nil)
   113  	if err, ok := errors.Cause(err).(gomaasapi.ServerError); ok && err.StatusCode == http.StatusUnauthorized {
   114  		logger.Debugf("authentication failed: %v", err)
   115  		return errors.New(`authentication failed.
   116  
   117  Please ensure the credentials are correct.`)
   118  	}
   119  	return nil
   120  }
   121  
   122  // SecretAttrs is specified in the EnvironProvider interface.
   123  func (prov maasEnvironProvider) SecretAttrs(cfg *config.Config) (map[string]string, error) {
   124  	secretAttrs := make(map[string]string)
   125  	maasCfg, err := prov.newConfig(cfg)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  	secretAttrs["maas-oauth"] = maasCfg.maasOAuth()
   130  	return secretAttrs, nil
   131  }
   132  
   133  // DetectRegions is specified in the environs.CloudRegionDetector interface.
   134  func (p maasEnvironProvider) DetectRegions() ([]cloud.Region, error) {
   135  	return nil, errors.NotFoundf("regions")
   136  }