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 }