Merge lp:~thumper/juju-core/consolidate-bootstrap-initial-check 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: 1389
Proposed branch: lp:~thumper/juju-core/consolidate-bootstrap-initial-check
Merge into: lp:~go-bot/juju-core/trunk
Prerequisite: lp:~thumper/juju-core/consolidate-bootstrap-state
Diff against target: 170 lines (+48/-42)
5 files modified
environs/bootstrap.go (+26/-0)
environs/dummy/environs.go (+6/-1)
environs/ec2/ec2.go (+1/-18)
environs/maas/environ.go (+13/-4)
environs/openstack/provider.go (+2/-19)
To merge this branch: bzr merge lp:~thumper/juju-core/consolidate-bootstrap-initial-check
Reviewer Review Type Date Requested Status
John A Meinel Approve
Review via email: mp+172715@code.launchpad.net

Commit message

Make a common verification function for bootstrap

https://codereview.appspot.com/10888044/

Description of the change

Make a common verification function for bootstrap

All the providers did the same pre-bootstrap verification
(or should have in the case of maas). As discussed in Oakland,
I pulled the common code out into a shared function.

https://codereview.appspot.com/10888044/

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

Reviewers: mp+172715_code.launchpad.net,

Message:
Please take a look.

Description:
Make a common verification function for bootstrap

All the providers did the same pre-bootstrap verification
(or should have in the case of maas). As discussed in Oakland,
I pulled the common code out into a shared function.

https://code.launchpad.net/~thumper/juju-core/consolidate-bootstrap-initial-check/+merge/172715

Requires:
https://code.launchpad.net/~thumper/juju-core/consolidate-bootstrap-state/+merge/172701

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   M environs/bootstrap.go
   M environs/dummy/environs.go
   M environs/ec2/ec2.go
   M environs/maas/environ.go
   M environs/openstack/provider.go

Index: [revision details]
=== added file '[revision details]'
--- [revision details] 2012-01-01 00:00:00 +0000
+++ [revision details] 2012-01-01 00:00:00 +0000
@@ -0,0 +1,2 @@
+Old revision: <email address hidden>
+New revision: <email address hidden>

Index: environs/bootstrap.go
=== modified file 'environs/bootstrap.go'
--- environs/bootstrap.go 2013-07-02 23:28:43 +0000
+++ environs/bootstrap.go 2013-07-03 01:16:51 +0000
@@ -7,6 +7,8 @@
   "fmt"

   "launchpad.net/juju-core/constraints"
+ "launchpad.net/juju-core/errors"
+ "launchpad.net/juju-core/utils"
  )

  // Bootstrap bootstraps the given environment. The supplied constraints are
@@ -33,3 +35,32 @@
   }
   return environ.Bootstrap(cons)
  }
+
+// VerifyBootstrapInit does the common initial check inside bootstrap to
+// confirm that the environment isn't already running, and that the storage
+// works.
+func VerifyBootstrapInit(env Environ, shortAttempt utils.AttemptStrategy)
error {
+ var err error
+
+ // If the state file exists, it might actually have just been
+ // removed by Destroy, and eventual consistency has not caught
+ // up yet, so we retry to verify if that is happening.
+ for a := shortAttempt.Start(); a.Next(); {
+ _, err = LoadProviderState(env.Storage())
+ if err != nil {
+ break
+ }
+ }
+ if err == nil {
+ return fmt.Errorf("environment is already bootstrapped")
+ }
+ if !errors.IsNotFoundError(err) {
+ return fmt.Errorf("cannot query old bootstrap state: %v", err)
+ }
+
+ err = VerifyStorage(env.Storage())
+ if err != nil {
+ return err
+ }
+ return nil
+}

Index: environs/dummy/environs.go
=== modified file 'environs/dummy/environs.go'
--- environs/dummy/environs.go 2013-06-30 23:37:23 +0000
+++ environs/dummy/environs.go 2013-07-03 01:23:46 +0000
@@ -433,7 +433,12 @@
   if _, ok := e.Config().CACert(); !ok {
    return fmt.Errorf("no CA certificate in environment configuration")
   }
