Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(292)

Side by Side Diff: environs/openstack/provider.go

Issue 6843106: Implemented PublicAddress() and PrivateAddress() (Closed)
Patch Set: Created 12 years, 4 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Stub provider for OpenStack, using goose will be implemented here 1 // Stub provider for OpenStack, using goose will be implemented here
2 2
3 package openstack 3 package openstack
4 4
5 import ( 5 import (
6 "fmt"
7 "io/ioutil"
6 "launchpad.net/juju-core/environs" 8 "launchpad.net/juju-core/environs"
7 "launchpad.net/juju-core/environs/config" 9 "launchpad.net/juju-core/environs/config"
8 "launchpad.net/juju-core/log" 10 "launchpad.net/juju-core/log"
9 "launchpad.net/juju-core/state" 11 "launchpad.net/juju-core/state"
12 "launchpad.net/juju-core/trivial"
13 "net/http"
14 "strings"
10 "sync" 15 "sync"
16 "time"
11 ) 17 )
12 18
13 type environProvider struct{} 19 type environProvider struct{}
14 20
15 var _ environs.EnvironProvider = (*environProvider)(nil) 21 var _ environs.EnvironProvider = (*environProvider)(nil)
16 22
17 var providerInstance environProvider 23 var providerInstance environProvider
18 24
25 // A request may fail to due "eventual consistency" semantics, which
26 // should resolve fairly quickly. A request may also fail due to a slow
27 // state transition (for instance an instance taking a while to release
28 // a security group after termination). The former failure mode is
29 // dealt with by shortAttempt, the latter by longAttempt.
30 var shortAttempt = trivial.AttemptStrategy{
rog 2012/11/22 15:11:48 does openstack have the same eventual-consistency
31 Total: 5 * time.Second,
32 Delay: 200 * time.Millisecond,
33 }
34
35 var longAttempt = trivial.AttemptStrategy{
36 Total: 3 * time.Minute,
37 Delay: 1 * time.Second,
38 }
39
19 func init() { 40 func init() {
20 environs.RegisterProvider("openstack", environProvider{}) 41 environs.RegisterProvider("openstack", environProvider{})
21 } 42 }
22 43
23 func (p environProvider) Open(cfg *config.Config) (environs.Environ, error) { 44 func (p environProvider) Open(cfg *config.Config) (environs.Environ, error) {
24 log.Printf("environs/openstack: opening environment %q", cfg.Name()) 45 log.Printf("environs/openstack: opening environment %q", cfg.Name())
25 e := new(environ) 46 e := new(environ)
26 err := e.SetConfig(cfg) 47 err := e.SetConfig(cfg)
27 if err != nil { 48 if err != nil {
28 return nil, err 49 return nil, err
29 } 50 }
30 return e, nil 51 return e, nil
31 } 52 }
32 53
33 func (p environProvider) SecretAttrs(cfg *config.Config) (map[string]interface{} , error) { 54 func (p environProvider) SecretAttrs(cfg *config.Config) (map[string]interface{} , error) {
34 m := make(map[string]interface{}) 55 m := make(map[string]interface{})
35 ecfg, err := providerInstance.newConfig(cfg) 56 ecfg, err := providerInstance.newConfig(cfg)
36 if err != nil { 57 if err != nil {
37 return nil, err 58 return nil, err
38 } 59 }
39 m["username"] = ecfg.username() 60 m["username"] = ecfg.username()
40 m["password"] = ecfg.password() 61 m["password"] = ecfg.password()
41 m["tenant-name"] = ecfg.tenantName() 62 m["tenant-name"] = ecfg.tenantName()
42 return m, nil 63 return m, nil
43 } 64 }
44 65
45 func (p environProvider) PublicAddress() (string, error) { 66 func (p environProvider) PublicAddress() (string, error) {
46 » panic("not implemented") 67 » return fetchMetadata("public-hostname")
47 } 68 }
48 69
49 func (p environProvider) PrivateAddress() (string, error) { 70 func (p environProvider) PrivateAddress() (string, error) {
50 » panic("not implemented") 71 » return fetchMetadata("local-hostname")
51 } 72 }
52 73
53 type environ struct { 74 type environ struct {
54 name string 75 name string
55 76
56 ecfgMutex sync.Mutex 77 ecfgMutex sync.Mutex
57 ecfgUnlocked *environConfig 78 ecfgUnlocked *environConfig
58 } 79 }
59 80
60 var _ environs.Environ = (*environ)(nil) 81 var _ environs.Environ = (*environ)(nil)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 panic("not implemented") 157 panic("not implemented")
137 } 158 }
138 159
139 func (e *environ) Ports() ([]state.Port, error) { 160 func (e *environ) Ports() ([]state.Port, error) {
140 panic("not implemented") 161 panic("not implemented")
141 } 162 }
142 163
143 func (e *environ) Provider() environs.EnvironProvider { 164 func (e *environ) Provider() environs.EnvironProvider {
144 return &providerInstance 165 return &providerInstance
145 } 166 }
167
168 // metadataHost holds the address of the instance metadata service.
169 // It is a variable so that tests can change it to refer to a local
170 // server when needed.
171 var metadataHost = "http://169.254.169.254"
172
173 // fetchMetadata fetches a single atom of data from the openstack instance metad ata service.
174 // http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/AESDG-chapter-insta ncedata.html
TheMue 2012/11/22 14:31:57 Here again a reference to EC2. But maybe only I do
175 func fetchMetadata(name string) (value string, err error) {
176 uri := fmt.Sprintf("%s/2011-01-01/meta-data/%s", metadataHost, name)
177 defer trivial.ErrorContextf(&err, "cannot get %q", uri)
178 for a := shortAttempt.Start(); a.Next(); {
179 var resp *http.Response
180 resp, err = http.Get(uri)
181 if err != nil {
182 continue
183 }
184 defer resp.Body.Close()
185 if resp.StatusCode != http.StatusOK {
186 err = fmt.Errorf("bad http response %v", resp.Status)
187 continue
188 }
189 var data []byte
190 data, err = ioutil.ReadAll(resp.Body)
191 if err != nil {
192 continue
193 }
194 return strings.TrimSpace(string(data)), nil
195 }
196 return
197 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b