github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/provider/gce/environ.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package gce 5 6 import ( 7 "sync" 8 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/environs" 12 "github.com/juju/juju/environs/config" 13 "github.com/juju/juju/environs/simplestreams" 14 "github.com/juju/juju/network" 15 "github.com/juju/juju/provider/common" 16 "github.com/juju/juju/provider/gce/google" 17 ) 18 19 type gceConnection interface { 20 VerifyCredentials() error 21 22 // Instance gets the up-to-date info about the given instance 23 // and returns it. 24 Instance(id, zone string) (google.Instance, error) 25 Instances(prefix string, statuses ...string) ([]google.Instance, error) 26 AddInstance(spec google.InstanceSpec, zones ...string) (*google.Instance, error) 27 RemoveInstances(prefix string, ids ...string) error 28 29 Ports(fwname string) ([]network.PortRange, error) 30 OpenPorts(fwname string, ports ...network.PortRange) error 31 ClosePorts(fwname string, ports ...network.PortRange) error 32 33 AvailabilityZones(region string) ([]google.AvailabilityZone, error) 34 35 // Storage related methods. 36 37 // CreateDisks will attempt to create the disks described by <disks> spec and 38 // return a slice of Disk representing the created disks or error if one of them failed. 39 CreateDisks(zone string, disks []google.DiskSpec) ([]*google.Disk, error) 40 // Disks will return a list of Disk found the passed <zone>. 41 Disks(zone string) ([]*google.Disk, error) 42 // Disk will return a Disk representing the disk identified by the 43 // passed <name> or error. 44 Disk(zone, id string) (*google.Disk, error) 45 // RemoveDisk will destroy the disk identified by <name> in <zone>. 46 RemoveDisk(zone, id string) error 47 // AttachDisk will attach the volume identified by <volumeName> into the instance 48 // <instanceId> and return an AttachedDisk representing it or error. 49 AttachDisk(zone, volumeName, instanceId string, mode google.DiskMode) (*google.AttachedDisk, error) 50 // DetachDisk will detach <volumeName> disk from <instanceId> if possible 51 // and return error. 52 DetachDisk(zone, instanceId, volumeName string) error 53 // InstanceDisks returns a list of the disks attached to the passed instance. 54 InstanceDisks(zone, instanceId string) ([]*google.AttachedDisk, error) 55 } 56 57 type environ struct { 58 common.SupportsUnitPlacementPolicy 59 60 name string 61 uuid string 62 gce gceConnection 63 64 lock sync.Mutex // lock protects access to ecfg 65 ecfg *environConfig 66 67 archLock sync.Mutex // protects supportedArchitectures 68 supportedArchitectures []string 69 } 70 71 func newEnviron(cfg *config.Config) (*environ, error) { 72 ecfg, err := newValidConfig(cfg, configDefaults) 73 if err != nil { 74 return nil, errors.Annotate(err, "invalid config") 75 } 76 77 // Connect and authenticate. 78 conn, err := newConnection(ecfg) 79 if err != nil { 80 return nil, errors.Trace(err) 81 } 82 83 env := &environ{ 84 name: ecfg.Name(), 85 uuid: ecfg.UUID(), 86 ecfg: ecfg, 87 gce: conn, 88 } 89 return env, nil 90 } 91 92 // Name returns the name of the environment. 93 func (env *environ) Name() string { 94 return env.name 95 } 96 97 // Provider returns the environment provider that created this env. 98 func (*environ) Provider() environs.EnvironProvider { 99 return providerInstance 100 } 101 102 // Region returns the CloudSpec to use for the provider, as configured. 103 func (env *environ) Region() (simplestreams.CloudSpec, error) { 104 return env.cloudSpec(env.ecfg.region()), nil 105 } 106 107 func (env *environ) cloudSpec(region string) simplestreams.CloudSpec { 108 return simplestreams.CloudSpec{ 109 Region: region, 110 Endpoint: env.ecfg.imageEndpoint(), 111 } 112 } 113 114 // SetConfig updates the env's configuration. 115 func (env *environ) SetConfig(cfg *config.Config) error { 116 env.lock.Lock() 117 defer env.lock.Unlock() 118 119 if env.ecfg == nil { 120 return errors.New("cannot set config on uninitialized env") 121 } 122 123 if err := env.ecfg.update(cfg); err != nil { 124 return errors.Annotate(err, "invalid config change") 125 } 126 return nil 127 } 128 129 var newConnection = func(ecfg *environConfig) (gceConnection, error) { 130 connCfg := ecfg.newConnection() 131 auth := ecfg.auth() 132 return google.Connect(connCfg, auth) 133 } 134 135 // Config returns the configuration data with which the env was created. 136 func (env *environ) Config() *config.Config { 137 env.lock.Lock() 138 cfg := env.ecfg.Config 139 env.lock.Unlock() 140 return cfg 141 } 142 143 var bootstrap = common.Bootstrap 144 145 // Bootstrap creates a new instance, chosing the series and arch out of 146 // available tools. The series and arch are returned along with a func 147 // that must be called to finalize the bootstrap process by transferring 148 // the tools and installing the initial juju controller. 149 func (env *environ) Bootstrap(ctx environs.BootstrapContext, params environs.BootstrapParams) (*environs.BootstrapResult, error) { 150 return bootstrap(ctx, env, params) 151 } 152 153 var destroyEnv = common.Destroy 154 155 // Destroy shuts down all known machines and destroys the rest of the 156 // known environment. 157 func (env *environ) Destroy() error { 158 ports, err := env.Ports() 159 if err != nil { 160 return errors.Trace(err) 161 } 162 163 if len(ports) > 0 { 164 if err := env.ClosePorts(ports); err != nil { 165 return errors.Trace(err) 166 } 167 } 168 169 return destroyEnv(env) 170 }