Merge lp:~thumper/juju-core/lxc-broker 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: 1330
Proposed branch: lp:~thumper/juju-core/lxc-broker
Merge into: lp:~go-bot/juju-core/trunk
Prerequisite: lp:~thumper/juju-core/lxc-container
Diff against target: 353 lines (+229/-27)
8 files modified
container/lxc/export_test.go (+0/-19)
container/lxc/lxc_test.go (+6/-5)
container/lxc/mock/mock-lxc.go (+1/-1)
container/lxc/test.go (+29/-0)
worker/provisioner/lxc-broker.go (+64/-0)
worker/provisioner/lxc-broker_test.go (+127/-0)
worker/provisioner/provisioner.go (+1/-1)
worker/provisioner/provisioner_task.go (+1/-1)
To merge this branch: bzr merge lp:~thumper/juju-core/lxc-broker
Reviewer Review Type Date Requested Status
William Reade (community) Approve
Review via email: mp+170713@code.launchpad.net

Commit message

Implement the lxc broker for the provisioner

Not hooked up yet.

https://codereview.appspot.com/10409049/

Description of the change

Implement the lxc broker for the provisioner

Had to make some test functions and helpers exported.

https://codereview.appspot.com/10409049/

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

Reviewers: mp+170713_code.launchpad.net,

Message:
Please take a look.

Description:
Implement the lxc broker for the provisioner

Had to make some test functions and helpers exported.

https://code.launchpad.net/~thumper/juju-core/lxc-broker/+merge/170713

Requires:
https://code.launchpad.net/~thumper/juju-core/lxc-container/+merge/169980

(do not edit description out of merge proposal)

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

Affected files:
   A [revision details]
   D container/lxc/export_test.go
   M container/lxc/lxc_test.go
   M container/lxc/mock/mock-lxc.go
   A container/lxc/test.go
   A worker/provisioner/lxc-broker.go
   A worker/provisioner/lxc-broker_test.go
   M worker/provisioner/provisioner.go
   M worker/provisioner/provisioner_task.go

Revision history for this message
Ian Booth (wallyworld) wrote :

Looks good with a few suggestions.

https://codereview.appspot.com/10409049/diff/1/container/lxc/test.go
File container/lxc/test.go (right):

https://codereview.appspot.com/10409049/diff/1/container/lxc/test.go#newcode4
container/lxc/test.go:4: package lxc
This limitation of Go really annoys me.
Could we add a big file level comment that these exported methods must
only be used for tests and not for normal business logic. I know each
method mentions the use of tests but I think a global comment would be
good too.

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker.go
File worker/provisioner/lxc-broker.go (right):

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker.go#newcode27
worker/provisioner/lxc-broker.go:27:
To help with understanding what interface lxcBroker implements, and to
cause a compile time error if the contract is not met, the idiom we have
been using for other things is to add a line like this above the struct
definition:

var _ Broker = (*lxcBroker)(nil)

(rinse and repeat for any other implemented interfaces).

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker_test.go
File worker/provisioner/lxc-broker_test.go (right):

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker_test.go#newcode80
worker/provisioner/lxc-broker_test.go:80: c.Assert(lxc.Id(), Equals,
instance.Id("juju-machine-1-lxc-0"))
Can we test more than this? Perhaps ensure the started instance is in
the list of running instances? Anything else we can check? Like
files/dirs created to show the instance is started?

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker_test.go#newcode88
worker/provisioner/lxc-broker_test.go:88: c.Assert(err, IsNil)
There's more we could do here - we haven't verified the stop actually
worked. The method could be empty and just return nil and the test would
still pass. Could we perhaps list the running instances and verify it's
empty? Oh, and invoke stop on just one instance and see that the others
remain.

https://codereview.appspot.com/10409049/

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

Please take a look.

https://codereview.appspot.com/10409049/diff/1/container/lxc/test.go
File container/lxc/test.go (right):

https://codereview.appspot.com/10409049/diff/1/container/lxc/test.go#newcode4
container/lxc/test.go:4: package lxc
On 2013/06/21 00:19:32, wallyworld wrote:
> This limitation of Go really annoys me.
> Could we add a big file level comment that these exported methods must
only be
> used for tests and not for normal business logic. I know each method
mentions
> the use of tests but I think a global comment would be good too.

Done.

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker.go
File worker/provisioner/lxc-broker.go (right):

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker.go#newcode27
worker/provisioner/lxc-broker.go:27:
On 2013/06/21 00:19:32, wallyworld wrote:
> To help with understanding what interface lxcBroker implements, and to
cause a
> compile time error if the contract is not met, the idiom we have been
using for
> other things is to add a line like this above the struct definition:

> var _ Broker = (*lxcBroker)(nil)

> (rinse and repeat for any other implemented interfaces).

Done.

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker_test.go
File worker/provisioner/lxc-broker_test.go (right):

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker_test.go#newcode80
worker/provisioner/lxc-broker_test.go:80: c.Assert(lxc.Id(), Equals,
instance.Id("juju-machine-1-lxc-0"))
On 2013/06/21 00:19:32, wallyworld wrote:
> Can we test more than this? Perhaps ensure the started instance is in
the list
> of running instances? Anything else we can check? Like files/dirs
created to
> show the instance is started?

Are we getting into duplication here? Perhaps we could check that there
is a container directory with this instance id.

https://codereview.appspot.com/10409049/diff/1/worker/provisioner/lxc-broker_test.go#newcode88
worker/provisioner/lxc-broker_test.go:88: c.Assert(err, IsNil)
On 2013/06/21 00:19:32, wallyworld wrote:
> There's more we could do here - we haven't verified the stop actually
worked.
> The method could be empty and just return nil and the test would still
pass.
> Could we perhaps list the running instances and verify it's empty? Oh,
and
> invoke stop on just one instance and see that the others remain.

Done.

https://codereview.appspot.com/10409049/