- if err := environs.VerifyStorage(e.Storage()); err != nil {
+
+ var shortAttempt = utils.AttemptStrategy{
+ Total: 200 * time.Millisecond,
+ Delay: 10 * time.Millisecond,
+ }
+ if err := environs.VerifyBootstrapInit(e, shortAttempt); err != nil {
    return err
   }

Index: environs/ec2/ec2.go
=== modified file 'environs/ec2/ec2.go'
--- environs/ec2/ec2.go 2013-07-02 23:15:14 +0000
+++ environs/ec2/ec2....

Read more...

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

An historical note on why MAAS skips the verification step. When we were implementing Bootstrap() in the MAAS provider, we were told that this verification step was needed specifically to deal with lazily-consistent storage — and since MAAS storage is immediately consistent, it wasn't needed in that case.

So that's why we did not duplicate this bit of code in the MAAS provider. Replacing the duplicated code with a generic function that applies to all cases makes it a whole different ballgame, of course.

Revision history for this message
John A Meinel (jameinel) wrote :

If we are not 'lazily consistent' then we can probably drop shortAttemptStrategy down to a max of 1s or something like that.

This code LGTM, though it depends on your earlier work which means sorting out the syntax for that.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'environs/bootstrap.go'
2--- environs/bootstrap.go 2013-07-04 23:08:28 +0000
3+++ environs/bootstrap.go 2013-07-04 23:08:28 +0000
4@@ -7,6 +7,8 @@
5 "fmt"
6
7 "launchpad.net/juju-core/constraints"
8+ "launchpad.net/juju-core/errors"
9+ "launchpad.net/juju-core/utils"
10 )
11
12 // Bootstrap bootstraps the given environment. The supplied constraints are
13@@ -33,3 +35,27 @@
14 }
15 return environ.Bootstrap(cons)
16 }
17+
18+// VerifyBootstrapInit does the common initial check inside bootstrap to
19+// confirm that the environment isn't already running, and that the storage
20+// works.
21+func VerifyBootstrapInit(env Environ, shortAttempt utils.AttemptStrategy) error {
22+ var err error
23+
24+ // If the state file exists, it might actually have just been
25+ // removed by Destroy, and eventual consistency has not caught
26+ // up yet, so we retry to verify if that is happening.
27+ for a := shortAttempt.Start(); a.Next(); {
28+ if _, err = LoadState(env.Storage()); err != nil {
29+ break
30+ }
31+ }
32+ if err == nil {
33+ return fmt.Errorf("environment is already bootstrapped")
34+ }
35+ if !errors.IsNotFoundError(err) {
36+ return fmt.Errorf("cannot query old bootstrap state: %v", err)
37+ }
38+
39+ return VerifyStorage(env.Storage())
40+}
41
42=== modified file 'environs/dummy/environs.go'
43--- environs/dummy/environs.go 2013-07-02 21:52:48 +0000
44+++ environs/dummy/environs.go 2013-07-04 23:08:28 +0000
45@@ -433,7 +433,12 @@
46 if _, ok := e.Config().CACert(); !ok {
47 return fmt.Errorf("no CA certificate in environment configuration")
48 }
49- if err := environs.VerifyStorage(e.Storage()); err != nil {
50+
51+ var shortAttempt = utils.AttemptStrategy{
52+ Total: 200 * time.Millisecond,
53+ Delay: 10 * time.Millisecond,
54+ }
55+ if err := environs.VerifyBootstrapInit(e, shortAttempt); err != nil {
56 return err
57 }
58
59
60=== modified file 'environs/ec2/ec2.go'
61--- environs/ec2/ec2.go 2013-07-02 21:52:48 +0000
62+++ environs/ec2/ec2.go 2013-07-04 23:08:28 +0000
63@@ -16,7 +16,6 @@
64 "launchpad.net/juju-core/environs/imagemetadata"
65 "launchpad.net/juju-core/environs/instances"
66 "launchpad.net/juju-core/environs/tools"
67- "launchpad.net/juju-core/errors"
68 "launchpad.net/juju-core/instance"
69 "launchpad.net/juju-core/log"
70 "launchpad.net/juju-core/state"
71@@ -240,25 +239,9 @@
72 // If the state file exists, it might actually have just been
73 // removed by Destroy, and eventual consistency has not caught
74 // up yet, so we retry to verify if that is happening.
75- var err error
76- for a := shortAttempt.Start(); a.Next(); {
77- _, err = environs.LoadState(e.Storage())
78- if err != nil {
79- break
80- }
81- }
82- if err == nil {
83- return fmt.Errorf("environment is already bootstrapped")
84- }
85- if !errors.IsNotFoundError(err) {
86- return fmt.Errorf("cannot query old bootstrap state: %v", err)
87- }
88-
89- err = environs.VerifyStorage(e.Storage())
90- if err != nil {
91+ if err := environs.VerifyBootstrapInit(e, shortAttempt); err != nil {
92 return err
93 }
94-
95 possibleTools, err := environs.FindBootstrapTools(e, cons)
96 if err != nil {
97 return err
98
99=== modified file 'environs/maas/environ.go'
100--- environs/maas/environ.go 2013-07-02 21:52:48 +0000
101+++ environs/maas/environ.go 2013-07-04 23:08:28 +0000
102@@ -28,6 +28,16 @@
103 apiVersion = "1.0"
104 )
105
106+// A request may fail to due "eventual consistency" semantics, which
107+// should resolve fairly quickly. A request may also fail due to a slow
108+// state transition (for instance an instance taking a while to release
109+// a security group after termination). The former failure mode is
110+// dealt with by shortAttempt, the latter by longAttempt.
111+var shortAttempt = utils.AttemptStrategy{
112+ Total: 5 * time.Second,
113+ Delay: 200 * time.Millisecond,
114+}
115+
116 var longAttempt = utils.AttemptStrategy{
117 Total: 3 * time.Minute,
118 Delay: 1 * time.Second,
119@@ -100,10 +110,9 @@
120
121 // Bootstrap is specified in the Environ interface.
122 func (env *maasEnviron) Bootstrap(cons constraints.Value) error {
123- // TODO(fwereade): this should check for an existing environment before
124- // starting a new one -- even given raciness, it's better than nothing.
125- if err := environs.VerifyStorage(env.Storage()); err != nil {
126- return fmt.Errorf("provider storage is not writeable")
127+
128+ if err := environs.VerifyBootstrapInit(env, shortAttempt); err != nil {
129+ return err
130 }
131
132 inst, err := env.startBootstrapNode(cons)
133
134=== modified file 'environs/openstack/provider.go'
135--- environs/openstack/provider.go 2013-07-02 21:52:48 +0000
136+++ environs/openstack/provider.go 2013-07-04 23:08:28 +0000
137@@ -22,7 +22,6 @@
138 "launchpad.net/juju-core/environs/imagemetadata"
139 "launchpad.net/juju-core/environs/instances"
140 "launchpad.net/juju-core/environs/tools"
141- coreerrors "launchpad.net/juju-core/errors"
142 "launchpad.net/juju-core/instance"
143 "launchpad.net/juju-core/log"
144 "launchpad.net/juju-core/state"
145@@ -466,24 +465,8 @@
146
147 func (e *environ) Bootstrap(cons constraints.Value) error {
148 log.Infof("environs/openstack: bootstrapping environment %q", e.name)
149- // If the state file exists, it might actually have just been
150- // removed by Destroy, and eventual consistency has not caught
151- // up yet, so we retry to verify if that is happening.
152- var err error
153- for a := shortAttempt.Start(); a.Next(); {
154- _, err = environs.LoadState(e.Storage())
155- if err != nil {
156- break
157- }
158- }
159- if err == nil {
160- return fmt.Errorf("environment is already bootstrapped")
161- }
162- if !coreerrors.IsNotFoundError(err) {
163- return fmt.Errorf("cannot query old bootstrap state: %v", err)
164- }
165- err = environs.VerifyStorage(e.Storage())
166- if err != nil {
167+
168+ if err := environs.VerifyBootstrapInit(e, shortAttempt); err != nil {
169 return err
170 }
171

Subscribers

People subscribed via source and target branches

to status/vote changes: