Merge lp:~thumper/juju-core/local-lxc-clone-settings into lp:~go-bot/juju-core/trunk
- local-lxc-clone-settings
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Tim Penhey | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 2432 | ||||
Proposed branch: | lp:~thumper/juju-core/local-lxc-clone-settings | ||||
Merge into: | lp:~go-bot/juju-core/trunk | ||||
Diff against target: |
590 lines (+220/-57) 13 files modified
cmd/juju/help_topics.go (+18/-0) container/lxc/initialisation_test.go (+0/-6) container/lxc/lxc.go (+8/-2) container/lxc/lxc_test.go (+29/-2) container/lxc/mock/mock-lxc.go (+18/-9) provider/local/config.go (+14/-0) provider/local/environ.go (+9/-10) provider/local/environprovider.go (+16/-5) provider/local/environprovider_test.go (+100/-0) provider/local/export_test.go (+7/-8) provider/local/lxc.go (+0/-8) provider/local/lxc_test.go (+0/-6) provider/local/prereqs.go (+1/-1) |
||||
To merge this branch: | bzr merge lp:~thumper/juju-core/local-lxc-clone-settings | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Juju Engineering | Pending | ||
Review via email: mp+211237@code.launchpad.net |
Commit message
Add local options lxc-clone and lxc-clone-aufs
These new values default to the existing behaviour.
That being that if the user is on trusty or above,
they default to true, otherwise false.
The reason for these values is two-fold. Firstly,
aufs isn't working on power, and we want to be able
to test effectively there. Secondly this gives the
user on saucy the ability to try it out (not originally
planned, but a helpful side effect).
Description of the change
Add local options lxc-clone and lxc-clone-aufs
These new values default to the existing behaviour.
That being that if the user is on trusty or above,
they default to true, otherwise false.
The reason for these values is two-fold. Firstly,
aufs isn't working on power, and we want to be able
to test effectively there. Secondly this gives the
user on saucy the ability to try it out (not originally
planned, but a helpful side effect).
Tim Penhey (thumper) wrote : | # |
Ian Booth (wallyworld) wrote : | # |
A few initial questions in the comments.
Also, now that there are config options for clone, doesn't that mean we
can now drop JUJU_TESTING_
with lxc-clone=false?
https:/
File cmd/juju/
https:/
cmd/juju/
... the use of clone...
https:/
cmd/juju/
block. If you have the main
They may not have called their local provider "local", or they may have
more than one defined. I'd just say "in the configuration for your local
provider".
https:/
File container/
https:/
container/
manager.useAUFS {
This logic looks different that what was there before? We are adding an
extra "manager.
https:/
File provider/
https:/
provider/
why not schema.Bool()?
(used with schema.Defaults to ensure default is true)
https:/
provider/
{
so this would return bool as per previous comment
https:/
provider/
string {
ditto
Tim Penhey (thumper) wrote : | # |
Please take a look.
https:/
File cmd/juju/
https:/
cmd/juju/
On 2014/03/17 03:08:52, wallyworld wrote:
> ... the use of clone...
Done.
https:/
cmd/juju/
block. If you have the main
On 2014/03/17 03:08:52, wallyworld wrote:
> They may not have called their local provider "local", or they may
have more
> than one defined. I'd just say "in the configuration for your local
provider".
Done.
https:/
File container/
https:/
container/
manager.useAUFS {
On 2014/03/17 03:08:52, wallyworld wrote:
> This logic looks different that what was there before? We are adding
an extra
> "manager.
What was there before was related to the second check below where
we now also check that the manager has useAUFS as true in order to
specify the aufs backingstore.
This first check is the one were we only want to specify --snapshot
when we have btrfs or aufs, but not in the case where we want to clone
without aufs.
https:/
File provider/
https:/
provider/
On 2014/03/17 03:08:52, wallyworld wrote:
> why not schema.Bool()?
> (used with schema.Defaults to ensure default is true)
Because there wasn't an easy way to identify whether
it was set or not. I needed three states, yes, no and
missing. If it is missing, and the container is lxc then
we specify values. If they are specified, we use them.
Tim Penhey (thumper) wrote : | # |
Please take a look.
Ian Booth (wallyworld) wrote : | # |
LGTM with typo fix
https:/
File cmd/juju/
https:/
cmd/juju/
If you have the main container
s/you/your
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~thumper/juju-core/local-lxc-clone-settings into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
Go Bot (go-bot) wrote : | # |
The attempt to merge lp:~thumper/juju-core/local-lxc-clone-settings into lp:juju-core failed. Below is the output from the failed tests.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
? launchpad.
? launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
? launchpad.
ok launchpad.
ok launchpad.
Preview Diff
1 | === modified file 'cmd/juju/help_topics.go' | |||
2 | --- cmd/juju/help_topics.go 2014-03-11 12:12:53 +0000 | |||
3 | +++ cmd/juju/help_topics.go 2014-03-17 22:08:13 +0000 | |||
4 | @@ -79,6 +79,24 @@ | |||
5 | 79 | juju deploy wordpress | 79 | juju deploy wordpress |
6 | 80 | juju add-relation wordpress mysql | 80 | juju add-relation wordpress mysql |
7 | 81 | 81 | ||
8 | 82 | As of trusty, the local provider will prefer to use lxc-clone to create | ||
9 | 83 | the machines. A 'template' container is created with the name | ||
10 | 84 | juju-<series>-tempalte | ||
11 | 85 | where <series> is the OS series, for example 'juju-precise-template'. | ||
12 | 86 | You can override the use of clone by specifying | ||
13 | 87 | use-clone: true | ||
14 | 88 | or | ||
15 | 89 | use-clone: false | ||
16 | 90 | in the configuration for your local provider. If you have the main container | ||
17 | 91 | directory mounted on a btrfs partition, then the clone will be using btrfs | ||
18 | 92 | snapshots to create the containers. This means that the clones use up much | ||
19 | 93 | less disk space. If you do not have btrfs, lxc will attempt to use aufs | ||
20 | 94 | (which is an overlay type filesystem). You can explicitly ask Juju to create | ||
21 | 95 | full containers and not overlays by specifying the following in the provider | ||
22 | 96 | configuration: | ||
23 | 97 | use-clone-aufs: false | ||
24 | 98 | |||
25 | 99 | |||
26 | 82 | References: | 100 | References: |
27 | 83 | 101 | ||
28 | 84 | http://askubuntu.com/questions/65359/how-do-i-configure-juju-for-local-usage | 102 | http://askubuntu.com/questions/65359/how-do-i-configure-juju-for-local-usage |
29 | 85 | 103 | ||
30 | === modified file 'container/lxc/initialisation_test.go' | |||
31 | --- container/lxc/initialisation_test.go 2014-03-13 17:21:05 +0000 | |||
32 | +++ container/lxc/initialisation_test.go 2014-03-17 22:08:13 +0000 | |||
33 | @@ -4,18 +4,12 @@ | |||
34 | 4 | package lxc | 4 | package lxc |
35 | 5 | 5 | ||
36 | 6 | import ( | 6 | import ( |
37 | 7 | stdtesting "testing" | ||
38 | 8 | |||
39 | 9 | gc "launchpad.net/gocheck" | 7 | gc "launchpad.net/gocheck" |
40 | 10 | 8 | ||
41 | 11 | "launchpad.net/juju-core/testing/testbase" | 9 | "launchpad.net/juju-core/testing/testbase" |
42 | 12 | "launchpad.net/juju-core/utils" | 10 | "launchpad.net/juju-core/utils" |
43 | 13 | ) | 11 | ) |
44 | 14 | 12 | ||
45 | 15 | func Test(t *stdtesting.T) { | ||
46 | 16 | gc.TestingT(t) | ||
47 | 17 | } | ||
48 | 18 | |||
49 | 19 | type InitialiserSuite struct { | 13 | type InitialiserSuite struct { |
50 | 20 | testbase.LoggingSuite | 14 | testbase.LoggingSuite |
51 | 21 | } | 15 | } |
52 | 22 | 16 | ||
53 | === modified file 'container/lxc/lxc.go' | |||
54 | --- container/lxc/lxc.go 2014-03-13 16:03:45 +0000 | |||
55 | +++ container/lxc/lxc.go 2014-03-17 22:08:13 +0000 | |||
56 | @@ -69,6 +69,7 @@ | |||
57 | 69 | name string | 69 | name string |
58 | 70 | logdir string | 70 | logdir string |
59 | 71 | createWithClone bool | 71 | createWithClone bool |
60 | 72 | useAUFS bool | ||
61 | 72 | backingFilesystem string | 73 | backingFilesystem string |
62 | 73 | } | 74 | } |
63 | 74 | 75 | ||
64 | @@ -91,6 +92,7 @@ | |||
65 | 91 | // If it fails to parse, the value is false, and this suits | 92 | // If it fails to parse, the value is false, and this suits |
66 | 92 | // us fine. | 93 | // us fine. |
67 | 93 | useClone, _ := strconv.ParseBool(conf.PopValue("use-clone")) | 94 | useClone, _ := strconv.ParseBool(conf.PopValue("use-clone")) |
68 | 95 | useAUFS, _ := strconv.ParseBool(conf.PopValue("use-aufs")) | ||
69 | 94 | backingFS, err := containerDirFilesystem() | 96 | backingFS, err := containerDirFilesystem() |
70 | 95 | if err != nil { | 97 | if err != nil { |
71 | 96 | // Especially in tests, or a bot, the lxc dir may not exist | 98 | // Especially in tests, or a bot, the lxc dir may not exist |
72 | @@ -105,6 +107,7 @@ | |||
73 | 105 | name: name, | 107 | name: name, |
74 | 106 | logdir: logDir, | 108 | logdir: logDir, |
75 | 107 | createWithClone: useClone, | 109 | createWithClone: useClone, |
76 | 110 | useAUFS: useAUFS, | ||
77 | 108 | backingFilesystem: backingFS, | 111 | backingFilesystem: backingFS, |
78 | 109 | }, nil | 112 | }, nil |
79 | 110 | } | 113 | } |
80 | @@ -158,8 +161,11 @@ | |||
81 | 158 | "--userdata", userDataFilename, // Our groovey cloud-init | 161 | "--userdata", userDataFilename, // Our groovey cloud-init |
82 | 159 | "--hostid", name, // Use the container name as the hostid | 162 | "--hostid", name, // Use the container name as the hostid |
83 | 160 | } | 163 | } |
86 | 161 | extraCloneArgs := []string{"--snapshot"} | 164 | var extraCloneArgs []string |
87 | 162 | if manager.backingFilesystem != Btrfs { | 165 | if manager.backingFilesystem == Btrfs || manager.useAUFS { |
88 | 166 | extraCloneArgs = append(extraCloneArgs, "--snapshot") | ||
89 | 167 | } | ||
90 | 168 | if manager.backingFilesystem != Btrfs && manager.useAUFS { | ||
91 | 163 | extraCloneArgs = append(extraCloneArgs, "--backingstore", "aufs") | 169 | extraCloneArgs = append(extraCloneArgs, "--backingstore", "aufs") |
92 | 164 | } | 170 | } |
93 | 165 | 171 | ||
94 | 166 | 172 | ||
95 | === modified file 'container/lxc/lxc_test.go' | |||
96 | --- container/lxc/lxc_test.go 2014-03-13 07:54:56 +0000 | |||
97 | +++ container/lxc/lxc_test.go 2014-03-17 22:08:13 +0000 | |||
98 | @@ -38,6 +38,7 @@ | |||
99 | 38 | 38 | ||
100 | 39 | events chan mock.Event | 39 | events chan mock.Event |
101 | 40 | useClone bool | 40 | useClone bool |
102 | 41 | useAUFS bool | ||
103 | 41 | } | 42 | } |
104 | 42 | 43 | ||
105 | 43 | var _ = gc.Suite(&LxcSuite{}) | 44 | var _ = gc.Suite(&LxcSuite{}) |
106 | @@ -95,6 +96,9 @@ | |||
107 | 95 | if s.useClone { | 96 | if s.useClone { |
108 | 96 | params["use-clone"] = "true" | 97 | params["use-clone"] = "true" |
109 | 97 | } | 98 | } |
110 | 99 | if s.useAUFS { | ||
111 | 100 | params["use-aufs"] = "true" | ||
112 | 101 | } | ||
113 | 98 | manager, err := lxc.NewContainerManager(params) | 102 | manager, err := lxc.NewContainerManager(params) |
114 | 99 | c.Assert(err, gc.IsNil) | 103 | c.Assert(err, gc.IsNil) |
115 | 100 | return manager | 104 | return manager |
116 | @@ -226,8 +230,31 @@ | |||
117 | 226 | manager := s.makeManager(c, "test") | 230 | manager := s.makeManager(c, "test") |
118 | 227 | instance := containertesting.StartContainer(c, manager, "1") | 231 | instance := containertesting.StartContainer(c, manager, "1") |
119 | 228 | name := string(instance.Id()) | 232 | name := string(instance.Id()) |
122 | 229 | s.AssertEvent(c, <-s.events, mock.Cloned, "juju-series-template") | 233 | cloned := <-s.events |
123 | 230 | s.AssertEvent(c, <-s.events, mock.Started, name) | 234 | s.AssertEvent(c, cloned, mock.Cloned, "juju-series-template") |
124 | 235 | c.Assert(cloned.Args, gc.IsNil) | ||
125 | 236 | s.AssertEvent(c, <-s.events, mock.Started, name) | ||
126 | 237 | } | ||
127 | 238 | |||
128 | 239 | func (s *LxcSuite) TestStartContainerEventsWithCloneExistingTemplateAUFS(c *gc.C) { | ||
129 | 240 | s.createTemplate(c) | ||
130 | 241 | s.PatchValue(&s.useClone, true) | ||
131 | 242 | s.PatchValue(&s.useAUFS, true) | ||
132 | 243 | manager := s.makeManager(c, "test") | ||
133 | 244 | instance := containertesting.StartContainer(c, manager, "1") | ||
134 | 245 | name := string(instance.Id()) | ||
135 | 246 | cloned := <-s.events | ||
136 | 247 | s.AssertEvent(c, cloned, mock.Cloned, "juju-series-template") | ||
137 | 248 | c.Assert(cloned.Args, gc.DeepEquals, []string{"--snapshot", "--backingstore", "aufs"}) | ||
138 | 249 | s.AssertEvent(c, <-s.events, mock.Started, name) | ||
139 | 250 | } | ||
140 | 251 | |||
141 | 252 | func (s *LxcSuite) TestStartContainerWithCloneMountsAndAutostarts(c *gc.C) { | ||
142 | 253 | s.createTemplate(c) | ||
143 | 254 | s.PatchValue(&s.useClone, true) | ||
144 | 255 | manager := s.makeManager(c, "test") | ||
145 | 256 | instance := containertesting.StartContainer(c, manager, "1") | ||
146 | 257 | name := string(instance.Id()) | ||
147 | 231 | 258 | ||
148 | 232 | autostartLink := lxc.RestartSymlink(name) | 259 | autostartLink := lxc.RestartSymlink(name) |
149 | 233 | config, err := ioutil.ReadFile(lxc.ContainerConfigFilename(name)) | 260 | config, err := ioutil.ReadFile(lxc.ContainerConfigFilename(name)) |
150 | 234 | 261 | ||
151 | === modified file 'container/lxc/mock/mock-lxc.go' | |||
152 | --- container/lxc/mock/mock-lxc.go 2014-03-12 04:27:25 +0000 | |||
153 | +++ container/lxc/mock/mock-lxc.go 2014-03-17 22:08:13 +0000 | |||
154 | @@ -54,8 +54,10 @@ | |||
155 | 54 | } | 54 | } |
156 | 55 | 55 | ||
157 | 56 | type Event struct { | 56 | type Event struct { |
160 | 57 | Action Action | 57 | Action Action |
161 | 58 | InstanceId string | 58 | InstanceId string |
162 | 59 | Args []string | ||
163 | 60 | TemplateArgs []string | ||
164 | 59 | } | 61 | } |
165 | 60 | 62 | ||
166 | 61 | type ContainerFactory interface { | 63 | type ContainerFactory interface { |
167 | @@ -124,7 +126,7 @@ | |||
168 | 124 | return err | 126 | return err |
169 | 125 | } | 127 | } |
170 | 126 | mock.setState(golxc.StateStopped) | 128 | mock.setState(golxc.StateStopped) |
172 | 127 | mock.factory.notify(Created, mock.name) | 129 | mock.factory.notify(eventArgs(Created, mock.name, extraArgs, templateArgs)) |
173 | 128 | return nil | 130 | return nil |
174 | 129 | } | 131 | } |
175 | 130 | 132 | ||
176 | @@ -140,7 +142,7 @@ | |||
177 | 140 | filepath.Join(container.ContainerDir, mock.name, "console.log"), | 142 | filepath.Join(container.ContainerDir, mock.name, "console.log"), |
178 | 141 | []byte("fake console.log"), 0644) | 143 | []byte("fake console.log"), 0644) |
179 | 142 | mock.setState(golxc.StateRunning) | 144 | mock.setState(golxc.StateRunning) |
181 | 143 | mock.factory.notify(Started, mock.name) | 145 | mock.factory.notify(event(Started, mock.name)) |
182 | 144 | return nil | 146 | return nil |
183 | 145 | } | 147 | } |
184 | 146 | 148 | ||
185 | @@ -153,7 +155,7 @@ | |||
186 | 153 | return fmt.Errorf("container is already stopped") | 155 | return fmt.Errorf("container is already stopped") |
187 | 154 | } | 156 | } |
188 | 155 | mock.setState(golxc.StateStopped) | 157 | mock.setState(golxc.StateStopped) |
190 | 156 | mock.factory.notify(Stopped, mock.name) | 158 | mock.factory.notify(event(Stopped, mock.name)) |
191 | 157 | return nil | 159 | return nil |
192 | 158 | } | 160 | } |
193 | 159 | 161 | ||
194 | @@ -183,7 +185,7 @@ | |||
195 | 183 | return nil, err | 185 | return nil, err |
196 | 184 | } | 186 | } |
197 | 185 | 187 | ||
199 | 186 | mock.factory.notify(Cloned, mock.name) | 188 | mock.factory.notify(eventArgs(Cloned, mock.name, extraArgs, templateArgs)) |
200 | 187 | return container, nil | 189 | return container, nil |
201 | 188 | } | 190 | } |
202 | 189 | 191 | ||
203 | @@ -209,7 +211,7 @@ | |||
204 | 209 | } | 211 | } |
205 | 210 | delete(mock.factory.instances, mock.name) | 212 | delete(mock.factory.instances, mock.name) |
206 | 211 | mock.setState(golxc.StateUnknown) | 213 | mock.setState(golxc.StateUnknown) |
208 | 212 | mock.factory.notify(Destroyed, mock.name) | 214 | mock.factory.notify(event(Destroyed, mock.name)) |
209 | 213 | return nil | 215 | return nil |
210 | 214 | } | 216 | } |
211 | 215 | 217 | ||
212 | @@ -290,8 +292,15 @@ | |||
213 | 290 | return | 292 | return |
214 | 291 | } | 293 | } |
215 | 292 | 294 | ||
218 | 293 | func (mock *mockFactory) notify(action Action, instanceId string) { | 295 | func event(action Action, instanceId string) Event { |
219 | 294 | event := Event{action, instanceId} | 296 | return Event{action, instanceId, nil, nil} |
220 | 297 | } | ||
221 | 298 | |||
222 | 299 | func eventArgs(action Action, instanceId string, args []string, template []string) Event { | ||
223 | 300 | return Event{action, instanceId, args, template} | ||
224 | 301 | } | ||
225 | 302 | |||
226 | 303 | func (mock *mockFactory) notify(event Event) { | ||
227 | 295 | for _, c := range mock.listeners { | 304 | for _, c := range mock.listeners { |
228 | 296 | c <- event | 305 | c <- event |
229 | 297 | } | 306 | } |
230 | 298 | 307 | ||
231 | === modified file 'provider/local/config.go' | |||
232 | --- provider/local/config.go 2014-02-27 05:24:43 +0000 | |||
233 | +++ provider/local/config.go 2014-03-17 22:08:13 +0000 | |||
234 | @@ -25,6 +25,8 @@ | |||
235 | 25 | "container": schema.String(), | 25 | "container": schema.String(), |
236 | 26 | "storage-port": schema.ForceInt(), | 26 | "storage-port": schema.ForceInt(), |
237 | 27 | "namespace": schema.String(), | 27 | "namespace": schema.String(), |
238 | 28 | "lxc-clone": schema.String(), | ||
239 | 29 | "lxc-clone-aufs": schema.String(), | ||
240 | 28 | } | 30 | } |
241 | 29 | // The port defaults below are not entirely arbitrary. Local user web | 31 | // The port defaults below are not entirely arbitrary. Local user web |
242 | 30 | // frameworks often use 8000 or 8080, so I didn't want to use either of | 32 | // frameworks often use 8000 or 8080, so I didn't want to use either of |
243 | @@ -37,6 +39,8 @@ | |||
244 | 37 | "bootstrap-ip": schema.Omit, | 39 | "bootstrap-ip": schema.Omit, |
245 | 38 | "storage-port": 8040, | 40 | "storage-port": 8040, |
246 | 39 | "namespace": "", | 41 | "namespace": "", |
247 | 42 | "lxc-clone": schema.Omit, | ||
248 | 43 | "lxc-clone-aufs": schema.Omit, | ||
249 | 40 | } | 44 | } |
250 | 41 | ) | 45 | ) |
251 | 42 | 46 | ||
252 | @@ -103,6 +107,16 @@ | |||
253 | 103 | return filepath.Join(c.rootDir(), filename) | 107 | return filepath.Join(c.rootDir(), filename) |
254 | 104 | } | 108 | } |
255 | 105 | 109 | ||
256 | 110 | func (c *environConfig) lxcClone() string { | ||
257 | 111 | value, _ := c.attrs["lxc-clone"].(string) | ||
258 | 112 | return value | ||
259 | 113 | } | ||
260 | 114 | |||
261 | 115 | func (c *environConfig) lxcCloneAUFS() string { | ||
262 | 116 | value, _ := c.attrs["lxc-clone-aufs"].(string) | ||
263 | 117 | return value | ||
264 | 118 | } | ||
265 | 119 | |||
266 | 106 | func (c *environConfig) createDirs() error { | 120 | func (c *environConfig) createDirs() error { |
267 | 107 | for _, dirname := range []string{ | 121 | for _, dirname := range []string{ |
268 | 108 | c.storageDir(), | 122 | c.storageDir(), |
269 | 109 | 123 | ||
270 | === modified file 'provider/local/environ.go' | |||
271 | --- provider/local/environ.go 2014-03-17 08:25:06 +0000 | |||
272 | +++ provider/local/environ.go 2014-03-17 22:08:13 +0000 | |||
273 | @@ -10,7 +10,6 @@ | |||
274 | 10 | "os/exec" | 10 | "os/exec" |
275 | 11 | "path/filepath" | 11 | "path/filepath" |
276 | 12 | "regexp" | 12 | "regexp" |
277 | 13 | "strconv" | ||
278 | 14 | "strings" | 13 | "strings" |
279 | 15 | "sync" | 14 | "sync" |
280 | 16 | "syscall" | 15 | "syscall" |
281 | @@ -61,7 +60,6 @@ | |||
282 | 61 | localStorage storage.Storage | 60 | localStorage storage.Storage |
283 | 62 | storageListener net.Listener | 61 | storageListener net.Listener |
284 | 63 | containerManager container.Manager | 62 | containerManager container.Manager |
285 | 64 | fastLXC bool | ||
286 | 65 | } | 63 | } |
287 | 66 | 64 | ||
288 | 67 | // GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata. | 65 | // GetToolsSources returns a list of sources which are used to search for simplestreams tools metadata. |
289 | @@ -214,15 +212,16 @@ | |||
290 | 214 | env.config = ecfg | 212 | env.config = ecfg |
291 | 215 | env.name = ecfg.Name() | 213 | env.name = ecfg.Name() |
292 | 216 | containerType := ecfg.container() | 214 | containerType := ecfg.container() |
295 | 217 | env.fastLXC = useFastLXC(containerType) | 215 | managerConfig := container.ManagerConfig{ |
296 | 218 | 216 | container.ConfigName: env.config.namespace(), | |
297 | 217 | container.ConfigLogDir: env.config.logDir(), | ||
298 | 218 | } | ||
299 | 219 | if containerType == instance.LXC { | ||
300 | 220 | managerConfig["use-clone"] = env.config.lxcClone() | ||
301 | 221 | managerConfig["use-aufs"] = env.config.lxcCloneAUFS() | ||
302 | 222 | } | ||
303 | 219 | env.containerManager, err = factory.NewContainerManager( | 223 | env.containerManager, err = factory.NewContainerManager( |
310 | 220 | containerType, | 224 | containerType, managerConfig) |
305 | 221 | container.ManagerConfig{ | ||
306 | 222 | container.ConfigName: env.config.namespace(), | ||
307 | 223 | container.ConfigLogDir: env.config.logDir(), | ||
308 | 224 | "use-clone": strconv.FormatBool(env.fastLXC), | ||
309 | 225 | }) | ||
311 | 226 | if err != nil { | 225 | if err != nil { |
312 | 227 | return err | 226 | return err |
313 | 228 | } | 227 | } |
314 | 229 | 228 | ||
315 | === modified file 'provider/local/environprovider.go' | |||
316 | --- provider/local/environprovider.go 2014-03-12 11:04:20 +0000 | |||
317 | +++ provider/local/environprovider.go 2014-03-17 22:08:13 +0000 | |||
318 | @@ -8,6 +8,7 @@ | |||
319 | 8 | "net" | 8 | "net" |
320 | 9 | "os" | 9 | "os" |
321 | 10 | "os/user" | 10 | "os/user" |
322 | 11 | "strconv" | ||
323 | 11 | "syscall" | 12 | "syscall" |
324 | 12 | 13 | ||
325 | 13 | "github.com/juju/loggo" | 14 | "github.com/juju/loggo" |
326 | @@ -180,15 +181,15 @@ | |||
327 | 180 | localConfig := newEnvironConfig(cfg, validated) | 181 | localConfig := newEnvironConfig(cfg, validated) |
328 | 181 | // Before potentially creating directories, make sure that the | 182 | // Before potentially creating directories, make sure that the |
329 | 182 | // root directory has not changed. | 183 | // root directory has not changed. |
330 | 184 | containerType := localConfig.container() | ||
331 | 183 | if old != nil { | 185 | if old != nil { |
332 | 184 | oldLocalConfig, err := provider.newConfig(old) | 186 | oldLocalConfig, err := provider.newConfig(old) |
333 | 185 | if err != nil { | 187 | if err != nil { |
334 | 186 | return nil, fmt.Errorf("old config is not a valid local config: %v", old) | 188 | return nil, fmt.Errorf("old config is not a valid local config: %v", old) |
335 | 187 | } | 189 | } |
337 | 188 | if localConfig.container() != oldLocalConfig.container() { | 190 | if containerType != oldLocalConfig.container() { |
338 | 189 | return nil, fmt.Errorf("cannot change container from %q to %q", | 191 | return nil, fmt.Errorf("cannot change container from %q to %q", |
341 | 190 | oldLocalConfig.container(), | 192 | oldLocalConfig.container(), containerType) |
340 | 191 | localConfig.container()) | ||
342 | 192 | } | 193 | } |
343 | 193 | if localConfig.rootDir() != oldLocalConfig.rootDir() { | 194 | if localConfig.rootDir() != oldLocalConfig.rootDir() { |
344 | 194 | return nil, fmt.Errorf("cannot change root-dir from %q to %q", | 195 | return nil, fmt.Errorf("cannot change root-dir from %q to %q", |
345 | @@ -207,8 +208,8 @@ | |||
346 | 207 | } | 208 | } |
347 | 208 | } | 209 | } |
348 | 209 | // Currently only supported containers are "lxc" and "kvm". | 210 | // Currently only supported containers are "lxc" and "kvm". |
351 | 210 | if localConfig.container() != instance.LXC && localConfig.container() != instance.KVM { | 211 | if containerType != instance.LXC && containerType != instance.KVM { |
352 | 211 | return nil, fmt.Errorf("unsupported container type: %q", localConfig.container()) | 212 | return nil, fmt.Errorf("unsupported container type: %q", containerType) |
353 | 212 | } | 213 | } |
354 | 213 | dir, err := utils.NormalizePath(localConfig.rootDir()) | 214 | dir, err := utils.NormalizePath(localConfig.rootDir()) |
355 | 214 | if err != nil { | 215 | if err != nil { |
356 | @@ -220,6 +221,16 @@ | |||
357 | 220 | // Always assign the normalized path. | 221 | // Always assign the normalized path. |
358 | 221 | localConfig.attrs["root-dir"] = dir | 222 | localConfig.attrs["root-dir"] = dir |
359 | 222 | 223 | ||
360 | 224 | if containerType != instance.KVM { | ||
361 | 225 | fastOptionAvailable := strconv.FormatBool(useFastLXC(containerType)) | ||
362 | 226 | if _, found := localConfig.attrs["lxc-clone"]; !found { | ||
363 | 227 | localConfig.attrs["lxc-clone"] = fastOptionAvailable | ||
364 | 228 | } | ||
365 | 229 | if _, found := localConfig.attrs["lxc-clone-aufs"]; !found { | ||
366 | 230 | localConfig.attrs["lxc-clone-aufs"] = fastOptionAvailable | ||
367 | 231 | } | ||
368 | 232 | } | ||
369 | 233 | |||
370 | 223 | // Apply the coerced unknown values back into the config. | 234 | // Apply the coerced unknown values back into the config. |
371 | 224 | return cfg.Apply(localConfig.attrs) | 235 | return cfg.Apply(localConfig.attrs) |
372 | 225 | } | 236 | } |
373 | 226 | 237 | ||
374 | === modified file 'provider/local/environprovider_test.go' | |||
375 | --- provider/local/environprovider_test.go 2014-03-09 20:48:29 +0000 | |||
376 | +++ provider/local/environprovider_test.go 2014-03-17 22:08:13 +0000 | |||
377 | @@ -8,11 +8,14 @@ | |||
378 | 8 | "os/user" | 8 | "os/user" |
379 | 9 | 9 | ||
380 | 10 | "github.com/juju/loggo" | 10 | "github.com/juju/loggo" |
381 | 11 | jc "github.com/juju/testing/checkers" | ||
382 | 11 | gc "launchpad.net/gocheck" | 12 | gc "launchpad.net/gocheck" |
383 | 12 | 13 | ||
384 | 14 | "launchpad.net/juju-core/container/kvm" | ||
385 | 13 | lxctesting "launchpad.net/juju-core/container/lxc/testing" | 15 | lxctesting "launchpad.net/juju-core/container/lxc/testing" |
386 | 14 | "launchpad.net/juju-core/environs" | 16 | "launchpad.net/juju-core/environs" |
387 | 15 | "launchpad.net/juju-core/environs/config" | 17 | "launchpad.net/juju-core/environs/config" |
388 | 18 | "launchpad.net/juju-core/instance" | ||
389 | 16 | "launchpad.net/juju-core/juju/osenv" | 19 | "launchpad.net/juju-core/juju/osenv" |
390 | 17 | "launchpad.net/juju-core/provider" | 20 | "launchpad.net/juju-core/provider" |
391 | 18 | "launchpad.net/juju-core/provider/local" | 21 | "launchpad.net/juju-core/provider/local" |
392 | @@ -297,3 +300,100 @@ | |||
393 | 297 | } | 300 | } |
394 | 298 | } | 301 | } |
395 | 299 | } | 302 | } |
396 | 303 | |||
397 | 304 | func (s *prepareSuite) TestFastLXCClone(c *gc.C) { | ||
398 | 305 | s.PatchValue(local.DetectAptProxies, func() (osenv.ProxySettings, error) { | ||
399 | 306 | return osenv.ProxySettings{}, nil | ||
400 | 307 | }) | ||
401 | 308 | s.PatchValue(&kvm.IsKVMSupported, func() (bool, error) { | ||
402 | 309 | return true, nil | ||
403 | 310 | }) | ||
404 | 311 | s.PatchValue(&local.VerifyPrerequisites, func(containerType instance.ContainerType) error { | ||
405 | 312 | return nil | ||
406 | 313 | }) | ||
407 | 314 | basecfg, err := config.New(config.UseDefaults, map[string]interface{}{ | ||
408 | 315 | "type": "local", | ||
409 | 316 | "name": "test", | ||
410 | 317 | }) | ||
411 | 318 | provider, err := environs.Provider("local") | ||
412 | 319 | c.Assert(err, gc.IsNil) | ||
413 | 320 | |||
414 | 321 | type test struct { | ||
415 | 322 | systemDefault bool | ||
416 | 323 | extraConfig map[string]interface{} | ||
417 | 324 | expectClone string | ||
418 | 325 | expectAUFS string | ||
419 | 326 | } | ||
420 | 327 | tests := []test{{ | ||
421 | 328 | extraConfig: map[string]interface{}{ | ||
422 | 329 | "container": "lxc", | ||
423 | 330 | }, | ||
424 | 331 | expectClone: "false", | ||
425 | 332 | expectAUFS: "false", | ||
426 | 333 | }, { | ||
427 | 334 | extraConfig: map[string]interface{}{ | ||
428 | 335 | "container": "lxc", | ||
429 | 336 | "lxc-clone": "true", | ||
430 | 337 | }, | ||
431 | 338 | expectClone: "true", | ||
432 | 339 | expectAUFS: "false", | ||
433 | 340 | }, { | ||
434 | 341 | systemDefault: true, | ||
435 | 342 | extraConfig: map[string]interface{}{ | ||
436 | 343 | "container": "lxc", | ||
437 | 344 | }, | ||
438 | 345 | expectClone: "true", | ||
439 | 346 | expectAUFS: "true", | ||
440 | 347 | }, { | ||
441 | 348 | systemDefault: true, | ||
442 | 349 | extraConfig: map[string]interface{}{ | ||
443 | 350 | "container": "kvm", | ||
444 | 351 | }, | ||
445 | 352 | }, { | ||
446 | 353 | systemDefault: true, | ||
447 | 354 | extraConfig: map[string]interface{}{ | ||
448 | 355 | "container": "lxc", | ||
449 | 356 | "lxc-clone": "false", | ||
450 | 357 | }, | ||
451 | 358 | expectClone: "false", | ||
452 | 359 | expectAUFS: "true", | ||
453 | 360 | }, { | ||
454 | 361 | systemDefault: true, | ||
455 | 362 | extraConfig: map[string]interface{}{ | ||
456 | 363 | "container": "lxc", | ||
457 | 364 | "lxc-clone-aufs": "false", | ||
458 | 365 | }, | ||
459 | 366 | expectClone: "true", | ||
460 | 367 | expectAUFS: "false", | ||
461 | 368 | }} | ||
462 | 369 | |||
463 | 370 | for i, test := range tests { | ||
464 | 371 | c.Logf("test %d: %v", i, test) | ||
465 | 372 | |||
466 | 373 | releaseVersion := "12.04" | ||
467 | 374 | if test.systemDefault { | ||
468 | 375 | releaseVersion = "14.04" | ||
469 | 376 | } | ||
470 | 377 | s.PatchValue(local.ReleaseVersion, func() string { return releaseVersion }) | ||
471 | 378 | testConfig, err := basecfg.Apply(test.extraConfig) | ||
472 | 379 | c.Assert(err, gc.IsNil) | ||
473 | 380 | env, err := provider.Open(testConfig) | ||
474 | 381 | c.Assert(err, gc.IsNil) | ||
475 | 382 | localAttributes := env.Config().UnknownAttrs() | ||
476 | 383 | |||
477 | 384 | if test.expectClone != "" { | ||
478 | 385 | c.Assert(localAttributes["lxc-clone"], gc.Equals, test.expectClone) | ||
479 | 386 | } else { | ||
480 | 387 | _, found := localAttributes["lxc-clone"] | ||
481 | 388 | c.Assert(found, jc.IsFalse) | ||
482 | 389 | } | ||
483 | 390 | |||
484 | 391 | if test.expectAUFS != "" { | ||
485 | 392 | c.Assert(localAttributes["lxc-clone-aufs"], gc.Equals, test.expectAUFS) | ||
486 | 393 | } else { | ||
487 | 394 | _, found := localAttributes["lxc-clone-aufs"] | ||
488 | 395 | c.Assert(found, jc.IsFalse) | ||
489 | 396 | } | ||
490 | 397 | |||
491 | 398 | } | ||
492 | 399 | } | ||
493 | 300 | 400 | ||
494 | === modified file 'provider/local/export_test.go' | |||
495 | --- provider/local/export_test.go 2014-03-07 04:22:00 +0000 | |||
496 | +++ provider/local/export_test.go 2014-03-17 22:08:13 +0000 | |||
497 | @@ -10,14 +10,13 @@ | |||
498 | 10 | ) | 10 | ) |
499 | 11 | 11 | ||
500 | 12 | var ( | 12 | var ( |
509 | 13 | CheckLocalPort = &checkLocalPort | 13 | CheckLocalPort = &checkLocalPort |
510 | 14 | DetectAptProxies = &detectAptProxies | 14 | DetectAptProxies = &detectAptProxies |
511 | 15 | EnvKeyTestingForceSlow = envKeyTestingForceSlow | 15 | FinishBootstrap = &finishBootstrap |
512 | 16 | FinishBootstrap = &finishBootstrap | 16 | Provider = providerInstance |
513 | 17 | Provider = providerInstance | 17 | ReleaseVersion = &releaseVersion |
514 | 18 | ReleaseVersion = &releaseVersion | 18 | UseFastLXC = useFastLXC |
515 | 19 | UseFastLXC = useFastLXC | 19 | UserCurrent = &userCurrent |
508 | 20 | UserCurrent = &userCurrent | ||
516 | 21 | ) | 20 | ) |
517 | 22 | 21 | ||
518 | 23 | // SetRootCheckFunction allows tests to override the check for a root user. | 22 | // SetRootCheckFunction allows tests to override the check for a root user. |
519 | 24 | 23 | ||
520 | === modified file 'provider/local/lxc.go' | |||
521 | --- provider/local/lxc.go 2014-03-07 04:24:27 +0000 | |||
522 | +++ provider/local/lxc.go 2014-03-17 22:08:13 +0000 | |||
523 | @@ -4,17 +4,12 @@ | |||
524 | 4 | package local | 4 | package local |
525 | 5 | 5 | ||
526 | 6 | import ( | 6 | import ( |
527 | 7 | "os" | ||
528 | 8 | "strconv" | 7 | "strconv" |
529 | 9 | 8 | ||
530 | 10 | "launchpad.net/juju-core/instance" | 9 | "launchpad.net/juju-core/instance" |
531 | 11 | "launchpad.net/juju-core/version" | 10 | "launchpad.net/juju-core/version" |
532 | 12 | ) | 11 | ) |
533 | 13 | 12 | ||
534 | 14 | // envKeyTestingForceSlow is an environment variable name to force the slow | ||
535 | 15 | // lxc path. Setting to any non-empty value will force the slow path. | ||
536 | 16 | const envKeyTestingForceSlow = "JUJU_TESTING_LXC_FORCE_SLOW" | ||
537 | 17 | |||
538 | 18 | // releaseVersion is a function that returns a string representing the | 13 | // releaseVersion is a function that returns a string representing the |
539 | 19 | // DISTRIB_RELEASE from the /etc/lsb-release file. | 14 | // DISTRIB_RELEASE from the /etc/lsb-release file. |
540 | 20 | var releaseVersion = version.ReleaseVersion | 15 | var releaseVersion = version.ReleaseVersion |
541 | @@ -23,9 +18,6 @@ | |||
542 | 23 | if containerType != instance.LXC { | 18 | if containerType != instance.LXC { |
543 | 24 | return false | 19 | return false |
544 | 25 | } | 20 | } |
545 | 26 | if os.Getenv(envKeyTestingForceSlow) != "" { | ||
546 | 27 | return false | ||
547 | 28 | } | ||
548 | 29 | release := releaseVersion() | 21 | release := releaseVersion() |
549 | 30 | if release == "" { | 22 | if release == "" { |
550 | 31 | return false | 23 | return false |
551 | 32 | 24 | ||
552 | === modified file 'provider/local/lxc_test.go' | |||
553 | --- provider/local/lxc_test.go 2014-03-13 07:54:56 +0000 | |||
554 | +++ provider/local/lxc_test.go 2014-03-17 22:08:13 +0000 | |||
555 | @@ -28,7 +28,6 @@ | |||
556 | 28 | message string | 28 | message string |
557 | 29 | releaseVersion string | 29 | releaseVersion string |
558 | 30 | expected bool | 30 | expected bool |
559 | 31 | overrideSlow string | ||
560 | 32 | }{{ | 31 | }{{ |
561 | 33 | message: "missing release file", | 32 | message: "missing release file", |
562 | 34 | }, { | 33 | }, { |
563 | @@ -45,14 +44,9 @@ | |||
564 | 45 | }, { | 44 | }, { |
565 | 46 | message: "jaunty", | 45 | message: "jaunty", |
566 | 47 | releaseVersion: "9.10", | 46 | releaseVersion: "9.10", |
567 | 48 | }, { | ||
568 | 49 | message: "env override", | ||
569 | 50 | releaseVersion: "14.04", | ||
570 | 51 | overrideSlow: "value", | ||
571 | 52 | }} { | 47 | }} { |
572 | 53 | c.Logf("%v: %v", i, test.message) | 48 | c.Logf("%v: %v", i, test.message) |
573 | 54 | t.PatchValue(local.ReleaseVersion, func() string { return test.releaseVersion }) | 49 | t.PatchValue(local.ReleaseVersion, func() string { return test.releaseVersion }) |
574 | 55 | t.PatchEnvironment(local.EnvKeyTestingForceSlow, test.overrideSlow) | ||
575 | 56 | value := local.UseFastLXC(instance.LXC) | 50 | value := local.UseFastLXC(instance.LXC) |
576 | 57 | c.Assert(value, gc.Equals, test.expected) | 51 | c.Assert(value, gc.Equals, test.expected) |
577 | 58 | } | 52 | } |
578 | 59 | 53 | ||
579 | === modified file 'provider/local/prereqs.go' | |||
580 | --- provider/local/prereqs.go 2014-03-06 20:35:21 +0000 | |||
581 | +++ provider/local/prereqs.go 2014-03-17 22:08:13 +0000 | |||
582 | @@ -85,7 +85,7 @@ | |||
583 | 85 | // VerifyPrerequisites verifies the prerequisites of | 85 | // VerifyPrerequisites verifies the prerequisites of |
584 | 86 | // the local machine (machine 0) for running the local | 86 | // the local machine (machine 0) for running the local |
585 | 87 | // provider. | 87 | // provider. |
587 | 88 | func VerifyPrerequisites(containerType instance.ContainerType) error { | 88 | var VerifyPrerequisites = func(containerType instance.ContainerType) error { |
588 | 89 | if goos != "linux" { | 89 | if goos != "linux" { |
589 | 90 | return fmt.Errorf(errUnsupportedOS, goos) | 90 | return fmt.Errorf(errUnsupportedOS, goos) |
590 | 91 | } | 91 | } |
Reviewers: mp+211237_ code.launchpad. net,
Message:
Please take a look.
Description:
Add local options lxc-clone and lxc-clone-aufs
These new values default to the existing behaviour.
That being that if the user is on trusty or above,
they default to true, otherwise false.
The reason for these values is two-fold. Firstly,
aufs isn't working on power, and we want to be able
to test effectively there. Secondly this gives the
user on saucy the ability to try it out (not originally
planned, but a helpful side effect).
https:/ /code.launchpad .net/~thumper/ juju-core/ local-lxc- clone-settings/ +merge/ 211237
(do not edit description out of merge proposal)
Please review this at https:/ /codereview. appspot. com/74660044/
Affected files (+206, -34 lines): help_topics. go lxc/initialisat ion_test. go lxc/lxc. go lxc/lxc_ test.go lxc/mock/ mock-lxc. go local/config. go local/environ. go local/environpr ovider. go local/environpr ovider_ test.go
A [revision details]
M cmd/juju/
M container/
M container/
M container/
M container/
M provider/
M provider/
M provider/
M provider/