Merge lp:~thumper/juju-core/verify-storage-move into lp:~go-bot/juju-core/trunk

Proposed by Tim Penhey
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 1939
Proposed branch: lp:~thumper/juju-core/verify-storage-move
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 478 lines (+116/-73)
10 files modified
cmd/juju/bootstrap.go (+6/-0)
cmd/juju/bootstrap_test.go (+29/-8)
environs/bootstrap/bootstrap.go (+10/-19)
environs/emptystorage.go (+0/-25)
environs/emptystorage_test.go (+2/-2)
environs/jujutest/livetests.go (+6/-2)
environs/jujutest/tests.go (+9/-5)
environs/open.go (+30/-2)
environs/open_test.go (+3/-3)
provider/dummy/environs.go (+21/-7)
To merge this branch: bzr merge lp:~thumper/juju-core/verify-storage-move
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+188974@code.launchpad.net

Commit message

Fail earlier when bootstrapping if up already.

I broke apart the VerifyBootstrap method into two:
  EnsureNotBootstrapped
  VerifyStorage
Well I didn't create the second, just didn't call it
from the EnsureNotBootstrapped call.

The ensure method is now called in the command bootstrap
prior to any upload tools checks.

However the implication of this was much futher reaching
than I expected. Many tests assumed that bootstrap.Bootstrap
was enough to bootstrap and environment, and that it would
complain if already bootstrapped. Since the complaining was
moved into the command function, some changes had to be made.
Since some of the tests were refactored to check the storage,
this required making the dummy provider actually write the
provider-state into storage like a normal provider.

I moved the VerifyStorage out of emptystorage.go and into open.go
as it seemed better fitting there (and the comment actually
makes sense now).

Also used the environs constant for the VerificationFilename.

https://codereview.appspot.com/14279044/

Description of the change

Fail earlier when bootstrapping if up already.

I broke apart the VerifyBootstrap method into two:
  EnsureNotBootstrapped
  VerifyStorage
Well I didn't create the second, just didn't call it
from the EnsureNotBootstrapped call.

The ensure method is now called in the command bootstrap
prior to any upload tools checks.

However the implication of this was much futher reaching
than I expected. Many tests assumed that bootstrap.Bootstrap
was enough to bootstrap and environment, and that it would
complain if already bootstrapped. Since the complaining was
moved into the command function, some changes had to be made.
Since some of the tests were refactored to check the storage,
this required making the dummy provider actually write the
provider-state into storage like a normal provider.

I moved the VerifyStorage out of emptystorage.go and into open.go
as it seemed better fitting there (and the comment actually
makes sense now).

Also used the environs constant for the VerificationFilename.

https://codereview.appspot.com/14279044/

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Reviewers: mp+188974_code.launchpad.net,

Message:
Please take a look.

Description:
Fail earlier when bootstrapping if up already.

I broke apart the VerifyBootstrap method into two:
   EnsureNotBootstrapped
   VerifyStorage
Well I didn't create the second, just didn't call it
from the EnsureNotBootstrapped call.

The ensure method is now called in the command bootstrap
prior to any upload tools checks.

However the implication of this was much futher reaching
than I expected. Many tests assumed that bootstrap.Bootstrap
was enough to bootstrap and environment, and that it would
complain if already bootstrapped. Since the complaining was
moved into the command function, some changes had to be made.
Since some of the tests were refactored to check the storage,
this required making the dummy provider actually write the
provider-state into storage like a normal provider.

I moved the VerifyStorage out of emptystorage.go and into open.go
as it seemed better fitting there (and the comment actually
makes sense now).

Also used the environs constant for the VerificationFilename.

https://code.launchpad.net/~thumper/juju-core/verify-storage-move/+merge/188974

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/14279044/

Affected files (+119, -74 lines):
   A [revision details]
   M cmd/juju/bootstrap.go
   M cmd/juju/bootstrap_test.go
   M environs/bootstrap/bootstrap.go
   M environs/emptystorage.go
   M environs/emptystorage_test.go
   M environs/jujutest/livetests.go
   M environs/jujutest/tests.go
   M environs/open.go
   M environs/open_test.go
   M provider/dummy/environs.go

