OLD | NEW |
1 // Copyright 2013 Joyent Inc. | 1 // Copyright 2013 Joyent Inc. |
2 // Licensed under the AGPLv3, see LICENCE file for details. | 2 // Licensed under the AGPLv3, see LICENCE file for details. |
3 | 3 |
4 package joyent | 4 package joyent |
5 | 5 |
6 import ( | 6 import ( |
7 "sync" | 7 "sync" |
8 | 8 |
9 "launchpad.net/juju-core/constraints" | 9 "launchpad.net/juju-core/constraints" |
10 "launchpad.net/juju-core/environs" | 10 "launchpad.net/juju-core/environs" |
11 "launchpad.net/juju-core/environs/config" | 11 "launchpad.net/juju-core/environs/config" |
12 "launchpad.net/juju-core/environs/imagemetadata" | 12 "launchpad.net/juju-core/environs/imagemetadata" |
13 "launchpad.net/juju-core/environs/simplestreams" | 13 "launchpad.net/juju-core/environs/simplestreams" |
14 "launchpad.net/juju-core/environs/storage" | 14 "launchpad.net/juju-core/environs/storage" |
15 "launchpad.net/juju-core/provider/common" | 15 "launchpad.net/juju-core/provider/common" |
16 "launchpad.net/juju-core/state" | 16 "launchpad.net/juju-core/state" |
17 "launchpad.net/juju-core/state/api" | 17 "launchpad.net/juju-core/state/api" |
18 ) | 18 ) |
19 | 19 |
20 // This file contains the core of the joyent Environ implementation. You will | 20 // This file contains the core of the Joyent Environ implementation. |
21 // probably not need to change this file very much to begin with; and if you | |
22 // never need to add any more fields, you may never need to touch it. | |
23 // | |
24 // The rest of the implementation is split into environ_instance.go (which | |
25 // must be implemented ) and environ_firewall.go (which can be safely | |
26 // ignored until you've got an environment bootstrapping successfully). | |
27 | 21 |
28 type environ struct { | 22 type joyentEnviron struct { |
29 name string | 23 name string |
30 | 24 |
31 // supportedArchitectures caches the architectures | 25 // supportedArchitectures caches the architectures |
32 // for which images can be instantiated. | 26 // for which images can be instantiated. |
| 27 archLock sync.Mutex |
33 supportedArchitectures []string | 28 supportedArchitectures []string |
34 | 29 |
35 // All mutating operations should lock the mutex. Non-mutating operation
s | 30 // All mutating operations should lock the mutex. Non-mutating operation
s |
36 // should read all fields (other than name, which is immutable) from a | 31 // should read all fields (other than name, which is immutable) from a |
37 // shallow copy taken with getSnapshot(). | 32 // shallow copy taken with getSnapshot(). |
38 // This advice is predicated on the goroutine-safety of the values of th
e | 33 // This advice is predicated on the goroutine-safety of the values of th
e |
39 // affected fields. | 34 // affected fields. |
40 lock sync.Mutex | 35 lock sync.Mutex |
41 ecfg *environConfig | 36 ecfg *environConfig |
42 storage storage.Storage | 37 storage storage.Storage |
| 38 compute *joyentCompute |
43 } | 39 } |
44 | 40 |
45 var _ environs.Environ = (*environ)(nil) | 41 var _ environs.Environ = (*joyentEnviron)(nil) |
46 | 42 |
47 func (env *environ) Name() string { | 43 // newEnviron create a new Joyent environ instance from config. |
| 44 func newEnviron(cfg *config.Config) (*joyentEnviron, error) { |
| 45 » env := new(joyentEnviron) |
| 46 » if err := env.SetConfig(cfg); err != nil { |
| 47 » » return nil, err |
| 48 » } |
| 49 » env.name = cfg.Name() |
| 50 » var err error |
| 51 » env.storage, err = newStorage(env.ecfg, "") |
| 52 » if err != nil { |
| 53 » » return nil, err |
| 54 » } |
| 55 » env.compute, err = newCompute(env.ecfg) |
| 56 » if err != nil { |
| 57 » » return nil, err |
| 58 » } |
| 59 » return env, nil |
| 60 } |
| 61 |
| 62 func (env *joyentEnviron) SetName(envName string) { |
| 63 » env.name = envName |
| 64 } |
| 65 |
| 66 func (env *joyentEnviron) Name() string { |
48 return env.name | 67 return env.name |
49 } | 68 } |
50 | 69 |
51 func (*environ) Provider() environs.EnvironProvider { | 70 func (*joyentEnviron) Provider() environs.EnvironProvider { |
52 return providerInstance | 71 return providerInstance |
53 } | 72 } |
54 | 73 |
55 // SupportedArchitectures is specified on the EnvironCapability interface. | 74 // SupportedArchitectures is specified on the EnvironCapability interface. |
56 func (e *environ) SupportedArchitectures() ([]string, error) { | 75 func (env *joyentEnviron) SupportedArchitectures() ([]string, error) { |
57 » e.lock.Lock() | 76 » env.archLock.Lock() |
58 » defer e.lock.Unlock() | 77 » defer env.archLock.Unlock() |
59 » if e.supportedArchitectures != nil { | 78 » if env.supportedArchitectures != nil { |
60 » » return e.supportedArchitectures, nil | 79 » » return env.supportedArchitectures, nil |
61 } | 80 } |
| 81 cfg := env.Ecfg() |
62 // Create a filter to get all images from our region and for the correct
stream. | 82 // Create a filter to get all images from our region and for the correct
stream. |
63 cloudSpec := simplestreams.CloudSpec{ | 83 cloudSpec := simplestreams.CloudSpec{ |
64 » // TODO - add in region and url when known. | 84 » » Region: cfg.Region(), |
65 » //» » Region: e.Config().sdcRegion(), | 85 » » Endpoint: cfg.SdcUrl(), |
66 » //» » Endpoint: "", | |
67 } | 86 } |
68 imageConstraint := imagemetadata.NewImageConstraint(simplestreams.Lookup
Params{ | 87 imageConstraint := imagemetadata.NewImageConstraint(simplestreams.Lookup
Params{ |
69 CloudSpec: cloudSpec, | 88 CloudSpec: cloudSpec, |
70 » » Stream: e.Config().ImageStream(), | 89 » » Stream: cfg.ImageStream(), |
71 }) | 90 }) |
72 var err error | 91 var err error |
73 » e.supportedArchitectures, err = common.SupportedArchitectures(e, imageCo
nstraint) | 92 » env.supportedArchitectures, err = common.SupportedArchitectures(env, ima
geConstraint) |
74 » return e.supportedArchitectures, err | 93 » return env.supportedArchitectures, err |
75 } | 94 } |
76 | 95 |
77 // SupportNetworks is specified on the EnvironCapability interface. | 96 // SupportNetworks is specified on the EnvironCapability interface. |
78 func (e *environ) SupportNetworks() bool { | 97 func (e *joyentEnviron) SupportNetworks() bool { |
79 return false | 98 return false |
80 } | 99 } |
81 | 100 |
82 func (env *environ) SetConfig(cfg *config.Config) error { | 101 func (env *joyentEnviron) SetConfig(cfg *config.Config) error { |
83 env.lock.Lock() | 102 env.lock.Lock() |
84 defer env.lock.Unlock() | 103 defer env.lock.Unlock() |
85 » ecfg, err := validateConfig(cfg, env.ecfg) | 104 » ecfg, err := providerInstance.newConfig(cfg) |
86 » if err != nil { | |
87 » » return err | |
88 » } | |
89 » storage, err := newStorage(ecfg) | |
90 if err != nil { | 105 if err != nil { |
91 return err | 106 return err |
92 } | 107 } |
93 env.ecfg = ecfg | 108 env.ecfg = ecfg |
94 env.storage = storage | |
95 return nil | 109 return nil |
96 } | 110 } |
97 | 111 |
98 func (env *environ) getSnapshot() *environ { | 112 func (env *joyentEnviron) getSnapshot() *joyentEnviron { |
99 env.lock.Lock() | 113 env.lock.Lock() |
100 clone := *env | 114 clone := *env |
101 env.lock.Unlock() | 115 env.lock.Unlock() |
102 clone.lock = sync.Mutex{} | 116 clone.lock = sync.Mutex{} |
103 return &clone | 117 return &clone |
104 } | 118 } |
105 | 119 |
106 func (env *environ) Config() *config.Config { | 120 func (env *joyentEnviron) Config() *config.Config { |
107 return env.getSnapshot().ecfg.Config | 121 return env.getSnapshot().ecfg.Config |
108 } | 122 } |
109 | 123 |
110 func (env *environ) Storage() storage.Storage { | 124 func (env *joyentEnviron) Storage() storage.Storage { |
111 return env.getSnapshot().storage | 125 return env.getSnapshot().storage |
112 } | 126 } |
113 | 127 |
114 func (env *environ) PublicStorage() storage.StorageReader { | 128 func (env *joyentEnviron) PublicStorage() storage.StorageReader { |
115 return environs.EmptyStorage | 129 return environs.EmptyStorage |
116 } | 130 } |
117 | 131 |
118 func (env *environ) Bootstrap(ctx environs.BootstrapContext, cons constraints.Va
lue) error { | 132 func (env *joyentEnviron) Bootstrap(ctx environs.BootstrapContext, cons constrai
nts.Value) error { |
119 return common.Bootstrap(ctx, env, cons) | 133 return common.Bootstrap(ctx, env, cons) |
120 } | 134 } |
121 | 135 |
122 func (env *environ) StateInfo() (*state.Info, *api.Info, error) { | 136 func (env *joyentEnviron) StateInfo() (*state.Info, *api.Info, error) { |
123 return common.StateInfo(env) | 137 return common.StateInfo(env) |
124 } | 138 } |
125 | 139 |
126 func (env *environ) Destroy() error { | 140 func (env *joyentEnviron) Destroy() error { |
127 return common.Destroy(env) | 141 return common.Destroy(env) |
128 } | 142 } |
| 143 |
| 144 func (env *joyentEnviron) Ecfg() *environConfig { |
| 145 return env.getSnapshot().ecfg |
| 146 } |
| 147 |
| 148 // MetadataLookupParams returns parameters which are used to query simplestreams
metadata. |
| 149 func (env *joyentEnviron) MetadataLookupParams(region string) (*simplestreams.Me
tadataLookupParams, error) { |
| 150 if region == "" { |
| 151 region = env.Ecfg().Region() |
| 152 } |
| 153 return &simplestreams.MetadataLookupParams{ |
| 154 Series: env.Ecfg().DefaultSeries(), |
| 155 Region: region, |
| 156 Endpoint: env.Ecfg().sdcUrl(), |
| 157 Architectures: []string{"amd64", "arm"}, |
| 158 }, nil |
| 159 } |
| 160 |
| 161 // Region is specified in the HasRegion interface. |
| 162 func (env *joyentEnviron) Region() (simplestreams.CloudSpec, error) { |
| 163 return simplestreams.CloudSpec{ |
| 164 Region: env.Ecfg().Region(), |
| 165 Endpoint: env.Ecfg().sdcUrl(), |
| 166 }, nil |
| 167 } |
| 168 |
| 169 // GetImageSources returns a list of sources which are used to search for simple
streams image metadata. |
| 170 func (env *joyentEnviron) GetImageSources() ([]simplestreams.DataSource, error)
{ |
| 171 // Add the simplestreams source off the control bucket. |
| 172 sources := []simplestreams.DataSource{ |
| 173 storage.NewStorageSimpleStreamsDataSource("cloud storage", env.S
torage(), storage.BaseImagesPath)} |
| 174 return sources, nil |
| 175 } |
| 176 |
| 177 // GetToolsSources returns a list of sources which are used to search for simple
streams tools metadata. |
| 178 func (env *joyentEnviron) GetToolsSources() ([]simplestreams.DataSource, error)
{ |
| 179 // Add the simplestreams source off the control bucket. |
| 180 sources := []simplestreams.DataSource{ |
| 181 storage.NewStorageSimpleStreamsDataSource("cloud storage", env.S
torage(), storage.BaseToolsPath)} |
| 182 return sources, nil |
| 183 } |
OLD | NEW |