mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 21:09:03 +02:00
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>
This commit is contained in:
parent
3f71378fde
commit
3bc3d26b46
6
bitbake/lib/toaster/toastergui/templates/health.html
Normal file
6
bitbake/lib/toaster/toastergui/templates/health.html
Normal file
|
@ -0,0 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head><title>Toaster Health</title></head>
|
||||
<body>Ok</body>
|
||||
</html>
|
||||
|
|
@ -244,6 +244,11 @@ urlpatterns = [
|
|||
url(r'^mostrecentbuilds$', widgets.MostRecentBuildsView.as_view(),
|
||||
name='most_recent_builds'),
|
||||
|
||||
# default redirection
|
||||
# JSON data for aggregators
|
||||
url(r'^api/builds$', views.json_builds, name='json_builds'),
|
||||
url(r'^api/building$', views.json_building, name='json_building'),
|
||||
url(r'^api/build/(?P<build_id>\d+)$', views.json_build, name='json_build'),
|
||||
|
||||
# default redirection
|
||||
url(r'^$', RedirectView.as_view(url='landing', permanent=True)),
|
||||
]
|
||||
|
|
|
@ -35,7 +35,7 @@ from orm.models import BitbakeVersion, CustomImageRecipe
|
|||
from django.core.urlresolvers import reverse, resolve
|
||||
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
|
||||
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
||||
from django.http import HttpResponseNotFound
|
||||
from django.http import HttpResponseNotFound, JsonResponse
|
||||
from django.utils import timezone
|
||||
from datetime import timedelta, datetime
|
||||
from toastergui.templatetags.projecttags import json as jsonfilter
|
||||
|
@ -1256,6 +1256,89 @@ def managedcontextprocessor(request):
|
|||
}
|
||||
return ret
|
||||
|
||||
# REST-based API calls to return build/building status to external Toaster
|
||||
# managers and aggregators via JSON
|
||||
|
||||
def _json_build_status(build_id,extend):
|
||||
build_stat = None
|
||||
try:
|
||||
build = Build.objects.get( pk = build_id )
|
||||
build_stat = {}
|
||||
build_stat['id'] = build.id
|
||||
build_stat['name'] = build.build_name
|
||||
build_stat['machine'] = build.machine
|
||||
build_stat['distro'] = build.distro
|
||||
build_stat['start'] = build.started_on
|
||||
# look up target name
|
||||
target= Target.objects.get( build = build )
|
||||
if target:
|
||||
if target.task:
|
||||
build_stat['target'] = '%s:%s' % (target.target,target.task)
|
||||
else:
|
||||
build_stat['target'] = '%s' % (target.target)
|
||||
else:
|
||||
build_stat['target'] = ''
|
||||
# look up project name
|
||||
project = Project.objects.get( build = build )
|
||||
if project:
|
||||
build_stat['project'] = project.name
|
||||
else:
|
||||
build_stat['project'] = ''
|
||||
if Build.IN_PROGRESS == build.outcome:
|
||||
now = timezone.now()
|
||||
timediff = now - build.started_on
|
||||
build_stat['seconds']='%.3f' % timediff.total_seconds()
|
||||
build_stat['clone']='%d:%d' % (build.repos_cloned,build.repos_to_clone)
|
||||
build_stat['parse']='%d:%d' % (build.recipes_parsed,build.recipes_to_parse)
|
||||
tf = Task.objects.filter(build = build)
|
||||
tfc = tf.count()
|
||||
if tfc > 0:
|
||||
tfd = tf.exclude(order__isnull=True).count()
|
||||
else:
|
||||
tfd = 0
|
||||
build_stat['task']='%d:%d' % (tfd,tfc)
|
||||
else:
|
||||
build_stat['outcome'] = build.get_outcome_text()
|
||||
timediff = build.completed_on - build.started_on
|
||||
build_stat['seconds']='%.3f' % timediff.total_seconds()
|
||||
build_stat['stop'] = build.completed_on
|
||||
messages = LogMessage.objects.all().filter(build = build)
|
||||
errors = len(messages.filter(level=LogMessage.ERROR) |
|
||||
messages.filter(level=LogMessage.EXCEPTION) |
|
||||
messages.filter(level=LogMessage.CRITICAL))
|
||||
build_stat['errors'] = errors
|
||||
warnings = len(messages.filter(level=LogMessage.WARNING))
|
||||
build_stat['warnings'] = warnings
|
||||
if extend:
|
||||
build_stat['cooker_log'] = build.cooker_log_path
|
||||
except Exception as e:
|
||||
build_state = str(e)
|
||||
return build_stat
|
||||
|
||||
def json_builds(request):
|
||||
build_table = []
|
||||
builds = []
|
||||
try:
|
||||
builds = Build.objects.exclude(outcome=Build.IN_PROGRESS).order_by("-started_on")
|
||||
for build in builds:
|
||||
build_table.append(_json_build_status(build.id,False))
|
||||
except Exception as e:
|
||||
build_table = str(e)
|
||||
return JsonResponse({'builds' : build_table, 'count' : len(builds)})
|
||||
|
||||
def json_building(request):
|
||||
build_table = []
|
||||
builds = []
|
||||
try:
|
||||
builds = Build.objects.filter(outcome=Build.IN_PROGRESS).order_by("-started_on")
|
||||
for build in builds:
|
||||
build_table.append(_json_build_status(build.id,False))
|
||||
except Exception as e:
|
||||
build_table = str(e)
|
||||
return JsonResponse({'building' : build_table, 'count' : len(builds)})
|
||||
|
||||
def json_build(request,build_id):
|
||||
return JsonResponse({'build' : _json_build_status(build_id,True)})
|
||||
|
||||
|
||||
import toastermain.settings
|
||||
|
@ -1694,3 +1777,4 @@ if True:
|
|||
return render(request, "unavailable_artifact.html")
|
||||
except (ObjectDoesNotExist, IOError):
|
||||
return render(request, "unavailable_artifact.html")
|
||||
|
||||
|
|
|
@ -20,9 +20,8 @@
|
|||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
from django.conf.urls import patterns, include, url
|
||||
from django.views.generic import RedirectView
|
||||
from django.views.generic import RedirectView, TemplateView
|
||||
from django.views.decorators.cache import never_cache
|
||||
|
||||
import bldcollector.views
|
||||
|
||||
import logging
|
||||
|
@ -46,6 +45,8 @@ urlpatterns = [
|
|||
# in the future.
|
||||
url(r'^orm/eventfile$', bldcollector.views.eventfile),
|
||||
|
||||
url(r'^health$', TemplateView.as_view(template_name="health.html"), name='Toaster Health'),
|
||||
|
||||
# if no application is selected, we have the magic toastergui app here
|
||||
url(r'^$', never_cache(RedirectView.as_view(url='/toastergui/', permanent=True))),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue
Block a user