Revision history for this message
Andrew Wilkins (axwalk) wrote :

On 2013/10/03 03:19:01, dfc wrote:
> LGTM. Some nice boy scout work in there as well.

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go
> File environs/bootstrap/bootstrap.go (right):

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go#newcode92
> environs/bootstrap/bootstrap.go:92: _, err :=
common.LoadState(env.Storage())
> this method hurt my head, but it makes sense in a double negative sort
of way.

LGTM

https://codereview.appspot.com/14279044/

Revision history for this message
Andrew Wilkins (axwalk) wrote :

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go
File environs/bootstrap/bootstrap.go (left):

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go#oldcode96
environs/bootstrap/bootstrap.go:96: // TODO(rog) this feels like a
layering violation - providers
Is this TODO no longer applicable? Seems to be...

https://codereview.appspot.com/14279044/

Revision history for this message
Tim Penhey (thumper) wrote :

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go
File environs/bootstrap/bootstrap.go (left):

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go#oldcode96
environs/bootstrap/bootstrap.go:96: // TODO(rog) this feels like a
layering violation - providers
On 2013/10/03 03:21:00, axw1 wrote:
> Is this TODO no longer applicable? Seems to be...

I took it out because everything expects it to be there.
It is how bootstrap checks to see if the environment
is already bootstrapped. I think for consistency across
providers this comment no longer makes sense.

https://codereview.appspot.com/14279044/

Revision history for this message
Roger Peppe (rogpeppe) wrote :

I have reservations about this.
I don't think we should be further entrenching the arbitrary way in
which the ec2 provider happened to mark its server instances.
Some thoughts below.

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go
File environs/bootstrap/bootstrap.go (left):

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go#oldcode96
environs/bootstrap/bootstrap.go:96: // TODO(rog) this feels like a
layering violation - providers
On 2013/10/03 03:38:01, thumper wrote:
> On 2013/10/03 03:21:00, axw1 wrote:
> > Is this TODO no longer applicable? Seems to be...

> I took it out because everything expects it to be there.
> It is how bootstrap checks to see if the environment
> is already bootstrapped. I think for consistency across
> providers this comment no longer makes sense.

The comment *is* still relevant IMHO. It has long been
the plan to move away from using file storage on ec2 to
indicate state servers (it could be done nicely with
instance tags) and therefore allow the possibility of
having an environment with no local storage at all.

It is *currently* how bootstrap checks to see if the
environment is already bootstrapped, but there's no
particular necessity for it to be this way.
It would be better to have an Environ.IsBootstrapped
call instead.

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go
File environs/bootstrap/bootstrap.go (right):

https://codereview.appspot.com/14279044/diff/1/environs/bootstrap/bootstrap.go#newcode91
environs/bootstrap/bootstrap.go:91: func EnsureNotBootstrapped(env
environs.Environ) error {
We usually use the word "ensure" to mean "ensure that something is so".
That's not the case here.

I'd prefer:

// IsBootstrapped returns whether the environment is
// bootstrapped.
func IsBootstrapped(env environs.Environ) (bool, error)

https://codereview.appspot.com/14279044/diff/1/environs/open.go
File environs/open.go (right):

https://codereview.appspot.com/14279044/diff/1/environs/open.go#newcode29
environs/open.go:29: VerifyStorageError error = fmt.Errorf(
s/ error//

https://codereview.appspot.com/14279044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'cmd/juju/bootstrap.go'
2--- cmd/juju/bootstrap.go 2013-10-02 05:18:02 +0000
3+++ cmd/juju/bootstrap.go 2013-10-03 03:45:40 +0000
4@@ -78,6 +78,12 @@
5 return fmt.Errorf("failed to enable bootstrap storage: %v", err)
6 }
7 }
8+ // Check to see if the environment is already bootstrapped
9+ // before potentially uploading any tools.
10+ if err := bootstrap.EnsureNotBootstrapped(environ); err != nil {
11+ return err
12+ }
13+
14 // TODO (wallyworld): 2013-09-20 bug 1227931
15 // We can set a custom tools data source instead of doing an
16 // unecessary upload.
17
18=== modified file 'cmd/juju/bootstrap_test.go'
19--- cmd/juju/bootstrap_test.go 2013-10-02 18:34:59 +0000
20+++ cmd/juju/bootstrap_test.go 2013-10-03 03:45:40 +0000
21@@ -53,6 +53,13 @@
22 s.LoggingSuite.TearDownSuite(c)
23 }
24
25+func (s *BootstrapSuite) TearDownTest(c *gc.C) {
26+ s.ToolsFixture.TearDownTest(c)
27+ s.MgoSuite.TearDownTest(c)
28+ s.LoggingSuite.TearDownTest(c)
29+ dummy.Reset()
30+}
31+
32 type bootstrapRetryTest struct {
33 info string
34 args []string
35@@ -101,13 +108,6 @@
36 c.Assert(err, gc.ErrorMatches, test.err)
37 }
38
39-func (s *BootstrapSuite) TearDownTest(c *gc.C) {
40- s.ToolsFixture.TearDownTest(c)
41- s.MgoSuite.TearDownTest(c)
42- s.LoggingSuite.TearDownTest(c)
43- dummy.Reset()
44-}
45-
46 func (s *BootstrapSuite) TestTest(c *gc.C) {
47 uploadTools = mockUploadTools
48 defer func() { uploadTools = sync.Upload }()
49@@ -190,7 +190,11 @@
50 }
51 opPutBootstrapVerifyFile := (<-opc).(dummy.OpPutFile)
52 c.Check(opPutBootstrapVerifyFile.Env, gc.Equals, "peckham")
53- c.Check(opPutBootstrapVerifyFile.FileName, gc.Equals, "bootstrap-verify")
54+ c.Check(opPutBootstrapVerifyFile.FileName, gc.Equals, environs.VerificationFilename)
55+
56+ opPutBootstrapInitFile := (<-opc).(dummy.OpPutFile)
57+ c.Check(opPutBootstrapInitFile.Env, gc.Equals, "peckham")
58+ c.Check(opPutBootstrapInitFile.FileName, gc.Equals, "provider-state")
59
60 opBootstrap := (<-opc).(dummy.OpBootstrap)
61 c.Check(opBootstrap.Env, gc.Equals, "peckham")
62@@ -265,6 +269,23 @@
63 },
64 }}
65
66+func (s *BootstrapSuite) TestBootstrapTwice(c *gc.C) {
67+ restore := createToolsStore(c)
68+ defer restore()
69+ _, fake := makeEmptyFakeHome(c)
70+ defer fake.Restore()
71+
72+ ctx := coretesting.Context(c)
73+ code := cmd.Main(&BootstrapCommand{}, ctx, nil)
74+ c.Check(code, gc.Equals, 0)
75+
76+ ctx2 := coretesting.Context(c)
77+ code2 := cmd.Main(&BootstrapCommand{}, ctx2, nil)
78+ c.Check(code2, gc.Equals, 1)
79+ c.Check(coretesting.Stderr(ctx2), gc.Equals, "error: environment is already bootstrapped\n")
80+ c.Check(coretesting.Stdout(ctx2), gc.Equals, "")
81+}
82+
83 func (s *BootstrapSuite) TestAutoSync(c *gc.C) {
84 // Prepare a mock storage for testing and store the
85 // dummy tools in there.
86
87=== modified file 'environs/bootstrap/bootstrap.go'
88--- environs/bootstrap/bootstrap.go 2013-10-02 10:39:12 +0000
89+++ environs/bootstrap/bootstrap.go 2013-10-03 03:45:40 +0000
90@@ -42,11 +42,8 @@
91 if _, hasCAKey := cfg.CAPrivateKey(); !hasCAKey {
92 return fmt.Errorf("environment configuration has no ca-private-key")
93 }
94- // If the state file exists, it might actually have just been
95- // removed by Destroy, and eventual consistency has not caught
96- // up yet, so we retry to verify if that is happening.
97- err := verifyBootstrapInit(environ)
98- if err != nil {
99+ // Write out the bootstrap-init file, and confirm storage is writeable.
100+ if err := environs.VerifyStorage(environ.Storage()); err != nil {
101 return err
102 }
103
104@@ -89,24 +86,18 @@
105 return environ.Bootstrap(cons, newestTools)
106 }
107
108-// verifyBootstrapInit does the common initial check before bootstrapping, to
109-// confirm that the environment isn't already running, and that the storage
110-// works.
111-func verifyBootstrapInit(env environs.Environ) error {
112- // TODO(rog) this feels like a layering violation - providers
113- // should not necessarily be required to store their bootstrap
114- // state in a file. This verification should probably
115- // be moved into provider and called by the providers themselves.
116- stor := env.Storage()
117- _, err := common.LoadState(stor)
118+// EnsureNotBootstrapped returns null if the environment is not bootstrapped,
119+// and an error if it is or if the function was not able to tell.
120+func EnsureNotBootstrapped(env environs.Environ) error {
121+ _, err := common.LoadState(env.Storage())
122+ // If there is no error loading the bootstrap state, then we are bootstrapped.
123 if err == nil {
124 return fmt.Errorf("environment is already bootstrapped")
125 }
126- if err != environs.ErrNotBootstrapped {
127- return fmt.Errorf("cannot query old bootstrap state: %v", err)
128+ if err == environs.ErrNotBootstrapped {
129+ return nil
130 }
131-
132- return environs.VerifyStorage(stor)
133+ return err
134 }
135
136 // ConfigureBootstrapMachine adds the initial machine into state. As a part
137
138=== modified file 'environs/emptystorage.go'
139--- environs/emptystorage.go 2013-09-18 07:13:09 +0000
140+++ environs/emptystorage.go 2013-10-03 03:45:40 +0000
141@@ -6,11 +6,9 @@
142 import (
143 "fmt"
144 "io"
145- "strings"
146
147 "launchpad.net/juju-core/environs/storage"
148 "launchpad.net/juju-core/errors"
149- "launchpad.net/juju-core/log"
150 "launchpad.net/juju-core/utils"
151 )
152
153@@ -20,16 +18,6 @@
154
155 type emptyStorage struct{}
156
157-// File named `verificationFilename` in the storage will contain
158-// `verificationContent`. This is also used to differentiate between
159-// Python Juju and juju-core environments, so change the content with
160-// care (and update CheckEnvironment below when you do that).
161-const verificationFilename string = "bootstrap-verify"
162-const verificationContent = "juju-core storage writing verified: ok\n"
163-
164-var VerifyStorageError error = fmt.Errorf(
165- "provider storage is not writable")
166-
167 func (s emptyStorage) Get(name string) (io.ReadCloser, error) {
168 return nil, errors.NotFoundf("file %q", name)
169 }
170@@ -51,16 +39,3 @@
171 func (s emptyStorage) ShouldRetry(err error) bool {
172 return false
173 }
174-
175-func VerifyStorage(stor storage.Storage) error {
176- reader := strings.NewReader(verificationContent)
177- err := stor.Put(verificationFilename, reader,
178- int64(len(verificationContent)))
179- if err != nil {
180- log.Debugf(
181- "environs: failed to write bootstrap-verify file: %v",
182- err)
183- return VerifyStorageError
184- }
185- return nil
186-}
187
188=== modified file 'environs/emptystorage_test.go'
189--- environs/emptystorage_test.go 2013-10-01 16:53:02 +0000
190+++ environs/emptystorage_test.go 2013-10-03 03:45:40 +0000
191@@ -68,7 +68,7 @@
192 stor := environ.Storage()
193 err = environs.VerifyStorage(stor)
194 c.Assert(err, gc.IsNil)
195- reader, err := storage.Get(stor, "bootstrap-verify")
196+ reader, err := storage.Get(stor, environs.VerificationFilename)
197 c.Assert(err, gc.IsNil)
198 defer reader.Close()
199 contents, err := ioutil.ReadAll(reader)
200@@ -84,7 +84,7 @@
201 c.Assert(err, gc.IsNil)
202 stor := environ.Storage()
203 someError := errors.Unauthorizedf("you shall not pass")
204- dummy.Poison(stor, "bootstrap-verify", someError)
205+ dummy.Poison(stor, environs.VerificationFilename, someError)
206 err = environs.VerifyStorage(stor)
207 c.Assert(err, gc.Equals, environs.VerifyStorageError)
208 }
209
210=== modified file 'environs/jujutest/livetests.go'
211--- environs/jujutest/livetests.go 2013-10-02 10:39:12 +0000
212+++ environs/jujutest/livetests.go 2013-10-03 03:45:40 +0000
213@@ -137,7 +137,9 @@
214 c.Assert(err, gc.IsNil)
215 }
216 envtesting.UploadFakeTools(c, t.Env.Storage())
217- err := bootstrap.Bootstrap(t.Env, cons)
218+ err := bootstrap.EnsureNotBootstrapped(t.Env)
219+ c.Assert(err, gc.IsNil)
220+ err = bootstrap.Bootstrap(t.Env, cons)
221 c.Assert(err, gc.IsNil)
222 t.bootstrapped = true
223 }
224@@ -385,9 +387,11 @@
225 }
226
227 func (t *LiveTests) TestBootstrapMultiple(c *gc.C) {
228+ // bootstrap.Bootstrap no longer raises errors if the environment is
229+ // already up, this has been moved into the bootstrap command.
230 t.BootstrapOnce(c)
231
232- err := bootstrap.Bootstrap(t.Env, constraints.Value{})
233+ err := bootstrap.EnsureNotBootstrapped(t.Env)
234 c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
235
236 c.Logf("destroy env")
237
238=== modified file 'environs/jujutest/tests.go'
239--- environs/jujutest/tests.go 2013-10-01 12:03:33 +0000
240+++ environs/jujutest/tests.go 2013-10-03 03:45:40 +0000
241@@ -131,19 +131,21 @@
242 func (t *Tests) TestBootstrap(c *gc.C) {
243 e := t.Prepare(c)
244 envtesting.UploadFakeTools(c, e.Storage())
245- err := bootstrap.Bootstrap(e, constraints.Value{})
246+ err := bootstrap.EnsureNotBootstrapped(e)
247+ c.Assert(err, gc.IsNil)
248+ err = bootstrap.Bootstrap(e, constraints.Value{})
249 c.Assert(err, gc.IsNil)
250
251 info, apiInfo, err := e.StateInfo()
252 c.Check(info.Addrs, gc.Not(gc.HasLen), 0)
253 c.Check(apiInfo.Addrs, gc.Not(gc.HasLen), 0)
254
255- err = bootstrap.Bootstrap(e, constraints.Value{})
256+ err = bootstrap.EnsureNotBootstrapped(e)
257 c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
258
259 e2 := t.Open(c)
260 envtesting.UploadFakeTools(c, e2.Storage())
261- err = bootstrap.Bootstrap(e2, constraints.Value{})
262+ err = bootstrap.EnsureNotBootstrapped(e2)
263 c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
264
265 info2, apiInfo2, err := e2.StateInfo()
266@@ -157,11 +159,13 @@
267 e3 := t.Prepare(c)
268 envtesting.UploadFakeTools(c, e3.Storage())
269
270+ err = bootstrap.EnsureNotBootstrapped(e3)
271+ c.Assert(err, gc.IsNil)
272 err = bootstrap.Bootstrap(e3, constraints.Value{})
273 c.Assert(err, gc.IsNil)
274
275- err = bootstrap.Bootstrap(e3, constraints.Value{})
276- c.Assert(err, gc.NotNil)
277+ err = bootstrap.EnsureNotBootstrapped(e3)
278+ c.Assert(err, gc.ErrorMatches, "environment is already bootstrapped")
279 }
280
281 var noRetry = utils.AttemptStrategy{}
282
283=== modified file 'environs/open.go'
284--- environs/open.go 2013-10-02 18:41:54 +0000
285+++ environs/open.go 2013-10-03 03:45:40 +0000
286@@ -6,6 +6,7 @@
287 import (
288 "fmt"
289 "io/ioutil"
290+ "strings"
291 "time"
292
293 "launchpad.net/juju-core/cert"
294@@ -15,7 +16,21 @@
295 "launchpad.net/juju-core/errors"
296 )
297
298-var InvalidEnvironmentError = fmt.Errorf("environment is not a juju-core environment")
299+// File named `VerificationFilename` in the storage will contain
300+// `verificationContent`. This is also used to differentiate between
301+// Python Juju and juju-core environments, so change the content with
302+// care (and update CheckEnvironment below when you do that).
303+const (
304+ VerificationFilename = "bootstrap-verify"
305+ verificationContent = "juju-core storage writing verified: ok\n"
306+)
307+
308+var (
309+ VerifyStorageError error = fmt.Errorf(
310+ "provider storage is not writable")
311+ InvalidEnvironmentError = fmt.Errorf(
312+ "environment is not a juju-core environment")
313+)
314
315 // ConfigForName returns the configuration for the environment with the
316 // given name from the default environments file. If the name is blank,
317@@ -199,6 +214,19 @@
318 return nil
319 }
320
321+// VerifyStorage writes the bootstrap init file to the storage to indicate
322+// that the storage is writable.
323+func VerifyStorage(stor storage.Storage) error {
324+ reader := strings.NewReader(verificationContent)
325+ err := stor.Put(VerificationFilename, reader,
326+ int64(len(verificationContent)))
327+ if err != nil {
328+ logger.Warningf("failed to write bootstrap-verify file: %v", err)
329+ return VerifyStorageError
330+ }
331+ return nil
332+}
333+
334 // CheckEnvironment checks if an environment has a bootstrap-verify
335 // that is written by juju-core commands (as compared to one being
336 // written by Python juju).
337@@ -210,7 +238,7 @@
338 // Returns InvalidEnvironmentError on failure, nil otherwise.
339 func CheckEnvironment(environ Environ) error {
340 stor := environ.Storage()
341- reader, err := storage.Get(stor, verificationFilename)
342+ reader, err := storage.Get(stor, VerificationFilename)
343 if errors.IsNotFoundError(err) {
344 // When verification file does not exist, this is a juju-core
345 // environment.
346
347=== modified file 'environs/open_test.go'
348--- environs/open_test.go 2013-10-02 18:41:54 +0000
349+++ environs/open_test.go 2013-10-03 03:45:40 +0000
350@@ -297,7 +297,7 @@
351 // When the bootstrap-verify file does not exist, it still believes
352 // the environment is a juju-core one because earlier versions
353 // did not create that file.
354- err = stor.Remove("bootstrap-verify")
355+ err = stor.Remove(environs.VerificationFilename)
356 c.Assert(err, gc.IsNil)
357 err = environs.CheckEnvironment(environ)
358 c.Assert(err, gc.IsNil)
359@@ -318,7 +318,7 @@
360 // When fetching the verification file from storage fails,
361 // we get an InvalidEnvironmentError.
362 someError := errors.Unauthorizedf("you shall not pass")
363- dummy.Poison(stor, "bootstrap-verify", someError)
364+ dummy.Poison(stor, environs.VerificationFilename, someError)
365 err = environs.CheckEnvironment(environ)
366 c.Assert(err, gc.Equals, someError)
367 }
368@@ -333,7 +333,7 @@
369 stor := environ.Storage()
370 content := "bad verification content"
371 reader := strings.NewReader(content)
372- err = stor.Put("bootstrap-verify", reader, int64(len(content)))
373+ err = stor.Put(environs.VerificationFilename, reader, int64(len(content)))
374 c.Assert(err, gc.IsNil)
375
376 // When the bootstrap-verify file contains unexpected content,
377
378=== modified file 'provider/dummy/environs.go'
379--- provider/dummy/environs.go 2013-10-03 00:40:14 +0000
380+++ provider/dummy/environs.go 2013-10-03 03:45:40 +0000
381@@ -33,6 +33,8 @@
382 "sync"
383 "time"
384
385+ "launchpad.net/loggo"
386+
387 "launchpad.net/juju-core/constraints"
388 "launchpad.net/juju-core/environs"
389 "launchpad.net/juju-core/environs/cloudinit"
390@@ -42,7 +44,6 @@
391 "launchpad.net/juju-core/environs/storage"
392 "launchpad.net/juju-core/environs/tools"
393 "launchpad.net/juju-core/instance"
394- "launchpad.net/juju-core/log"
395 "launchpad.net/juju-core/names"
396 "launchpad.net/juju-core/provider"
397 "launchpad.net/juju-core/provider/common"
398@@ -55,6 +56,8 @@
399 "launchpad.net/juju-core/utils"
400 )
401
402+var logger = loggo.GetLogger("juju.provider.dummy")
403+
404 // SampleConfig() returns an environment configuration with all required
405 // attributes set.
406 func SampleConfig() testing.Attrs {
407@@ -208,7 +211,7 @@
408 // operation listener. All opened environments after Reset will share
409 // the same underlying state.
410 func Reset() {
411- log.Infof("environs/dummy: reset environment")
412+ logger.Infof("reset environment")
413 p := &providerInstance
414 p.mu.Lock()
415 defer p.mu.Unlock()
416@@ -538,7 +541,7 @@
417 return fmt.Errorf("no CA certificate in environment configuration")
418 }
419
420- log.Infof("environs/dummy: would pick tools from %s", possibleTools)
421+ logger.Infof("would pick tools from %s", possibleTools)
422 cfg, err := environs.BootstrapConfig(e.Config())
423 if err != nil {
424 return fmt.Errorf("cannot make bootstrap config: %v", err)
425@@ -553,6 +556,17 @@
426 if estate.bootstrapped {
427 return fmt.Errorf("environment is already bootstrapped")
428 }
429+ // Write the bootstrap file just like a normal provider. However
430+ // we need to release the mutex for the save state to work, so regain
431+ // it after the call.
432+ estate.mu.Unlock()
433+ if err := common.SaveState(e.Storage(), &common.BootstrapState{StateInstances: []instance.Id{"localhost"}}); err != nil {
434+ logger.Errorf("failed to save state instances: %v", err)
435+ estate.mu.Lock() // otherwise defered unlock will fail
436+ return err
437+ }
438+ estate.mu.Lock() // back at it
439+
440 if e.ecfg().stateServer() {
441 // TODO(rog) factor out relevant code from cmd/jujud/bootstrap.go
442 // so that we can call it here.
443@@ -653,7 +667,7 @@
444
445 defer delay()
446 machineId := machineConfig.MachineId
447- log.Infof("environs/dummy: dummy startinstance, machine %s", machineId)
448+ logger.Infof("dummy startinstance, machine %s", machineId)
449 if err := e.checkBroken("StartInstance"); err != nil {
450 return nil, nil, err
451 }
452@@ -675,7 +689,7 @@
453 if machineConfig.APIInfo.Tag != names.MachineTag(machineId) {
454 return nil, nil, fmt.Errorf("entity tag must match started machine")
455 }
456- log.Infof("environs/dummy: would pick tools from %s", possibleTools)
457+ logger.Infof("would pick tools from %s", possibleTools)
458 series := possibleTools.OneSeries()
459 i := &dummyInstance{
460 id: instance.Id(fmt.Sprintf("%s-%d", e.name, estate.maxId)),
461@@ -899,7 +913,7 @@
462
463 func (inst *dummyInstance) OpenPorts(machineId string, ports []instance.Port) error {
464 defer delay()
465- log.Infof("environs/dummy: openPorts %s, %#v", machineId, ports)
466+ logger.Infof("openPorts %s, %#v", machineId, ports)
467 if inst.firewallMode != config.FwInstance {
468 return fmt.Errorf("invalid firewall mode %q for opening ports on instance",
469 inst.firewallMode)
470@@ -970,7 +984,7 @@
471 // pause execution to simulate the latency of a real provider
472 func delay() {
473 if providerDelay > 0 {
474- log.Infof("environs/dummy: pausing for %v", providerDelay)
475+ logger.Infof("pausing for %v", providerDelay)
476 <-time.After(providerDelay)
477 }
478 }

Subscribers

People subscribed via source and target branches

to status/vote changes: