diff options
| author | David Reyna <David.Reyna@windriver.com> | 2017-07-28 17:14:13 -0700 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-07-31 15:13:53 +0100 |
| commit | 3bc3d26b465b5af3cebc1d4c0d1fa382965c32cf (patch) | |
| tree | 6723a54029a4a3c5eaa75d19eae07aec792c792d /bitbake/lib/toaster/toastergui/views.py | |
| parent | 3f71378fdeed0d5f18eb7c58776fd313a0ab8fe3 (diff) | |
| download | poky-3bc3d26b465b5af3cebc1d4c0d1fa382965c32cf.tar.gz | |
bitbake: toaster: enable remote HTTP API for status aggregation
Add support for Toaster aggregators with a set of api links that
return JSON data for (a) builds in progress, (b) builds completed,
(c) specific build data, and (d) an is-alive health ping link.
[YOCTO #11794]
(Bitbake rev: d8e79661c69671dd424dca5cc3f7f2f855b0afed)
Signed-off-by: David Reyna <David.Reyna@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/toastergui/views.py')
| -rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 86 |
1 files changed, 85 insertions, 1 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 5720b9d5e4..334bb4a2e9 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -35,7 +35,7 @@ from orm.models import BitbakeVersion, CustomImageRecipe | |||
| 35 | from django.core.urlresolvers import reverse, resolve | 35 | from django.core.urlresolvers import reverse, resolve |
| 36 | from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist | 36 | from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist |
| 37 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | 37 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
| 38 | from django.http import HttpResponseNotFound | 38 | from django.http import HttpResponseNotFound, JsonResponse |
| 39 | from django.utils import timezone | 39 | from django.utils import timezone |
| 40 | from datetime import timedelta, datetime | 40 | from datetime import timedelta, datetime |
| 41 | from toastergui.templatetags.projecttags import json as jsonfilter | 41 | from toastergui.templatetags.projecttags import json as jsonfilter |
| @@ -1256,6 +1256,89 @@ def managedcontextprocessor(request): | |||
| 1256 | } | 1256 | } |
| 1257 | return ret | 1257 | return ret |
| 1258 | 1258 | ||
| 1259 | # REST-based API calls to return build/building status to external Toaster | ||
| 1260 | # managers and aggregators via JSON | ||
| 1261 | |||
| 1262 | def _json_build_status(build_id,extend): | ||
| 1263 | build_stat = None | ||
| 1264 | try: | ||
| 1265 | build = Build.objects.get( pk = build_id ) | ||
| 1266 | build_stat = {} | ||
| 1267 | build_stat['id'] = build.id | ||
| 1268 | build_stat['name'] = build.build_name | ||
| 1269 | build_stat['machine'] = build.machine | ||
| 1270 | build_stat['distro'] = build.distro | ||
| 1271 | build_stat['start'] = build.started_on | ||
| 1272 | # look up target name | ||
| 1273 | target= Target.objects.get( build = build ) | ||
| 1274 | if target: | ||
| 1275 | if target.task: | ||
| 1276 | build_stat['target'] = '%s:%s' % (target.target,target.task) | ||
| 1277 | else: | ||
| 1278 | build_stat['target'] = '%s' % (target.target) | ||
| 1279 | else: | ||
| 1280 | build_stat['target'] = '' | ||
| 1281 | # look up project name | ||
| 1282 | project = Project.objects.get( build = build ) | ||
| 1283 | if project: | ||
| 1284 | build_stat['project'] = project.name | ||
| 1285 | else: | ||
| 1286 | build_stat['project'] = '' | ||
| 1287 | if Build.IN_PROGRESS == build.outcome: | ||
| 1288 | now = timezone.now() | ||
| 1289 | timediff = now - build.started_on | ||
| 1290 | build_stat['seconds']='%.3f' % timediff.total_seconds() | ||
| 1291 | build_stat['clone']='%d:%d' % (build.repos_cloned,build.repos_to_clone) | ||
| 1292 | build_stat['parse']='%d:%d' % (build.recipes_parsed,build.recipes_to_parse) | ||
| 1293 | tf = Task.objects.filter(build = build) | ||
| 1294 | tfc = tf.count() | ||
| 1295 | if tfc > 0: | ||
| 1296 | tfd = tf.exclude(order__isnull=True).count() | ||
| 1297 | else: | ||
| 1298 | tfd = 0 | ||
| 1299 | build_stat['task']='%d:%d' % (tfd,tfc) | ||
| 1300 | else: | ||
| 1301 | build_stat['outcome'] = build.get_outcome_text() | ||
| 1302 | timediff = build.completed_on - build.started_on | ||
| 1303 | build_stat['seconds']='%.3f' % timediff.total_seconds() | ||
| 1304 | build_stat['stop'] = build.completed_on | ||
| 1305 | messages = LogMessage.objects.all().filter(build = build) | ||
| 1306 | errors = len(messages.filter(level=LogMessage.ERROR) | | ||
| 1307 | messages.filter(level=LogMessage.EXCEPTION) | | ||
| 1308 | messages.filter(level=LogMessage.CRITICAL)) | ||
| 1309 | build_stat['errors'] = errors | ||
| 1310 | warnings = len(messages.filter(level=LogMessage.WARNING)) | ||
| 1311 | build_stat['warnings'] = warnings | ||
| 1312 | if extend: | ||
| 1313 | build_stat['cooker_log'] = build.cooker_log_path | ||
| 1314 | except Exception as e: | ||
| 1315 | build_state = str(e) | ||
| 1316 | return build_stat | ||
| 1317 | |||
| 1318 | def json_builds(request): | ||
| 1319 | build_table = [] | ||
| 1320 | builds = [] | ||
| 1321 | try: | ||
| 1322 | builds = Build.objects.exclude(outcome=Build.IN_PROGRESS).order_by("-started_on") | ||
| 1323 | for build in builds: | ||
| 1324 | build_table.append(_json_build_status(build.id,False)) | ||
| 1325 | except Exception as e: | ||
| 1326 | build_table = str(e) | ||
| 1327 | return JsonResponse({'builds' : build_table, 'count' : len(builds)}) | ||
| 1328 | |||
| 1329 | def json_building(request): | ||
| 1330 | build_table = [] | ||
| 1331 | builds = [] | ||
| 1332 | try: | ||
| 1333 | builds = Build.objects.filter(outcome=Build.IN_PROGRESS).order_by("-started_on") | ||
| 1334 | for build in builds: | ||
| 1335 | build_table.append(_json_build_status(build.id,False)) | ||
| 1336 | except Exception as e: | ||
| 1337 | build_table = str(e) | ||
| 1338 | return JsonResponse({'building' : build_table, 'count' : len(builds)}) | ||
| 1339 | |||
| 1340 | def json_build(request,build_id): | ||
| 1341 | return JsonResponse({'build' : _json_build_status(build_id,True)}) | ||
| 1259 | 1342 | ||
| 1260 | 1343 | ||
| 1261 | import toastermain.settings | 1344 | import toastermain.settings |
| @@ -1694,3 +1777,4 @@ if True: | |||
| 1694 | return render(request, "unavailable_artifact.html") | 1777 | return render(request, "unavailable_artifact.html") |
| 1695 | except (ObjectDoesNotExist, IOError): | 1778 | except (ObjectDoesNotExist, IOError): |
| 1696 | return render(request, "unavailable_artifact.html") | 1779 | return render(request, "unavailable_artifact.html") |
| 1780 | |||
