Merge lp:~thumper/juju-core/container-interface into lp:~go-bot/juju-core/trunk
- container-interface
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Tim Penhey |
Approved revision: | no longer in the source branch. |
Merged at revision: | 2047 |
Proposed branch: | lp:~thumper/juju-core/container-interface |
Merge into: | lp:~go-bot/juju-core/trunk |
Prerequisite: | lp:~thumper/juju-core/fix-add-machine-test |
Diff against target: |
439 lines (+104/-81) 6 files modified
container/interface.go (+31/-0) container/lxc/lxc.go (+21/-61) container/lxc/lxc_test.go (+15/-14) container/network.go (+29/-0) provider/local/environ.go (+4/-3) worker/provisioner/lxc-broker.go (+4/-3) |
To merge this branch: | bzr merge lp:~thumper/juju-core/container-interface |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+194757@code.launchpad.net |
Commit message
Move generic bits to container package.
The ContainerManager and the config type to create
it are common over both LXC and KVM. Also, network
config is similarly generic.
Most of this work is just moving types, changing imports
and parameter types.
Description of the change
Move generic bits to container package.
The ContainerManager and the config type to create
it are common over both LXC and KVM. Also, network
config is similarly generic.
Most of this work is just moving types, changing imports
and parameter types.
Tim Penhey (thumper) wrote : | # |
Ian Booth (wallyworld) wrote : | # |
LGTM. Very pleased to see this factored out.
https:/
File container/
https:/
container/
lxc bridge.
s/lxc/network ?
Tim Penhey (thumper) wrote : | # |
https:/
File container/
https:/
container/
lxc bridge.
On 2013/11/11 22:59:14, wallyworld wrote:
> s/lxc/network ?
Done.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~thumper/juju-core/container-interface into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok 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.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpa...
Preview Diff
1 | === added file 'container/interface.go' |
2 | --- container/interface.go 1970-01-01 00:00:00 +0000 |
3 | +++ container/interface.go 2013-11-12 00:35:23 +0000 |
4 | @@ -0,0 +1,31 @@ |
5 | +// Copyright 2013 Canonical Ltd. |
6 | +// Licensed under the AGPLv3, see LICENCE file for details. |
7 | + |
8 | +package container |
9 | + |
10 | +import ( |
11 | + "launchpad.net/juju-core/environs/cloudinit" |
12 | + "launchpad.net/juju-core/instance" |
13 | +) |
14 | + |
15 | +// ManagerConfig contains the initialization parameters for the ContainerManager. |
16 | +// The name of the manager is used to namespace the containers on the machine. |
17 | +type ManagerConfig struct { |
18 | + Name string |
19 | + LogDir string |
20 | +} |
21 | + |
22 | +// Manager is responsible for starting containers, and stopping and listing |
23 | +// containers that it has started. |
24 | +type Manager interface { |
25 | + // StartContainer creates and starts a new container for the specified machine. |
26 | + StartContainer( |
27 | + machineConfig *cloudinit.MachineConfig, |
28 | + series string, |
29 | + network *NetworkConfig) (instance.Instance, error) |
30 | + // StopContainer stops and destroyes the container identified by Instance. |
31 | + StopContainer(instance.Instance) error |
32 | + // ListContainers return a list of containers that have been started by |
33 | + // this manager. |
34 | + ListContainers() ([]instance.Instance, error) |
35 | +} |
36 | |
37 | === modified file 'container/lxc/lxc.go' |
38 | --- container/lxc/lxc.go 2013-11-11 10:57:06 +0000 |
39 | +++ container/lxc/lxc.go 2013-11-12 00:35:23 +0000 |
40 | @@ -14,6 +14,7 @@ |
41 | "launchpad.net/golxc" |
42 | "launchpad.net/loggo" |
43 | |
44 | + "launchpad.net/juju-core/container" |
45 | "launchpad.net/juju-core/environs/cloudinit" |
46 | "launchpad.net/juju-core/instance" |
47 | "launchpad.net/juju-core/names" |
48 | @@ -33,58 +34,14 @@ |
49 | ) |
50 | |
51 | const ( |
52 | - // BridgeNetwork will have the container use the lxc bridge. |
53 | - bridgeNetwork = "bridge" |
54 | - // PhyscialNetwork will have the container use a specified network device. |
55 | - physicalNetwork = "physical" |
56 | // DefaultLxcBridge is the package created container bridge |
57 | DefaultLxcBridge = "lxcbr0" |
58 | ) |
59 | |
60 | -// NetworkConfig defines how the container network will be configured. |
61 | -type NetworkConfig struct { |
62 | - networkType string |
63 | - device string |
64 | -} |
65 | - |
66 | // DefaultNetworkConfig returns a valid NetworkConfig to use the |
67 | // defaultLxcBridge that is created by the lxc package. |
68 | -func DefaultNetworkConfig() *NetworkConfig { |
69 | - return &NetworkConfig{bridgeNetwork, DefaultLxcBridge} |
70 | -} |
71 | - |
72 | -// BridgeNetworkConfig returns a valid NetworkConfig to use the specified |
73 | -// device as a network bridge for the container. |
74 | -func BridgeNetworkConfig(device string) *NetworkConfig { |
75 | - return &NetworkConfig{bridgeNetwork, device} |
76 | -} |
77 | - |
78 | -// PhysicalNetworkConfig returns a valid NetworkConfig to use the specified |
79 | -// device as the network device for the container. |
80 | -func PhysicalNetworkConfig(device string) *NetworkConfig { |
81 | - return &NetworkConfig{physicalNetwork, device} |
82 | -} |
83 | - |
84 | -// ManagerConfig contains the initialization parameters for the ContainerManager. |
85 | -type ManagerConfig struct { |
86 | - Name string |
87 | - LogDir string |
88 | -} |
89 | - |
90 | -// ContainerManager is responsible for starting containers, and stopping and |
91 | -// listing containers that it has started. The name of the manager is used to |
92 | -// namespace the lxc containers on the machine. |
93 | -type ContainerManager interface { |
94 | - // StartContainer creates and starts a new lxc container for the specified machine. |
95 | - StartContainer( |
96 | - machineConfig *cloudinit.MachineConfig, |
97 | - series string, |
98 | - network *NetworkConfig) (instance.Instance, error) |
99 | - // StopContainer stops and destroyes the lxc container identified by Instance. |
100 | - StopContainer(instance.Instance) error |
101 | - // ListContainers return a list of containers that have been started by |
102 | - // this manager. |
103 | - ListContainers() ([]instance.Instance, error) |
104 | +func DefaultNetworkConfig() *container.NetworkConfig { |
105 | + return container.BridgeNetworkConfig(DefaultLxcBridge) |
106 | } |
107 | |
108 | type containerManager struct { |
109 | @@ -92,10 +49,13 @@ |
110 | logdir string |
111 | } |
112 | |
113 | +// containerManager implements container.Manager. |
114 | +var _ container.Manager = (*containerManager)(nil) |
115 | + |
116 | // NewContainerManager returns a manager object that can start and stop lxc |
117 | // containers. The containers that are created are namespaced by the name |
118 | // parameter. |
119 | -func NewContainerManager(conf ManagerConfig) ContainerManager { |
120 | +func NewContainerManager(conf container.ManagerConfig) container.Manager { |
121 | logdir := "/var/log/juju" |
122 | if conf.LogDir != "" { |
123 | logdir = conf.LogDir |
124 | @@ -106,7 +66,7 @@ |
125 | func (manager *containerManager) StartContainer( |
126 | machineConfig *cloudinit.MachineConfig, |
127 | series string, |
128 | - network *NetworkConfig) (instance.Instance, error) { |
129 | + network *container.NetworkConfig) (instance.Instance, error) { |
130 | |
131 | name := names.MachineTag(machineConfig.MachineId) |
132 | if manager.name != "" { |
133 | @@ -115,7 +75,7 @@ |
134 | // Note here that the lxcObjectFacotry only returns a valid container |
135 | // object, and doesn't actually construct the underlying lxc container on |
136 | // disk. |
137 | - container := LxcObjectFactory.New(name) |
138 | + lxcContainer := LxcObjectFactory.New(name) |
139 | |
140 | // Create the cloud-init. |
141 | directory := jujuContainerDirectory(name) |
142 | @@ -144,7 +104,7 @@ |
143 | } |
144 | // Create the container. |
145 | logger.Tracef("create the container") |
146 | - if err := container.Create(configFile, defaultTemplate, templateParams...); err != nil { |
147 | + if err := lxcContainer.Create(configFile, defaultTemplate, templateParams...); err != nil { |
148 | logger.Errorf("lxc container creation failed: %v", err) |
149 | return nil, err |
150 | } |
151 | @@ -165,18 +125,18 @@ |
152 | // Start the lxc container with the appropriate settings for grabbing the |
153 | // console output and a log file. |
154 | consoleFile := filepath.Join(directory, "console.log") |
155 | - container.SetLogFile(filepath.Join(directory, "container.log"), golxc.LogDebug) |
156 | + lxcContainer.SetLogFile(filepath.Join(directory, "container.log"), golxc.LogDebug) |
157 | logger.Tracef("start the container") |
158 | // We explicitly don't pass through the config file to the container.Start |
159 | // method as we have passed it through at container creation time. This |
160 | // is necessary to get the appropriate rootfs reference without explicitly |
161 | // setting it ourselves. |
162 | - if err = container.Start("", consoleFile); err != nil { |
163 | + if err = lxcContainer.Start("", consoleFile); err != nil { |
164 | logger.Errorf("container failed to start: %v", err) |
165 | return nil, err |
166 | } |
167 | logger.Tracef("container started") |
168 | - return &lxcInstance{container, name}, nil |
169 | + return &lxcInstance{lxcContainer, name}, nil |
170 | } |
171 | |
172 | func (manager *containerManager) StopContainer(instance instance.Instance) error { |
173 | @@ -262,23 +222,23 @@ |
174 | return fmt.Sprintf(networkTemplate, networkType, networkLink) |
175 | } |
176 | |
177 | -func generateNetworkConfig(network *NetworkConfig) string { |
178 | +func generateNetworkConfig(network *container.NetworkConfig) string { |
179 | if network == nil { |
180 | logger.Warningf("network unspecified, using default networking config") |
181 | network = DefaultNetworkConfig() |
182 | } |
183 | - switch network.networkType { |
184 | - case physicalNetwork: |
185 | - return networkConfigTemplate("phys", network.device) |
186 | + switch network.NetworkType { |
187 | + case container.PhysicalNetwork: |
188 | + return networkConfigTemplate("phys", network.Device) |
189 | default: |
190 | - logger.Warningf("Unknown network config type %q: using bridge", network.networkType) |
191 | + logger.Warningf("Unknown network config type %q: using bridge", network.NetworkType) |
192 | fallthrough |
193 | - case bridgeNetwork: |
194 | - return networkConfigTemplate("veth", network.device) |
195 | + case container.BridgeNetwork: |
196 | + return networkConfigTemplate("veth", network.Device) |
197 | } |
198 | } |
199 | |
200 | -func writeLxcConfig(network *NetworkConfig, directory, logdir string) (string, error) { |
201 | +func writeLxcConfig(network *container.NetworkConfig, directory, logdir string) (string, error) { |
202 | networkConfig := generateNetworkConfig(network) |
203 | configFilename := filepath.Join(directory, "lxc.conf") |
204 | configContent := fmt.Sprintf(localConfig, networkConfig, logdir) |
205 | |
206 | === modified file 'container/lxc/lxc_test.go' |
207 | --- container/lxc/lxc_test.go 2013-11-11 10:57:06 +0000 |
208 | +++ container/lxc/lxc_test.go 2013-11-12 00:35:23 +0000 |
209 | @@ -15,6 +15,7 @@ |
210 | "launchpad.net/goyaml" |
211 | "launchpad.net/loggo" |
212 | |
213 | + "launchpad.net/juju-core/container" |
214 | "launchpad.net/juju-core/container/lxc" |
215 | lxctesting "launchpad.net/juju-core/container/lxc/testing" |
216 | "launchpad.net/juju-core/environs" |
217 | @@ -65,7 +66,7 @@ |
218 | aptConfigScript = fmt.Sprintf("#!/bin/sh\n echo '%s\n%s'", configHttpProxy, configProxyExtra) |
219 | ) |
220 | |
221 | -func StartContainer(c *gc.C, manager lxc.ContainerManager, machineId string) instance.Instance { |
222 | +func StartContainer(c *gc.C, manager container.Manager, machineId string) instance.Instance { |
223 | stateInfo := jujutesting.FakeStateInfo(machineId) |
224 | apiInfo := jujutesting.FakeAPIInfo(machineId) |
225 | machineConfig := environs.NewMachineConfig(machineId, "fake-nonce", stateInfo, apiInfo) |
226 | @@ -75,14 +76,14 @@ |
227 | } |
228 | |
229 | series := "series" |
230 | - network := lxc.BridgeNetworkConfig("nic42") |
231 | + network := container.BridgeNetworkConfig("nic42") |
232 | inst, err := manager.StartContainer(machineConfig, series, network) |
233 | c.Assert(err, gc.IsNil) |
234 | return inst |
235 | } |
236 | |
237 | func (s *LxcSuite) TestStartContainer(c *gc.C) { |
238 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{}) |
239 | + manager := lxc.NewContainerManager(container.ManagerConfig{}) |
240 | instance := StartContainer(c, manager, "1/lxc/0") |
241 | |
242 | name := string(instance.Id()) |
243 | @@ -130,7 +131,7 @@ |
244 | } |
245 | |
246 | func (s *LxcSuite) TestContainerState(c *gc.C) { |
247 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{}) |
248 | + manager := lxc.NewContainerManager(container.ManagerConfig{}) |
249 | instance := StartContainer(c, manager, "1/lxc/0") |
250 | |
251 | // The mock container will be immediately "running". |
252 | @@ -144,7 +145,7 @@ |
253 | } |
254 | |
255 | func (s *LxcSuite) TestStopContainer(c *gc.C) { |
256 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{}) |
257 | + manager := lxc.NewContainerManager(container.ManagerConfig{}) |
258 | instance := StartContainer(c, manager, "1/lxc/0") |
259 | |
260 | err := manager.StopContainer(instance) |
261 | @@ -158,7 +159,7 @@ |
262 | } |
263 | |
264 | func (s *LxcSuite) TestStopContainerNameClash(c *gc.C) { |
265 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{}) |
266 | + manager := lxc.NewContainerManager(container.ManagerConfig{}) |
267 | instance := StartContainer(c, manager, "1/lxc/0") |
268 | |
269 | name := string(instance.Id()) |
270 | @@ -176,14 +177,14 @@ |
271 | } |
272 | |
273 | func (s *LxcSuite) TestNamedManagerPrefix(c *gc.C) { |
274 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{Name: "eric"}) |
275 | + manager := lxc.NewContainerManager(container.ManagerConfig{Name: "eric"}) |
276 | instance := StartContainer(c, manager, "1/lxc/0") |
277 | c.Assert(string(instance.Id()), gc.Equals, "eric-machine-1-lxc-0") |
278 | } |
279 | |
280 | func (s *LxcSuite) TestListContainers(c *gc.C) { |
281 | - foo := lxc.NewContainerManager(lxc.ManagerConfig{Name: "foo"}) |
282 | - bar := lxc.NewContainerManager(lxc.ManagerConfig{Name: "bar"}) |
283 | + foo := lxc.NewContainerManager(container.ManagerConfig{Name: "foo"}) |
284 | + bar := lxc.NewContainerManager(container.ManagerConfig{Name: "bar"}) |
285 | |
286 | foo1 := StartContainer(c, foo, "1/lxc/0") |
287 | foo2 := StartContainer(c, foo, "1/lxc/1") |
288 | @@ -202,14 +203,14 @@ |
289 | } |
290 | |
291 | func (s *LxcSuite) TestStartContainerAutostarts(c *gc.C) { |
292 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{}) |
293 | + manager := lxc.NewContainerManager(container.ManagerConfig{}) |
294 | instance := StartContainer(c, manager, "1/lxc/0") |
295 | autostartLink := lxc.RestartSymlink(string(instance.Id())) |
296 | c.Assert(autostartLink, jc.IsSymlink) |
297 | } |
298 | |
299 | func (s *LxcSuite) TestStopContainerRemovesAutostartLink(c *gc.C) { |
300 | - manager := lxc.NewContainerManager(lxc.ManagerConfig{}) |
301 | + manager := lxc.NewContainerManager(container.ManagerConfig{}) |
302 | instance := StartContainer(c, manager, "1/lxc/0") |
303 | err := manager.StopContainer(instance) |
304 | c.Assert(err, gc.IsNil) |
305 | @@ -225,7 +226,7 @@ |
306 | |
307 | func (*NetworkSuite) TestGenerateNetworkConfig(c *gc.C) { |
308 | for _, test := range []struct { |
309 | - config *lxc.NetworkConfig |
310 | + config *container.NetworkConfig |
311 | net string |
312 | link string |
313 | }{{ |
314 | @@ -237,11 +238,11 @@ |
315 | net: "veth", |
316 | link: "lxcbr0", |
317 | }, { |
318 | - config: lxc.BridgeNetworkConfig("foo"), |
319 | + config: container.BridgeNetworkConfig("foo"), |
320 | net: "veth", |
321 | link: "foo", |
322 | }, { |
323 | - config: lxc.PhysicalNetworkConfig("foo"), |
324 | + config: container.PhysicalNetworkConfig("foo"), |
325 | net: "phys", |
326 | link: "foo", |
327 | }} { |
328 | |
329 | === added file 'container/network.go' |
330 | --- container/network.go 1970-01-01 00:00:00 +0000 |
331 | +++ container/network.go 2013-11-12 00:35:23 +0000 |
332 | @@ -0,0 +1,29 @@ |
333 | +// Copyright 2013 Canonical Ltd. |
334 | +// Licensed under the AGPLv3, see LICENCE file for details. |
335 | + |
336 | +package container |
337 | + |
338 | +const ( |
339 | + // BridgeNetwork will have the container use the network bridge. |
340 | + BridgeNetwork = "bridge" |
341 | + // PhyscialNetwork will have the container use a specified network device. |
342 | + PhysicalNetwork = "physical" |
343 | +) |
344 | + |
345 | +// NetworkConfig defines how the container network will be configured. |
346 | +type NetworkConfig struct { |
347 | + NetworkType string |
348 | + Device string |
349 | +} |
350 | + |
351 | +// BridgeNetworkConfig returns a valid NetworkConfig to use the specified |
352 | +// device as a network bridge for the container. |
353 | +func BridgeNetworkConfig(device string) *NetworkConfig { |
354 | + return &NetworkConfig{BridgeNetwork, device} |
355 | +} |
356 | + |
357 | +// PhysicalNetworkConfig returns a valid NetworkConfig to use the specified |
358 | +// device as the network device for the container. |
359 | +func PhysicalNetworkConfig(device string) *NetworkConfig { |
360 | + return &NetworkConfig{PhysicalNetwork, device} |
361 | +} |
362 | |
363 | === modified file 'provider/local/environ.go' |
364 | --- provider/local/environ.go 2013-11-07 09:09:55 +0000 |
365 | +++ provider/local/environ.go 2013-11-12 00:35:23 +0000 |
366 | @@ -16,6 +16,7 @@ |
367 | "launchpad.net/juju-core/agent" |
368 | agenttools "launchpad.net/juju-core/agent/tools" |
369 | "launchpad.net/juju-core/constraints" |
370 | + "launchpad.net/juju-core/container" |
371 | "launchpad.net/juju-core/container/lxc" |
372 | "launchpad.net/juju-core/environs" |
373 | "launchpad.net/juju-core/environs/cloudinit" |
374 | @@ -58,7 +59,7 @@ |
375 | name string |
376 | sharedStorageListener net.Listener |
377 | storageListener net.Listener |
378 | - containerManager lxc.ContainerManager |
379 | + containerManager container.Manager |
380 | } |
381 | |
382 | // GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata. |
383 | @@ -175,7 +176,7 @@ |
384 | env.name = ecfg.Name() |
385 | |
386 | env.containerManager = lxc.NewContainerManager( |
387 | - lxc.ManagerConfig{ |
388 | + container.ManagerConfig{ |
389 | Name: env.config.namespace(), |
390 | LogDir: env.config.logDir(), |
391 | }) |
392 | @@ -266,7 +267,7 @@ |
393 | machineConfig.Tools = possibleTools[0] |
394 | machineConfig.MachineContainerType = instance.LXC |
395 | logger.Debugf("tools: %#v", machineConfig.Tools) |
396 | - network := lxc.BridgeNetworkConfig(env.config.networkBridge()) |
397 | + network := container.BridgeNetworkConfig(env.config.networkBridge()) |
398 | if err := environs.FinishMachineConfig(machineConfig, env.config.Config, cons); err != nil { |
399 | return nil, nil, err |
400 | } |
401 | |
402 | === modified file 'worker/provisioner/lxc-broker.go' |
403 | --- worker/provisioner/lxc-broker.go 2013-10-31 21:36:40 +0000 |
404 | +++ worker/provisioner/lxc-broker.go 2013-11-12 00:35:23 +0000 |
405 | @@ -8,6 +8,7 @@ |
406 | |
407 | "launchpad.net/juju-core/agent" |
408 | "launchpad.net/juju-core/constraints" |
409 | + "launchpad.net/juju-core/container" |
410 | "launchpad.net/juju-core/container/lxc" |
411 | "launchpad.net/juju-core/environs" |
412 | "launchpad.net/juju-core/environs/cloudinit" |
413 | @@ -27,7 +28,7 @@ |
414 | |
415 | func NewLxcBroker(api APICalls, tools *tools.Tools, agentConfig agent.Config) environs.InstanceBroker { |
416 | return &lxcBroker{ |
417 | - manager: lxc.NewContainerManager(lxc.ManagerConfig{Name: "juju"}), |
418 | + manager: lxc.NewContainerManager(container.ManagerConfig{Name: "juju"}), |
419 | api: api, |
420 | tools: tools, |
421 | agentConfig: agentConfig, |
422 | @@ -35,7 +36,7 @@ |
423 | } |
424 | |
425 | type lxcBroker struct { |
426 | - manager lxc.ContainerManager |
427 | + manager container.Manager |
428 | api APICalls |
429 | tools *tools.Tools |
430 | agentConfig agent.Config |
431 | @@ -57,7 +58,7 @@ |
432 | if bridgeDevice == "" { |
433 | bridgeDevice = lxc.DefaultLxcBridge |
434 | } |
435 | - network := lxc.BridgeNetworkConfig(bridgeDevice) |
436 | + network := container.BridgeNetworkConfig(bridgeDevice) |
437 | |
438 | series := possibleTools.OneSeries() |
439 | machineConfig.MachineContainerType = instance.LXC |
Reviewers: mp+194757_ code.launchpad. net,
Message:
Please take a look.
Description:
Move generic bits to container package.
The ContainerManager and the config type to create
it are common over both LXC and KVM. Also, network
config is similarly generic.
Most of this work is just moving types, changing imports
and parameter types.
https:/ /code.launchpad .net/~thumper/ juju-core/ container- interface/ +merge/ 194757
Requires: /code.launchpad .net/~thumper/ juju-core/ fix-add- machine- test/+merge/ 194753
https:/
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/24780043/
Affected files (+106, -81 lines): interface. go lxc/lxc. go lxc/lxc_ test.go network. go local/environ. go provisioner/ lxc-broker. go
A [revision details]
A container/
M container/
M container/
A container/
M provider/
M worker/