Merge lp:~mvo/snappy/snappy-snapfs-refactor-ftw into lp:~snappy-dev/snappy/snappy-moved-to-github
- snappy-snapfs-refactor-ftw
- Merge into snappy-moved-to-github
Proposed by
Michael Vogt
Status: | Work in progress |
---|---|
Proposed branch: | lp:~mvo/snappy/snappy-snapfs-refactor-ftw |
Merge into: | lp:~snappy-dev/snappy/snappy-moved-to-github |
Prerequisite: | lp:~mvo/snappy/snappy-snapfs-boot-ok |
Diff against target: |
588 lines (+191/-80) 11 files modified
pkg/clickdeb/deb.go (+11/-2) pkg/lightweight/lightweight_test.go (+1/-1) snappy/click.go (+0/-1) snappy/kernel.go (+31/-8) snappy/oem.go (+27/-1) snappy/os.go (+36/-0) snappy/purge.go (+1/-1) snappy/purge_test.go (+1/-1) snappy/snapp.go (+56/-47) snappy/snapp_snapfs_test.go (+23/-14) snappy/snapp_test.go (+4/-4) |
To merge this branch: | bzr merge lp:~mvo/snappy/snappy-snapfs-refactor-ftw |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
John Lenton (community) | Needs Fixing | ||
Review via email: mp+275024@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 786. By Michael Vogt
-
more snap types
- 787. By Michael Vogt
-
start refactor code out of generic and into OemSnap
Revision history for this message
John Lenton (chipaca) : | # |
- 788. By Michael Vogt
-
more SnapIF work
- 789. By Michael Vogt
-
move kernel unpack into kernel snap
Revision history for this message
Michael Vogt (mvo) : | # |
Unmerged revisions
- 789. By Michael Vogt
-
move kernel unpack into kernel snap
- 788. By Michael Vogt
-
more SnapIF work
- 787. By Michael Vogt
-
start refactor code out of generic and into OemSnap
- 786. By Michael Vogt
-
more snap types
- 785. By Michael Vogt
-
start refactor to have OemSnap etc
- 784. By Michael Vogt
-
add boot-ok for new-style all-snaps
- 783. By Michael Vogt
-
disallow removal of the active kernel and os
- 782. By Michael Vogt
-
remove kernel assets in /boot/ on snap removal
- 781. By Michael Vogt
-
show a reboot required message (not complete yet)
- 780. By Michael Vogt
-
go fmt
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'pkg/clickdeb/deb.go' | |||
2 | --- pkg/clickdeb/deb.go 2015-10-20 14:48:11 +0000 | |||
3 | +++ pkg/clickdeb/deb.go 2015-10-20 14:48:11 +0000 | |||
4 | @@ -30,6 +30,7 @@ | |||
5 | 30 | "os" | 30 | "os" |
6 | 31 | "os/exec" | 31 | "os/exec" |
7 | 32 | "path/filepath" | 32 | "path/filepath" |
8 | 33 | "runtime" | ||
9 | 33 | "strings" | 34 | "strings" |
10 | 34 | "time" | 35 | "time" |
11 | 35 | 36 | ||
12 | @@ -127,13 +128,19 @@ | |||
13 | 127 | file *os.File | 128 | file *os.File |
14 | 128 | } | 129 | } |
15 | 129 | 130 | ||
16 | 131 | func clickDebFinalizer(d *ClickDeb) { | ||
17 | 132 | d.file.Close() | ||
18 | 133 | } | ||
19 | 134 | |||
20 | 130 | // Open calls os.Open and uses that file for the backing file. | 135 | // Open calls os.Open and uses that file for the backing file. |
21 | 131 | func Open(path string) (*ClickDeb, error) { | 136 | func Open(path string) (*ClickDeb, error) { |
22 | 132 | f, err := os.Open(path) | 137 | f, err := os.Open(path) |
23 | 133 | if err != nil { | 138 | if err != nil { |
24 | 134 | return nil, err | 139 | return nil, err |
25 | 135 | } | 140 | } |
27 | 136 | return &ClickDeb{f}, nil | 141 | deb := &ClickDeb{f} |
28 | 142 | runtime.SetFinalizer(deb, clickDebFinalizer) | ||
29 | 143 | return deb, nil | ||
30 | 137 | } | 144 | } |
31 | 138 | 145 | ||
32 | 139 | // Create calls os.Create and uses that file for the backing file. | 146 | // Create calls os.Create and uses that file for the backing file. |
33 | @@ -142,7 +149,9 @@ | |||
34 | 142 | if err != nil { | 149 | if err != nil { |
35 | 143 | return nil, err | 150 | return nil, err |
36 | 144 | } | 151 | } |
38 | 145 | return &ClickDeb{f}, nil | 152 | deb := &ClickDeb{f} |
39 | 153 | runtime.SetFinalizer(deb, clickDebFinalizer) | ||
40 | 154 | return deb, nil | ||
41 | 146 | } | 155 | } |
42 | 147 | 156 | ||
43 | 148 | // Name returns the Name of the backing file | 157 | // Name returns the Name of the backing file |
44 | 149 | 158 | ||
45 | === modified file 'pkg/lightweight/lightweight_test.go' | |||
46 | --- pkg/lightweight/lightweight_test.go 2015-10-10 09:48:49 +0000 | |||
47 | +++ pkg/lightweight/lightweight_test.go 2015-10-20 14:48:11 +0000 | |||
48 | @@ -388,7 +388,7 @@ | |||
49 | 388 | c.Check(oem.ActiveIndex(), check.Equals, -1) | 388 | c.Check(oem.ActiveIndex(), check.Equals, -1) |
50 | 389 | p, err := oem.Load(0) | 389 | p, err := oem.Load(0) |
51 | 390 | c.Check(err, check.IsNil) | 390 | c.Check(err, check.IsNil) |
53 | 391 | c.Check(p, check.FitsTypeOf, new(snappy.SnapPart)) | 391 | c.Check(p, check.FitsTypeOf, new(snappy.OemSnap)) |
54 | 392 | c.Check(p.Version(), check.Equals, "3") | 392 | c.Check(p.Version(), check.Equals, "3") |
55 | 393 | } | 393 | } |
56 | 394 | 394 | ||
57 | 395 | 395 | ||
58 | === modified file 'snappy/click.go' | |||
59 | --- snappy/click.go 2015-10-15 07:32:34 +0000 | |||
60 | +++ snappy/click.go 2015-10-20 14:48:11 +0000 | |||
61 | @@ -771,7 +771,6 @@ | |||
62 | 771 | if err != nil { | 771 | if err != nil { |
63 | 772 | return "", err | 772 | return "", err |
64 | 773 | } | 773 | } |
65 | 774 | defer part.deb.Close() | ||
66 | 775 | 774 | ||
67 | 776 | return part.Install(inter, flags) | 775 | return part.Install(inter, flags) |
68 | 777 | } | 776 | } |
69 | 778 | 777 | ||
70 | === modified file 'snappy/kernel.go' | |||
71 | --- snappy/kernel.go 2015-10-20 14:48:11 +0000 | |||
72 | +++ snappy/kernel.go 2015-10-20 14:48:11 +0000 | |||
73 | @@ -25,47 +25,70 @@ | |||
74 | 25 | 25 | ||
75 | 26 | "launchpad.net/snappy/partition" | 26 | "launchpad.net/snappy/partition" |
76 | 27 | "launchpad.net/snappy/pkg/snapfs" | 27 | "launchpad.net/snappy/pkg/snapfs" |
77 | 28 | "launchpad.net/snappy/progress" | ||
78 | 28 | ) | 29 | ) |
79 | 29 | 30 | ||
81 | 30 | func unpackKernel(s *SnapPart) error { | 31 | type KernelSnap struct { |
82 | 32 | SnapPart | ||
83 | 33 | } | ||
84 | 34 | |||
85 | 35 | // OEM snaps should not be removed as they are a key | ||
86 | 36 | // building block for OEMs. Prunning non active ones | ||
87 | 37 | // is acceptible. | ||
88 | 38 | func (s *KernelSnap) Uninstall(pb progress.Meter) (err error) { | ||
89 | 39 | if s.IsActive() { | ||
90 | 40 | return ErrPackageNotRemovable | ||
91 | 41 | } | ||
92 | 42 | |||
93 | 43 | return s.SnapPart.Uninstall(pb) | ||
94 | 44 | } | ||
95 | 45 | |||
96 | 46 | func (s *KernelSnap) Install(inter progress.Meter, flags InstallFlags) (name string, err error) { | ||
97 | 47 | // do the generic install | ||
98 | 48 | name, err = s.SnapPart.Install(inter, flags) | ||
99 | 49 | if err != nil { | ||
100 | 50 | return name, err | ||
101 | 51 | } | ||
102 | 52 | |||
103 | 53 | // now do the kernel specific bits | ||
104 | 31 | bootdir := partition.BootloaderDir() | 54 | bootdir := partition.BootloaderDir() |
105 | 32 | if err := os.MkdirAll(filepath.Join(bootdir, s.Version()), 0755); err != | 55 | if err := os.MkdirAll(filepath.Join(bootdir, s.Version()), 0755); err != |
106 | 33 | nil { | 56 | nil { |
108 | 34 | return err | 57 | return name, err |
109 | 35 | } | 58 | } |
110 | 36 | blobName := filepath.Base(snapfs.BlobPath(s.basedir)) | 59 | blobName := filepath.Base(snapfs.BlobPath(s.basedir)) |
111 | 37 | dstDir := filepath.Join(bootdir, blobName) | 60 | dstDir := filepath.Join(bootdir, blobName) |
112 | 38 | if s.m.Kernel != "" { | 61 | if s.m.Kernel != "" { |
113 | 39 | src := s.m.Kernel | 62 | src := s.m.Kernel |
114 | 40 | if err := s.deb.Unpack(src, dstDir); err != nil { | 63 | if err := s.deb.Unpack(src, dstDir); err != nil { |
116 | 41 | return err | 64 | return name, err |
117 | 42 | } | 65 | } |
118 | 43 | src = filepath.Join(dstDir, s.m.Kernel) | 66 | src = filepath.Join(dstDir, s.m.Kernel) |
119 | 44 | dst := filepath.Join(dstDir, partition.NormalizeKernelInitrdName(s.m.Kernel)) | 67 | dst := filepath.Join(dstDir, partition.NormalizeKernelInitrdName(s.m.Kernel)) |
120 | 45 | if err := os.Rename(src, dst); err != nil { | 68 | if err := os.Rename(src, dst); err != nil { |
122 | 46 | return err | 69 | return name, err |
123 | 47 | } | 70 | } |
124 | 48 | } | 71 | } |
125 | 49 | if s.m.Initrd != "" { | 72 | if s.m.Initrd != "" { |
126 | 50 | src := s.m.Initrd | 73 | src := s.m.Initrd |
127 | 51 | if err := s.deb.Unpack(src, dstDir); err != nil { | 74 | if err := s.deb.Unpack(src, dstDir); err != nil { |
129 | 52 | return err | 75 | return name, err |
130 | 53 | } | 76 | } |
131 | 54 | src = filepath.Join(dstDir, s.m.Initrd) | 77 | src = filepath.Join(dstDir, s.m.Initrd) |
132 | 55 | dst := filepath.Join(dstDir, partition.NormalizeKernelInitrdName(s.m.Initrd)) | 78 | dst := filepath.Join(dstDir, partition.NormalizeKernelInitrdName(s.m.Initrd)) |
133 | 56 | if err := os.Rename(src, dst); err != nil { | 79 | if err := os.Rename(src, dst); err != nil { |
135 | 57 | return err | 80 | return name, err |
136 | 58 | } | 81 | } |
137 | 59 | } | 82 | } |
138 | 60 | if s.m.Dtbs != "" { | 83 | if s.m.Dtbs != "" { |
139 | 61 | src := s.m.Dtbs | 84 | src := s.m.Dtbs |
140 | 62 | dst := filepath.Join(dstDir, s.m.Dtbs) | 85 | dst := filepath.Join(dstDir, s.m.Dtbs) |
141 | 63 | if err := s.deb.Unpack(src, dst); err != nil { | 86 | if err := s.deb.Unpack(src, dst); err != nil { |
143 | 64 | return err | 87 | return name, err |
144 | 65 | } | 88 | } |
145 | 66 | } | 89 | } |
146 | 67 | 90 | ||
148 | 68 | return nil | 91 | return name, nil |
149 | 69 | } | 92 | } |
150 | 70 | 93 | ||
151 | 71 | func removeKernel(s *SnapPart) error { | 94 | func removeKernel(s *SnapPart) error { |
152 | 72 | 95 | ||
153 | === modified file 'snappy/oem.go' | |||
154 | --- snappy/oem.go 2015-09-25 15:27:11 +0000 | |||
155 | +++ snappy/oem.go 2015-10-20 14:48:11 +0000 | |||
156 | @@ -34,8 +34,34 @@ | |||
157 | 34 | "launchpad.net/snappy/dirs" | 34 | "launchpad.net/snappy/dirs" |
158 | 35 | "launchpad.net/snappy/logger" | 35 | "launchpad.net/snappy/logger" |
159 | 36 | "launchpad.net/snappy/pkg" | 36 | "launchpad.net/snappy/pkg" |
160 | 37 | "launchpad.net/snappy/progress" | ||
161 | 37 | ) | 38 | ) |
162 | 38 | 39 | ||
163 | 40 | type OemSnap struct { | ||
164 | 41 | SnapPart | ||
165 | 42 | } | ||
166 | 43 | |||
167 | 44 | func (s *OemSnap) Install(inter progress.Meter, flags InstallFlags) (name string, err error) { | ||
168 | 45 | name, err = s.SnapPart.Install(inter, flags) | ||
169 | 46 | if err != nil { | ||
170 | 47 | return "", err | ||
171 | 48 | } | ||
172 | 49 | |||
173 | 50 | if err := installOemHardwareUdevRules(s.m); err != nil { | ||
174 | 51 | return "", err | ||
175 | 52 | } | ||
176 | 53 | |||
177 | 54 | return name, nil | ||
178 | 55 | } | ||
179 | 56 | |||
180 | 57 | func (s *OemSnap) Uninstall(pb progress.Meter) (err error) { | ||
181 | 58 | if s.IsActive() { | ||
182 | 59 | return ErrPackageNotRemovable | ||
183 | 60 | } | ||
184 | 61 | |||
185 | 62 | return s.SnapPart.Uninstall(pb) | ||
186 | 63 | } | ||
187 | 64 | |||
188 | 39 | // OEM represents the structure inside the package.yaml for the oem component | 65 | // OEM represents the structure inside the package.yaml for the oem component |
189 | 40 | // of an oem package type. | 66 | // of an oem package type. |
190 | 41 | type OEM struct { | 67 | type OEM struct { |
191 | @@ -129,7 +155,7 @@ | |||
192 | 129 | func getOemImpl() (*packageYaml, error) { | 155 | func getOemImpl() (*packageYaml, error) { |
193 | 130 | oems, _ := ActiveSnapsByType(pkg.TypeOem) | 156 | oems, _ := ActiveSnapsByType(pkg.TypeOem) |
194 | 131 | if len(oems) == 1 { | 157 | if len(oems) == 1 { |
196 | 132 | return oems[0].(*SnapPart).m, nil | 158 | return oems[0].(*OemSnap).m, nil |
197 | 133 | } | 159 | } |
198 | 134 | 160 | ||
199 | 135 | return nil, errors.New("no oem snap") | 161 | return nil, errors.New("no oem snap") |
200 | 136 | 162 | ||
201 | === added file 'snappy/os.go' | |||
202 | --- snappy/os.go 1970-01-01 00:00:00 +0000 | |||
203 | +++ snappy/os.go 2015-10-20 14:48:11 +0000 | |||
204 | @@ -0,0 +1,36 @@ | |||
205 | 1 | package snappy | ||
206 | 2 | |||
207 | 3 | // -*- Mode: Go; indent-tabs-mode: t -*- | ||
208 | 4 | |||
209 | 5 | /* | ||
210 | 6 | * Copyright (C) 2014-2015 Canonical Ltd | ||
211 | 7 | * | ||
212 | 8 | * This program is free software: you can redistribute it and/or modify | ||
213 | 9 | * it under the terms of the GNU General Public License version 3 as | ||
214 | 10 | * published by the Free Software Foundation. | ||
215 | 11 | * | ||
216 | 12 | * This program is distributed in the hope that it will be useful, | ||
217 | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
218 | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
219 | 15 | * GNU General Public License for more details. | ||
220 | 16 | * | ||
221 | 17 | * You should have received a copy of the GNU General Public License | ||
222 | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
223 | 19 | * | ||
224 | 20 | */ | ||
225 | 21 | |||
226 | 22 | import ( | ||
227 | 23 | "launchpad.net/snappy/progress" | ||
228 | 24 | ) | ||
229 | 25 | |||
230 | 26 | type OsSnap struct { | ||
231 | 27 | SnapPart | ||
232 | 28 | } | ||
233 | 29 | |||
234 | 30 | func (s *OsSnap) Uninstall(pb progress.Meter) (err error) { | ||
235 | 31 | if s.IsActive() { | ||
236 | 32 | return ErrPackageNotRemovable | ||
237 | 33 | } | ||
238 | 34 | |||
239 | 35 | return s.SnapPart.Uninstall(pb) | ||
240 | 36 | } | ||
241 | 0 | 37 | ||
242 | === modified file 'snappy/purge.go' | |||
243 | --- snappy/purge.go 2015-09-25 15:27:11 +0000 | |||
244 | +++ snappy/purge.go 2015-10-20 14:48:11 +0000 | |||
245 | @@ -48,7 +48,7 @@ | |||
246 | 48 | 48 | ||
247 | 49 | purgeActive := flags&DoPurgeActive != 0 | 49 | purgeActive := flags&DoPurgeActive != 0 |
248 | 50 | 50 | ||
250 | 51 | var active []*SnapPart | 51 | var active []SnapIF |
251 | 52 | 52 | ||
252 | 53 | for _, datadir := range datadirs { | 53 | for _, datadir := range datadirs { |
253 | 54 | yamlPath := filepath.Join(dirs.SnapAppsDir, datadir.QualifiedName(), datadir.Version, "meta", "package.yaml") | 54 | yamlPath := filepath.Join(dirs.SnapAppsDir, datadir.QualifiedName(), datadir.Version, "meta", "package.yaml") |
254 | 55 | 55 | ||
255 | === modified file 'snappy/purge_test.go' | |||
256 | --- snappy/purge_test.go 2015-10-10 13:27:50 +0000 | |||
257 | +++ snappy/purge_test.go 2015-10-20 14:48:11 +0000 | |||
258 | @@ -59,7 +59,7 @@ | |||
259 | 59 | c.Check(inter.notified, HasLen, 0) | 59 | c.Check(inter.notified, HasLen, 0) |
260 | 60 | } | 60 | } |
261 | 61 | 61 | ||
263 | 62 | func (s *purgeSuite) mkpkg(c *C, args ...string) (dataDir string, part *SnapPart) { | 62 | func (s *purgeSuite) mkpkg(c *C, args ...string) (dataDir string, part SnapIF) { |
264 | 63 | version := "1.10" | 63 | version := "1.10" |
265 | 64 | extra := "" | 64 | extra := "" |
266 | 65 | switch len(args) { | 65 | switch len(args) { |
267 | 66 | 66 | ||
268 | === modified file 'snappy/snapp.go' | |||
269 | --- snappy/snapp.go 2015-10-20 14:48:11 +0000 | |||
270 | +++ snappy/snapp.go 2015-10-20 14:48:11 +0000 | |||
271 | @@ -209,6 +209,16 @@ | |||
272 | 209 | return nil | 209 | return nil |
273 | 210 | } | 210 | } |
274 | 211 | 211 | ||
275 | 212 | // FIXME: name suckso | ||
276 | 213 | type SnapIF interface { | ||
277 | 214 | Part | ||
278 | 215 | activate(inhibitHooks bool, inter interacter) error | ||
279 | 216 | deactivate(inhibitHooks bool, inter interacter) error | ||
280 | 217 | Dir() string | ||
281 | 218 | remove(inter interacter) error | ||
282 | 219 | ServiceYamls() []ServiceYaml | ||
283 | 220 | } | ||
284 | 221 | |||
285 | 212 | // TODO split into payloads per package type composing the common | 222 | // TODO split into payloads per package type composing the common |
286 | 213 | // elements for all snaps. | 223 | // elements for all snaps. |
287 | 214 | type packageYaml struct { | 224 | type packageYaml struct { |
288 | @@ -529,17 +539,16 @@ | |||
289 | 529 | } | 539 | } |
290 | 530 | 540 | ||
291 | 531 | // NewInstalledSnapPart returns a new SnapPart from the given yamlPath | 541 | // NewInstalledSnapPart returns a new SnapPart from the given yamlPath |
293 | 532 | func NewInstalledSnapPart(yamlPath, origin string) (*SnapPart, error) { | 542 | func NewInstalledSnapPart(yamlPath, origin string) (SnapIF, error) { |
294 | 533 | m, err := parsePackageYamlFile(yamlPath) | 543 | m, err := parsePackageYamlFile(yamlPath) |
295 | 534 | if err != nil { | 544 | if err != nil { |
296 | 535 | return nil, err | 545 | return nil, err |
297 | 536 | } | 546 | } |
298 | 537 | 547 | ||
300 | 538 | part, err := NewSnapPartFromYaml(yamlPath, origin, m) | 548 | part, err := newSnapPartFromYaml(yamlPath, origin, m, true) |
301 | 539 | if err != nil { | 549 | if err != nil { |
302 | 540 | return nil, err | 550 | return nil, err |
303 | 541 | } | 551 | } |
304 | 542 | part.isInstalled = true | ||
305 | 543 | 552 | ||
306 | 544 | return part, nil | 553 | return part, nil |
307 | 545 | } | 554 | } |
308 | @@ -547,7 +556,7 @@ | |||
309 | 547 | // NewSnapPartFromSnapFile loads a snap from the given (clickdeb) snap file. | 556 | // NewSnapPartFromSnapFile loads a snap from the given (clickdeb) snap file. |
310 | 548 | // Caller should call Close on the pkg. | 557 | // Caller should call Close on the pkg. |
311 | 549 | // TODO: expose that Close. | 558 | // TODO: expose that Close. |
313 | 550 | func NewSnapPartFromSnapFile(snapFile string, origin string, unauthOk bool) (*SnapPart, error) { | 559 | func NewSnapPartFromSnapFile(snapFile string, origin string, unauthOk bool) (SnapIF, error) { |
314 | 551 | d, err := pkg.Open(snapFile) | 560 | d, err := pkg.Open(snapFile) |
315 | 552 | if err != nil { | 561 | if err != nil { |
316 | 553 | return nil, err | 562 | return nil, err |
317 | @@ -570,41 +579,45 @@ | |||
318 | 570 | return nil, err | 579 | return nil, err |
319 | 571 | } | 580 | } |
320 | 572 | 581 | ||
321 | 573 | // FIXME: make a special OemSnap that knows its install dir | ||
322 | 574 | // instead of having this special case here | ||
323 | 575 | targetDir := dirs.SnapAppsDir | ||
324 | 576 | // the "oem" parts are special | ||
325 | 577 | if m.Type == pkg.TypeOem { | ||
326 | 578 | targetDir = dirs.SnapOemDir | ||
327 | 579 | } | ||
328 | 580 | |||
329 | 581 | if origin == SideloadedOrigin { | 582 | if origin == SideloadedOrigin { |
330 | 582 | m.Version = helpers.NewSideloadVersion() | 583 | m.Version = helpers.NewSideloadVersion() |
331 | 583 | } | 584 | } |
332 | 584 | 585 | ||
333 | 585 | fullName := m.qualifiedName(origin) | 586 | fullName := m.qualifiedName(origin) |
335 | 586 | instDir := filepath.Join(targetDir, fullName, m.Version) | 587 | instDir := filepath.Join(dirs.SnapAppsDir, fullName, m.Version) |
336 | 587 | 588 | ||
338 | 588 | baseSnap := &SnapPart{ | 589 | basePart := &SnapPart{ |
339 | 589 | basedir: instDir, | 590 | basedir: instDir, |
340 | 590 | origin: origin, | 591 | origin: origin, |
341 | 591 | m: m, | 592 | m: m, |
342 | 592 | deb: d, | 593 | deb: d, |
343 | 593 | } | 594 | } |
344 | 594 | 595 | ||
346 | 595 | return baseSnap, nil | 596 | // FIXME: duplicated code |
347 | 597 | switch m.Type { | ||
348 | 598 | case pkg.TypeOem: | ||
349 | 599 | basePart.basedir = filepath.Join(dirs.SnapOemDir, fullName, m.Version) | ||
350 | 600 | return &OemSnap{SnapPart: *basePart}, nil | ||
351 | 601 | case pkg.TypeOS: | ||
352 | 602 | return &OsSnap{SnapPart: *basePart}, nil | ||
353 | 603 | case pkg.TypeKernel: | ||
354 | 604 | return &KernelSnap{SnapPart: *basePart}, nil | ||
355 | 605 | } | ||
356 | 606 | |||
357 | 607 | return basePart, nil | ||
358 | 596 | } | 608 | } |
359 | 597 | 609 | ||
362 | 598 | // NewSnapPartFromYaml returns a new SnapPart from the given *packageYaml at yamlPath | 610 | // newSnapPartFromYaml returns a new SnapPart from the given *packageYaml at yamlPath |
363 | 599 | func NewSnapPartFromYaml(yamlPath, origin string, m *packageYaml) (*SnapPart, error) { | 611 | func newSnapPartFromYaml(yamlPath, origin string, m *packageYaml, installed bool) (SnapIF, error) { |
364 | 600 | if _, err := os.Stat(yamlPath); err != nil { | 612 | if _, err := os.Stat(yamlPath); err != nil { |
365 | 601 | return nil, err | 613 | return nil, err |
366 | 602 | } | 614 | } |
367 | 603 | 615 | ||
368 | 604 | part := &SnapPart{ | 616 | part := &SnapPart{ |
372 | 605 | basedir: filepath.Dir(filepath.Dir(yamlPath)), | 617 | basedir: filepath.Dir(filepath.Dir(yamlPath)), |
373 | 606 | origin: origin, | 618 | origin: origin, |
374 | 607 | m: m, | 619 | m: m, |
375 | 620 | isInstalled: installed, | ||
376 | 608 | } | 621 | } |
377 | 609 | 622 | ||
378 | 610 | // override the package's idea of its version | 623 | // override the package's idea of its version |
379 | @@ -656,6 +669,19 @@ | |||
380 | 656 | part.remoteM = &r | 669 | part.remoteM = &r |
381 | 657 | } | 670 | } |
382 | 658 | 671 | ||
383 | 672 | // FIXME: duplicated code | ||
384 | 673 | basePart := part | ||
385 | 674 | switch m.Type { | ||
386 | 675 | case pkg.TypeOem: | ||
387 | 676 | fullName := m.qualifiedName(origin) | ||
388 | 677 | basePart.basedir = filepath.Join(dirs.SnapOemDir, fullName, m.Version) | ||
389 | 678 | return &OemSnap{SnapPart: *basePart}, nil | ||
390 | 679 | case pkg.TypeOS: | ||
391 | 680 | return &OsSnap{SnapPart: *basePart}, nil | ||
392 | 681 | case pkg.TypeKernel: | ||
393 | 682 | return &KernelSnap{SnapPart: *basePart}, nil | ||
394 | 683 | } | ||
395 | 684 | |||
396 | 659 | return part, nil | 685 | return part, nil |
397 | 660 | } | 686 | } |
398 | 661 | 687 | ||
399 | @@ -674,6 +700,10 @@ | |||
400 | 674 | return s.m.Name | 700 | return s.m.Name |
401 | 675 | } | 701 | } |
402 | 676 | 702 | ||
403 | 703 | func (s *SnapPart) Dir() string { | ||
404 | 704 | return s.basedir | ||
405 | 705 | } | ||
406 | 706 | |||
407 | 677 | // Version returns the version | 707 | // Version returns the version |
408 | 678 | func (s *SnapPart) Version() string { | 708 | func (s *SnapPart) Version() string { |
409 | 679 | if s.basedir != "" { | 709 | if s.basedir != "" { |
410 | @@ -809,17 +839,10 @@ | |||
411 | 809 | return "", err | 839 | return "", err |
412 | 810 | } | 840 | } |
413 | 811 | 841 | ||
414 | 812 | // the "oem" parts are special | ||
415 | 813 | if s.Type() == pkg.TypeOem { | ||
416 | 814 | if err := installOemHardwareUdevRules(s.m); err != nil { | ||
417 | 815 | return "", err | ||
418 | 816 | } | ||
419 | 817 | } | ||
420 | 818 | |||
421 | 819 | fullName := QualifiedName(s) | 842 | fullName := QualifiedName(s) |
422 | 820 | dataDir := filepath.Join(dirs.SnapDataDir, fullName, s.Version()) | 843 | dataDir := filepath.Join(dirs.SnapDataDir, fullName, s.Version()) |
423 | 821 | 844 | ||
425 | 822 | var oldPart *SnapPart | 845 | var oldPart SnapIF |
426 | 823 | if currentActiveDir, _ := filepath.EvalSymlinks(filepath.Join(s.basedir, "..", "current")); currentActiveDir != "" { | 846 | if currentActiveDir, _ := filepath.EvalSymlinks(filepath.Join(s.basedir, "..", "current")); currentActiveDir != "" { |
427 | 824 | oldPart, err = NewInstalledSnapPart(filepath.Join(currentActiveDir, "meta", "package.yaml"), s.origin) | 847 | oldPart, err = NewInstalledSnapPart(filepath.Join(currentActiveDir, "meta", "package.yaml"), s.origin) |
428 | 825 | if err != nil { | 848 | if err != nil { |
429 | @@ -854,13 +877,6 @@ | |||
430 | 854 | } | 877 | } |
431 | 855 | } | 878 | } |
432 | 856 | 879 | ||
433 | 857 | // FIXME: move into KernelSnap instead of poluting generic code | ||
434 | 858 | if s.m.Type == pkg.TypeKernel { | ||
435 | 859 | if err := unpackKernel(s); err != nil { | ||
436 | 860 | return "", err | ||
437 | 861 | } | ||
438 | 862 | } | ||
439 | 863 | |||
440 | 864 | // legacy, the hooks (e.g. apparmor) need this. Once we converted | 880 | // legacy, the hooks (e.g. apparmor) need this. Once we converted |
441 | 865 | // all hooks this can go away | 881 | // all hooks this can go away |
442 | 866 | clickMetaDir := filepath.Join(s.basedir, ".click", "info") | 882 | clickMetaDir := filepath.Join(s.basedir, ".click", "info") |
443 | @@ -1160,13 +1176,6 @@ | |||
444 | 1160 | 1176 | ||
445 | 1161 | // Uninstall remove the snap from the system | 1177 | // Uninstall remove the snap from the system |
446 | 1162 | func (s *SnapPart) Uninstall(pb progress.Meter) (err error) { | 1178 | func (s *SnapPart) Uninstall(pb progress.Meter) (err error) { |
447 | 1163 | // OEM snaps should not be removed as they are a key | ||
448 | 1164 | // building block for OEMs. Prunning non active ones | ||
449 | 1165 | // is acceptible. | ||
450 | 1166 | if (s.m.Type == pkg.TypeOem || s.m.Type == pkg.TypeKernel || s.m.Type == pkg.TypeOS) && s.IsActive() { | ||
451 | 1167 | return ErrPackageNotRemovable | ||
452 | 1168 | } | ||
453 | 1169 | |||
454 | 1170 | if IsBuiltInSoftware(s.Name()) && s.IsActive() { | 1179 | if IsBuiltInSoftware(s.Name()) && s.IsActive() { |
455 | 1171 | return ErrPackageNotRemovable | 1180 | return ErrPackageNotRemovable |
456 | 1172 | } | 1181 | } |
457 | @@ -1396,12 +1405,12 @@ | |||
458 | 1396 | } | 1405 | } |
459 | 1397 | 1406 | ||
460 | 1398 | // RefreshDependentsSecurity refreshes the security policies of dependent snaps | 1407 | // RefreshDependentsSecurity refreshes the security policies of dependent snaps |
462 | 1399 | func (s *SnapPart) RefreshDependentsSecurity(oldPart *SnapPart, inter interacter) (err error) { | 1408 | func (s *SnapPart) RefreshDependentsSecurity(oldPart SnapIF, inter interacter) (err error) { |
463 | 1400 | oldBaseDir := "" | 1409 | oldBaseDir := "" |
464 | 1401 | if oldPart != nil { | 1410 | if oldPart != nil { |
466 | 1402 | oldBaseDir = oldPart.basedir | 1411 | oldBaseDir = oldPart.Dir() |
467 | 1403 | } | 1412 | } |
469 | 1404 | upPol, upTpl := policy.AppArmorDelta(oldBaseDir, s.basedir, s.Name()+"_") | 1413 | upPol, upTpl := policy.AppArmorDelta(oldBaseDir, s.Dir(), s.Name()+"_") |
470 | 1405 | 1414 | ||
471 | 1406 | deps, err := s.Dependents() | 1415 | deps, err := s.Dependents() |
472 | 1407 | if err != nil { | 1416 | if err != nil { |
473 | @@ -2066,7 +2075,7 @@ | |||
474 | 2066 | // The returned environment contains additional SNAP_* variables that | 2075 | // The returned environment contains additional SNAP_* variables that |
475 | 2067 | // are required when calling a meta/hook/ script and that will override | 2076 | // are required when calling a meta/hook/ script and that will override |
476 | 2068 | // any already existing SNAP_* variables in os.Environment() | 2077 | // any already existing SNAP_* variables in os.Environment() |
478 | 2069 | func makeSnapHookEnv(part *SnapPart) (env []string) { | 2078 | func makeSnapHookEnv(part SnapIF) (env []string) { |
479 | 2070 | desc := struct { | 2079 | desc := struct { |
480 | 2071 | AppName string | 2080 | AppName string |
481 | 2072 | AppArch string | 2081 | AppArch string |
482 | @@ -2077,7 +2086,7 @@ | |||
483 | 2077 | }{ | 2086 | }{ |
484 | 2078 | part.Name(), | 2087 | part.Name(), |
485 | 2079 | helpers.UbuntuArchitecture(), | 2088 | helpers.UbuntuArchitecture(), |
487 | 2080 | part.basedir, | 2089 | part.Dir(), |
488 | 2081 | part.Version(), | 2090 | part.Version(), |
489 | 2082 | QualifiedName(part), | 2091 | QualifiedName(part), |
490 | 2083 | part.Origin(), | 2092 | part.Origin(), |
491 | 2084 | 2093 | ||
492 | === modified file 'snappy/snapp_snapfs_test.go' | |||
493 | --- snappy/snapp_snapfs_test.go 2015-10-20 14:48:11 +0000 | |||
494 | +++ snappy/snapp_snapfs_test.go 2015-10-20 14:48:11 +0000 | |||
495 | @@ -138,7 +138,7 @@ | |||
496 | 138 | c.Assert(err, IsNil) | 138 | c.Assert(err, IsNil) |
497 | 139 | 139 | ||
498 | 140 | // ensure the right backend got picked up | 140 | // ensure the right backend got picked up |
500 | 141 | c.Assert(part.deb, FitsTypeOf, &snapfs.Snap{}) | 141 | c.Assert(part.(*SnapPart).deb, FitsTypeOf, &snapfs.Snap{}) |
501 | 142 | } | 142 | } |
502 | 143 | 143 | ||
503 | 144 | func (s *SnapfsTestSuite) TestInstallViaSnapfsWorks(c *C) { | 144 | func (s *SnapfsTestSuite) TestInstallViaSnapfsWorks(c *C) { |
504 | @@ -312,7 +312,7 @@ | |||
505 | 312 | c.Assert(err, IsNil) | 312 | c.Assert(err, IsNil) |
506 | 313 | c.Assert(snap.NeedsReboot(), Equals, false) | 313 | c.Assert(snap.NeedsReboot(), Equals, false) |
507 | 314 | 314 | ||
509 | 315 | snap.isActive = false | 315 | snap.(*OsSnap).isActive = false |
510 | 316 | mockb.bootvars["snappy_os"] = "ubuntu-core." + testOrigin + "_15.10-1.snap" | 316 | mockb.bootvars["snappy_os"] = "ubuntu-core." + testOrigin + "_15.10-1.snap" |
511 | 317 | c.Assert(snap.NeedsReboot(), Equals, true) | 317 | c.Assert(snap.NeedsReboot(), Equals, true) |
512 | 318 | } | 318 | } |
513 | @@ -325,7 +325,7 @@ | |||
514 | 325 | c.Assert(err, IsNil) | 325 | c.Assert(err, IsNil) |
515 | 326 | c.Assert(snap.NeedsReboot(), Equals, false) | 326 | c.Assert(snap.NeedsReboot(), Equals, false) |
516 | 327 | 327 | ||
518 | 328 | snap.isActive = false | 328 | snap.(*KernelSnap).isActive = false |
519 | 329 | mockb.bootvars["snappy_kernel"] = "ubuntu-kernel." + testOrigin + "_4.0-1.snap" | 329 | mockb.bootvars["snappy_kernel"] = "ubuntu-kernel." + testOrigin + "_4.0-1.snap" |
520 | 330 | c.Assert(snap.NeedsReboot(), Equals, true) | 330 | c.Assert(snap.NeedsReboot(), Equals, true) |
521 | 331 | } | 331 | } |
522 | @@ -350,15 +350,24 @@ | |||
523 | 350 | c.Assert(helpers.FileExists(kernelAssetsDir), Equals, false) | 350 | c.Assert(helpers.FileExists(kernelAssetsDir), Equals, false) |
524 | 351 | } | 351 | } |
525 | 352 | 352 | ||
537 | 353 | func (s *SnapfsTestSuite) TestActiveKernelOSNotRemovable(c *C) { | 353 | func (s *SnapfsTestSuite) TestActiveKernelNotRemovable(c *C) { |
538 | 354 | for _, yaml := range []string{packageKernel, packageOS} { | 354 | snapYaml, err := makeInstalledMockSnap(dirs.GlobalRootDir, packageKernel) |
539 | 355 | snapYaml, err := makeInstalledMockSnap(dirs.GlobalRootDir, yaml) | 355 | c.Assert(err, IsNil) |
540 | 356 | c.Assert(err, IsNil) | 356 | |
541 | 357 | 357 | snap, err := NewInstalledSnapPart(snapYaml, testOrigin) | |
542 | 358 | snap, err := NewInstalledSnapPart(snapYaml, testOrigin) | 358 | c.Assert(err, IsNil) |
543 | 359 | c.Assert(err, IsNil) | 359 | |
544 | 360 | 360 | snap.(*KernelSnap).isActive = true | |
545 | 361 | snap.isActive = true | 361 | c.Assert(snap.Uninstall(&MockProgressMeter{}), Equals, ErrPackageNotRemovable) |
546 | 362 | c.Assert(snap.Uninstall(&MockProgressMeter{}), Equals, ErrPackageNotRemovable) | 362 | } |
547 | 363 | } | 363 | |
548 | 364 | func (s *SnapfsTestSuite) TestActiveOSNotRemovable(c *C) { | ||
549 | 365 | snapYaml, err := makeInstalledMockSnap(dirs.GlobalRootDir, packageOS) | ||
550 | 366 | c.Assert(err, IsNil) | ||
551 | 367 | |||
552 | 368 | snap, err := NewInstalledSnapPart(snapYaml, testOrigin) | ||
553 | 369 | c.Assert(err, IsNil) | ||
554 | 370 | |||
555 | 371 | snap.(*OsSnap).isActive = true | ||
556 | 372 | c.Assert(snap.Uninstall(&MockProgressMeter{}), Equals, ErrPackageNotRemovable) | ||
557 | 364 | } | 373 | } |
558 | 365 | 374 | ||
559 | === modified file 'snappy/snapp_test.go' | |||
560 | --- snappy/snapp_test.go 2015-10-20 07:03:39 +0000 | |||
561 | +++ snappy/snapp_test.go 2015-10-20 14:48:11 +0000 | |||
562 | @@ -152,11 +152,11 @@ | |||
563 | 152 | c.Assert(services[0].Name, Equals, "svc1") | 152 | c.Assert(services[0].Name, Equals, "svc1") |
564 | 153 | 153 | ||
565 | 154 | // ensure we get valid Date() | 154 | // ensure we get valid Date() |
567 | 155 | st, err := os.Stat(snap.basedir) | 155 | st, err := os.Stat(snap.Dir()) |
568 | 156 | c.Assert(err, IsNil) | 156 | c.Assert(err, IsNil) |
569 | 157 | c.Assert(snap.Date(), Equals, st.ModTime()) | 157 | c.Assert(snap.Date(), Equals, st.ModTime()) |
570 | 158 | 158 | ||
572 | 159 | c.Assert(snap.basedir, Equals, filepath.Join(s.tempdir, "apps", helloAppComposedName, "1.10")) | 159 | c.Assert(snap.Dir(), Equals, filepath.Join(s.tempdir, "apps", helloAppComposedName, "1.10")) |
573 | 160 | c.Assert(snap.InstalledSize(), Not(Equals), -1) | 160 | c.Assert(snap.InstalledSize(), Not(Equals), -1) |
574 | 161 | } | 161 | } |
575 | 162 | 162 | ||
576 | @@ -825,11 +825,11 @@ | |||
577 | 825 | c.Assert(services[1].Description, Equals, "Service #2") | 825 | c.Assert(services[1].Description, Equals, "Service #2") |
578 | 826 | 826 | ||
579 | 827 | // ensure we get valid Date() | 827 | // ensure we get valid Date() |
581 | 828 | st, err := os.Stat(snap.basedir) | 828 | st, err := os.Stat(snap.Dir()) |
582 | 829 | c.Assert(err, IsNil) | 829 | c.Assert(err, IsNil) |
583 | 830 | c.Assert(snap.Date(), Equals, st.ModTime()) | 830 | c.Assert(snap.Date(), Equals, st.ModTime()) |
584 | 831 | 831 | ||
586 | 832 | c.Assert(snap.basedir, Equals, filepath.Join(s.tempdir, "apps", helloAppComposedName, "1.10")) | 832 | c.Assert(snap.Dir(), Equals, filepath.Join(s.tempdir, "apps", helloAppComposedName, "1.10")) |
587 | 833 | c.Assert(snap.InstalledSize(), Not(Equals), -1) | 833 | c.Assert(snap.InstalledSize(), Not(Equals), -1) |
588 | 834 | } | 834 | } |
589 | 835 | 835 |