Merge lp:~axwalk/juju-core/cmdapi-ensureavailability into lp:~go-bot/juju-core/trunk
- cmdapi-ensureavailability
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Andrew Wilkins |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2507 |
Proposed branch: | lp:~axwalk/juju-core/cmdapi-ensureavailability |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
343 lines (+288/-0) 7 files modified
cmd/juju/ensureavailability.go (+81/-0) cmd/juju/ensureavailability_test.go (+114/-0) cmd/juju/main.go (+4/-0) state/api/client.go (+10/-0) state/api/params/params.go (+10/-0) state/apiserver/client/client.go (+13/-0) state/apiserver/client/client_test.go (+56/-0) |
To merge this branch: | bzr merge lp:~axwalk/juju-core/cmdapi-ensureavailability |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+213190@code.launchpad.net |
Commit message
Add ensure-availability command, EnsureAvailability API
We introduce a new ensure-availability juju subcommand, which
calls the new EnsureAvailability client API. This
is the CLI for ensuring high availability of Juju
state servers.
Note: I have not exposed the ensure-availability command yet,
as there is still work to be done in the agents to
properly support HA state servers.
Description of the change
ensure-availability command
We introduce a new ensure-availability juju subcommand,
which calls the new EnsureAvailability client API. This
is the CLI for ensuring high availability of Juju
state servers.
Note: I have not exposed the ensure-availability command yet,
as there is still work to be done in the agents to
properly support HA state servers.
Andrew Wilkins (axwalk) wrote : | # |
Roger Peppe (rogpeppe) wrote : | # |
LGTM modulo the below, thanks!
https:/
File cmd/juju/
https:/
cmd/juju/
environment default-series
use this series for newly started instances ?
https:/
cmd/juju/
I'm not sure about "ha" in lower case - it looks too much like a word.
I'm thinking that either we make it into a proper word ("availability")
or we capitalise the ha - ensure-HA, thus making it clearer that it's an
acronym.
https:/
cmd/juju/
state servers to make available")
Thought for the future - it would be good to be able to run "juju
ensure-HA" without any arguments at all, for when we just want to
maintain the current availability. Perhaps rather than defaulting to 1,
we should default to -1 and complain if it's not specified. That way we
leave that path open.
https:/
File state/api/client.go (right):
https:/
state/api/
There's no point in having an Error in the result as well as an error
return.
https:/
File state/api/
https:/
state/api/
d
https:/
File state/apiserver
https:/
state/apiserver
c.api.state.
series); err != nil {
err := c.api.state.
args.Constraints, series)
return params.
Andrew Wilkins (axwalk) wrote : | # |
Please take a look.
https:/
File cmd/juju/
https:/
cmd/juju/
environment default-series
On 2014/03/28 07:54:23, rog wrote:
> use this series for newly started instances ?
Done.
https:/
cmd/juju/
On 2014/03/28 07:54:23, rog wrote:
> I'm not sure about "ha" in lower case - it looks too much like a word.
I'm
> thinking that either we make it into a proper word ("availability") or
we
> capitalise the ha - ensure-HA, thus making it clearer that it's an
acronym.
Yeah, it didn't look quite right to me, I was following what was in the
card. I've changed it to ensure-availability to be consistent with the
API.
If others disagree, it can be changed easily enough later -- this
command is not yet exposed.
https:/
cmd/juju/
state servers to make available")
On 2014/03/28 07:54:23, rog wrote:
> Thought for the future - it would be good to be able to run "juju
ensure-HA"
> without any arguments at all, for when we just want to maintain the
current
> availability. Perhaps rather than defaulting to 1, we should default
to -1 and
> complain if it's not specified. That way we leave that path open.
Good point, will disallow for now.
https:/
File state/api/client.go (right):
https:/
state/api/
On 2014/03/28 07:54:23, rog wrote:
> There's no point in having an Error in the result as well as an error
return.
Done.
https:/
File state/api/
https:/
state/api/
On 2014/03/28 07:54:23, rog wrote:
> d
Done.
https:/
File state/apiserver
https:/
state/apiserver
c.api.state.
series); err != nil {
On 2014/03/28 07:54:23, rog wrote:
> err := c.api.state.
args.Constraints,
> series)
> return params.
Done, except the result is no longer necessary so I've dropped it.
Roger Peppe (rogpeppe) wrote : | # |
On 2014/03/28 10:03:41, axw wrote:
> Please take a look.
> https:/
> File cmd/juju/
https:/
> cmd/juju/
the
> environment default-series
> On 2014/03/28 07:54:23, rog wrote:
> > use this series for newly started instances ?
> Done.
https:/
> cmd/juju/
> On 2014/03/28 07:54:23, rog wrote:
> > I'm not sure about "ha" in lower case - it looks too much like a
word. I'm
> > thinking that either we make it into a proper word ("availability")
or we
> > capitalise the ha - ensure-HA, thus making it clearer that it's an
acronym.
> Yeah, it didn't look quite right to me, I was following what was in
the card.
> I've changed it to ensure-availability to be consistent with the API.
> If others disagree, it can be changed easily enough later -- this
command is not
> yet exposed.
https:/
> cmd/juju/
of state
> servers to make available")
> On 2014/03/28 07:54:23, rog wrote:
> > Thought for the future - it would be good to be able to run "juju
ensure-HA"
> > without any arguments at all, for when we just want to maintain the
current
> > availability. Perhaps rather than defaulting to 1, we should default
to -1 and
> > complain if it's not specified. That way we leave that path open.
> Good point, will disallow for now.
> https:/
> File state/api/client.go (right):
https:/
> state/api/
> On 2014/03/28 07:54:23, rog wrote:
> > There's no point in having an Error in the result as well as an
error return.
> Done.
https:/
> File state/api/
https:/
> state/api/
> On 2014/03/28 07:54:23, rog wrote:
> > d
> Done.
https:/
> File state/apiserver
https:/
> state/apiserver
> c.api.state.
series);
> err != nil {
> On 2014/03/28 07:54:23, rog wrote:
> > err := c.api.state.
args.Constraints,
> > series)
> > return params.
> Done, except the result is no longer necessary so I've dropped it.
LGTM, thanks!
Go Bot (go-bot) wrote : | # |
Attempt to merge into lp:juju-core failed due to conflicts:
text conflict in state/api/client.go
text conflict in state/api/
text conflict in state/apiserver
text conflict in state/apiserver
Andrew Wilkins (axwalk) wrote : | # |
Please take a look.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~axwalk/juju-core/cmdapi-ensureavailability into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
Preview Diff
1 | === added file 'cmd/juju/ensureavailability.go' | |||
2 | --- cmd/juju/ensureavailability.go 1970-01-01 00:00:00 +0000 | |||
3 | +++ cmd/juju/ensureavailability.go 2014-03-28 13:32:35 +0000 | |||
4 | @@ -0,0 +1,81 @@ | |||
5 | 1 | // Copyright 2014 Canonical Ltd. | ||
6 | 2 | // Licensed under the AGPLv3, see LICENCE file for details. | ||
7 | 3 | |||
8 | 4 | package main | ||
9 | 5 | |||
10 | 6 | import ( | ||
11 | 7 | "fmt" | ||
12 | 8 | |||
13 | 9 | "launchpad.net/gnuflag" | ||
14 | 10 | |||
15 | 11 | "launchpad.net/juju-core/cmd" | ||
16 | 12 | "launchpad.net/juju-core/constraints" | ||
17 | 13 | "launchpad.net/juju-core/juju" | ||
18 | 14 | ) | ||
19 | 15 | |||
20 | 16 | type EnsureAvailabilityCommand struct { | ||
21 | 17 | cmd.EnvCommandBase | ||
22 | 18 | NumStateServers int | ||
23 | 19 | // If specified, use this series for newly created machines, | ||
24 | 20 | // else use the environment's default-series | ||
25 | 21 | Series string | ||
26 | 22 | // If specified, these constraints will be merged with those | ||
27 | 23 | // already in the environment when creating new machines. | ||
28 | 24 | Constraints constraints.Value | ||
29 | 25 | } | ||
30 | 26 | |||
31 | 27 | const ensureAvailabilityDoc = ` | ||
32 | 28 | To ensure availability of deployed services, the Juju infrastructure | ||
33 | 29 | must itself be highly available. Ensure-availability must be called | ||
34 | 30 | to ensure that the specified number of state servers are made available. | ||
35 | 31 | |||
36 | 32 | An odd number of state servers is required. | ||
37 | 33 | |||
38 | 34 | Examples: | ||
39 | 35 | juju ensure-availability -n 3 | ||
40 | 36 | Ensure that 3 state servers are available, | ||
41 | 37 | with newly created state server machines | ||
42 | 38 | having the default series and constraints. | ||
43 | 39 | juju ensure-availability -n 5 --series=trusty | ||
44 | 40 | Ensure that 5 state servers are available, | ||
45 | 41 | with newly created state server machines | ||
46 | 42 | having the "trusty" series. | ||
47 | 43 | juju ensure-availability -n 7 --constraints mem=8G | ||
48 | 44 | Ensure that 7 state servers are available, | ||
49 | 45 | with newly created state server machines | ||
50 | 46 | having the default series, and at least | ||
51 | 47 | 8GB RAM. | ||
52 | 48 | ` | ||
53 | 49 | |||
54 | 50 | func (c *EnsureAvailabilityCommand) Info() *cmd.Info { | ||
55 | 51 | return &cmd.Info{ | ||
56 | 52 | Name: "ensure-availability", | ||
57 | 53 | Purpose: "ensure the availability of Juju state servers", | ||
58 | 54 | Doc: ensureAvailabilityDoc, | ||
59 | 55 | } | ||
60 | 56 | } | ||
61 | 57 | |||
62 | 58 | func (c *EnsureAvailabilityCommand) SetFlags(f *gnuflag.FlagSet) { | ||
63 | 59 | c.EnvCommandBase.SetFlags(f) | ||
64 | 60 | f.IntVar(&c.NumStateServers, "n", -1, "number of state servers to make available") | ||
65 | 61 | f.StringVar(&c.Series, "series", "", "the charm series") | ||
66 | 62 | f.Var(constraints.ConstraintsValue{&c.Constraints}, "constraints", "additional machine constraints") | ||
67 | 63 | } | ||
68 | 64 | |||
69 | 65 | func (c *EnsureAvailabilityCommand) Init(args []string) error { | ||
70 | 66 | if c.NumStateServers%2 != 1 || c.NumStateServers <= 0 { | ||
71 | 67 | return fmt.Errorf("must specify a number of state servers odd and greater than zero") | ||
72 | 68 | } | ||
73 | 69 | return cmd.CheckEmpty(args) | ||
74 | 70 | } | ||
75 | 71 | |||
76 | 72 | // Run connects to the environment specified on the command line | ||
77 | 73 | // and calls EnsureAvailability. | ||
78 | 74 | func (c *EnsureAvailabilityCommand) Run(_ *cmd.Context) error { | ||
79 | 75 | client, err := juju.NewAPIClientFromName(c.EnvName) | ||
80 | 76 | if err != nil { | ||
81 | 77 | return err | ||
82 | 78 | } | ||
83 | 79 | defer client.Close() | ||
84 | 80 | return client.EnsureAvailability(c.NumStateServers, c.Constraints, c.Series) | ||
85 | 81 | } | ||
86 | 0 | 82 | ||
87 | === added file 'cmd/juju/ensureavailability_test.go' | |||
88 | --- cmd/juju/ensureavailability_test.go 1970-01-01 00:00:00 +0000 | |||
89 | +++ cmd/juju/ensureavailability_test.go 2014-03-28 13:32:35 +0000 | |||
90 | @@ -0,0 +1,114 @@ | |||
91 | 1 | // Copyright 2013 Canonical Ltd. | ||
92 | 2 | // Licensed under the AGPLv3, see LICENCE file for details. | ||
93 | 3 | |||
94 | 4 | package main | ||
95 | 5 | |||
96 | 6 | import ( | ||
97 | 7 | "fmt" | ||
98 | 8 | |||
99 | 9 | jc "github.com/juju/testing/checkers" | ||
100 | 10 | gc "launchpad.net/gocheck" | ||
101 | 11 | |||
102 | 12 | "launchpad.net/juju-core/constraints" | ||
103 | 13 | jujutesting "launchpad.net/juju-core/juju/testing" | ||
104 | 14 | "launchpad.net/juju-core/state" | ||
105 | 15 | "launchpad.net/juju-core/testing" | ||
106 | 16 | ) | ||
107 | 17 | |||
108 | 18 | type EnsureAvailabilitySuite struct { | ||
109 | 19 | jujutesting.RepoSuite | ||
110 | 20 | } | ||
111 | 21 | |||
112 | 22 | var _ = gc.Suite(&EnsureAvailabilitySuite{}) | ||
113 | 23 | |||
114 | 24 | func runEnsureAvailability(c *gc.C, args ...string) error { | ||
115 | 25 | _, err := testing.RunCommand(c, &EnsureAvailabilityCommand{}, args) | ||
116 | 26 | return err | ||
117 | 27 | } | ||
118 | 28 | |||
119 | 29 | func (s *EnsureAvailabilitySuite) TestEnsureAvailability(c *gc.C) { | ||
120 | 30 | err := runEnsureAvailability(c, "-n", "1") | ||
121 | 31 | c.Assert(err, gc.IsNil) | ||
122 | 32 | m, err := s.State.Machine("0") | ||
123 | 33 | c.Assert(err, gc.IsNil) | ||
124 | 34 | c.Assert(m.Life(), gc.Equals, state.Alive) | ||
125 | 35 | c.Assert(m.Series(), gc.DeepEquals, "precise") | ||
126 | 36 | mcons, err := m.Constraints() | ||
127 | 37 | c.Assert(err, gc.IsNil) | ||
128 | 38 | c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) | ||
129 | 39 | } | ||
130 | 40 | |||
131 | 41 | func (s *EnsureAvailabilitySuite) TestEnsureAvailabilityWithSeries(c *gc.C) { | ||
132 | 42 | err := runEnsureAvailability(c, "--series", "series", "-n", "1") | ||
133 | 43 | c.Assert(err, gc.IsNil) | ||
134 | 44 | m, err := s.State.Machine("0") | ||
135 | 45 | c.Assert(err, gc.IsNil) | ||
136 | 46 | c.Assert(m.Series(), gc.DeepEquals, "series") | ||
137 | 47 | } | ||
138 | 48 | |||
139 | 49 | func (s *EnsureAvailabilitySuite) TestEnsureAvailabilityWithConstraints(c *gc.C) { | ||
140 | 50 | err := runEnsureAvailability(c, "--constraints", "mem=4G", "-n", "1") | ||
141 | 51 | c.Assert(err, gc.IsNil) | ||
142 | 52 | m, err := s.State.Machine("0") | ||
143 | 53 | c.Assert(err, gc.IsNil) | ||
144 | 54 | mcons, err := m.Constraints() | ||
145 | 55 | c.Assert(err, gc.IsNil) | ||
146 | 56 | expectedCons := constraints.MustParse("mem=4G") | ||
147 | 57 | c.Assert(mcons, gc.DeepEquals, expectedCons) | ||
148 | 58 | } | ||
149 | 59 | |||
150 | 60 | func (s *EnsureAvailabilitySuite) TestEnsureAvailabilityIdempotent(c *gc.C) { | ||
151 | 61 | for i := 0; i < 2; i++ { | ||
152 | 62 | err := runEnsureAvailability(c, "-n", "1") | ||
153 | 63 | c.Assert(err, gc.IsNil) | ||
154 | 64 | } | ||
155 | 65 | m, err := s.State.Machine("0") | ||
156 | 66 | c.Assert(err, gc.IsNil) | ||
157 | 67 | mcons, err := m.Constraints() | ||
158 | 68 | c.Assert(err, gc.IsNil) | ||
159 | 69 | c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) | ||
160 | 70 | |||
161 | 71 | // Running ensure-availability with constraints or series | ||
162 | 72 | // will have no effect unless new machines are | ||
163 | 73 | // created. | ||
164 | 74 | err = runEnsureAvailability(c, "-n", "1", "--constraints", "mem=4G") | ||
165 | 75 | c.Assert(err, gc.IsNil) | ||
166 | 76 | m, err = s.State.Machine("0") | ||
167 | 77 | c.Assert(err, gc.IsNil) | ||
168 | 78 | mcons, err = m.Constraints() | ||
169 | 79 | c.Assert(err, gc.IsNil) | ||
170 | 80 | c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) | ||
171 | 81 | } | ||
172 | 82 | |||
173 | 83 | func (s *EnsureAvailabilitySuite) TestEnsureAvailabilityMultiple(c *gc.C) { | ||
174 | 84 | err := runEnsureAvailability(c, "-n", "1") | ||
175 | 85 | c.Assert(err, gc.IsNil) | ||
176 | 86 | err = runEnsureAvailability(c, "-n", "3", "--constraints", "mem=4G") | ||
177 | 87 | c.Assert(err, gc.IsNil) | ||
178 | 88 | |||
179 | 89 | machines, err := s.State.AllMachines() | ||
180 | 90 | c.Assert(err, gc.IsNil) | ||
181 | 91 | c.Assert(machines, gc.HasLen, 3) | ||
182 | 92 | mcons, err := machines[0].Constraints() | ||
183 | 93 | c.Assert(err, gc.IsNil) | ||
184 | 94 | c.Assert(&mcons, jc.Satisfies, constraints.IsEmpty) | ||
185 | 95 | for i := 1; i < 3; i++ { | ||
186 | 96 | mcons, err := machines[i].Constraints() | ||
187 | 97 | c.Assert(err, gc.IsNil) | ||
188 | 98 | expectedCons := constraints.MustParse("mem=4G") | ||
189 | 99 | c.Assert(mcons, gc.DeepEquals, expectedCons) | ||
190 | 100 | } | ||
191 | 101 | } | ||
192 | 102 | |||
193 | 103 | func (s *EnsureAvailabilitySuite) TestEnsureAvailabilityErrors(c *gc.C) { | ||
194 | 104 | err := runEnsureAvailability(c) | ||
195 | 105 | c.Assert(err, gc.ErrorMatches, "must specify a number of state servers odd and greater than zero") | ||
196 | 106 | for _, n := range []int{-1, 0, 2} { | ||
197 | 107 | err := runEnsureAvailability(c, "-n", fmt.Sprint(n)) | ||
198 | 108 | c.Assert(err, gc.ErrorMatches, "must specify a number of state servers odd and greater than zero") | ||
199 | 109 | } | ||
200 | 110 | err = runEnsureAvailability(c, "-n", "3") | ||
201 | 111 | c.Assert(err, gc.IsNil) | ||
202 | 112 | err = runEnsureAvailability(c, "-n", "1") | ||
203 | 113 | c.Assert(err, gc.ErrorMatches, "cannot reduce state server count") | ||
204 | 114 | } | ||
205 | 0 | 115 | ||
206 | === modified file 'cmd/juju/main.go' | |||
207 | --- cmd/juju/main.go 2014-03-26 13:40:28 +0000 | |||
208 | +++ cmd/juju/main.go 2014-03-28 13:32:35 +0000 | |||
209 | @@ -125,6 +125,10 @@ | |||
210 | 125 | // Manage authorised ssh keys. | 125 | // Manage authorised ssh keys. |
211 | 126 | jujucmd.Register(wrap(NewAuthorisedKeysCommand())) | 126 | jujucmd.Register(wrap(NewAuthorisedKeysCommand())) |
212 | 127 | 127 | ||
213 | 128 | // Manage state server availability. | ||
214 | 129 | // TODO: enable once the backend is ready for it. | ||
215 | 130 | //jujucmd.Register(wrap(&EnsureAvailabilityCommand{})) | ||
216 | 131 | |||
217 | 128 | // Common commands. | 132 | // Common commands. |
218 | 129 | jujucmd.Register(wrap(&cmd.VersionCommand{})) | 133 | jujucmd.Register(wrap(&cmd.VersionCommand{})) |
219 | 130 | 134 | ||
220 | 131 | 135 | ||
221 | === modified file 'state/api/client.go' | |||
222 | --- state/api/client.go 2014-03-28 05:59:48 +0000 | |||
223 | +++ state/api/client.go 2014-03-28 13:32:35 +0000 | |||
224 | @@ -675,3 +675,13 @@ | |||
225 | 675 | } | 675 | } |
226 | 676 | return result.Servers, nil | 676 | return result.Servers, nil |
227 | 677 | } | 677 | } |
228 | 678 | |||
229 | 679 | // EnsureAvailability ensures the availability of Juju state servers. | ||
230 | 680 | func (c *Client) EnsureAvailability(numStateServers int, cons constraints.Value, series string) error { | ||
231 | 681 | args := params.EnsureAvailability{ | ||
232 | 682 | NumStateServers: numStateServers, | ||
233 | 683 | Constraints: cons, | ||
234 | 684 | Series: series, | ||
235 | 685 | } | ||
236 | 686 | return c.call("EnsureAvailability", args, nil) | ||
237 | 687 | } | ||
238 | 678 | 688 | ||
239 | === modified file 'state/api/params/params.go' | |||
240 | --- state/api/params/params.go 2014-03-28 05:59:48 +0000 | |||
241 | +++ state/api/params/params.go 2014-03-28 13:32:35 +0000 | |||
242 | @@ -639,3 +639,13 @@ | |||
243 | 639 | type APIHostPortsResult struct { | 639 | type APIHostPortsResult struct { |
244 | 640 | Servers [][]instance.HostPort | 640 | Servers [][]instance.HostPort |
245 | 641 | } | 641 | } |
246 | 642 | |||
247 | 643 | // EnsureAvailability contains arguments for | ||
248 | 644 | // the EnsureAvailability client API call. | ||
249 | 645 | type EnsureAvailability struct { | ||
250 | 646 | NumStateServers int | ||
251 | 647 | Constraints constraints.Value | ||
252 | 648 | // Series is the series to associate with new state server machines. | ||
253 | 649 | // If this is empty, then the environment's default series is used. | ||
254 | 650 | Series string | ||
255 | 651 | } | ||
256 | 642 | 652 | ||
257 | === modified file 'state/apiserver/client/client.go' | |||
258 | --- state/apiserver/client/client.go 2014-03-28 05:59:48 +0000 | |||
259 | +++ state/apiserver/client/client.go 2014-03-28 13:32:35 +0000 | |||
260 | @@ -984,3 +984,16 @@ | |||
261 | 984 | } | 984 | } |
262 | 985 | return result, nil | 985 | return result, nil |
263 | 986 | } | 986 | } |
264 | 987 | |||
265 | 988 | // EnsureAvailability ensures the availability of Juju state servers. | ||
266 | 989 | func (c *Client) EnsureAvailability(args params.EnsureAvailability) error { | ||
267 | 990 | series := args.Series | ||
268 | 991 | if series == "" { | ||
269 | 992 | cfg, err := c.api.state.EnvironConfig() | ||
270 | 993 | if err != nil { | ||
271 | 994 | return err | ||
272 | 995 | } | ||
273 | 996 | series = cfg.DefaultSeries() | ||
274 | 997 | } | ||
275 | 998 | return c.api.state.EnsureAvailability(args.NumStateServers, args.Constraints, series) | ||
276 | 999 | } | ||
277 | 987 | 1000 | ||
278 | === modified file 'state/apiserver/client/client_test.go' | |||
279 | --- state/apiserver/client/client_test.go 2014-03-28 09:57:37 +0000 | |||
280 | +++ state/apiserver/client/client_test.go 2014-03-28 13:32:35 +0000 | |||
281 | @@ -2083,6 +2083,62 @@ | |||
282 | 2083 | c.Assert(data["transient"], gc.Equals, true) | 2083 | c.Assert(data["transient"], gc.Equals, true) |
283 | 2084 | } | 2084 | } |
284 | 2085 | 2085 | ||
285 | 2086 | func (s *clientSuite) TestClientEnsureAvailabilitySeries(c *gc.C) { | ||
286 | 2087 | apiParams := []params.EnsureAvailability{{ | ||
287 | 2088 | NumStateServers: 1, | ||
288 | 2089 | }, { | ||
289 | 2090 | NumStateServers: 3, | ||
290 | 2091 | Series: "non-default", | ||
291 | 2092 | }} | ||
292 | 2093 | for _, p := range apiParams { | ||
293 | 2094 | err := s.APIState.Client().EnsureAvailability(p.NumStateServers, p.Constraints, p.Series) | ||
294 | 2095 | c.Assert(err, gc.IsNil) | ||
295 | 2096 | } | ||
296 | 2097 | machines, err := s.State.AllMachines() | ||
297 | 2098 | c.Assert(err, gc.IsNil) | ||
298 | 2099 | c.Assert(machines, gc.HasLen, 3) | ||
299 | 2100 | c.Assert(machines[0].Series(), gc.Equals, "precise") | ||
300 | 2101 | c.Assert(machines[1].Series(), gc.Equals, "non-default") | ||
301 | 2102 | c.Assert(machines[2].Series(), gc.Equals, "non-default") | ||
302 | 2103 | } | ||
303 | 2104 | |||
304 | 2105 | func (s *clientSuite) TestClientEnsureAvailabilityConstraints(c *gc.C) { | ||
305 | 2106 | apiParams := []params.EnsureAvailability{{ | ||
306 | 2107 | NumStateServers: 1, | ||
307 | 2108 | }, { | ||
308 | 2109 | NumStateServers: 3, | ||
309 | 2110 | Constraints: constraints.MustParse("mem=4G"), | ||
310 | 2111 | }} | ||
311 | 2112 | for _, p := range apiParams { | ||
312 | 2113 | err := s.APIState.Client().EnsureAvailability(p.NumStateServers, p.Constraints, p.Series) | ||
313 | 2114 | c.Assert(err, gc.IsNil) | ||
314 | 2115 | } | ||
315 | 2116 | machines, err := s.State.AllMachines() | ||
316 | 2117 | c.Assert(err, gc.IsNil) | ||
317 | 2118 | c.Assert(machines, gc.HasLen, 3) | ||
318 | 2119 | expectedCons := []constraints.Value{ | ||
319 | 2120 | constraints.Value{}, | ||
320 | 2121 | constraints.MustParse("mem=4G"), | ||
321 | 2122 | constraints.MustParse("mem=4G"), | ||
322 | 2123 | } | ||
323 | 2124 | for i, m := range machines { | ||
324 | 2125 | cons, err := m.Constraints() | ||
325 | 2126 | c.Assert(err, gc.IsNil) | ||
326 | 2127 | c.Check(cons, gc.DeepEquals, expectedCons[i]) | ||
327 | 2128 | } | ||
328 | 2129 | } | ||
329 | 2130 | |||
330 | 2131 | func (s *clientSuite) TestClientEnsureAvailabilityErrors(c *gc.C) { | ||
331 | 2132 | var emptyCons constraints.Value | ||
332 | 2133 | defaultSeries := "" | ||
333 | 2134 | err := s.APIState.Client().EnsureAvailability(0, emptyCons, defaultSeries) | ||
334 | 2135 | c.Assert(err, gc.ErrorMatches, "number of state servers must be odd and greater than zero") | ||
335 | 2136 | err = s.APIState.Client().EnsureAvailability(3, emptyCons, defaultSeries) | ||
336 | 2137 | c.Assert(err, gc.IsNil) | ||
337 | 2138 | err = s.APIState.Client().EnsureAvailability(1, emptyCons, defaultSeries) | ||
338 | 2139 | c.Assert(err, gc.ErrorMatches, "cannot reduce state server count") | ||
339 | 2140 | } | ||
340 | 2141 | |||
341 | 2086 | func (s *clientSuite) TestAPIHostPorts(c *gc.C) { | 2142 | func (s *clientSuite) TestAPIHostPorts(c *gc.C) { |
342 | 2087 | apiHostPorts, err := s.APIState.Client().APIHostPorts() | 2143 | apiHostPorts, err := s.APIState.Client().APIHostPorts() |
343 | 2088 | c.Assert(err, gc.IsNil) | 2144 | c.Assert(err, gc.IsNil) |
Reviewers: mp+213190_ code.launchpad. net,
Message:
Please take a look.
Description:
Add ensure-ha command, EnsureAvailability API
We introduce a new ensure-ha juju subcommand, which
calls the new EnsureAvailability client API. This
is the CLI for ensuring high availability of Juju
state servers.
Note: I have not exposed the ensure-ha command yet,
as there is still work to be done in the agents to
properly support HA state servers.
https:/ /code.launchpad .net/~axwalk/ juju-core/ cmdapi- ensureavailabil ity/+merge/ 213190
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/81700043/
Affected files (+301, -0 lines): ensureha. go ensureha_ test.go params/ params. go /client/ client. go /client/ client_ test.go
A [revision details]
A cmd/juju/
A cmd/juju/
M cmd/juju/main.go
M state/api/client.go
M state/api/
M state/apiserver
M state/apiserver