Merge lp:~dimitern/juju-core/350-api-service-deploy-with-networks into lp:~go-bot/juju-core/trunk
- 350-api-service-deploy-with-networks
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Dimiter Naydenov |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2487 |
Proposed branch: | lp:~dimitern/juju-core/350-api-service-deploy-with-networks |
Merge into: | lp:~go-bot/juju-core/trunk |
Diff against target: |
427 lines (+183/-49) 9 files modified
juju/conn_test.go (+19/-1) juju/deploy.go (+21/-5) state/api/client.go (+19/-2) state/api/params/params.go (+4/-0) state/apiserver/client/client.go (+15/-6) state/apiserver/client/client_test.go (+45/-23) state/apiserver/client/perm_test.go (+12/-0) state/assign_test.go (+16/-1) state/unit.go (+32/-11) |
To merge this branch: | bzr merge lp:~dimitern/juju-core/350-api-service-deploy-with-networks |
Related bugs: | |
Related blueprints: |
Support MaaS VLANs in Juju
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+211773@code.launchpad.net |
Commit message
state/api: Add Client.
This adds a new client API call: ServiceDeployWi
which works exactly like ServiceDeploy, but takes two extra
arguments: IncludeNetworks and ExcludeNetworks.
These specify a list of VLANs/networks to enable or disable
at boot time for the machine being deployed, and also record
that into the service document.
AddUnits is also changed (and its tests) to respect networks
set on the service and pass them through MachineTemplate when
deploying or a new machine or container.
https:/
R=gz, rogpeppe
Description of the change
state/api: Add Client.
This adds a new client API call: ServiceDeployWi
which works exactly like ServiceDeploy, but takes two extra
arguments: IncludeNetworks and ExcludeNetworks.
These specify a list of VLANs/networks to enable or disable
at boot time for the machine being deployed, and also record
that into the service document.
AddUnits is also changed (and its tests) to respect networks
set on the service and pass them through MachineTemplate when
deploying or a new machine or container.
Dimiter Naydenov (dimitern) wrote : | # |
William Reade (fwereade) wrote : | # |
1) it's hard to approve this without an implementation in the background
2) should we be talking network tags?
https:/
File state/apiserver
https:/
state/apiserver
might be nicer to copy args into a ServiceDeployWi
https:/
state/apiserver
serviceDeploy(args0 *params.
*params.
...and just handle one arg type here?
Roger Peppe (rogpeppe) wrote : | # |
https:/
File state/api/
https:/
state/api/
I suggest that instead of making a new set of parameters, we could just
add the networks parameters to ServiceDeploy, and make
ServiceDeployWi
We can document the new fields as recognised only in 1.18 (1.19? 1.20?)
API servers.
This means that clients that care that the networks fields are
recognised can use ServiceDeployWi
continue to use Deploy, and eventually we should be able to deprecate
ServiceDeployWi
This adds minimal clutter to the code, and provides the same
functionality AFAICS.
Dimiter Naydenov (dimitern) wrote : | # |
Please take a look.
https:/
File state/api/
https:/
state/api/
On 2014/03/20 14:06:23, rog wrote:
> I suggest that instead of making a new set of parameters, we could
just add the
> networks parameters to ServiceDeploy, and make
ServiceDeployWi
> alias of Deploy.
> We can document the new fields as recognised only in 1.18 (1.19?
1.20?) API
> servers.
> This means that clients that care that the networks fields are
recognised can
> use ServiceDeployWi
use Deploy,
> and eventually we should be able to deprecate
ServiceDeployWi
> This adds minimal clutter to the code, and provides the same
functionality
> AFAICS.
Done.
https:/
File state/apiserver
https:/
state/apiserver
On 2014/03/20 13:42:50, fwereade wrote:
> might be nicer to copy args into a ServiceDeployWi
Done as rog suggested - ServiceDeployWi
ServiceDeploy.
https:/
state/apiserver
serviceDeploy(args0 *params.
*params.
On 2014/03/20 13:42:50, fwereade wrote:
> ...and just handle one arg type here?
Done differently.
Roger Peppe (rogpeppe) wrote : | # |
much nicer, thanks.
LGTM with one suggestion below.
https:/
File state/apiserver
https:/
state/apiserver
&& len(args.
I'd remove this and make the two commands exactly the same. Then clients
can use this call for all Deploy purposes if they wish.
John A Meinel (jameinel) wrote : | # |
https:/
File state/apiserver
https:/
state/apiserver
&& len(args.
On 2014/03/20 15:45:03, rog wrote:
> I'd remove this and make the two commands exactly the same. Then
clients can use
> this call for all Deploy purposes if they wish.
As William pointed out in IRC, I think the "ideal" would be to have API
versioning and then we'd just have ServiceDeploy that accepts
everything. However, I think lacking that I agree with Roger. I'd rather
have just 1 API that is always called.
(So we effectively have API versioning, just via a clumsy renaming of
the API each time.)
Dimiter Naydenov (dimitern) wrote : | # |
Please take a look.
https:/
File state/apiserver
https:/
state/apiserver
&& len(args.
On 2014/03/20 15:45:03, rog wrote:
> I'd remove this and make the two commands exactly the same. Then
clients can use
> this call for all Deploy purposes if they wish.
Done.
https:/
state/apiserver
&& len(args.
On 2014/03/20 20:38:22, jameinel wrote:
> On 2014/03/20 15:45:03, rog wrote:
> > I'd remove this and make the two commands exactly the same. Then
clients can
> use
> > this call for all Deploy purposes if they wish.
> As William pointed out in IRC, I think the "ideal" would be to have
API
> versioning and then we'd just have ServiceDeploy that accepts
everything.
> However, I think lacking that I agree with Roger. I'd rather have just
1 API
> that is always called.
> (So we effectively have API versioning, just via a clumsy renaming of
the API
> each time.)
Done as rog suggested. Also, I'm not landing this until mgz's branch
lands. Then I'll integrate the two and drop the related TODOs.
William Reade (fwereade) wrote : | # |
On 2014/03/20 20:38:21, jameinel wrote:
> As William pointed out in IRC, I think the "ideal" would be to have
API
> versioning and then we'd just have ServiceDeploy that accepts
everything.
> However, I think lacking that I agree with Roger. I'd rather have just
1 API
> that is always called.
> (So we effectively have API versioning, just via a clumsy renaming of
the API
> each time.)
I can bear it on this occasion, but this is only suitable in the
ultra-short-term: it will now look as though the old version supports
networks, even though it doesn't (especially if we start autogenerating
docs etc).
Dimiter Naydenov (dimitern) wrote : | # |
Please take a look.
Martin Packman (gz) wrote : | # |
Preview Diff
1 | === modified file 'juju/conn_test.go' |
2 | --- juju/conn_test.go 2014-03-25 15:48:47 +0000 |
3 | +++ juju/conn_test.go 2014-03-26 10:43:53 +0000 |
4 | @@ -398,15 +398,30 @@ |
5 | c.Assert(sch.Revision(), gc.Equals, rev+1) |
6 | } |
7 | |
8 | +func (s *ConnSuite) assertAssignedMachineNetworks(c *gc.C, unit *state.Unit, expectInclude, expectExclude []string) { |
9 | + machineId, err := unit.AssignedMachineId() |
10 | + c.Assert(err, gc.IsNil) |
11 | + machine, err := s.conn.State.Machine(machineId) |
12 | + c.Assert(err, gc.IsNil) |
13 | + include, exclude, err := machine.Networks() |
14 | + c.Assert(err, gc.IsNil) |
15 | + c.Assert(include, jc.DeepEquals, expectInclude) |
16 | + c.Assert(exclude, jc.DeepEquals, expectExclude) |
17 | +} |
18 | + |
19 | func (s *ConnSuite) TestAddUnits(c *gc.C) { |
20 | + withNets := []string{"net1", "net2"} |
21 | + withoutNets := []string{"net3", "net4"} |
22 | curl := coretesting.Charms.ClonedURL(s.repo.Path, "quantal", "riak") |
23 | sch, err := s.conn.PutCharm(curl, s.repo, false) |
24 | c.Assert(err, gc.IsNil) |
25 | - svc, err := s.conn.State.AddService("testriak", "user-admin", sch, nil, nil) |
26 | + svc, err := s.conn.State.AddService("testriak", "user-admin", sch, withNets, withoutNets) |
27 | c.Assert(err, gc.IsNil) |
28 | units, err := juju.AddUnits(s.conn.State, svc, 2, "") |
29 | c.Assert(err, gc.IsNil) |
30 | c.Assert(units, gc.HasLen, 2) |
31 | + s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets) |
32 | + s.assertAssignedMachineNetworks(c, units[1], withNets, withoutNets) |
33 | |
34 | id0, err := units[0].AssignedMachineId() |
35 | c.Assert(err, gc.IsNil) |
36 | @@ -419,16 +434,19 @@ |
37 | |
38 | units, err = juju.AddUnits(s.conn.State, svc, 1, "0") |
39 | c.Assert(err, gc.IsNil) |
40 | + s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets) |
41 | id2, err := units[0].AssignedMachineId() |
42 | c.Assert(id2, gc.Equals, id0) |
43 | |
44 | units, err = juju.AddUnits(s.conn.State, svc, 1, "lxc:0") |
45 | c.Assert(err, gc.IsNil) |
46 | + s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets) |
47 | id3, err := units[0].AssignedMachineId() |
48 | c.Assert(id3, gc.Equals, id0+"/lxc/0") |
49 | |
50 | units, err = juju.AddUnits(s.conn.State, svc, 1, "lxc:"+id3) |
51 | c.Assert(err, gc.IsNil) |
52 | + s.assertAssignedMachineNetworks(c, units[0], withNets, withoutNets) |
53 | id4, err := units[0].AssignedMachineId() |
54 | c.Assert(id4, gc.Equals, id0+"/lxc/0/lxc/0") |
55 | |
56 | |
57 | === modified file 'juju/deploy.go' |
58 | --- juju/deploy.go 2014-03-25 15:06:31 +0000 |
59 | +++ juju/deploy.go 2014-03-26 10:43:53 +0000 |
60 | @@ -28,6 +28,10 @@ |
61 | // - a new container on an existing machine eg "lxc:1" |
62 | // Use string to avoid ambiguity around machine 0. |
63 | ToMachineSpec string |
64 | + // IncludeNetworks holds a list of networks to start on boot. |
65 | + IncludeNetworks []string |
66 | + // ExcludeNetworks holds a list of networks to disable on boot. |
67 | + ExcludeNetworks []string |
68 | } |
69 | |
70 | // DeployService takes a charm and various parameters and deploys it. |
71 | @@ -49,8 +53,13 @@ |
72 | } |
73 | // TODO(fwereade): transactional State.AddService including settings, constraints |
74 | // (minimumUnitCount, initialMachineIds?). |
75 | - // TODO(gz): pass through real includeNetworks and excludeNetworks vals |
76 | - service, err := st.AddService(args.ServiceName, "user-admin", args.Charm, nil, nil) |
77 | + service, err := st.AddService( |
78 | + args.ServiceName, |
79 | + "user-admin", |
80 | + args.Charm, |
81 | + args.IncludeNetworks, |
82 | + args.ExcludeNetworks, |
83 | + ) |
84 | if err != nil { |
85 | return nil, err |
86 | } |
87 | @@ -81,6 +90,11 @@ |
88 | units := make([]*state.Unit, n) |
89 | // Hard code for now till we implement a different approach. |
90 | policy := state.AssignCleanEmpty |
91 | + // All units should have the same networks as the service. |
92 | + includeNetworks, excludeNetworks, err := svc.Networks() |
93 | + if err != nil { |
94 | + return nil, fmt.Errorf("cannot get service %q networks: %v", svc.Name(), err) |
95 | + } |
96 | // TODO what do we do if we fail half-way through this process? |
97 | for i := 0; i < n; i++ { |
98 | unit, err := svc.AddUnit() |
99 | @@ -116,9 +130,11 @@ |
100 | // Create the new machine marked as dirty so that |
101 | // nothing else will grab it before we assign the unit to it. |
102 | template := state.MachineTemplate{ |
103 | - Series: unit.Series(), |
104 | - Jobs: []state.MachineJob{state.JobHostUnits}, |
105 | - Dirty: true, |
106 | + Series: unit.Series(), |
107 | + Jobs: []state.MachineJob{state.JobHostUnits}, |
108 | + Dirty: true, |
109 | + IncludeNetworks: includeNetworks, |
110 | + ExcludeNetworks: excludeNetworks, |
111 | } |
112 | m, err = st.AddMachineInsideMachine(template, mid, containerType) |
113 | } else { |
114 | |
115 | === modified file 'state/api/client.go' |
116 | --- state/api/client.go 2014-03-26 07:01:48 +0000 |
117 | +++ state/api/client.go 2014-03-26 10:43:53 +0000 |
118 | @@ -256,12 +256,29 @@ |
119 | return c.call("ServiceUnexpose", params, nil) |
120 | } |
121 | |
122 | +// ServiceDeployWithNetworks works exactly like ServiceDeploy, but |
123 | +// allows specifying networks to either include or exclude on the |
124 | +// machine where the charm is deployed. |
125 | +func (c *Client) ServiceDeployWithNetworks(charmURL string, serviceName string, numUnits int, configYAML string, cons constraints.Value, toMachineSpec string, includeNetworks, excludeNetworks []string) error { |
126 | + params := params.ServiceDeploy{ |
127 | + ServiceName: serviceName, |
128 | + CharmUrl: charmURL, |
129 | + NumUnits: numUnits, |
130 | + ConfigYAML: configYAML, |
131 | + Constraints: cons, |
132 | + ToMachineSpec: toMachineSpec, |
133 | + IncludeNetworks: includeNetworks, |
134 | + ExcludeNetworks: excludeNetworks, |
135 | + } |
136 | + return c.st.Call("Client", "", "ServiceDeployWithNetworks", params, nil) |
137 | +} |
138 | + |
139 | // ServiceDeploy obtains the charm, either locally or from the charm store, |
140 | // and deploys it. |
141 | -func (c *Client) ServiceDeploy(charmUrl string, serviceName string, numUnits int, configYAML string, cons constraints.Value, toMachineSpec string) error { |
142 | +func (c *Client) ServiceDeploy(charmURL string, serviceName string, numUnits int, configYAML string, cons constraints.Value, toMachineSpec string) error { |
143 | params := params.ServiceDeploy{ |
144 | ServiceName: serviceName, |
145 | - CharmUrl: charmUrl, |
146 | + CharmUrl: charmURL, |
147 | NumUnits: numUnits, |
148 | ConfigYAML: configYAML, |
149 | Constraints: cons, |
150 | |
151 | === modified file 'state/api/params/params.go' |
152 | --- state/api/params/params.go 2014-03-26 07:01:48 +0000 |
153 | +++ state/api/params/params.go 2014-03-26 10:43:53 +0000 |
154 | @@ -149,6 +149,10 @@ |
155 | ConfigYAML string // Takes precedence over config if both are present. |
156 | Constraints constraints.Value |
157 | ToMachineSpec string |
158 | + // The following fields are supported from 1.17.7 onwards and |
159 | + // ignored before that. |
160 | + IncludeNetworks []string |
161 | + ExcludeNetworks []string |
162 | } |
163 | |
164 | // ServiceUpdate holds the parameters for making the ServiceUpdate call. |
165 | |
166 | === modified file 'state/apiserver/client/client.go' |
167 | --- state/apiserver/client/client.go 2014-03-26 07:01:48 +0000 |
168 | +++ state/apiserver/client/client.go 2014-03-26 10:43:53 +0000 |
169 | @@ -282,16 +282,25 @@ |
170 | |
171 | _, err = juju.DeployService(c.api.state, |
172 | juju.DeployServiceParams{ |
173 | - ServiceName: args.ServiceName, |
174 | - Charm: ch, |
175 | - NumUnits: args.NumUnits, |
176 | - ConfigSettings: settings, |
177 | - Constraints: args.Constraints, |
178 | - ToMachineSpec: args.ToMachineSpec, |
179 | + ServiceName: args.ServiceName, |
180 | + Charm: ch, |
181 | + NumUnits: args.NumUnits, |
182 | + ConfigSettings: settings, |
183 | + Constraints: args.Constraints, |
184 | + ToMachineSpec: args.ToMachineSpec, |
185 | + IncludeNetworks: args.IncludeNetworks, |
186 | + ExcludeNetworks: args.ExcludeNetworks, |
187 | }) |
188 | return err |
189 | } |
190 | |
191 | +// ServiceDeployWithNetworks works exactly like ServiceDeploy, but |
192 | +// allows specifying networks to include or exclude on the machine |
193 | +// where the charm gets deployed. |
194 | +func (c *Client) ServiceDeployWithNetworks(args params.ServiceDeploy) error { |
195 | + return c.ServiceDeploy(args) |
196 | +} |
197 | + |
198 | // ServiceUpdate updates the service attributes, including charm URL, |
199 | // minimum number of units, settings and constraints. |
200 | // All parameters in params.ServiceUpdate except the service name are optional. |
201 | |
202 | === modified file 'state/apiserver/client/client_test.go' |
203 | --- state/apiserver/client/client_test.go 2014-03-26 07:01:48 +0000 |
204 | +++ state/apiserver/client/client_test.go 2014-03-26 10:43:53 +0000 |
205 | @@ -680,6 +680,50 @@ |
206 | } |
207 | } |
208 | |
209 | +func (s *clientSuite) TestClientServiceDeployWithNetworks(c *gc.C) { |
210 | + store, restore := makeMockCharmStore() |
211 | + defer restore() |
212 | + curl, bundle := addCharm(c, store, "dummy") |
213 | + mem4g := constraints.MustParse("mem=4G") |
214 | + err := s.APIState.Client().ServiceDeployWithNetworks( |
215 | + curl.String(), "service", 3, "", mem4g, "", []string{"net1", "net2"}, []string{"net3"}, |
216 | + ) |
217 | + c.Assert(err, gc.IsNil) |
218 | + service := s.assertPrincipalDeployed(c, "service", curl, false, bundle, mem4g) |
219 | + |
220 | + include, exclude, err := service.Networks() |
221 | + c.Assert(err, gc.IsNil) |
222 | + c.Assert(include, gc.DeepEquals, []string{"net1", "net2"}) |
223 | + c.Assert(exclude, gc.DeepEquals, []string{"net3"}) |
224 | +} |
225 | + |
226 | +func (s *clientSuite) assertPrincipalDeployed(c *gc.C, serviceName string, curl *charm.URL, forced bool, bundle charm.Charm, cons constraints.Value) *state.Service { |
227 | + service, err := s.State.Service(serviceName) |
228 | + c.Assert(err, gc.IsNil) |
229 | + charm, force, err := service.Charm() |
230 | + c.Assert(err, gc.IsNil) |
231 | + c.Assert(force, gc.Equals, forced) |
232 | + c.Assert(charm.URL(), gc.DeepEquals, curl) |
233 | + c.Assert(charm.Meta(), gc.DeepEquals, bundle.Meta()) |
234 | + c.Assert(charm.Config(), gc.DeepEquals, bundle.Config()) |
235 | + |
236 | + serviceCons, err := service.Constraints() |
237 | + c.Assert(err, gc.IsNil) |
238 | + c.Assert(serviceCons, gc.DeepEquals, cons) |
239 | + units, err := service.AllUnits() |
240 | + c.Assert(err, gc.IsNil) |
241 | + for _, unit := range units { |
242 | + mid, err := unit.AssignedMachineId() |
243 | + c.Assert(err, gc.IsNil) |
244 | + machine, err := s.State.Machine(mid) |
245 | + c.Assert(err, gc.IsNil) |
246 | + machineCons, err := machine.Constraints() |
247 | + c.Assert(err, gc.IsNil) |
248 | + c.Assert(machineCons, gc.DeepEquals, cons) |
249 | + } |
250 | + return service |
251 | +} |
252 | + |
253 | func (s *clientSuite) TestClientServiceDeployPrincipal(c *gc.C) { |
254 | // TODO(fwereade): test ToMachineSpec directly on srvClient, when we |
255 | // manage to extract it as a package and can thus do it conveniently. |
256 | @@ -691,29 +735,7 @@ |
257 | curl.String(), "service", 3, "", mem4g, "", |
258 | ) |
259 | c.Assert(err, gc.IsNil) |
260 | - service, err := s.State.Service("service") |
261 | - c.Assert(err, gc.IsNil) |
262 | - charm, force, err := service.Charm() |
263 | - c.Assert(err, gc.IsNil) |
264 | - c.Assert(force, gc.Equals, false) |
265 | - c.Assert(charm.URL(), gc.DeepEquals, curl) |
266 | - c.Assert(charm.Meta(), gc.DeepEquals, bundle.Meta()) |
267 | - c.Assert(charm.Config(), gc.DeepEquals, bundle.Config()) |
268 | - |
269 | - cons, err := service.Constraints() |
270 | - c.Assert(err, gc.IsNil) |
271 | - c.Assert(cons, gc.DeepEquals, mem4g) |
272 | - units, err := service.AllUnits() |
273 | - c.Assert(err, gc.IsNil) |
274 | - for _, unit := range units { |
275 | - mid, err := unit.AssignedMachineId() |
276 | - c.Assert(err, gc.IsNil) |
277 | - machine, err := s.State.Machine(mid) |
278 | - c.Assert(err, gc.IsNil) |
279 | - cons, err := machine.Constraints() |
280 | - c.Assert(err, gc.IsNil) |
281 | - c.Assert(cons, gc.DeepEquals, mem4g) |
282 | - } |
283 | + s.assertPrincipalDeployed(c, "service", curl, false, bundle, mem4g) |
284 | } |
285 | |
286 | func (s *clientSuite) TestClientServiceDeploySubordinate(c *gc.C) { |
287 | |
288 | === modified file 'state/apiserver/client/perm_test.go' |
289 | --- state/apiserver/client/perm_test.go 2014-03-13 07:54:56 +0000 |
290 | +++ state/apiserver/client/perm_test.go 2014-03-26 10:43:53 +0000 |
291 | @@ -69,6 +69,10 @@ |
292 | op: opClientServiceDeploy, |
293 | allow: []string{"user-admin", "user-other"}, |
294 | }, { |
295 | + about: "Client.ServiceDeployWithNetworks", |
296 | + op: opClientServiceDeployWithNetworks, |
297 | + allow: []string{"user-admin", "user-other"}, |
298 | +}, { |
299 | about: "Client.ServiceUpdate", |
300 | op: opClientServiceUpdate, |
301 | allow: []string{"user-admin", "user-other"}, |
302 | @@ -321,6 +325,14 @@ |
303 | return func() {}, err |
304 | } |
305 | |
306 | +func opClientServiceDeployWithNetworks(c *gc.C, st *api.State, mst *state.State) (func(), error) { |
307 | + err := st.Client().ServiceDeployWithNetworks("mad:bad/url-1", "x", 1, "", constraints.Value{}, "", nil, nil) |
308 | + if err.Error() == `charm URL has invalid schema: "mad:bad/url-1"` { |
309 | + err = nil |
310 | + } |
311 | + return func() {}, err |
312 | +} |
313 | + |
314 | func opClientServiceUpdate(c *gc.C, st *api.State, mst *state.State) (func(), error) { |
315 | args := params.ServiceUpdate{ |
316 | ServiceName: "no-such-charm", |
317 | |
318 | === modified file 'state/assign_test.go' |
319 | --- state/assign_test.go 2014-03-13 07:54:56 +0000 |
320 | +++ state/assign_test.go 2014-03-26 10:43:53 +0000 |
321 | @@ -28,7 +28,13 @@ |
322 | |
323 | func (s *AssignSuite) SetUpTest(c *gc.C) { |
324 | s.ConnSuite.SetUpTest(c) |
325 | - wordpress := s.AddTestingService(c, "wordpress", s.AddTestingCharm(c, "wordpress")) |
326 | + wordpress := s.AddTestingServiceWithNetworks( |
327 | + c, |
328 | + "wordpress", |
329 | + s.AddTestingCharm(c, "wordpress"), |
330 | + []string{"net1", "net2"}, |
331 | + []string{"net3", "net4"}, |
332 | + ) |
333 | s.wordpress = wordpress |
334 | } |
335 | |
336 | @@ -312,12 +318,21 @@ |
337 | } |
338 | |
339 | func (s *AssignSuite) assertAssignedUnit(c *gc.C, unit *state.Unit) string { |
340 | + // Get service networks. |
341 | + service, err := unit.Service() |
342 | + c.Assert(err, gc.IsNil) |
343 | + includeNetworks, excludeNetworks, err := service.Networks() |
344 | + c.Assert(err, gc.IsNil) |
345 | // Check the machine on the unit is set. |
346 | machineId, err := unit.AssignedMachineId() |
347 | c.Assert(err, gc.IsNil) |
348 | // Check that the principal is set on the machine. |
349 | machine, err := s.State.Machine(machineId) |
350 | c.Assert(err, gc.IsNil) |
351 | + include, exclude, err := machine.Networks() |
352 | + c.Assert(err, gc.IsNil) |
353 | + c.Assert(include, gc.DeepEquals, includeNetworks) |
354 | + c.Assert(exclude, gc.DeepEquals, excludeNetworks) |
355 | machineUnits, err := machine.Units() |
356 | c.Assert(err, gc.IsNil) |
357 | c.Assert(machineUnits, gc.HasLen, 1) |
358 | |
359 | === modified file 'state/unit.go' |
360 | --- state/unit.go 2014-03-19 23:07:33 +0000 |
361 | +++ state/unit.go 2014-03-26 10:43:53 +0000 |
362 | @@ -991,11 +991,12 @@ |
363 | return &cons, nil |
364 | } |
365 | |
366 | -// AssignToNewMachineOrContainer assigns the unit to a new machine, with constraints |
367 | -// determined according to the service and environment constraints at the time of unit creation. |
368 | -// If a container is required, a clean, empty machine instance is required on which to create |
369 | -// the container. An existing clean, empty instance is first searched for, and if not found, |
370 | -// a new one is created. |
371 | +// AssignToNewMachineOrContainer assigns the unit to a new machine, |
372 | +// with constraints determined according to the service and |
373 | +// environment constraints at the time of unit creation. If a |
374 | +// container is required, a clean, empty machine instance is required |
375 | +// on which to create the container. An existing clean, empty instance |
376 | +// is first searched for, and if not found, a new one is created. |
377 | func (u *Unit) AssignToNewMachineOrContainer() (err error) { |
378 | defer assignContextf(&err, u, "new machine or container") |
379 | if u.doc.Principal != "" { |
380 | @@ -1026,10 +1027,20 @@ |
381 | } else if err != nil { |
382 | return err |
383 | } |
384 | + svc, err := u.Service() |
385 | + if err != nil { |
386 | + return err |
387 | + } |
388 | + includeNetworks, excludeNetworks, err := svc.Networks() |
389 | + if err != nil { |
390 | + return err |
391 | + } |
392 | template := MachineTemplate{ |
393 | - Series: u.doc.Series, |
394 | - Constraints: *cons, |
395 | - Jobs: []MachineJob{JobHostUnits}, |
396 | + Series: u.doc.Series, |
397 | + Constraints: *cons, |
398 | + Jobs: []MachineJob{JobHostUnits}, |
399 | + IncludeNetworks: includeNetworks, |
400 | + ExcludeNetworks: excludeNetworks, |
401 | } |
402 | err = u.assignToNewMachine(template, host.Id, *cons.Container) |
403 | if err == machineNotCleanErr { |
404 | @@ -1059,10 +1070,20 @@ |
405 | if cons.HasContainer() { |
406 | containerType = *cons.Container |
407 | } |
408 | + svc, err := u.Service() |
409 | + if err != nil { |
410 | + return err |
411 | + } |
412 | + includeNetworks, excludeNetworks, err := svc.Networks() |
413 | + if err != nil { |
414 | + return err |
415 | + } |
416 | template := MachineTemplate{ |
417 | - Series: u.doc.Series, |
418 | - Constraints: *cons, |
419 | - Jobs: []MachineJob{JobHostUnits}, |
420 | + Series: u.doc.Series, |
421 | + Constraints: *cons, |
422 | + Jobs: []MachineJob{JobHostUnits}, |
423 | + IncludeNetworks: includeNetworks, |
424 | + ExcludeNetworks: excludeNetworks, |
425 | } |
426 | return u.assignToNewMachine(template, "", containerType) |
427 | } |
Reviewers: mp+211773_ code.launchpad. net,
Message:
Please take a look.
Description: ServiceDeployWi thNetworks
state/api: Add Client.
This adds a new client API call: ServiceDeployWi thNetworks,
which works exactly like ServiceDeploy, but takes two extra
arguments (required) IncludedNetworks and ExcludedNetworks.
These specify a list of VLANs/networks to enable or disable
at boot time for the machine being deployed, and also record
that into the service document.
Right now, the new API does not change the service and/or
machine documents to add the networks, because there's another
branch mgz is doing for that right now.
https:/ /code.launchpad .net/~dimitern/ juju-core/ 350-api- service- deploy- with-networks/ +merge/ 211773
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/76910044/
Affected files (+162, -37 lines): params/ params. go /client/ client. go /client/ client_ test.go /client/ perm_test. go
A [revision details]
M juju/deploy.go
M state/api/client.go
M state/api/
M state/apiserver
M state/apiserver
M state/apiserver