Status: | Merged |
---|---|
Merged at revision: | 8 |
Proposed branch: | lp:~thumper/golxc/clone |
Merge into: | lp:golxc |
Diff against target: |
432 lines (+149/-48) 3 files modified
golxc.go (+50/-11) golxc_test.go (+85/-37) package_test.go (+14/-0) |
To merge this branch: | bzr merge lp:~thumper/golxc/clone |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ian Booth | Approve | ||
Review via email: mp+209790@code.launchpad.net |
Commit message
Description of the change
Update signature for Create and Clone
Make it possible for the caller to specify additional args for both
Create and Clone. Instead of trying to provide an abstracted
interface for this, just allowing the caller to provide extra
args.
Some test cleanup.
To post a comment you must log in.
lp:~thumper/golxc/clone
updated
- 10. By Tim Penhey
-
Add a test to show command line args.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'golxc.go' | |||
2 | --- golxc.go 2014-03-05 03:36:19 +0000 | |||
3 | +++ golxc.go 2014-03-11 00:35:14 +0000 | |||
4 | @@ -11,10 +11,15 @@ | |||
5 | 11 | "fmt" | 11 | "fmt" |
6 | 12 | "os" | 12 | "os" |
7 | 13 | "os/exec" | 13 | "os/exec" |
8 | 14 | "path" | ||
9 | 14 | "strconv" | 15 | "strconv" |
10 | 15 | "strings" | 16 | "strings" |
11 | 17 | |||
12 | 18 | "github.com/juju/loggo" | ||
13 | 16 | ) | 19 | ) |
14 | 17 | 20 | ||
15 | 21 | var logger = loggo.GetLogger("golxc") | ||
16 | 22 | |||
17 | 18 | // Error reports the failure of a LXC command. | 23 | // Error reports the failure of a LXC command. |
18 | 19 | type Error struct { | 24 | type Error struct { |
19 | 20 | Name string | 25 | Name string |
20 | @@ -65,7 +70,7 @@ | |||
21 | 65 | Name() string | 70 | Name() string |
22 | 66 | 71 | ||
23 | 67 | // Create creates a new container based on the given template. | 72 | // Create creates a new container based on the given template. |
25 | 68 | Create(configFile, template string, templateArgs ...string) error | 73 | Create(configFile, template string, extraArgs []string, templateArgs []string) error |
26 | 69 | 74 | ||
27 | 70 | // Start runs the container as a daemon. | 75 | // Start runs the container as a daemon. |
28 | 71 | Start(configFile, consoleFile string) error | 76 | Start(configFile, consoleFile string) error |
29 | @@ -74,7 +79,7 @@ | |||
30 | 74 | Stop() error | 79 | Stop() error |
31 | 75 | 80 | ||
32 | 76 | // Clone creates a copy of the container, giving the copy the specified name. | 81 | // Clone creates a copy of the container, giving the copy the specified name. |
34 | 77 | Clone(name string) (Container, error) | 82 | Clone(name string, extraArgs []string, templateArgs []string) (Container, error) |
35 | 78 | 83 | ||
36 | 79 | // Freeze freezes all the container's processes. | 84 | // Freeze freezes all the container's processes. |
37 | 80 | Freeze() error | 85 | Freeze() error |
38 | @@ -127,18 +132,26 @@ | |||
39 | 127 | return &containerFactory{} | 132 | return &containerFactory{} |
40 | 128 | } | 133 | } |
41 | 129 | 134 | ||
42 | 135 | const DefaultLXCDir = "/var/lib/lxc" | ||
43 | 136 | |||
44 | 137 | var ContainerDir = DefaultLXCDir | ||
45 | 138 | |||
46 | 130 | type container struct { | 139 | type container struct { |
47 | 131 | name string | 140 | name string |
48 | 132 | logFile string | 141 | logFile string |
49 | 133 | logLevel LogLevel | 142 | logLevel LogLevel |
50 | 143 | // Newer LXC libraries can have containers in non-default locations. The | ||
51 | 144 | // containerDir is the directory that is the 'home' of this container. | ||
52 | 145 | containerDir string | ||
53 | 134 | } | 146 | } |
54 | 135 | 147 | ||
55 | 136 | type containerFactory struct{} | 148 | type containerFactory struct{} |
56 | 137 | 149 | ||
57 | 138 | func (*containerFactory) New(name string) Container { | 150 | func (*containerFactory) New(name string) Container { |
58 | 139 | return &container{ | 151 | return &container{ |
61 | 140 | name: name, | 152 | name: name, |
62 | 141 | logLevel: LogWarning, | 153 | logLevel: LogWarning, |
63 | 154 | containerDir: ContainerDir, | ||
64 | 142 | } | 155 | } |
65 | 143 | } | 156 | } |
66 | 144 | 157 | ||
67 | @@ -179,7 +192,7 @@ | |||
68 | 179 | } | 192 | } |
69 | 180 | 193 | ||
70 | 181 | // Create creates a new container based on the given template. | 194 | // Create creates a new container based on the given template. |
72 | 182 | func (c *container) Create(configFile, template string, templateArgs ...string) error { | 195 | func (c *container) Create(configFile, template string, extraArgs []string, templateArgs []string) error { |
73 | 183 | if c.IsConstructed() { | 196 | if c.IsConstructed() { |
74 | 184 | return fmt.Errorf("container %q is already created", c.Name()) | 197 | return fmt.Errorf("container %q is already created", c.Name()) |
75 | 185 | } | 198 | } |
76 | @@ -190,8 +203,12 @@ | |||
77 | 190 | if configFile != "" { | 203 | if configFile != "" { |
78 | 191 | args = append(args, "-f", configFile) | 204 | args = append(args, "-f", configFile) |
79 | 192 | } | 205 | } |
81 | 193 | args = append(args, "--") | 206 | if len(extraArgs) != 0 { |
82 | 207 | args = append(args, extraArgs...) | ||
83 | 208 | } | ||
84 | 194 | if len(templateArgs) != 0 { | 209 | if len(templateArgs) != 0 { |
85 | 210 | // Must be done in two steps due to current language implementation details. | ||
86 | 211 | args = append(args, "--") | ||
87 | 195 | args = append(args, templateArgs...) | 212 | args = append(args, templateArgs...) |
88 | 196 | } | 213 | } |
89 | 197 | _, err := run("lxc-create", args...) | 214 | _, err := run("lxc-create", args...) |
90 | @@ -223,7 +240,13 @@ | |||
91 | 223 | if err != nil { | 240 | if err != nil { |
92 | 224 | return err | 241 | return err |
93 | 225 | } | 242 | } |
95 | 226 | return c.Wait(StateRunning, StateStopped) | 243 | if err := c.Wait(StateRunning, StateStopped); err != nil { |
96 | 244 | return err | ||
97 | 245 | } | ||
98 | 246 | if !c.IsRunning() { | ||
99 | 247 | return fmt.Errorf("container failed to start") | ||
100 | 248 | } | ||
101 | 249 | return nil | ||
102 | 227 | } | 250 | } |
103 | 228 | 251 | ||
104 | 229 | // Stop terminates the running container. | 252 | // Stop terminates the running container. |
105 | @@ -249,10 +272,13 @@ | |||
106 | 249 | } | 272 | } |
107 | 250 | 273 | ||
108 | 251 | // Clone creates a copy of the container, it gets the given name. | 274 | // Clone creates a copy of the container, it gets the given name. |
110 | 252 | func (c *container) Clone(name string) (Container, error) { | 275 | func (c *container) Clone(name string, extraArgs []string, templateArgs []string) (Container, error) { |
111 | 253 | if !c.IsConstructed() { | 276 | if !c.IsConstructed() { |
112 | 254 | return nil, fmt.Errorf("container %q is not yet created", c.name) | 277 | return nil, fmt.Errorf("container %q is not yet created", c.name) |
113 | 255 | } | 278 | } |
114 | 279 | if c.IsRunning() { | ||
115 | 280 | return nil, fmt.Errorf("cannot clone a running container") | ||
116 | 281 | } | ||
117 | 256 | cc := &container{ | 282 | cc := &container{ |
118 | 257 | name: name, | 283 | name: name, |
119 | 258 | } | 284 | } |
120 | @@ -263,6 +289,14 @@ | |||
121 | 263 | "-o", c.name, | 289 | "-o", c.name, |
122 | 264 | "-n", name, | 290 | "-n", name, |
123 | 265 | } | 291 | } |
124 | 292 | if len(extraArgs) != 0 { | ||
125 | 293 | args = append(args, extraArgs...) | ||
126 | 294 | } | ||
127 | 295 | if len(templateArgs) != 0 { | ||
128 | 296 | // Must be done in two steps due to current language implementation details. | ||
129 | 297 | args = append(args, "--") | ||
130 | 298 | args = append(args, templateArgs...) | ||
131 | 299 | } | ||
132 | 266 | _, err := run("lxc-clone", args...) | 300 | _, err := run("lxc-clone", args...) |
133 | 267 | if err != nil { | 301 | if err != nil { |
134 | 268 | return nil, err | 302 | return nil, err |
135 | @@ -388,27 +422,32 @@ | |||
136 | 388 | 422 | ||
137 | 389 | // containerHome returns the name of the container directory. | 423 | // containerHome returns the name of the container directory. |
138 | 390 | func (c *container) containerHome() string { | 424 | func (c *container) containerHome() string { |
140 | 391 | return "/var/lib/lxc/" + c.name | 425 | return path.Join(c.containerDir, c.name) |
141 | 392 | } | 426 | } |
142 | 393 | 427 | ||
143 | 394 | // rootfs returns the name of the directory containing the | 428 | // rootfs returns the name of the directory containing the |
144 | 395 | // root filesystem of the container. | 429 | // root filesystem of the container. |
145 | 396 | func (c *container) rootfs() string { | 430 | func (c *container) rootfs() string { |
147 | 397 | return c.containerHome() + "/rootfs/" | 431 | return path.Join(c.containerHome(), "rootfs") |
148 | 398 | } | 432 | } |
149 | 399 | 433 | ||
150 | 400 | // run executes the passed command and returns the out. | 434 | // run executes the passed command and returns the out. |
151 | 401 | func run(name string, args ...string) (string, error) { | 435 | func run(name string, args ...string) (string, error) { |
152 | 436 | logger := loggo.GetLogger(fmt.Sprintf("golxc.run.%s", name)) | ||
153 | 437 | logger.Tracef("run: %s %v", name, args) | ||
154 | 402 | cmd := exec.Command(name, args...) | 438 | cmd := exec.Command(name, args...) |
155 | 403 | // LXC tools do not use stdout and stderr in a predictable | 439 | // LXC tools do not use stdout and stderr in a predictable |
156 | 404 | // way; based on experimentation, the most convenient | 440 | // way; based on experimentation, the most convenient |
157 | 405 | // solution is to combine them and leave the client to | 441 | // solution is to combine them and leave the client to |
158 | 406 | // determine sanity as best it can. | 442 | // determine sanity as best it can. |
159 | 407 | out, err := cmd.CombinedOutput() | 443 | out, err := cmd.CombinedOutput() |
160 | 444 | result := string(out) | ||
161 | 408 | if err != nil { | 445 | if err != nil { |
162 | 446 | logger.Tracef("run failed output: %s", result) | ||
163 | 409 | return "", runError(name, err, out) | 447 | return "", runError(name, err, out) |
164 | 410 | } | 448 | } |
166 | 411 | return string(out), nil | 449 | logger.Tracef("run successful output: %s", result) |
167 | 450 | return result, nil | ||
168 | 412 | } | 451 | } |
169 | 413 | 452 | ||
170 | 414 | // runError creates an error if run fails. | 453 | // runError creates an error if run fails. |
171 | 415 | 454 | ||
172 | === modified file 'golxc_test.go' | |||
173 | --- golxc_test.go 2014-03-05 03:36:19 +0000 | |||
174 | +++ golxc_test.go 2014-03-11 00:35:14 +0000 | |||
175 | @@ -5,17 +5,18 @@ | |||
176 | 5 | 5 | ||
177 | 6 | import ( | 6 | import ( |
178 | 7 | "io/ioutil" | 7 | "io/ioutil" |
179 | 8 | . "launchpad.net/gocheck" | ||
180 | 9 | "os" | 8 | "os" |
181 | 10 | "os/user" | 9 | "os/user" |
182 | 11 | "path/filepath" | 10 | "path/filepath" |
184 | 12 | "testing" | 11 | |
185 | 12 | "github.com/juju/testing" | ||
186 | 13 | jc "github.com/juju/testing/checkers" | ||
187 | 14 | "github.com/juju/testing/logging" | ||
188 | 15 | . "launchpad.net/gocheck" | ||
189 | 13 | 16 | ||
190 | 14 | "launchpad.net/golxc" | 17 | "launchpad.net/golxc" |
191 | 15 | ) | 18 | ) |
192 | 16 | 19 | ||
193 | 17 | func Test(t *testing.T) { TestingT(t) } | ||
194 | 18 | |||
195 | 19 | var lxcfile = `# MIRROR to be used by ubuntu template at container creation: | 20 | var lxcfile = `# MIRROR to be used by ubuntu template at container creation: |
196 | 20 | # Leaving it undefined is fine | 21 | # Leaving it undefined is fine |
197 | 21 | #MIRROR="http://archive.ubuntu.com/ubuntu" | 22 | #MIRROR="http://archive.ubuntu.com/ubuntu" |
198 | @@ -142,6 +143,15 @@ | |||
199 | 142 | } | 143 | } |
200 | 143 | } | 144 | } |
201 | 144 | 145 | ||
202 | 146 | func (s *LXCSuite) createContainer(c *C) golxc.Container { | ||
203 | 147 | container := s.factory.New("golxc") | ||
204 | 148 | c.Assert(container.IsConstructed(), Equals, false) | ||
205 | 149 | err := container.Create("", "ubuntu", nil, nil) | ||
206 | 150 | c.Assert(err, IsNil) | ||
207 | 151 | c.Assert(container.IsConstructed(), Equals, true) | ||
208 | 152 | return container | ||
209 | 153 | } | ||
210 | 154 | |||
211 | 145 | func (s *LXCSuite) TestCreateDestroy(c *C) { | 155 | func (s *LXCSuite) TestCreateDestroy(c *C) { |
212 | 146 | // Test clean creation and destroying of a container. | 156 | // Test clean creation and destroying of a container. |
213 | 147 | lc := s.factory.New("golxc") | 157 | lc := s.factory.New("golxc") |
214 | @@ -149,7 +159,7 @@ | |||
215 | 149 | home := golxc.ContainerHome(lc) | 159 | home := golxc.ContainerHome(lc) |
216 | 150 | _, err := os.Stat(home) | 160 | _, err := os.Stat(home) |
217 | 151 | c.Assert(err, ErrorMatches, "stat .*: no such file or directory") | 161 | c.Assert(err, ErrorMatches, "stat .*: no such file or directory") |
219 | 152 | err = lc.Create("", "ubuntu") | 162 | err = lc.Create("", "ubuntu", nil, nil) |
220 | 153 | c.Assert(err, IsNil) | 163 | c.Assert(err, IsNil) |
221 | 154 | c.Assert(lc.IsConstructed(), Equals, true) | 164 | c.Assert(lc.IsConstructed(), Equals, true) |
222 | 155 | defer func() { | 165 | defer func() { |
223 | @@ -165,16 +175,13 @@ | |||
224 | 165 | 175 | ||
225 | 166 | func (s *LXCSuite) TestCreateTwice(c *C) { | 176 | func (s *LXCSuite) TestCreateTwice(c *C) { |
226 | 167 | // Test that a container cannot be created twice. | 177 | // Test that a container cannot be created twice. |
231 | 168 | lc1 := s.factory.New("golxc") | 178 | lc1 := s.createContainer(c) |
228 | 169 | c.Assert(lc1.IsConstructed(), Equals, false) | ||
229 | 170 | err := lc1.Create("", "ubuntu") | ||
230 | 171 | c.Assert(err, IsNil) | ||
232 | 172 | c.Assert(lc1.IsConstructed(), Equals, true) | 179 | c.Assert(lc1.IsConstructed(), Equals, true) |
233 | 173 | defer func() { | 180 | defer func() { |
234 | 174 | c.Assert(lc1.Destroy(), IsNil) | 181 | c.Assert(lc1.Destroy(), IsNil) |
235 | 175 | }() | 182 | }() |
236 | 176 | lc2 := s.factory.New("golxc") | 183 | lc2 := s.factory.New("golxc") |
238 | 177 | err = lc2.Create("", "ubuntu") | 184 | err := lc2.Create("", "ubuntu", nil, nil) |
239 | 178 | c.Assert(err, ErrorMatches, "container .* is already created") | 185 | c.Assert(err, ErrorMatches, "container .* is already created") |
240 | 179 | } | 186 | } |
241 | 180 | 187 | ||
242 | @@ -183,7 +190,7 @@ | |||
243 | 183 | // case of an illegal template. | 190 | // case of an illegal template. |
244 | 184 | lc := s.factory.New("golxc") | 191 | lc := s.factory.New("golxc") |
245 | 185 | c.Assert(lc.IsConstructed(), Equals, false) | 192 | c.Assert(lc.IsConstructed(), Equals, false) |
247 | 186 | err := lc.Create("", "name-of-a-not-existing-template-for-golxc") | 193 | err := lc.Create("", "name-of-a-not-existing-template-for-golxc", nil, nil) |
248 | 187 | c.Assert(err, ErrorMatches, `error executing "lxc-create": .*bad template.*`) | 194 | c.Assert(err, ErrorMatches, `error executing "lxc-create": .*bad template.*`) |
249 | 188 | c.Assert(lc.IsConstructed(), Equals, false) | 195 | c.Assert(lc.IsConstructed(), Equals, false) |
250 | 189 | } | 196 | } |
251 | @@ -211,10 +218,7 @@ | |||
252 | 211 | oldLen := len(lcs) | 218 | oldLen := len(lcs) |
253 | 212 | c.Assert(err, IsNil) | 219 | c.Assert(err, IsNil) |
254 | 213 | c.Assert(oldLen >= 0, Equals, true) | 220 | c.Assert(oldLen >= 0, Equals, true) |
259 | 214 | lc := s.factory.New("golxc") | 221 | lc := s.createContainer(c) |
256 | 215 | c.Assert(lc.IsConstructed(), Equals, false) | ||
257 | 216 | c.Assert(lc.Create("", "ubuntu"), IsNil) | ||
258 | 217 | c.Assert(lc.IsConstructed(), Equals, true) | ||
260 | 218 | defer func() { | 222 | defer func() { |
261 | 219 | c.Assert(lc.Destroy(), IsNil) | 223 | c.Assert(lc.Destroy(), IsNil) |
262 | 220 | }() | 224 | }() |
263 | @@ -226,16 +230,13 @@ | |||
264 | 226 | 230 | ||
265 | 227 | func (s *LXCSuite) TestClone(c *C) { | 231 | func (s *LXCSuite) TestClone(c *C) { |
266 | 228 | // Test the cloning of an existing container. | 232 | // Test the cloning of an existing container. |
271 | 229 | lc1 := s.factory.New("golxc") | 233 | lc1 := s.createContainer(c) |
268 | 230 | c.Assert(lc1.IsConstructed(), Equals, false) | ||
269 | 231 | c.Assert(lc1.Create("", "ubuntu"), IsNil) | ||
270 | 232 | c.Assert(lc1.IsConstructed(), Equals, true) | ||
272 | 233 | defer func() { | 234 | defer func() { |
273 | 234 | c.Assert(lc1.Destroy(), IsNil) | 235 | c.Assert(lc1.Destroy(), IsNil) |
274 | 235 | }() | 236 | }() |
275 | 236 | lcs, _ := s.factory.List() | 237 | lcs, _ := s.factory.List() |
276 | 237 | oldLen := len(lcs) | 238 | oldLen := len(lcs) |
278 | 238 | lc2, err := lc1.Clone("golxcclone") | 239 | lc2, err := lc1.Clone("golxcclone", nil, nil) |
279 | 239 | c.Assert(err, IsNil) | 240 | c.Assert(err, IsNil) |
280 | 240 | c.Assert(lc2.IsConstructed(), Equals, true) | 241 | c.Assert(lc2.IsConstructed(), Equals, true) |
281 | 241 | defer func() { | 242 | defer func() { |
282 | @@ -252,15 +253,13 @@ | |||
283 | 252 | // Test the cloning of a non-existing container. | 253 | // Test the cloning of a non-existing container. |
284 | 253 | lc := s.factory.New("golxc") | 254 | lc := s.factory.New("golxc") |
285 | 254 | c.Assert(lc.IsConstructed(), Equals, false) | 255 | c.Assert(lc.IsConstructed(), Equals, false) |
287 | 255 | _, err := lc.Clone("golxcclone") | 256 | _, err := lc.Clone("golxcclone", nil, nil) |
288 | 256 | c.Assert(err, ErrorMatches, "container .* is not yet created") | 257 | c.Assert(err, ErrorMatches, "container .* is not yet created") |
289 | 257 | } | 258 | } |
290 | 258 | 259 | ||
291 | 259 | func (s *LXCSuite) TestStartStop(c *C) { | 260 | func (s *LXCSuite) TestStartStop(c *C) { |
292 | 260 | // Test starting and stopping a container. | 261 | // Test starting and stopping a container. |
296 | 261 | lc := s.factory.New("golxc") | 262 | lc := s.createContainer(c) |
294 | 262 | c.Assert(lc.IsConstructed(), Equals, false) | ||
295 | 263 | c.Assert(lc.Create("", "ubuntu"), IsNil) | ||
297 | 264 | defer func() { | 263 | defer func() { |
298 | 265 | c.Assert(lc.Destroy(), IsNil) | 264 | c.Assert(lc.Destroy(), IsNil) |
299 | 266 | }() | 265 | }() |
300 | @@ -279,9 +278,7 @@ | |||
301 | 279 | 278 | ||
302 | 280 | func (s *LXCSuite) TestStopNotRunning(c *C) { | 279 | func (s *LXCSuite) TestStopNotRunning(c *C) { |
303 | 281 | // Test that a not running container can't be stopped. | 280 | // Test that a not running container can't be stopped. |
307 | 282 | lc := s.factory.New("golxc") | 281 | lc := s.createContainer(c) |
305 | 283 | c.Assert(lc.IsConstructed(), Equals, false) | ||
306 | 284 | c.Assert(lc.Create("", "ubuntu"), IsNil) | ||
308 | 285 | defer func() { | 282 | defer func() { |
309 | 286 | c.Assert(lc.Destroy(), IsNil) | 283 | c.Assert(lc.Destroy(), IsNil) |
310 | 287 | }() | 284 | }() |
311 | @@ -296,7 +293,7 @@ | |||
312 | 296 | c.Assert(lc.Wait(), ErrorMatches, "no states specified") | 293 | c.Assert(lc.Wait(), ErrorMatches, "no states specified") |
313 | 297 | c.Assert(lc.Wait(golxc.StateStopped), IsNil) | 294 | c.Assert(lc.Wait(golxc.StateStopped), IsNil) |
314 | 298 | c.Assert(lc.Wait(golxc.StateStopped, golxc.StateRunning), IsNil) | 295 | c.Assert(lc.Wait(golxc.StateStopped, golxc.StateRunning), IsNil) |
316 | 299 | c.Assert(lc.Create("", "ubuntu"), IsNil) | 296 | c.Assert(lc.Create("", "ubuntu", nil, nil), IsNil) |
317 | 300 | defer func() { | 297 | defer func() { |
318 | 301 | c.Assert(lc.Destroy(), IsNil) | 298 | c.Assert(lc.Destroy(), IsNil) |
319 | 302 | }() | 299 | }() |
320 | @@ -308,9 +305,7 @@ | |||
321 | 308 | 305 | ||
322 | 309 | func (s *LXCSuite) TestFreezeUnfreeze(c *C) { | 306 | func (s *LXCSuite) TestFreezeUnfreeze(c *C) { |
323 | 310 | // Test the freezing and unfreezing of a started container. | 307 | // Test the freezing and unfreezing of a started container. |
327 | 311 | lc := s.factory.New("golxc") | 308 | lc := s.createContainer(c) |
325 | 312 | c.Assert(lc.IsConstructed(), Equals, false) | ||
326 | 313 | c.Assert(lc.Create("", "ubuntu"), IsNil) | ||
328 | 314 | defer func() { | 309 | defer func() { |
329 | 315 | c.Assert(lc.Destroy(), IsNil) | 310 | c.Assert(lc.Destroy(), IsNil) |
330 | 316 | }() | 311 | }() |
331 | @@ -327,9 +322,7 @@ | |||
332 | 327 | 322 | ||
333 | 328 | func (s *LXCSuite) TestFreezeNotStarted(c *C) { | 323 | func (s *LXCSuite) TestFreezeNotStarted(c *C) { |
334 | 329 | // Test that a not running container can't be frozen. | 324 | // Test that a not running container can't be frozen. |
338 | 330 | lc := s.factory.New("golxc") | 325 | lc := s.createContainer(c) |
336 | 331 | c.Assert(lc.IsConstructed(), Equals, false) | ||
337 | 332 | c.Assert(lc.Create("", "ubuntu"), IsNil) | ||
339 | 333 | defer func() { | 326 | defer func() { |
340 | 334 | c.Assert(lc.Destroy(), IsNil) | 327 | c.Assert(lc.Destroy(), IsNil) |
341 | 335 | }() | 328 | }() |
342 | @@ -352,9 +345,7 @@ | |||
343 | 352 | 345 | ||
344 | 353 | func (s *LXCSuite) TestUnfreezeNotFrozen(c *C) { | 346 | func (s *LXCSuite) TestUnfreezeNotFrozen(c *C) { |
345 | 354 | // Test that a running container can't be unfrozen. | 347 | // Test that a running container can't be unfrozen. |
349 | 355 | lc := s.factory.New("golxc") | 348 | lc := s.createContainer(c) |
347 | 356 | c.Assert(lc.IsConstructed(), Equals, false) | ||
348 | 357 | c.Assert(lc.Create("", "ubuntu"), IsNil) | ||
350 | 358 | defer func() { | 349 | defer func() { |
351 | 359 | c.Assert(lc.Destroy(), IsNil) | 350 | c.Assert(lc.Destroy(), IsNil) |
352 | 360 | }() | 351 | }() |
353 | @@ -364,3 +355,60 @@ | |||
354 | 364 | }() | 355 | }() |
355 | 365 | c.Assert(lc.Unfreeze(), ErrorMatches, "container .* is not frozen") | 356 | c.Assert(lc.Unfreeze(), ErrorMatches, "container .* is not frozen") |
356 | 366 | } | 357 | } |
357 | 358 | |||
358 | 359 | type commandArgs struct { | ||
359 | 360 | logging.LoggingSuite | ||
360 | 361 | } | ||
361 | 362 | |||
362 | 363 | var _ = Suite(&commandArgs{}) | ||
363 | 364 | |||
364 | 365 | func (s *commandArgs) TestCreateArgs(c *C) { | ||
365 | 366 | s.PatchValue(&golxc.ContainerDir, c.MkDir()) | ||
366 | 367 | testing.PatchExecutableAsEchoArgs(c, s, "lxc-create") | ||
367 | 368 | |||
368 | 369 | factory := golxc.Factory() | ||
369 | 370 | container := factory.New("test") | ||
370 | 371 | err := container.Create( | ||
371 | 372 | "config-file", "template", | ||
372 | 373 | []string{"extra-1", "extra-2"}, | ||
373 | 374 | []string{"template-1", "template-2"}, | ||
374 | 375 | ) | ||
375 | 376 | c.Assert(err, IsNil) | ||
376 | 377 | testing.AssertEchoArgs( | ||
377 | 378 | c, "lxc-create", | ||
378 | 379 | "-n", "test", | ||
379 | 380 | "-t", "template", | ||
380 | 381 | "-f", "config-file", | ||
381 | 382 | "extra-1", "extra-2", | ||
382 | 383 | "--", "template-1", "template-2") | ||
383 | 384 | } | ||
384 | 385 | |||
385 | 386 | func (s *commandArgs) TestCloneArgs(c *C) { | ||
386 | 387 | dir := c.MkDir() | ||
387 | 388 | s.PatchValue(&golxc.ContainerDir, dir) | ||
388 | 389 | // Patch lxc-info too as clone checks to see if it is running. | ||
389 | 390 | testing.PatchExecutableAsEchoArgs(c, s, "lxc-info") | ||
390 | 391 | testing.PatchExecutableAsEchoArgs(c, s, "lxc-clone") | ||
391 | 392 | |||
392 | 393 | factory := golxc.Factory() | ||
393 | 394 | container := factory.New("test") | ||
394 | 395 | // Make the rootfs for the "test" container so it thinks it is created. | ||
395 | 396 | rootfs := filepath.Join(dir, "test", "rootfs") | ||
396 | 397 | err := os.MkdirAll(rootfs, 0755) | ||
397 | 398 | c.Assert(err, IsNil) | ||
398 | 399 | c.Assert(rootfs, jc.IsDirectory) | ||
399 | 400 | c.Assert(container.IsConstructed(), jc.IsTrue) | ||
400 | 401 | clone, err := container.Clone( | ||
401 | 402 | "name", | ||
402 | 403 | []string{"extra-1", "extra-2"}, | ||
403 | 404 | []string{"template-1", "template-2"}, | ||
404 | 405 | ) | ||
405 | 406 | c.Assert(err, IsNil) | ||
406 | 407 | testing.AssertEchoArgs( | ||
407 | 408 | c, "lxc-clone", | ||
408 | 409 | "-o", "test", | ||
409 | 410 | "-n", "name", | ||
410 | 411 | "extra-1", "extra-2", | ||
411 | 412 | "--", "template-1", "template-2") | ||
412 | 413 | c.Assert(clone.Name(), Equals, "name") | ||
413 | 414 | } | ||
414 | 367 | 415 | ||
415 | === added file 'package_test.go' | |||
416 | --- package_test.go 1970-01-01 00:00:00 +0000 | |||
417 | +++ package_test.go 2014-03-11 00:35:14 +0000 | |||
418 | @@ -0,0 +1,14 @@ | |||
419 | 1 | // Copyright 2013 Canonical Ltd. | ||
420 | 2 | // Licensed under the LGPLv3, see COPYING and COPYING.LESSER file for details. | ||
421 | 3 | |||
422 | 4 | package golxc_test | ||
423 | 5 | |||
424 | 6 | import ( | ||
425 | 7 | "testing" | ||
426 | 8 | |||
427 | 9 | gc "launchpad.net/gocheck" | ||
428 | 10 | ) | ||
429 | 11 | |||
430 | 12 | func Test(t *testing.T) { | ||
431 | 13 | gc.TestingT(t) | ||
432 | 14 | } |
Nice.