summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/toaster/toastergui/views.py')
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py237
1 files changed, 198 insertions, 39 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 3fde3c9a62..5fe4a9d869 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -387,6 +387,17 @@ def builds(request):
387 ] 387 ]
388 } 388 }
389 389
390 if toastermain.settings.MANAGED:
391 context['tablecols'].append(
392 {'name': 'Project', 'clclass': 'project',
393 'filter': {'class': 'project',
394 'label': 'Project:',
395 'options': map(lambda x: (x.name,'',x.build_set.filter(outcome__lt=Build.IN_PROGRESS).count()), Project.objects.all()),
396
397 }
398 })
399
400
390 response = render(request, template, context) 401 response = render(request, template, context)
391 _save_parameters_cookies(response, pagesize, orderby, request) 402 _save_parameters_cookies(response, pagesize, orderby, request)
392 return response 403 return response
@@ -1799,7 +1810,7 @@ if toastermain.settings.MANAGED:
1799 from django.contrib.auth.decorators import login_required 1810 from django.contrib.auth.decorators import login_required
1800 1811
1801 from orm.models import Project, ProjectLayer, ProjectTarget, ProjectVariable 1812 from orm.models import Project, ProjectLayer, ProjectTarget, ProjectVariable
1802 from orm.models import Branch, LayerSource, ToasterSetting, Release, Machine 1813 from orm.models import Branch, LayerSource, ToasterSetting, Release, Machine, LayerVersionDependency
1803 from bldcontrol.models import BuildRequest 1814 from bldcontrol.models import BuildRequest
1804 1815
1805 import traceback 1816 import traceback
@@ -1831,7 +1842,7 @@ if toastermain.settings.MANAGED:
1831 # render new project page 1842 # render new project page
1832 return render(request, template, context) 1843 return render(request, template, context)
1833 elif request.method == "POST": 1844 elif request.method == "POST":
1834 mandatory_fields = ['projectname', 'email', 'username', 'projectversion'] 1845 mandatory_fields = ['projectname', 'projectversion']
1835 try: 1846 try:
1836 # make sure we have values for all mandatory_fields 1847 # make sure we have values for all mandatory_fields
1837 if reduce( lambda x, y: x or y, map(lambda x: len(request.POST.get(x, '')) == 0, mandatory_fields)): 1848 if reduce( lambda x, y: x or y, map(lambda x: len(request.POST.get(x, '')) == 0, mandatory_fields)):
@@ -1840,9 +1851,9 @@ if toastermain.settings.MANAGED:
1840 ", ".join([x for x in mandatory_fields if len(request.POST.get(x, '')) == 0 ])) 1851 ", ".join([x for x in mandatory_fields if len(request.POST.get(x, '')) == 0 ]))
1841 1852
1842 if not request.user.is_authenticated(): 1853 if not request.user.is_authenticated():
1843 user = authenticate(username = request.POST['username'], password = 'nopass') 1854 user = authenticate(username = request.POST.get('username', '_anonuser'), password = 'nopass')
1844 if user is None: 1855 if user is None:
1845 user = User.objects.create_user(username = request.POST['username'], email = request.POST['email'], password = "nopass") 1856 user = User.objects.create_user(username = request.POST.get('username', '_anonuser'), email = request.POST.get('email', ''), password = "nopass")
1846 1857
1847 user = authenticate(username = user.username, password = 'nopass') 1858 user = authenticate(username = user.username, password = 'nopass')
1848 login(request, user) 1859 login(request, user)
@@ -1852,7 +1863,7 @@ if toastermain.settings.MANAGED:
1852 release = Release.objects.get(pk = request.POST['projectversion'])) 1863 release = Release.objects.get(pk = request.POST['projectversion']))
1853 prj.user_id = request.user.pk 1864 prj.user_id = request.user.pk
1854 prj.save() 1865 prj.save()
1855 return redirect(reverse(project, args = (prj.pk,))) 1866 return redirect(reverse(project, args = (prj.pk,)) + "#/newproject")
1856 1867
1857 except (IntegrityError, BadParameterException) as e: 1868 except (IntegrityError, BadParameterException) as e:
1858 # fill in page with previously submitted values 1869 # fill in page with previously submitted values
@@ -1865,6 +1876,40 @@ if toastermain.settings.MANAGED:
1865 1876
1866 raise Exception("Invalid HTTP method for this page") 1877 raise Exception("Invalid HTTP method for this page")
1867 1878
1879
1880 def _project_recent_build_list(prj):
1881 # build requests not yet started
1882 return (map(lambda x: {
1883 "id": x.pk,
1884 "targets" : map(lambda y: {"target": y.target }, x.brtarget_set.all()),
1885 "status": x.get_state_display(),
1886 }, prj.buildrequest_set.filter(state__lt = BuildRequest.REQ_INPROGRESS).order_by("-pk")) +
1887 # build requests started, but with no build yet
1888 map(lambda x: {
1889 "id": x.pk,
1890 "targets" : map(lambda y: {"target": y.target }, x.brtarget_set.all()),
1891 "status": x.get_state_display(),
1892 }, prj.buildrequest_set.filter(state = BuildRequest.REQ_INPROGRESS, build = None).order_by("-pk")) +
1893 # build requests that failed
1894 map(lambda x: {
1895 "id": x.pk,
1896 "targets" : map(lambda y: {"target": y.target }, x.brtarget_set.all()),
1897 "status": x.get_state_display(),
1898 "errors": map(lambda y: {"type": y.errtype, "msg": y.errmsg, "tb": y.traceback}, x.brerror_set.all()),
1899 }, prj.buildrequest_set.filter(state = BuildRequest.REQ_FAILED).order_by("-pk")) +
1900 # and already made builds
1901 map(lambda x: {
1902 "id": x.pk,
1903 "targets": map(lambda y: {"target": y.target }, x.target_set.all()),
1904 "status": x.get_outcome_display(),
1905 "completed_on" : x.completed_on.strftime('%s')+"000",
1906 "build_time" : (x.completed_on - x.started_on).total_seconds(),
1907 "build_page_url" : reverse('builddashboard', args=(x.pk,)),
1908 "completeper": x.completeper(),
1909 "eta": x.eta().ctime(),
1910 }, prj.build_set.all()))
1911
1912
1868 # Shows the edit project page 1913 # Shows the edit project page
1869 def project(request, pid): 1914 def project(request, pid):
1870 template = "project.html" 1915 template = "project.html"
@@ -1881,27 +1926,40 @@ if toastermain.settings.MANAGED:
1881 # we use implicit knowledge of the current user's project to filter layer information, e.g. 1926 # we use implicit knowledge of the current user's project to filter layer information, e.g.
1882 request.session['project_id'] = prj.id 1927 request.session['project_id'] = prj.id
1883 1928
1929 from collections import Counter
1930 freqtargets = []
1931 try:
1932 freqtargets += map(lambda x: x.target, reduce(lambda x, y: x + y, map(lambda x: list(x.target_set.all()), Build.objects.filter(project = prj, outcome__lt = Build.IN_PROGRESS))))
1933 freqtargets += map(lambda x: x.target, reduce(lambda x, y: x + y, map(lambda x: list(x.brtarget_set.all()), BuildRequest.objects.filter(project = prj, state__lte = BuildRequest.REQ_QUEUED))))
1934 except TypeError:
1935 pass
1936 freqtargets = Counter(freqtargets)
1937 freqtargets = sorted(freqtargets, key = lambda x: freqtargets[x])
1938
1884 context = { 1939 context = {
1885 "project" : prj, 1940 "project" : prj,
1941 "completedbuilds": Build.objects.filter(project = prj).exclude(outcome = Build.IN_PROGRESS),
1942 "prj" : json.dumps({"name": prj.name, "release": { "id": prj.release.pk, "name": prj.release.name}}),
1886 #"buildrequests" : prj.buildrequest_set.filter(state=BuildRequest.REQ_QUEUED), 1943 #"buildrequests" : prj.buildrequest_set.filter(state=BuildRequest.REQ_QUEUED),
1887 "buildrequests" : map(lambda x: (x, {"machine" : x.brvariable_set.filter(name="MACHINE")[0]}), prj.buildrequest_set.filter(state__lt = BuildRequest.REQ_INPROGRESS).order_by("-pk")), 1944 "builds" : json.dumps(_project_recent_build_list(prj)),
1888 "builds" : prj.build_set.all(), 1945 "layers" : json.dumps(map(lambda x: {"id": x.layercommit.pk, "name" : x.layercommit.layer.name, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(x.layercommit.layer.pk,)), "branch" : { "name" : x.layercommit.up_branch.name, "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all())),
1889 "puser": puser, 1946 "targets" : json.dumps(map(lambda x: {"target" : x.target, "task" : x.task, "pk": x.pk}, prj.projecttarget_set.all())),
1947 "freqtargets": json.dumps(freqtargets),
1948 "releases": json.dumps(map(lambda x: {"id": x.pk, "name": x.name}, Release.objects.all())),
1890 } 1949 }
1891 try: 1950 try:
1892 context["machine"] = prj.projectvariable_set.get(name="MACHINE").value 1951 context["machine"] = json.dumps({"name": prj.projectvariable_set.get(name="MACHINE").value})
1893 except ProjectVariable.DoesNotExist: 1952 except ProjectVariable.DoesNotExist:
1894 context["machine"] = "-- not set yet" 1953 context["machine"] = json.dumps(None)
1895
1896 try: 1954 try:
1897 context["distro"] = prj.projectvariable_set.get(name="DISTRO").value 1955 context["distro"] = prj.projectvariable_set.get(name="DISTRO").value
1898 except ProjectVariable.DoesNotExist: 1956 except ProjectVariable.DoesNotExist:
1899 context["distro"] = "-- not set yet" 1957 context["distro"] = "-- not set yet"
1900 1958
1901 1959 response = render(request, template, context)
1902 return render(request, template, context) 1960 response['Cache-Control'] = "no-cache, must-revalidate, no-store"
1903 1961 response['Pragma'] = "no-cache"
1904 import json 1962 return response
1905 1963
1906 def xhr_projectbuild(request, pid): 1964 def xhr_projectbuild(request, pid):
1907 try: 1965 try:
@@ -1909,57 +1967,155 @@ if toastermain.settings.MANAGED:
1909 raise BadParameterException("invalid method") 1967 raise BadParameterException("invalid method")
1910 prj = Project.objects.get(id = pid) 1968 prj = Project.objects.get(id = pid)
1911 1969
1912 if prj.projecttarget_set.count() == 0:
1913 raise BadParameterException("no targets selected")
1914 1970
1915 br = prj.schedule_build() 1971 if 'buildCancel' in request.POST:
1916 return HttpResponse(json.dumps({"error":"ok", 1972 for i in request.POST['buildCancel'].strip().split(" "):
1917 "brtarget" : map(lambda x: x.target, br.brtarget_set.all()), 1973 br = BuildRequest.objects.select_for_update().get(project = prj, pk = i, state__lte = BuildRequest.REQ_QUEUED)
1918 "machine" : br.brvariable_set.get(name="MACHINE").value, 1974 print "selected for delete", br.pk
1975 br.delete()
1976 print "selected for delete", br.pk
1919 1977
1920 }), content_type = "application/json") 1978 if 'targets' in request.POST:
1921 except Exception as e: 1979 ProjectTarget.objects.filter(project = prj).delete()
1922 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") 1980 for t in request.POST['targets'].strip().split(" "):
1923
1924 def xhr_projectedit(request, pid):
1925 try:
1926 prj = Project.objects.get(id = pid)
1927 # add targets
1928 if 'targetAdd' in request.POST:
1929 for t in request.POST['targetAdd'].strip().split(" "):
1930 if ":" in t: 1981 if ":" in t:
1931 target, task = t.split(":") 1982 target, task = t.split(":")
1932 else: 1983 else:
1933 target = t 1984 target = t
1934 task = "" 1985 task = ""
1986 ProjectTarget.objects.create(project = prj, target = target, task = task)
1935 1987
1936 pt, created = ProjectTarget.objects.get_or_create(project = prj, target = target, task = task) 1988 br = prj.schedule_build()
1937 # remove targets
1938 if 'targetDel' in request.POST:
1939 for t in request.POST['targetDel'].strip().split(" "):
1940 pt = ProjectTarget.objects.get(pk = int(t)).delete()
1941 1989
1990 return HttpResponse(json.dumps({"error":"ok",
1991 "builds" : _project_recent_build_list(prj),
1992 }), content_type = "application/json")
1993 except Exception as e:
1994 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
1995
1996 def xhr_projectedit(request, pid):
1997 try:
1998 prj = Project.objects.get(id = pid)
1942 # add layers 1999 # add layers
2000 if 'layerAdd' in request.POST:
2001 for lc in Layer_Version.objects.filter(pk__in=request.POST['layerAdd'].split(",")):
2002 ProjectLayer.objects.get_or_create(project = prj, layercommit = lc)
1943 2003
1944 # remove layers 2004 # remove layers
2005 if 'layerDel' in request.POST:
2006 for t in request.POST['layerDel'].strip().split(" "):
2007 pt = ProjectLayer.objects.get(project = prj, layercommit_id = int(t)).delete()
2008
2009 if 'projectName' in request.POST:
2010 prj.name = request.POST['projectName']
2011 prj.save();
2012
2013
2014 if 'projectVersion' in request.POST:
2015 prj.release = Release.objects.get(pk = request.POST['projectVersion'])
2016 prj.save()
2017 # we need to change the layers
2018 for i in prj.projectlayer_set.all():
2019 # find and add a similarly-named layer from the same layer source on the new branch
2020 lv = Layer_Version.objects.filter(layer_source = i.layercommit.layer_source, layer__name = i.layercommit.layer.name, up_branch__in = Branch.objects.filter(name = prj.release.branch))
2021 if lv.count() == 1:
2022 ProjectLayer.objects.get_or_create(project = prj, layercommit = lv[0])
2023 # get rid of the old entry
2024 i.delete()
1945 2025
1946 # return all project settings 2026 # return all project settings
1947 return HttpResponse(json.dumps( { 2027 return HttpResponse(json.dumps( {
1948 "error": "ok", 2028 "error": "ok",
1949 "layers": map(lambda x: (x.layercommit.layer.name, x.layercommit.layer.layer_index_url), prj.projectlayer_set.all()), 2029 "layers" : map(lambda x: {"id": x.layercommit.pk, "name" : x.layercommit.layer.name, "url": x.layercommit.layer.layer_index_url, "layerdetailurl": reverse("layerdetails", args=(x.layercommit.layer.pk,)), "branch" : { "name" : x.layercommit.up_branch.name, "layersource" : x.layercommit.up_branch.layer_source.name}}, prj.projectlayer_set.all()),
1950 "targets" : map(lambda x: {"target" : x.target, "task" : x.task, "pk": x.pk}, prj.projecttarget_set.all()), 2030 "builds" : _project_recent_build_list(prj),
1951 "variables": map(lambda x: (x.name, x.value), prj.projectvariable_set.all()), 2031 "variables": map(lambda x: (x.name, x.value), prj.projectvariable_set.all()),
2032 "prj": {"name": prj.name, "release": { "id": prj.release.pk, "name": prj.release.name}},
1952 }), content_type = "application/json") 2033 }), content_type = "application/json")
1953 2034
1954 except Exception as e: 2035 except Exception as e:
1955 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") 2036 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
1956 2037
2038
2039 from django.views.decorators.csrf import csrf_exempt
2040 @csrf_exempt
2041 def xhr_datatypeahead(request):
2042 try:
2043 if request.GET['type'] == "layers":
2044 queryset_all = Layer_Version.objects.all()
2045 if 'project_id' in request.session:
2046 prj = Project.objects.get(pk = request.session['project_id'])
2047 queryset_all = queryset_all.filter(up_branch__in = Branch.objects.filter(name = prj.release.name)).exclude(pk__in = map(lambda x: x.layercommit_id, prj.projectlayer_set.all()))
2048 queryset_all = queryset_all.filter(layer__name__icontains=request.GET.get('value',''))
2049 return HttpResponse(json.dumps( { "error":"ok",
2050 "list" : map( lambda x: {"id": x.pk, "name": x.layer.name, "detail": "(" + x.layer.layer_source.name + (")" if x.up_branch == None else " | "+x.up_branch.name+")")},
2051 queryset_all[:8])
2052 }), content_type = "application/json")
2053
2054 if request.GET['type'] == "layerdeps":
2055 queryset_all = LayerVersionDependency.objects.filter(layer_version_id = request.GET['value'])
2056
2057 if 'project_id' in request.session:
2058 prj = Project.objects.get(pk = request.session['project_id'])
2059 queryset_all = queryset_all.exclude(depends_on__in = map(lambda x: x.layercommit, prj.projectlayer_set.all()))
2060
2061 queryset_all.order_by("-up_id");
2062
2063 return HttpResponse(json.dumps( { "error":"ok",
2064 "list" : map(
2065 lambda x: {"id": x.pk, "name": x.layer.name, "detail": "(" + x.layer.layer_source.name + (")" if x.up_branch == None else " | "+x.up_branch.name+")")},
2066 map(lambda x: x.depends_on, queryset_all))
2067 }), content_type = "application/json")
2068
2069 if request.GET['type'] == "versionlayers":
2070 if not 'project_id' in request.session:
2071 raise Exception("This call cannot makes no sense outside a project context")
2072
2073 retval = []
2074 prj = Project.objects.get(pk = request.session['project_id'])
2075 for i in prj.projectlayer_set.all():
2076 lv = Layer_Version.objects.filter(layer_source = i.layercommit.layer_source, layer__name = i.layercommit.layer.name, up_branch__in = Branch.objects.filter(name = Release.objects.get(pk=request.GET['value']).branch))
2077 if lv.count() != 1:
2078 retval.append(i)
2079
2080 return HttpResponse(json.dumps( {"error":"ok",
2081 "list": map(
2082 lambda x: {"id": x.layercommit.pk, "name": x.layercommit.layer.name, "detail": "(" + x.layercommit.layer.layer_source.name + (")" if x.layercommit.up_branch == None else " | "+x.layercommit.up_branch.name+")")},
2083 retval) }), content_type = "application/json")
2084
2085
2086 if request.GET['type'] == "targets":
2087 queryset_all = Recipe.objects.all()
2088 if 'project_id' in request.session:
2089 queryset_all = queryset_all.filter(layer_version__layer__in = map(lambda x: x.layercommit.layer, ProjectLayer.objects.filter(project_id=request.session['project_id'])))
2090 return HttpResponse(json.dumps({ "error":"ok",
2091 "list" : map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ (" | " + x.layer_version.up_branch.name + "]" if x.layer_version.up_branch is not None else "]")},
2092 queryset_all.filter(name__istartswith=request.GET.get('value',''))[:8]),
2093
2094 }), content_type = "application/json")
2095
2096 if request.GET['type'] == "machines":
2097 queryset_all = Machine.objects.all()
2098 if 'project_id' in request.session:
2099 queryset_all = queryset_all.filter(layer_version__layer__in = map(lambda x: x.layercommit.layer, ProjectLayer.objects.filter(project_id=request.session['project_id'])))
2100 return HttpResponse(json.dumps({ "error":"ok",
2101 "list" : map ( lambda x: {"id": x.pk, "name": x.name, "detail":"[" + x.layer_version.layer.name+ (" | " + x.layer_version.up_branch.name + "]" if x.layer_version.up_branch is not None else "]")},
2102 queryset_all.filter(name__istartswith=request.GET.get('value',''))[:8]),
2103
2104 }), content_type = "application/json")
2105
2106 raise Exception("Unknown request! " + request.GET.get('type', "No parameter supplied"))
2107 except Exception as e:
2108 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
2109
2110
2111
1957 def importlayer(request): 2112 def importlayer(request):
1958 template = "importlayer.html" 2113 template = "importlayer.html"
1959 context = { 2114 context = {
1960 } 2115 }
1961 return render(request, template, context) 2116 return render(request, template, context)
1962 2117
2118
1963 def layers(request): 2119 def layers(request):
1964 template = "layers.html" 2120 template = "layers.html"
1965 # define here what parameters the view needs in the GET portion in order to 2121 # define here what parameters the view needs in the GET portion in order to
@@ -2220,7 +2376,7 @@ if toastermain.settings.MANAGED:
2220 # boilerplate code that takes a request for an object type and returns a queryset 2376 # boilerplate code that takes a request for an object type and returns a queryset
2221 # for that object type. copypasta for all needed table searches 2377 # for that object type. copypasta for all needed table searches
2222 (filter_string, search_term, ordering_string) = _search_tuple(request, Build) 2378 (filter_string, search_term, ordering_string) = _search_tuple(request, Build)
2223 queryset_all = Build.objects.all.exclude(outcome = Build.IN_PROGRESS) 2379 queryset_all = Build.objects.all().exclude(outcome = Build.IN_PROGRESS)
2224 queryset_with_search = _get_queryset(Build, queryset_all, None, search_term, ordering_string, '-completed_on') 2380 queryset_with_search = _get_queryset(Build, queryset_all, None, search_term, ordering_string, '-completed_on')
2225 queryset = _get_queryset(Build, queryset_all, filter_string, search_term, ordering_string, '-completed_on') 2381 queryset = _get_queryset(Build, queryset_all, filter_string, search_term, ordering_string, '-completed_on')
2226 2382
@@ -2388,6 +2544,9 @@ else:
2388 def xhr_projectedit(request, pid): 2544 def xhr_projectedit(request, pid):
2389 raise Exception("page not available in interactive mode") 2545 raise Exception("page not available in interactive mode")
2390 2546
2547 def xhr_datatypeahead(request):
2548 raise Exception("page not available in interactive mode")
2549
2391 def importlayer(request): 2550 def importlayer(request):
2392 raise Exception("page not available in interactive mode") 2551 raise Exception("page not available in interactive mode")
2393 2552