Revision history for this message
Ian Booth (wallyworld) wrote :
Revision history for this message
William Reade (fwereade) wrote :
Revision history for this message
William Reade (fwereade) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== removed file 'container/lxc/export_test.go'
2--- container/lxc/export_test.go 2013-06-24 00:35:22 +0000
3+++ container/lxc/export_test.go 1970-01-01 00:00:00 +0000
4@@ -1,19 +0,0 @@
5-// Copyright 2013 Canonical Ltd.
6-// Licensed under the AGPLv3, see LICENCE file for details.
7-
8-package lxc
9-
10-func SetContainerDir(dir string) (old string) {
11- old, containerDir = containerDir, dir
12- return
13-}
14-
15-func SetLxcContainerDir(dir string) (old string) {
16- old, lxcContainerDir = lxcContainerDir, dir
17- return
18-}
19-
20-func SetRemovedContainerDir(dir string) (old string) {
21- old, removedContainerDir = removedContainerDir, dir
22- return
23-}
24
25=== modified file 'container/lxc/lxc_test.go'
26--- container/lxc/lxc_test.go 2013-06-24 00:57:19 +0000
27+++ container/lxc/lxc_test.go 2013-06-25 22:06:25 +0000
28@@ -13,6 +13,7 @@
29 . "launchpad.net/gocheck"
30 "launchpad.net/goyaml"
31 "launchpad.net/juju-core/container/lxc"
32+ "launchpad.net/juju-core/container/lxc/mock"
33 "launchpad.net/juju-core/instance"
34 jujutesting "launchpad.net/juju-core/juju/testing"
35 "launchpad.net/juju-core/state"
36@@ -80,7 +81,7 @@
37 }
38
39 func (s *LxcSuite) TestStartContainer(c *C) {
40- manager := lxc.NewContainerManager(MockFactory(), "")
41+ manager := lxc.NewContainerManager(mock.MockFactory(), "")
42 instance := StartContainer(c, manager, "1/lxc/0")
43
44 name := string(instance.Id())
45@@ -108,7 +109,7 @@
46 }
47
48 func (s *LxcSuite) TestStopContainer(c *C) {
49- manager := lxc.NewContainerManager(MockFactory(), "")
50+ manager := lxc.NewContainerManager(mock.MockFactory(), "")
51 instance := StartContainer(c, manager, "1/lxc/0")
52
53 err := manager.StopContainer(instance)
54@@ -122,7 +123,7 @@
55 }
56
57 func (s *LxcSuite) TestStopContainerNameClash(c *C) {
58- manager := lxc.NewContainerManager(MockFactory(), "")
59+ manager := lxc.NewContainerManager(mock.MockFactory(), "")
60 instance := StartContainer(c, manager, "1/lxc/0")
61
62 name := string(instance.Id())
63@@ -140,13 +141,13 @@
64 }
65
66 func (s *LxcSuite) TestNamedManagerPrefix(c *C) {
67- manager := lxc.NewContainerManager(MockFactory(), "eric")
68+ manager := lxc.NewContainerManager(mock.MockFactory(), "eric")
69 instance := StartContainer(c, manager, "1/lxc/0")
70 c.Assert(string(instance.Id()), Equals, "eric-machine-1-lxc-0")
71 }
72
73 func (s *LxcSuite) TestListContainers(c *C) {
74- factory := MockFactory()
75+ factory := mock.MockFactory()
76 foo := lxc.NewContainerManager(factory, "foo")
77 bar := lxc.NewContainerManager(factory, "bar")
78
79
80=== added directory 'container/lxc/mock'
81=== renamed file 'container/lxc/mock-lxc_test.go' => 'container/lxc/mock/mock-lxc.go'
82--- container/lxc/mock-lxc_test.go 2013-06-19 03:36:33 +0000
83+++ container/lxc/mock/mock-lxc.go 2013-06-25 22:06:25 +0000
84@@ -1,7 +1,7 @@
85 // Copyright 2013 Canonical Ltd.
86 // Licensed under the AGPLv3, see LICENCE file for details.
87
88-package lxc_test
89+package mock
90
91 import (
92 "fmt"
93
94=== added file 'container/lxc/test.go'
95--- container/lxc/test.go 1970-01-01 00:00:00 +0000
96+++ container/lxc/test.go 2013-06-25 22:06:25 +0000
97@@ -0,0 +1,29 @@
98+// Copyright 2013 Canonical Ltd.
99+// Licensed under the AGPLv3, see LICENCE file for details.
100+
101+// Functions defined in this file should *ONLY* be used for testing. These
102+// functions are exported for testing purposes only, and shouldn't be called
103+// from code that isn't in a test file.
104+
105+package lxc
106+
107+// SetContainerDir allows tests in other packages to override the
108+// containerDir.
109+func SetContainerDir(dir string) (old string) {
110+ old, containerDir = containerDir, dir
111+ return
112+}
113+
114+// SetLxcContainerDir allows tests in other packages to override the
115+// lxcContainerDir.
116+func SetLxcContainerDir(dir string) (old string) {
117+ old, lxcContainerDir = lxcContainerDir, dir
118+ return
119+}
120+
121+// SetRemovedContainerDir allows tests in other packages to override the
122+// removedContainerDir.
123+func SetRemovedContainerDir(dir string) (old string) {
124+ old, removedContainerDir = removedContainerDir, dir
125+ return
126+}
127
128=== added file 'worker/provisioner/lxc-broker.go'
129--- worker/provisioner/lxc-broker.go 1970-01-01 00:00:00 +0000
130+++ worker/provisioner/lxc-broker.go 2013-06-25 22:06:25 +0000
131@@ -0,0 +1,64 @@
132+// Copyright 2013 Canonical Ltd.
133+// Licensed under the AGPLv3, see LICENCE file for details.
134+
135+package provisioner
136+
137+import (
138+ "launchpad.net/golxc"
139+ "launchpad.net/juju-core/constraints"
140+ "launchpad.net/juju-core/container/lxc"
141+ "launchpad.net/juju-core/environs/config"
142+ "launchpad.net/juju-core/instance"
143+ "launchpad.net/juju-core/state"
144+ "launchpad.net/juju-core/state/api"
145+ "launchpad.net/loggo"
146+)
147+
148+var lxcLogger = loggo.GetLogger("juju.provisioner.lxc")
149+
150+var _ Broker = (*lxcBroker)(nil)
151+
152+func NewLxcBroker(factory golxc.ContainerFactory, config *config.Config, tools *state.Tools) Broker {
153+ return &lxcBroker{
154+ golxc: factory,
155+ manager: lxc.NewContainerManager(factory, "juju"),
156+ config: config,
157+ tools: tools,
158+ }
159+}
160+
161+type lxcBroker struct {
162+ golxc golxc.ContainerFactory
163+ manager lxc.ContainerManager
164+ config *config.Config
165+ tools *state.Tools
166+}
167+
168+func (broker *lxcBroker) StartInstance(machineId, machineNonce string, series string, cons constraints.Value, info *state.Info, apiInfo *api.Info) (instance.Instance, *instance.HardwareCharacteristics, error) {
169+ lxcLogger.Infof("starting lxc container for machineId: %s", machineId)
170+
171+ inst, err := broker.manager.StartContainer(machineId, series, machineNonce, broker.tools, broker.config, info, apiInfo)
172+ if err != nil {
173+ lxcLogger.Errorf("failed to start container: %v", err)
174+ return nil, nil, err
175+ }
176+ return inst, nil, nil
177+}
178+
179+// StopInstances shuts down the given instances.
180+func (broker *lxcBroker) StopInstances(instances []instance.Instance) error {
181+ // TODO: potentially parallelise.
182+ for _, instance := range instances {
183+ lxcLogger.Infof("stopping lxc container for instance: %s", instance.Id())
184+ if err := broker.manager.StopContainer(instance); err != nil {
185+ lxcLogger.Errorf("container did not stop: %v", err)
186+ return err
187+ }
188+ }
189+ return nil
190+}
191+
192+// AllInstances only returns running containers.
193+func (broker *lxcBroker) AllInstances() (result []instance.Instance, err error) {
194+ return broker.manager.ListContainers()
195+}
196
197=== added file 'worker/provisioner/lxc-broker_test.go'
198--- worker/provisioner/lxc-broker_test.go 1970-01-01 00:00:00 +0000
199+++ worker/provisioner/lxc-broker_test.go 2013-06-25 22:06:25 +0000
200@@ -0,0 +1,127 @@
201+// Copyright 2013 Canonical Ltd.
202+// Licensed under the AGPLv3, see LICENCE file for details.
203+
204+package provisioner_test
205+
206+import (
207+ "path/filepath"
208+
209+ . "launchpad.net/gocheck"
210+ "launchpad.net/golxc"
211+ "launchpad.net/juju-core/constraints"
212+ "launchpad.net/juju-core/container/lxc"
213+ "launchpad.net/juju-core/container/lxc/mock"
214+ "launchpad.net/juju-core/instance"
215+ jujutesting "launchpad.net/juju-core/juju/testing"
216+ "launchpad.net/juju-core/state"
217+ "launchpad.net/juju-core/testing"
218+ . "launchpad.net/juju-core/testing/checkers"
219+ "launchpad.net/juju-core/version"
220+ "launchpad.net/juju-core/worker/provisioner"
221+)
222+
223+type lxcBrokerSuite struct {
224+ testing.LoggingSuite
225+ golxc golxc.ContainerFactory
226+ broker provisioner.Broker
227+ containerDir string
228+ removedDir string
229+ lxcDir string
230+ oldContainerDir string
231+ oldRemovedDir string
232+ oldLxcContainerDir string
233+}
234+
235+var _ = Suite(&lxcBrokerSuite{})
236+
237+func (s *lxcBrokerSuite) SetUpSuite(c *C) {
238+ s.LoggingSuite.SetUpSuite(c)
239+}
240+
241+func (s *lxcBrokerSuite) TearDownSuite(c *C) {
242+ s.LoggingSuite.TearDownSuite(c)
243+}
244+
245+func (s *lxcBrokerSuite) SetUpTest(c *C) {
246+ s.LoggingSuite.SetUpTest(c)
247+ s.containerDir = c.MkDir()
248+ s.oldContainerDir = lxc.SetContainerDir(s.containerDir)
249+ s.removedDir = c.MkDir()
250+ s.oldRemovedDir = lxc.SetRemovedContainerDir(s.removedDir)
251+ s.lxcDir = c.MkDir()
252+ s.oldLxcContainerDir = lxc.SetLxcContainerDir(s.lxcDir)
253+ s.golxc = mock.MockFactory()
254+ tools := &state.Tools{
255+ Binary: version.MustParseBinary("2.3.4-foo-bar"),
256+ URL: "http://tools.example.com/2.3.4-foo-bar.tgz",
257+ }
258+ s.broker = provisioner.NewLxcBroker(s.golxc, testing.EnvironConfig(c), tools)
259+}
260+
261+func (s *lxcBrokerSuite) TearDownTest(c *C) {
262+ lxc.SetContainerDir(s.oldContainerDir)
263+ lxc.SetLxcContainerDir(s.oldLxcContainerDir)
264+ lxc.SetRemovedContainerDir(s.oldRemovedDir)
265+ s.LoggingSuite.TearDownTest(c)
266+}
267+
268+func (s *lxcBrokerSuite) startInstance(c *C, machineId string) instance.Instance {
269+ stateInfo := jujutesting.FakeStateInfo(machineId)
270+ apiInfo := jujutesting.FakeAPIInfo(machineId)
271+
272+ series := "series"
273+ nonce := "fake-nonce"
274+ cons := constraints.Value{}
275+ lxc, _, err := s.broker.StartInstance(machineId, nonce, series, cons, stateInfo, apiInfo)
276+ c.Assert(err, IsNil)
277+ return lxc
278+}
279+
280+func (s *lxcBrokerSuite) TestStartInstance(c *C) {
281+ machineId := "1/lxc/0"
282+ lxc := s.startInstance(c, machineId)
283+ c.Assert(lxc.Id(), Equals, instance.Id("juju-machine-1-lxc-0"))
284+ c.Assert(s.lxcContainerDir(lxc), IsDirectory)
285+ s.assertInstances(c, lxc)
286+}
287+
288+func (s *lxcBrokerSuite) TestStopInstance(c *C) {
289+ lxc0 := s.startInstance(c, "1/lxc/0")
290+ lxc1 := s.startInstance(c, "1/lxc/1")
291+ lxc2 := s.startInstance(c, "1/lxc/2")
292+
293+ err := s.broker.StopInstances([]instance.Instance{lxc0})
294+ c.Assert(err, IsNil)
295+ s.assertInstances(c, lxc1, lxc2)
296+ c.Assert(s.lxcContainerDir(lxc0), DoesNotExist)
297+ c.Assert(s.lxcRemovedContainerDir(lxc0), IsDirectory)
298+
299+ err = s.broker.StopInstances([]instance.Instance{lxc1, lxc2})
300+ c.Assert(err, IsNil)
301+ s.assertInstances(c)
302+}
303+
304+func (s *lxcBrokerSuite) TestAllInstances(c *C) {
305+ lxc0 := s.startInstance(c, "1/lxc/0")
306+ lxc1 := s.startInstance(c, "1/lxc/1")
307+ s.assertInstances(c, lxc0, lxc1)
308+
309+ err := s.broker.StopInstances([]instance.Instance{lxc1})
310+ c.Assert(err, IsNil)
311+ lxc2 := s.startInstance(c, "1/lxc/2")
312+ s.assertInstances(c, lxc0, lxc2)
313+}
314+
315+func (s *lxcBrokerSuite) assertInstances(c *C, inst ...instance.Instance) {
316+ results, err := s.broker.AllInstances()
317+ c.Assert(err, IsNil)
318+ testing.MatchInstances(c, results, inst...)
319+}
320+
321+func (s *lxcBrokerSuite) lxcContainerDir(inst instance.Instance) string {
322+ return filepath.Join(s.containerDir, string(inst.Id()))
323+}
324+
325+func (s *lxcBrokerSuite) lxcRemovedContainerDir(inst instance.Instance) string {
326+ return filepath.Join(s.removedDir, string(inst.Id()))
327+}
328
329=== modified file 'worker/provisioner/provisioner.go'
330--- worker/provisioner/provisioner.go 2013-06-20 11:03:10 +0000
331+++ worker/provisioner/provisioner.go 2013-06-25 22:06:25 +0000
332@@ -80,7 +80,7 @@
333 // to the environment config.
334 machinesWatcher := p.st.WatchEnvironMachines()
335 environmentBroker := newEnvironBroker(p.environ)
336- environmentProvisioner := newProvisionerTask(
337+ environmentProvisioner := NewProvisionerTask(
338 p.machineId,
339 p.st,
340 machinesWatcher,
341
342=== modified file 'worker/provisioner/provisioner_task.go'
343--- worker/provisioner/provisioner_task.go 2013-06-20 04:27:32 +0000
344+++ worker/provisioner/provisioner_task.go 2013-06-25 22:06:25 +0000
345@@ -34,7 +34,7 @@
346 Machine(id string) (*state.Machine, error)
347 }
348
349-func newProvisionerTask(
350+func NewProvisionerTask(
351 machineId string,
352 machineGetter MachineGetter,
353 watcher Watcher,

Subscribers

People subscribed via source and target branches

to status/vote changes: