Merge lp:~mwhudson/lava-scheduler/create-private-job into lp:lava-scheduler

Proposed by Michael Hudson-Doyle
Status: Superseded
Proposed branch: lp:~mwhudson/lava-scheduler/create-private-job
Merge into: lp:lava-scheduler
Diff against target: 433 lines (+148/-63)
4 files modified
lava_scheduler_app/models.py (+30/-11)
lava_scheduler_app/tests.py (+112/-34)
lava_scheduler_daemon/dbjobsource.py (+4/-18)
setup.py (+2/-0)
To merge this branch: bzr merge lp:~mwhudson/lava-scheduler/create-private-job
Reviewer Review Type Date Requested Status
Zygmunt Krynicki (community) Approve
Review via email: mp+96703@code.launchpad.net

Description of the change

This branch enables the creation of private testjobs. It does so by looking for the bundle stream named by the submit_results action and copying the access data over to the new job. Because this means poking around in the JSON way more than before, I also finally implemented validation of the json at submit_job time -- this branch depends on https://code.launchpad.net/~mwhudson/lava-dispatcher/more-validation/+merge/96507 -- which should be a useful usability improvement in its own right anyway. It did mean that many tests needed to be built up to create more realistic jobs though.

So, what do you think? I think I more or less like this approach -- it avoids repetition of access information and the potential for inconsistency there. I do find grubbing through the actions for the submit_results action to be a bit strange still, both for the UX and the implementation -- I think I would be happier if the bundle_stream name and (ideally, optional, at least for jobs that run through the scheduler) xml-rpc endpoint were top level properties of the job description. But that can wait for another day, perhaps.

Cheers,
mwh

To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

I think you forgot the prerequisite branch - this makes reading it harder.

60 + try:
61 + bundle_stream = BundleStream.objects.get(pathname=stream)
62 + except BundleStream.DoesNotExist:
63 + raise ValueError("stream %s not found" % stream)

429 + "lava-dashboard",

So it's official (netcraft confirms it). The scheduler depends on the dashboard now. Can we please look at how to merge them? This is a bigger topic. I'd like to get rid of lots of things from the dashboard proper. Perhaps we should move the base models to lava-server (tree-wise) application. lava.silo or lava.testdata or something like that.

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Otherwise this looks good :-) +1

review: Approve

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lava_scheduler_app/models.py'
--- lava_scheduler_app/models.py 2012-03-07 01:56:57 +0000
+++ lava_scheduler_app/models.py 2012-03-09 04:16:33 +0000
@@ -3,16 +3,17 @@
3from django.contrib.auth.models import User3from django.contrib.auth.models import User
4from django.core.exceptions import ValidationError4from django.core.exceptions import ValidationError
5from django.db import models5from django.db import models
6from django.db.models.query import QuerySet
7from django.utils.translation import ugettext as _6from django.utils.translation import ugettext as _
87
9
10from django_restricted_resource.managers import RestrictedResourceManager
11from django_restricted_resource.models import RestrictedResource8from django_restricted_resource.models import RestrictedResource
12from django_restricted_resource.utils import filter_bogus_users9
10from dashboard_app.models import BundleStream
11
12from lava_dispatcher.job import validate_job_data
1313
14from linaro_django_xmlrpc.models import AuthToken14from linaro_django_xmlrpc.models import AuthToken
1515
16
16class JSONDataError(ValueError):17class JSONDataError(ValueError):
17 """Error raised when JSON is syntactically valid but ill-formed."""18 """Error raised when JSON is syntactically valid but ill-formed."""
1819
@@ -30,12 +31,9 @@
30def validate_job_json(data):31def validate_job_json(data):
31 try:32 try:
32 ob = simplejson.loads(data)33 ob = simplejson.loads(data)
34 validate_job_data(ob)
33 except ValueError, e:35 except ValueError, e:
34 raise ValidationError(str(e))36 raise ValidationError(str(e))
35 else:
36 if not isinstance(ob, dict):
37 raise ValidationError(
38 "job json must be an object, not %s" % type(ob).__name__)
3937
4038
41class DeviceType(models.Model):39class DeviceType(models.Model):
@@ -266,6 +264,7 @@
266 @classmethod264 @classmethod
267 def from_json_and_user(cls, json_data, user):265 def from_json_and_user(cls, json_data, user):
268 job_data = simplejson.loads(json_data)266 job_data = simplejson.loads(json_data)
267 validate_job_data(job_data)
269 if 'target' in job_data:268 if 'target' in job_data:
270 target = Device.objects.get(hostname=job_data['target'])269 target = Device.objects.get(hostname=job_data['target'])
271 device_type = None270 device_type = None
@@ -279,6 +278,25 @@
279278
280 is_check = job_data.get('health_check', False)279 is_check = job_data.get('health_check', False)
281280
281 submitter = user
282 group = None
283 is_public = True
284
285 for action in job_data['actions']:
286 if not action['command'].startswith('submit_results'):
287 continue
288 stream = action['parameters']['stream']
289 try:
290 bundle_stream = BundleStream.objects.get(pathname=stream)
291 except BundleStream.DoesNotExist:
292 raise ValueError("stream %s not found" % stream)
293 if not bundle_stream.is_owned_by(submitter):
294 raise ValueError(
295 "you cannot submit to the stream %s" % stream)
296 user, group, is_public = (bundle_stream.user,
297 bundle_stream.group,
298 bundle_stream.is_public)
299
282 tags = []300 tags = []
283 for tag_name in job_data.get('device_tags', []):301 for tag_name in job_data.get('device_tags', []):
284 try:302 try:
@@ -286,9 +304,10 @@
286 except Tag.DoesNotExist:304 except Tag.DoesNotExist:
287 raise JSONDataError("tag %r does not exist" % tag_name)305 raise JSONDataError("tag %r does not exist" % tag_name)
288 job = TestJob(306 job = TestJob(
289 definition=json_data, submitter=user, requested_device=target,307 definition=json_data, submitter=submitter,
290 requested_device_type=device_type, description=job_name,308 requested_device=target, requested_device_type=device_type,
291 health_check=is_check, user=user)309 description=job_name, health_check=is_check, user=user,
310 group=group, is_public=is_public)
292 job.save()311 job.save()
293 for tag in tags:312 for tag in tags:
294 job.tags.add(tag)313 job.tags.add(tag)
295314
=== modified file 'lava_scheduler_app/tests.py'
--- lava_scheduler_app/tests.py 2012-02-28 03:53:16 +0000
+++ lava_scheduler_app/tests.py 2012-03-09 04:16:33 +0000
@@ -3,7 +3,9 @@
3import json3import json
4import xmlrpclib4import xmlrpclib
55
6from django.contrib.auth.models import Permission, User6from dashboard_app.models import BundleStream
7
8from django.contrib.auth.models import Group, Permission, User
7from django.test import TransactionTestCase9from django.test import TransactionTestCase
8from django.test.client import Client10from django.test.client import Client
911
@@ -84,9 +86,22 @@
84 device.save()86 device.save()
85 return device87 return device
8688
89 def make_job_data(self, actions=[], **kw):
90 data = {'actions': actions, 'timeout': 1}
91 data.update(kw)
92 if 'target' not in data and 'device_type' not in data:
93 if DeviceType.objects.all():
94 data['device_type'] = DeviceType.objects.all()[0].name
95 else:
96 data['device_type'] = self.ensure_device_type().name
97 return data
98
99 def make_job_json(self, **kw):
100 return json.dumps(self.make_job_data(**kw))
101
87 def make_testjob(self, definition=None, submitter=None, **kwargs):102 def make_testjob(self, definition=None, submitter=None, **kwargs):
88 if definition is None:103 if definition is None:
89 definition = json.dumps({})104 definition = self.make_job_json()
90 if submitter is None:105 if submitter is None:
91 submitter = self.make_user()106 submitter = self.make_user()
92 if 'user' not in kwargs:107 if 'user' not in kwargs:
@@ -107,70 +122,68 @@
107class TestTestJob(TestCaseWithFactory):122class TestTestJob(TestCaseWithFactory):
108123
109 def test_from_json_and_user_sets_definition(self):124 def test_from_json_and_user_sets_definition(self):
110 self.factory.ensure_device_type(name='panda')125 definition = self.factory.make_job_json()
111 definition = json.dumps({'device_type':'panda'})
112 job = TestJob.from_json_and_user(definition, self.factory.make_user())126 job = TestJob.from_json_and_user(definition, self.factory.make_user())
113 self.assertEqual(definition, job.definition)127 self.assertEqual(definition, job.definition)
114128
115 def test_from_json_and_user_sets_submitter(self):129 def test_from_json_and_user_sets_submitter(self):
116 self.factory.ensure_device_type(name='panda')
117 user = self.factory.make_user()130 user = self.factory.make_user()
118 job = TestJob.from_json_and_user(131 job = TestJob.from_json_and_user(
119 json.dumps({'device_type':'panda'}), user)132 self.factory.make_job_json(), user)
120 self.assertEqual(user, job.submitter)133 self.assertEqual(user, job.submitter)
121134
122 def test_from_json_and_user_sets_device_type(self):135 def test_from_json_and_user_sets_device_type(self):
123 panda_type = self.factory.ensure_device_type(name='panda')136 panda_type = self.factory.ensure_device_type(name='panda')
124 job = TestJob.from_json_and_user(137 job = TestJob.from_json_and_user(
125 json.dumps({'device_type':'panda'}), self.factory.make_user())138 self.factory.make_job_json(device_type='panda'),
139 self.factory.make_user())
126 self.assertEqual(panda_type, job.requested_device_type)140 self.assertEqual(panda_type, job.requested_device_type)
127141
128 def test_from_json_and_user_sets_target(self):142 def test_from_json_and_user_sets_target(self):
129 panda_board = self.factory.make_device(hostname='panda01')143 panda_board = self.factory.make_device(hostname='panda01')
130 job = TestJob.from_json_and_user(144 job = TestJob.from_json_and_user(
131 json.dumps({'target':'panda01'}), self.factory.make_user())145 self.factory.make_job_json(target='panda01'),
146 self.factory.make_user())
132 self.assertEqual(panda_board, job.requested_device)147 self.assertEqual(panda_board, job.requested_device)
133148
134 def test_from_json_and_user_does_not_set_device_type_from_target(self):149 def test_from_json_and_user_does_not_set_device_type_from_target(self):
135 panda_type = self.factory.ensure_device_type(name='panda')150 panda_type = self.factory.ensure_device_type(name='panda')
136 self.factory.make_device(device_type=panda_type, hostname='panda01')151 self.factory.make_device(device_type=panda_type, hostname='panda01')
137 job = TestJob.from_json_and_user(152 job = TestJob.from_json_and_user(
138 json.dumps({'target':'panda01'}), self.factory.make_user())153 self.factory.make_job_json(target='panda01'),
154 self.factory.make_user())
139 self.assertEqual(None, job.requested_device_type)155 self.assertEqual(None, job.requested_device_type)
140156
141 def test_from_json_and_user_sets_date_submitted(self):157 def test_from_json_and_user_sets_date_submitted(self):
142 self.factory.ensure_device_type(name='panda')
143 before = datetime.datetime.now()158 before = datetime.datetime.now()
144 job = TestJob.from_json_and_user(159 job = TestJob.from_json_and_user(
145 json.dumps({'device_type':'panda'}), self.factory.make_user())160 self.factory.make_job_json(),
161 self.factory.make_user())
146 after = datetime.datetime.now()162 after = datetime.datetime.now()
147 self.assertTrue(before < job.submit_time < after)163 self.assertTrue(before < job.submit_time < after)
148164
149 def test_from_json_and_user_sets_status_to_SUBMITTED(self):165 def test_from_json_and_user_sets_status_to_SUBMITTED(self):
150 self.factory.ensure_device_type(name='panda')
151 job = TestJob.from_json_and_user(166 job = TestJob.from_json_and_user(
152 json.dumps({'device_type':'panda'}), self.factory.make_user())167 self.factory.make_job_json(),
168 self.factory.make_user())
153 self.assertEqual(job.status, TestJob.SUBMITTED)169 self.assertEqual(job.status, TestJob.SUBMITTED)
154170
155 def test_from_json_and_user_sets_no_tags_if_no_tags(self):171 def test_from_json_and_user_sets_no_tags_if_no_tags(self):
156 self.factory.ensure_device_type(name='panda')
157 job = TestJob.from_json_and_user(172 job = TestJob.from_json_and_user(
158 json.dumps({'device_type':'panda', 'device_tags':[]}),173 self.factory.make_job_json(device_tags=[]),
159 self.factory.make_user())174 self.factory.make_user())
160 self.assertEqual(set(job.tags.all()), set([]))175 self.assertEqual(set(job.tags.all()), set([]))
161176
162 def test_from_json_and_user_errors_on_unknown_tags(self):177 def test_from_json_and_user_errors_on_unknown_tags(self):
163 self.factory.ensure_device_type(name='panda')
164 self.assertRaises(178 self.assertRaises(
165 JSONDataError, TestJob.from_json_and_user,179 JSONDataError, TestJob.from_json_and_user,
166 json.dumps({'device_type':'panda', 'device_tags':['unknown']}),180 self.factory.make_job_json(device_tags=['unknown']),
167 self.factory.make_user())181 self.factory.make_user())
168182
169 def test_from_json_and_user_sets_tag_from_device_tags(self):183 def test_from_json_and_user_sets_tag_from_device_tags(self):
170 self.factory.ensure_device_type(name='panda')
171 self.factory.ensure_tag('tag')184 self.factory.ensure_tag('tag')
172 job = TestJob.from_json_and_user(185 job = TestJob.from_json_and_user(
173 json.dumps({'device_type':'panda', 'device_tags':['tag']}),186 self.factory.make_job_json(device_tags=['tag']),
174 self.factory.make_user())187 self.factory.make_user())
175 self.assertEqual(188 self.assertEqual(
176 set(tag.name for tag in job.tags.all()), set(['tag']))189 set(tag.name for tag in job.tags.all()), set(['tag']))
@@ -180,7 +193,7 @@
180 self.factory.ensure_tag('tag1')193 self.factory.ensure_tag('tag1')
181 self.factory.ensure_tag('tag2')194 self.factory.ensure_tag('tag2')
182 job = TestJob.from_json_and_user(195 job = TestJob.from_json_and_user(
183 json.dumps({'device_type':'panda', 'device_tags':['tag1', 'tag2']}),196 self.factory.make_job_json(device_tags=['tag1', 'tag2']),
184 self.factory.make_user())197 self.factory.make_user())
185 self.assertEqual(198 self.assertEqual(
186 set(tag.name for tag in job.tags.all()), set(['tag1', 'tag2']))199 set(tag.name for tag in job.tags.all()), set(['tag1', 'tag2']))
@@ -189,15 +202,75 @@
189 self.factory.ensure_device_type(name='panda')202 self.factory.ensure_device_type(name='panda')
190 self.factory.ensure_tag('tag')203 self.factory.ensure_tag('tag')
191 job1 = TestJob.from_json_and_user(204 job1 = TestJob.from_json_and_user(
192 json.dumps({'device_type':'panda', 'device_tags':['tag']}),205 self.factory.make_job_json(device_tags=['tag']),
193 self.factory.make_user())206 self.factory.make_user())
194 job2 = TestJob.from_json_and_user(207 job2 = TestJob.from_json_and_user(
195 json.dumps({'device_type':'panda', 'device_tags':['tag']}),208 self.factory.make_job_json(device_tags=['tag']),
196 self.factory.make_user())209 self.factory.make_user())
197 self.assertEqual(210 self.assertEqual(
198 set(tag.pk for tag in job1.tags.all()),211 set(tag.pk for tag in job1.tags.all()),
199 set(tag.pk for tag in job2.tags.all()))212 set(tag.pk for tag in job2.tags.all()))
200213
214 def test_from_json_and_user_rejects_invalid_json(self):
215 self.assertRaises(
216 ValueError, TestJob.from_json_and_user, '{',
217 self.factory.make_user())
218
219 def test_from_json_and_user_rejects_invalid_job(self):
220 # job data must have the 'actions' and 'timeout' properties, so this
221 # will be rejected.
222 self.assertRaises(
223 ValueError, TestJob.from_json_and_user, '{}',
224 self.factory.make_user())
225
226 def make_job_json_for_stream_name(self, stream_name):
227 return self.factory.make_job_json(
228 actions=[
229 {
230 'command':'submit_results',
231 'parameters': {
232 'server': '...',
233 'stream': stream_name,
234 }
235 }
236 ])
237
238 def test_from_json_and_user_sets_group_from_bundlestream(self):
239 group = Group.objects.create(name='group')
240 user = self.factory.make_user()
241 user.groups.add(group)
242 b = BundleStream.objects.create(
243 group=group, slug='blah', is_public=True)
244 b.save()
245 j = self.make_job_json_for_stream_name(b.pathname)
246 job = TestJob.from_json_and_user(j, user)
247 self.assertEqual(group, job.group)
248
249 def test_from_json_and_user_sets_is_public_from_bundlestream(self):
250 group = Group.objects.create(name='group')
251 user = self.factory.make_user()
252 user.groups.add(group)
253 b = BundleStream.objects.create(
254 group=group, slug='blah', is_public=False)
255 b.save()
256 j = self.make_job_json_for_stream_name(b.pathname)
257 job = TestJob.from_json_and_user(j, user)
258 self.assertEqual(False, job.is_public)
259
260 def test_from_json_and_user_rejects_missing_bundlestream(self):
261 user = self.factory.make_user()
262 j = self.make_job_json_for_stream_name('no such stream')
263 self.assertRaises(ValueError, TestJob.from_json_and_user, j, user)
264
265 def test_from_json_and_user_rejects_inaccessible_bundlestream(self):
266 stream_user = self.factory.make_user()
267 job_user = self.factory.make_user()
268 b = BundleStream.objects.create(
269 user=stream_user, slug='blah', is_public=True)
270 b.save()
271 j = self.make_job_json_for_stream_name(b.pathname)
272 self.assertRaises(ValueError, TestJob.from_json_and_user, j, job_user)
273
201274
202class TestSchedulerAPI(TestCaseWithFactory):275class TestSchedulerAPI(TestCaseWithFactory):
203276
@@ -231,8 +304,7 @@
231 Permission.objects.get(codename='add_testjob'))304 Permission.objects.get(codename='add_testjob'))
232 user.save()305 user.save()
233 server = self.server_proxy('test', 'test')306 server = self.server_proxy('test', 'test')
234 self.factory.ensure_device_type(name='panda')307 definition = self.factory.make_job_json()
235 definition = json.dumps({'device_type':'panda'})
236 job_id = server.scheduler.submit_job(definition)308 job_id = server.scheduler.submit_job(definition)
237 job = TestJob.objects.get(id=job_id)309 job = TestJob.objects.get(id=job_id)
238 self.assertEqual(definition, job.definition)310 self.assertEqual(definition, job.definition)
@@ -296,14 +368,19 @@
296368
297 def test_getJobForBoard_returns_json(self):369 def test_getJobForBoard_returns_json(self):
298 device = self.factory.make_device(hostname='panda01')370 device = self.factory.make_device(hostname='panda01')
299 definition = {'foo': 'bar', 'target': 'panda01'}371 definition = self.factory.make_job_data(target='panda01')
300 self.factory.make_testjob(372 self.factory.make_testjob(
301 requested_device=device, definition=json.dumps(definition))373 requested_device=device, definition=json.dumps(definition))
302 self.assertEqual(374 self.assertEqual(
303 definition, self.source.getJobForBoard('panda01'))375 definition, self.source.getJobForBoard('panda01'))
304376
305 health_job = json.dumps({'health_check': True})377 @property
306 ordinary_job = json.dumps({'health_check': False})378 def health_job(self):
379 return self.factory.make_job_json(health_check=True)
380
381 @property
382 def ordinary_job(self):
383 return self.factory.make_job_json(health_check=False)
307384
308 def assertHealthJobAssigned(self, device):385 def assertHealthJobAssigned(self, device):
309 job_data = self.source.getJobForBoard(device.hostname)386 job_data = self.source.getJobForBoard(device.hostname)
@@ -371,7 +448,7 @@
371 def test_getJobForBoard_considers_device_type(self):448 def test_getJobForBoard_considers_device_type(self):
372 panda_type = self.factory.ensure_device_type(name='panda')449 panda_type = self.factory.ensure_device_type(name='panda')
373 self.factory.make_device(hostname='panda01', device_type=panda_type)450 self.factory.make_device(hostname='panda01', device_type=panda_type)
374 definition = {'foo': 'bar'}451 definition = self.factory.make_job_data()
375 self.factory.make_testjob(452 self.factory.make_testjob(
376 requested_device_type=panda_type,453 requested_device_type=panda_type,
377 definition=json.dumps(definition))454 definition=json.dumps(definition))
@@ -383,8 +460,8 @@
383 panda_type = self.factory.ensure_device_type(name='panda')460 panda_type = self.factory.ensure_device_type(name='panda')
384 panda01 = self.factory.make_device(461 panda01 = self.factory.make_device(
385 hostname='panda01', device_type=panda_type)462 hostname='panda01', device_type=panda_type)
386 first_definition = {'foo': 'bar', 'target': 'panda01'}463 first_definition = self.factory.make_job_data(foo='bar', target='panda01')
387 second_definition = {'foo': 'baz', 'target': 'panda01'}464 second_definition = self.factory.make_job_data(foo='baz', target='panda01')
388 self.factory.make_testjob(465 self.factory.make_testjob(
389 requested_device=panda01, definition=json.dumps(first_definition),466 requested_device=panda01, definition=json.dumps(first_definition),
390 submit_time=datetime.datetime.now() - datetime.timedelta(days=1))467 submit_time=datetime.datetime.now() - datetime.timedelta(days=1))
@@ -399,12 +476,13 @@
399 panda_type = self.factory.ensure_device_type(name='panda')476 panda_type = self.factory.ensure_device_type(name='panda')
400 panda01 = self.factory.make_device(477 panda01 = self.factory.make_device(
401 hostname='panda01', device_type=panda_type)478 hostname='panda01', device_type=panda_type)
402 type_definition = {'foo': 'bar'}479 type_definition = self.factory.make_job_data()
403 self.factory.make_testjob(480 self.factory.make_testjob(
404 requested_device_type=panda_type,481 requested_device_type=panda_type,
405 definition=json.dumps(type_definition),482 definition=json.dumps(type_definition),
406 submit_time=datetime.datetime.now() - datetime.timedelta(days=1))483 submit_time=datetime.datetime.now() - datetime.timedelta(days=1))
407 device_definition = {'foo': 'baz', 'target': 'panda01'}484 device_definition = self.factory.make_job_data(
485 foo='baz', target='panda01')
408 self.factory.make_testjob(486 self.factory.make_testjob(
409 requested_device=panda01,487 requested_device=panda01,
410 definition=json.dumps(device_definition))488 definition=json.dumps(device_definition))
@@ -417,7 +495,7 @@
417 panda01 = self.factory.make_device(495 panda01 = self.factory.make_device(
418 hostname='panda01', device_type=panda_type)496 hostname='panda01', device_type=panda_type)
419 self.factory.make_device(hostname='panda02', device_type=panda_type)497 self.factory.make_device(hostname='panda02', device_type=panda_type)
420 definition = {'foo': 'bar', 'target': 'panda01'}498 definition = self.factory.make_job_data(foo='bar', target='panda01')
421 self.factory.make_testjob(499 self.factory.make_testjob(
422 requested_device=panda01,500 requested_device=panda01,
423 definition=json.dumps(definition))501 definition=json.dumps(definition))
@@ -515,7 +593,7 @@
515 def test_getJobForBoard_inserts_target_into_json(self):593 def test_getJobForBoard_inserts_target_into_json(self):
516 panda_type = self.factory.ensure_device_type(name='panda')594 panda_type = self.factory.ensure_device_type(name='panda')
517 self.factory.make_device(hostname='panda01', device_type=panda_type)595 self.factory.make_device(hostname='panda01', device_type=panda_type)
518 definition = {'foo': 'bar'}596 definition = self.factory.make_job_data(device_type='panda')
519 self.factory.make_testjob(597 self.factory.make_testjob(
520 requested_device_type=panda_type,598 requested_device_type=panda_type,
521 definition=json.dumps(definition))599 definition=json.dumps(definition))
522600
=== modified file 'lava_scheduler_daemon/dbjobsource.py'
--- lava_scheduler_daemon/dbjobsource.py 2012-03-07 01:59:51 +0000
+++ lava_scheduler_daemon/dbjobsource.py 2012-03-09 04:16:33 +0000
@@ -88,25 +88,11 @@
88 def _get_json_data(self, job):88 def _get_json_data(self, job):
89 json_data = json.loads(job.definition)89 json_data = json.loads(job.definition)
90 json_data['target'] = job.actual_device.hostname90 json_data['target'] = job.actual_device.hostname
91 # The rather extreme paranoia in what follows could be much reduced if91 for action in json_data['actions']:
92 # we thoroughly validated job data in submit_job. We don't (yet?)92 if not action['command'].startswith('submit_results'):
93 # and there is no sane way to report errors at this stage, so,93 continue
94 # paranoia (the dispatcher will choke on bogus input in a more94 params = action['parameters']
95 # informative way).
96 if 'actions' not in json_data:
97 return json_data
98 actions = json_data['actions']
99 for action in actions:
100 if not isinstance(action, dict):
101 continue
102 if action.get('command') != 'submit_results':
103 continue
104 params = action.get('parameters')
105 if not isinstance(params, dict):
106 continue
107 params['token'] = job.submit_token.secret95 params['token'] = job.submit_token.secret
108 if not 'server' in params or not isinstance(params['server'], unicode):
109 continue
110 parsed = urlparse.urlsplit(params['server'])96 parsed = urlparse.urlsplit(params['server'])
111 netloc = job.submitter.username + '@' + parsed.hostname97 netloc = job.submitter.username + '@' + parsed.hostname
112 parsed = list(parsed)98 parsed = list(parsed)
11399
=== modified file 'setup.py'
--- setup.py 2012-03-07 03:49:20 +0000
+++ setup.py 2012-03-09 04:16:33 +0000
@@ -35,6 +35,8 @@
35 install_requires=[35 install_requires=[
36 "django-restricted-resource",36 "django-restricted-resource",
37 "django-tables2 >= 0.9.4",37 "django-tables2 >= 0.9.4",
38 "lava-dashboard",
39 "lava-dispatcher",
38 "lava-server >= 0.10",40 "lava-server >= 0.10",
39 "simplejson",41 "simplejson",
40 "south >= 0.7.3",42 "south >= 0.7.3",

Subscribers

People subscribed via source and target branches