Merge lp:~sylvain-pineau/checkbox/fix-1361071 into lp:checkbox
- fix-1361071
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Sylvain Pineau |
Approved revision: | 3531 |
Merged at revision: | 3527 |
Proposed branch: | lp:~sylvain-pineau/checkbox/fix-1361071 |
Merge into: | lp:checkbox |
Diff against target: |
263 lines (+53/-27) 7 files modified
checkbox-support/checkbox_support/parsers/udevadm.py (+15/-4) plainbox/plainbox/impl/ctrl.py (+1/-1) plainbox/plainbox/impl/secure/launcher1.py (+25/-8) plainbox/plainbox/impl/secure/test_launcher1.py (+3/-3) plainbox/plainbox/impl/test_ctrl.py (+2/-2) providers/plainbox-provider-checkbox/jobs/disk.txt.in (+6/-8) providers/plainbox-provider-resource-generic/bin/udev_resource (+1/-1) |
To merge this branch: | bzr merge lp:~sylvain-pineau/checkbox/fix-1361071 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sylvain Pineau (community) | Approve | ||
Zygmunt Krynicki (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
Fixes https:/
The trusted launcher now understands jobs generated from local AND resources jobs.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zygmunt Krynicki (zyga) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zygmunt Krynicki (zyga) wrote : | # |
Let's work on landing via-changes and rebase this one on top
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sylvain Pineau (sylvain-pineau) wrote : | # |
rebased on trunk with via changes. also fixed plainbox/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zygmunt Krynicki (zyga) wrote : | # |
Looks good apart from the _name that you are already fixing thing :)
The comment below about how jobs are instantiated. Do you think we should copy the checks from the session controller?
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sylvain Pineau (sylvain-pineau) wrote : | # |
fixed udevadm parser to create a dedicated property for "name"
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Zygmunt Krynicki (zyga) wrote : | # |
+1
16:05 <@spineau> zyga: when you're referring to the check in session controller code (https:/
16:05 <@zyga> yes>
16:05 <@zyga> ?
16:06 <@spineau> zyga: are you suggesting to call new_unit.validate() ?
16:06 <@zyga> IIRC not just that
16:06 <@zyga> let me see
16:07 <@zyga> http://
16:07 <@zyga> if you trace how that call unfolds
16:07 <@zyga> you'll see validity checks and duplicate checks
16:07 <@zyga> I think it's okay as is (as it it will work in the good case)
16:08 <@zyga> my worry is just about the bad case and what happens then
16:10 <@spineau> zyga: but the check should have been done by the session controller already, why duplicating this logic a second time in the secure launcher?*
16:10 <@zyga> the outcome may be different
16:10 <@zyga> and the original may have discarded something (separate concern)
16:10 <@zyga> that we're not discarding
16:11 <@spineau> zyga: we had this problem before then
16:13 <@spineau> zyga: as the check for duplicated jobs is only performed by the session controller
16:17 <@zyga> spineau: yes, though that doesn't mean the problem goes away
16:18 <@spineau> zyga: almost EOD for me, could you please explain in the merge request your concern about validity checks and duplicate checks missing from the trusted launcher?
16:18 <@spineau> zyga: are you seeing that as a blocker?
16:18 <@zyga> spineau: well, I think this can be merged
16:18 <@zyga> spineau: but I would still love to explore how the trusted launcher can be broken today
16:18 <@spineau> zyga: in that case we should follow up your remarks in a bug report I think
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Daniel Manrique (roadmr) wrote : | # |
The attempt to merge lp:~sylvain-pineau/checkbox/fix-1361071 into lp:checkbox failed. Below is the output from the failed tests.
[precise] starting container
[precise] (timing) 0.04user 0.03system 0:04.19elapsed 1%CPU (0avgtext+0avgdata 7864maxresident)k
[precise] (timing) 0inputs+32outputs (0major+
[precise] provisioning container
[precise] (timing) 39.36user 11.37system 1:19.11elapsed 64%CPU (0avgtext+0avgdata 51604maxresident)k
[precise] (timing) 0inputs+
[precise-testing] Starting tests...
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 32.33user 2.33system 0:35.15elapsed 98%CPU (0avgtext+0avgdata 116152maxresident)k
[precise-testing] (timing) 0inputs+4216outputs (0major+
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 0.63user 0.12system 0:00.77elapsed 97%CPU (0avgtext+0avgdata 39872maxresident)k
[precise-testing] (timing) 0inputs+3456outputs (0major+
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 16.67user 0.12system 0:16.88elapsed 99%CPU (0avgtext+0avgdata 83084maxresident)k
[precise-testing] (timing) 0inputs+1032outputs (0major+
Found a test script: ./checkbox-
[precise-testing] container-
[precise-testing] (timing) 0.00user 0.00system 0:00.02elapsed 40%CPU (0avgtext+0avgdata 2020maxresident)k
[precise-testing] (timing) 0inputs+8outputs (0major+
Found a test script: ./plainbox/
[precise-testing] container-
[precise-testing] (timing) 0.16user 0.04system 0:00.21elapsed 94%CPU (0avgtext+0avgdata 13496maxresident)k
[precise-testing] (timing) 0inputs+176outputs (0major+
Found a test script: ./plainbox/
[precise-testing] 001-container-
[precise-testing] (timing) 0.13user 0.02system 0:00.17elapsed 92%CPU (0avgtext+0avgdata 10500maxresident)k
[precise-testing] (timing) 0inputs+88outputs (0major+
Found a test script: ./plainbox/
[precise-testing] container-
[precise-testing] stdout: http://
[precise-testing] stderr: http://
[precise-testing] (timing) Command exited with non-zero status 1
[precise-testing] (timing) 5.12user 0.36system 0:05.53elapsed 99%CPU (0avgtext+0avgdata 63804maxresident)k
[precise-testing] (timing) 0inputs+2624outputs (0major+
Found...
- 3527. By Sylvain Pineau
-
checkbox-
support: parsers: udevadm. py: Keep the device name in the slots Most of local/template jobs are using the device name /dev/<XXXX> to create
child jobs.
To avoid recreating the full device path in the job definition, the udev parser
now returns - if present - the device name, the one stating with "N: <XXXX>" in
the "udevadm info --export-db" output. - 3528. By Sylvain Pineau
-
providers:
resource- generic: udev_resource: return the device name attribute The device name attribute is now part of the output and can be used by local or
template jobs. - 3529. By Sylvain Pineau
-
plainbox:ctrl: Change how we get the source job to create parent_env
For template jobs, job.origin.
source. job fails withthe following error: AttributeError: 'FileTextSource' object has no attribute 'job'
job.origin.
source. job cannot be used for all types of generated jobs.
A generic way to get the source job is to use now job_state.via_job. - 3530. By Sylvain Pineau
-
plainbox:
impl:secure: launcher1. py: Add support for template jobs When the generator job is a resource job, the trusted launcher will now recreate
all the possible template jobs that use it.
That way generated jobs requiring root privileges can be created from templates
and still use the plainbox trusted launcher.
The command line options are untouched. - 3531. By Sylvain Pineau
-
providers:
checkbox: disks.txt. in: staging/disk now use the device resource This new template job now use the udevadm parser to solve two problems:
- all the device parsing logic is delegated to the resource, not the template
filter (i.e. removal of ram and loop devices)
- the udev resource is not the default udevadm parser and thus not part of
default whitelists, causing https://bugs.launchpad .net/plainbox/ +bug/1361071
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sylvain Pineau (sylvain-pineau) wrote : | # |
Fixed ctrl and launcher unit tests
Preview Diff
1 | === modified file 'checkbox-support/checkbox_support/parsers/udevadm.py' |
2 | --- checkbox-support/checkbox_support/parsers/udevadm.py 2014-11-19 12:19:27 +0000 |
3 | +++ checkbox-support/checkbox_support/parsers/udevadm.py 2015-01-09 21:49:01 +0000 |
4 | @@ -90,6 +90,7 @@ |
5 | class UdevadmDevice(object): |
6 | __slots__ = ( |
7 | "_environment", |
8 | + "_name", |
9 | "_bits", |
10 | "_stack", |
11 | "_bus", |
12 | @@ -99,8 +100,9 @@ |
13 | "_vendor", |
14 | "_vendor_id",) |
15 | |
16 | - def __init__(self, environment, bits=None, stack=[]): |
17 | + def __init__(self, environment, name, bits=None, stack=[]): |
18 | self._environment = environment |
19 | + self._name = name |
20 | self._bits = bits |
21 | self._stack = stack |
22 | self._bus = None |
23 | @@ -118,6 +120,11 @@ |
24 | self.product)) |
25 | |
26 | @property |
27 | + def name(self): |
28 | + if self._name is not None: |
29 | + return self._name |
30 | + |
31 | + @property |
32 | def bus(self): |
33 | if self._bus is not None: |
34 | return self._bus |
35 | @@ -639,7 +646,7 @@ |
36 | def as_json(self): |
37 | attributes = ("path", "bus", "category", "driver", "product_id", |
38 | "vendor_id", "subproduct_id", "subvendor_id", "product", |
39 | - "vendor", "interface",) |
40 | + "vendor", "interface", "name") |
41 | |
42 | return {a: getattr(self, a) for a in attributes if getattr(self, a)} |
43 | |
44 | @@ -715,8 +722,9 @@ |
45 | if not record: |
46 | continue |
47 | |
48 | - # Determine path and environment |
49 | + # Determine path, name and environment |
50 | path = None |
51 | + name = None |
52 | element = None |
53 | environment = {} |
54 | for line in record.splitlines(): |
55 | @@ -732,6 +740,8 @@ |
56 | |
57 | if key == "P": |
58 | path = value |
59 | + elif key == "N": |
60 | + name = value |
61 | elif key == "E": |
62 | key_match = multi_pattern.match(value) |
63 | if not key_match: |
64 | @@ -749,7 +759,8 @@ |
65 | # Set default DEVPATH |
66 | environment.setdefault("DEVPATH", path) |
67 | |
68 | - device = self.device_factory(environment, self.bits, list(stack)) |
69 | + device = self.device_factory( |
70 | + environment, name, self.bits, list(stack)) |
71 | if not self._ignoreDevice(device): |
72 | if device._raw_path in self.devices: |
73 | if self.devices[device._raw_path].category == 'CARDREADER': |
74 | |
75 | === modified file 'plainbox/plainbox/impl/ctrl.py' |
76 | --- plainbox/plainbox/impl/ctrl.py 2015-01-07 14:55:36 +0000 |
77 | +++ plainbox/plainbox/impl/ctrl.py 2015-01-09 21:49:01 +0000 |
78 | @@ -954,7 +954,7 @@ |
79 | cmd += ['--generator', job_state.via_job.checksum] |
80 | parent_env = self.get_differential_execution_environment( |
81 | # FIXME: job_state is from an unrelated job :/ |
82 | - job.origin.source.job, job_state, config, session_dir, |
83 | + job_state.via_job, job_state, config, session_dir, |
84 | nest_dir) |
85 | for key, value in sorted(parent_env.items()): |
86 | cmd += ['-G', '{}={}'.format(key, value)] |
87 | |
88 | === modified file 'plainbox/plainbox/impl/secure/launcher1.py' |
89 | --- plainbox/plainbox/impl/secure/launcher1.py 2014-07-22 13:58:51 +0000 |
90 | +++ plainbox/plainbox/impl/secure/launcher1.py 2015-01-09 21:49:01 +0000 |
91 | @@ -30,6 +30,8 @@ |
92 | |
93 | from plainbox.i18n import gettext as _ |
94 | from plainbox.impl.job import JobDefinition |
95 | +from plainbox.impl.resource import Resource |
96 | +from plainbox.impl.unit.template import TemplateUnit |
97 | from plainbox.impl.secure.origin import JobOutputTextSource |
98 | from plainbox.impl.secure.providers.v1 import all_providers |
99 | from plainbox.impl.secure.rfc822 import load_rfc822_records, RFC822SyntaxError |
100 | @@ -92,16 +94,16 @@ |
101 | cmd = [job.shell, '-c', job.command] |
102 | return subprocess.call(cmd, env=self.modify_execution_environment(env)) |
103 | |
104 | - def run_local_job(self, checksum, env): |
105 | + def run_generator_job(self, checksum, env): |
106 | """ |
107 | - Run a job with and interpret the stdout as a job definition. |
108 | + Run a job with and process the stdout to get a job definition. |
109 | |
110 | :param checksum: |
111 | The checksum of the job to execute |
112 | :param env: |
113 | Environment to execute the job in. |
114 | :returns: |
115 | - A list of job definitions that were parsed out of the output. |
116 | + A list of job definitions that were processed from the output. |
117 | :raises LookupError: |
118 | If the checksum does not match any known job |
119 | """ |
120 | @@ -116,11 +118,26 @@ |
121 | record_list = load_rfc822_records(output, source=source) |
122 | except RFC822SyntaxError as exc: |
123 | logging.error( |
124 | - _("Syntax error in job generated from %s: %s"), job, exc) |
125 | + _("Syntax error in record generated from %s: %s"), job, exc) |
126 | else: |
127 | - for record in record_list: |
128 | - job = JobDefinition.from_rfc822_record(record) |
129 | - job_list.append(job) |
130 | + if job.plugin == 'local': |
131 | + for record in record_list: |
132 | + job = JobDefinition.from_rfc822_record(record) |
133 | + job_list.append(job) |
134 | + elif job.plugin == 'resource': |
135 | + resource_list = [] |
136 | + for record in record_list: |
137 | + resource = Resource(record.data) |
138 | + resource_list.append(resource) |
139 | + for plugin in all_providers.get_all_plugins(): |
140 | + for u in plugin.plugin_object.get_units()[0]: |
141 | + if ( |
142 | + isinstance(u, TemplateUnit) and |
143 | + u.resource_id == job.id |
144 | + ): |
145 | + logging.info(_("Instantiating unit: %s"), u) |
146 | + for new_unit in u.instantiate_all(resource_list): |
147 | + job_list.append(new_unit) |
148 | return job_list |
149 | |
150 | |
151 | @@ -252,7 +269,7 @@ |
152 | # Run the local job and feed the result back to the launcher |
153 | if ns.generator: |
154 | try: |
155 | - generated_job_list = launcher.run_local_job( |
156 | + generated_job_list = launcher.run_generator_job( |
157 | ns.generator, ns.generator_env) |
158 | launcher.add_job_list(generated_job_list) |
159 | except LookupError as exc: |
160 | |
161 | === modified file 'plainbox/plainbox/impl/secure/test_launcher1.py' |
162 | --- plainbox/plainbox/impl/secure/test_launcher1.py 2014-09-13 11:37:17 +0000 |
163 | +++ plainbox/plainbox/impl/secure/test_launcher1.py 2015-01-09 21:49:01 +0000 |
164 | @@ -117,7 +117,7 @@ |
165 | def test_run_local_job(self, mock_check_output, mock_load_rfc822_records, |
166 | mock_from_rfc822_record): |
167 | # Create a mock job and add it to the launcher |
168 | - job = mock.Mock(spec=JobDefinition, name='job') |
169 | + job = mock.Mock(spec=JobDefinition, name='job', plugin='local') |
170 | self.launcher.add_job_list([job]) |
171 | # Create two mock rfc822 records |
172 | record1 = mock.Mock(spec=RFC822Record, name='record') |
173 | @@ -125,7 +125,7 @@ |
174 | # Ensure that load_rfc822_records() returns some mocked records |
175 | mock_load_rfc822_records.return_value = [record1, record2] |
176 | # Run the tested method |
177 | - job_list = self.launcher.run_local_job(job.checksum, None) |
178 | + job_list = self.launcher.run_generator_job(job.checksum, None) |
179 | # Ensure that we run the job command via job.shell |
180 | mock_check_output.assert_called_with( |
181 | [job.shell, '-c', job.command], env={}, universal_newlines=True) |
182 | @@ -271,7 +271,7 @@ |
183 | with TestIO(combined=True) as io: |
184 | retval = main(['--target=1234', '--generator=5678']) |
185 | # Ensure that the local job command was invoked |
186 | - mock_launcher().run_local_job.assert_called_with(local_job.checksum, None) |
187 | + mock_launcher().run_generator_job.assert_called_with(local_job.checksum, None) |
188 | # Ensure that the target job command was invoked |
189 | mock_launcher().run_shell_from_job.assert_called_with( |
190 | target_job.checksum, None) |
191 | |
192 | === modified file 'plainbox/plainbox/impl/test_ctrl.py' |
193 | --- plainbox/plainbox/impl/test_ctrl.py 2015-01-07 14:55:36 +0000 |
194 | +++ plainbox/plainbox/impl/test_ctrl.py 2015-01-09 21:49:01 +0000 |
195 | @@ -792,7 +792,7 @@ |
196 | verify that we run plainbox-trusted-launcher-1 as the desired user |
197 | """ |
198 | self.job.get_environ_settings.return_value = [] |
199 | - self.job.origin.source.job = mock.Mock( |
200 | + self.job_state.via_job = mock.Mock( |
201 | name='generator_job', |
202 | spec=JobDefinition, |
203 | provider=mock.Mock( |
204 | @@ -803,7 +803,7 @@ |
205 | units_dir="units_dir-generator", |
206 | CHECKBOX_SHARE='CHECKBOX_SHARE-generator')) |
207 | # Mock the default flags (empty set) |
208 | - self.job.origin.source.job.get_flag_set.return_value = frozenset() |
209 | + self.job_state.via_job.get_flag_set.return_value = frozenset() |
210 | PATH = os.pathsep.join([self.NEST_DIR, 'vanilla-path']) |
211 | expected = [ |
212 | 'pkexec', '--user', self.job.user, |
213 | |
214 | === modified file 'providers/plainbox-provider-checkbox/jobs/disk.txt.in' |
215 | --- providers/plainbox-provider-checkbox/jobs/disk.txt.in 2014-09-09 16:02:53 +0000 |
216 | +++ providers/plainbox-provider-checkbox/jobs/disk.txt.in 2015-01-09 21:49:01 +0000 |
217 | @@ -6,16 +6,16 @@ |
218 | |
219 | unit: template |
220 | template-unit: job |
221 | -template-imports: from 2013.com.canonical.certification import staging/udev as udev |
222 | -template-resource: udev |
223 | -template-filter: udev.attr_DEVTYPE == 'disk' and 'ram' not in udev.name and 'loop' not in udev.name |
224 | +template-imports: from 2013.com.canonical.certification import device |
225 | +template-resource: device |
226 | +template-filter: device.category == 'DISK' |
227 | plugin: shell |
228 | id: staging/disk/stats_{name} |
229 | requires: |
230 | block_device.{name}_state != 'removable' |
231 | user: root |
232 | command: disk_stats_test {name} |
233 | -_summary: Disk statistics for {attr_DEVNAME} |
234 | +_summary: Disk statistics for /dev/{name} |
235 | _description: |
236 | This test checks disk stats, generates some activity and rechecks stats to |
237 | verify they've changed. It also verifies that disks appear in the various |
238 | @@ -23,11 +23,9 @@ |
239 | . |
240 | This test will inspect the following disk: |
241 | . |
242 | - product vendor: {attr_ID_VENDOR} |
243 | - product name: {attr_ID_MODEL} |
244 | - serial number: {attr_ID_SERIAL_SHORT} |
245 | + product name: {product} |
246 | sysfs path: {path} |
247 | - device node path: {attr_DEVNAME} |
248 | + device node path: /dev/{name} |
249 | |
250 | plugin: local |
251 | _summary: Check stats changes for each disk |
252 | |
253 | === modified file 'providers/plainbox-provider-resource-generic/bin/udev_resource' |
254 | --- providers/plainbox-provider-resource-generic/bin/udev_resource 2014-08-08 16:35:49 +0000 |
255 | +++ providers/plainbox-provider-resource-generic/bin/udev_resource 2015-01-09 21:49:01 +0000 |
256 | @@ -27,7 +27,7 @@ |
257 | |
258 | class UdevResult: |
259 | |
260 | - attributes = ("path", "bus", "category", "driver", "product_id", |
261 | + attributes = ("path", "name", "bus", "category", "driver", "product_id", |
262 | "vendor_id", "subproduct_id", "subvendor_id", "product", |
263 | "vendor", "interface",) |
264 |
Not sure if needs fixing or not. Have a look at the comments below please