diff options
author | David Reyna <David.Reyna@windriver.com> | 2017-11-30 00:55:28 -0800 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-12-18 15:05:30 +0000 |
commit | 299e8ff1f7f0888cf630848aa423747fb4f8eedd (patch) | |
tree | 7ecafbcb82458cb4866007d9bc7e5b24221ae028 | |
parent | 0d9914721a8750071f9b6ec233c23d8451ee1a77 (diff) | |
download | poky-299e8ff1f7f0888cf630848aa423747fb4f8eedd.tar.gz |
bitbake: toaster: add 'nobuild' option to Toaster
Add a 'nobuild' option for starting Toaster without the project
and hosted builds support. This allows a Toaster host to provide
local build statistics without opening the host to external users
building projects.
[YOCTO #12315]
(Bitbake rev: 2d14d6004b6add5ce07295fff1144ade2e54e1c9)
Signed-off-by: David Reyna <David.Reyna@windriver.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rwxr-xr-x | bitbake/bin/toaster | 19 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/base.html | 4 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/templates/landing.html | 2 | ||||
-rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 57 | ||||
-rw-r--r-- | bitbake/lib/toaster/toastergui/widgets.py | 4 |
5 files changed, 58 insertions, 28 deletions
diff --git a/bitbake/bin/toaster b/bitbake/bin/toaster index 762451df23..4036f0ad58 100755 --- a/bitbake/bin/toaster +++ b/bitbake/bin/toaster | |||
@@ -18,9 +18,10 @@ | |||
18 | # along with this program. If not, see http://www.gnu.org/licenses/. | 18 | # along with this program. If not, see http://www.gnu.org/licenses/. |
19 | 19 | ||
20 | HELP=" | 20 | HELP=" |
21 | Usage: source toaster start|stop [webport=<address:port>] [noweb] | 21 | Usage: source toaster start|stop [webport=<address:port>] [noweb] [nobuild] |
22 | Optional arguments: | 22 | Optional arguments: |
23 | [noweb] Setup the environment for building with toaster but don't start the development server | 23 | [nobuild] Setup the environment for capturing builds with toaster but disable managed builds |
24 | [noweb] Setup the environment for capturing builds with toaster but don't start the web server | ||
24 | [webport] Set the development server (default: localhost:8000) | 25 | [webport] Set the development server (default: localhost:8000) |
25 | " | 26 | " |
26 | 27 | ||
@@ -183,6 +184,7 @@ unset OE_ROOT | |||
183 | 184 | ||
184 | 185 | ||
185 | WEBSERVER=1 | 186 | WEBSERVER=1 |
187 | export TOASTER_BUILDSERVER=1 | ||
186 | ADDR_PORT="localhost:8000" | 188 | ADDR_PORT="localhost:8000" |
187 | unset CMD | 189 | unset CMD |
188 | for param in $*; do | 190 | for param in $*; do |
@@ -190,6 +192,9 @@ for param in $*; do | |||
190 | noweb ) | 192 | noweb ) |
191 | WEBSERVER=0 | 193 | WEBSERVER=0 |
192 | ;; | 194 | ;; |
195 | nobuild ) | ||
196 | TOASTER_BUILDSERVER=0 | ||
197 | ;; | ||
193 | start ) | 198 | start ) |
194 | CMD=$param | 199 | CMD=$param |
195 | ;; | 200 | ;; |
@@ -286,9 +291,13 @@ case $CMD in | |||
286 | return 4 | 291 | return 4 |
287 | fi | 292 | fi |
288 | export BITBAKE_UI='toasterui' | 293 | export BITBAKE_UI='toasterui' |
289 | $MANAGE runbuilds \ | 294 | if [ $TOASTER_BUILDSERVER -eq 1 ] ; then |
290 | </dev/null >>${BUILDDIR}/toaster_runbuilds.log 2>&1 \ | 295 | $MANAGE runbuilds \ |
291 | & echo $! >${BUILDDIR}/.runbuilds.pid | 296 | </dev/null >>${BUILDDIR}/toaster_runbuilds.log 2>&1 \ |
297 | & echo $! >${BUILDDIR}/.runbuilds.pid | ||
298 | else | ||
299 | echo "Toaster build server not started." | ||
300 | fi | ||
292 | 301 | ||
293 | # set fail safe stop system on terminal exit | 302 | # set fail safe stop system on terminal exit |
294 | trap stop_system SIGHUP | 303 | trap stop_system SIGHUP |
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html index edbd110c25..4f7206489b 100644 --- a/bitbake/lib/toaster/toastergui/templates/base.html +++ b/bitbake/lib/toaster/toastergui/templates/base.html | |||
@@ -110,6 +110,7 @@ | |||
110 | All builds | 110 | All builds |
111 | </a> | 111 | </a> |
112 | </li> | 112 | </li> |
113 | {% if project_enable %} | ||
113 | <li id="navbar-all-projects" | 114 | <li id="navbar-all-projects" |
114 | {% if request.resolver_match.url_name == 'all-projects' %} | 115 | {% if request.resolver_match.url_name == 'all-projects' %} |
115 | class="active" | 116 | class="active" |
@@ -119,6 +120,7 @@ | |||
119 | All projects | 120 | All projects |
120 | </a> | 121 | </a> |
121 | </li> | 122 | </li> |
123 | {% endif %} | ||
122 | {% endif %} | 124 | {% endif %} |
123 | <li id="navbar-docs"> | 125 | <li id="navbar-docs"> |
124 | <a target="_blank" href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html"> | 126 | <a target="_blank" href="http://www.yoctoproject.org/docs/latest/toaster-manual/toaster-manual.html"> |
@@ -127,7 +129,9 @@ | |||
127 | </a> | 129 | </a> |
128 | </li> | 130 | </li> |
129 | </ul> | 131 | </ul> |
132 | {% if project_enable %} | ||
130 | <a class="btn btn-default navbar-btn navbar-right" id="new-project-button" href="{% url 'newproject' %}">New project</a> | 133 | <a class="btn btn-default navbar-btn navbar-right" id="new-project-button" href="{% url 'newproject' %}">New project</a> |
134 | {% endif %} | ||
131 | </div> | 135 | </div> |
132 | </div> | 136 | </div> |
133 | </nav> | 137 | </nav> |
diff --git a/bitbake/lib/toaster/toastergui/templates/landing.html b/bitbake/lib/toaster/toastergui/templates/landing.html index cf7516dbc8..70c7359fad 100644 --- a/bitbake/lib/toaster/toastergui/templates/landing.html +++ b/bitbake/lib/toaster/toastergui/templates/landing.html | |||
@@ -21,11 +21,13 @@ | |||
21 | </p> | 21 | </p> |
22 | 22 | ||
23 | {% if lvs_nos %} | 23 | {% if lvs_nos %} |
24 | {% if project_enable %} | ||
24 | <p class="top-air"> | 25 | <p class="top-air"> |
25 | <a class="btn btn-primary btn-lg" href="{% url 'newproject' %}"> | 26 | <a class="btn btn-primary btn-lg" href="{% url 'newproject' %}"> |
26 | Create your first Toaster project to run manage builds | 27 | Create your first Toaster project to run manage builds |
27 | </a> | 28 | </a> |
28 | </p> | 29 | </p> |
30 | {% endif %} | ||
29 | {% else %} | 31 | {% else %} |
30 | <div class="alert alert-info lead top-air"> | 32 | <div class="alert alert-info lead top-air"> |
31 | Toaster has no layer information. Without layer information, you cannot run builds. To generate layer information you can: | 33 | Toaster has no layer information. Without layer information, you cannot run builds. To generate layer information you can: |
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 209b07dad8..34ed2b2e3c 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -49,6 +49,8 @@ import logging | |||
49 | 49 | ||
50 | logger = logging.getLogger("toaster") | 50 | logger = logging.getLogger("toaster") |
51 | 51 | ||
52 | # Project creation and managed build enable | ||
53 | project_enable = ('1' == os.environ.get('TOASTER_BUILDSERVER')) | ||
52 | 54 | ||
53 | class MimeTypeFinder(object): | 55 | class MimeTypeFinder(object): |
54 | # setting this to False enables additional non-standard mimetypes | 56 | # setting this to False enables additional non-standard mimetypes |
@@ -65,6 +67,12 @@ class MimeTypeFinder(object): | |||
65 | guessed_type = 'application/octet-stream' | 67 | guessed_type = 'application/octet-stream' |
66 | return guessed_type | 68 | return guessed_type |
67 | 69 | ||
70 | # single point to add global values into the context before rendering | ||
71 | def toaster_render(request, page, context): | ||
72 | context['project_enable'] = project_enable | ||
73 | return render(request, page, context) | ||
74 | |||
75 | |||
68 | # all new sessions should come through the landing page; | 76 | # all new sessions should come through the landing page; |
69 | # determine in which mode we are running in, and redirect appropriately | 77 | # determine in which mode we are running in, and redirect appropriately |
70 | def landing(request): | 78 | def landing(request): |
@@ -86,7 +94,7 @@ def landing(request): | |||
86 | 94 | ||
87 | context = {'lvs_nos' : Layer_Version.objects.all().count()} | 95 | context = {'lvs_nos' : Layer_Version.objects.all().count()} |
88 | 96 | ||
89 | return render(request, 'landing.html', context) | 97 | return toaster_render(request, 'landing.html', context) |
90 | 98 | ||
91 | def objtojson(obj): | 99 | def objtojson(obj): |
92 | from django.db.models.query import QuerySet | 100 | from django.db.models.query import QuerySet |
@@ -519,7 +527,7 @@ def builddashboard( request, build_id ): | |||
519 | 'packagecount' : packageCount, | 527 | 'packagecount' : packageCount, |
520 | 'logmessages' : logmessages, | 528 | 'logmessages' : logmessages, |
521 | } | 529 | } |
522 | return render( request, template, context ) | 530 | return toaster_render( request, template, context ) |
523 | 531 | ||
524 | 532 | ||
525 | 533 | ||
@@ -591,7 +599,7 @@ def task( request, build_id, task_id ): | |||
591 | build__completed_on__lt=task_object.build.completed_on).exclude( | 599 | build__completed_on__lt=task_object.build.completed_on).exclude( |
592 | order__isnull=True).exclude(outcome=Task.OUTCOME_NA).order_by('-build__completed_on') | 600 | order__isnull=True).exclude(outcome=Task.OUTCOME_NA).order_by('-build__completed_on') |
593 | 601 | ||
594 | return render( request, template, context ) | 602 | return toaster_render( request, template, context ) |
595 | 603 | ||
596 | def recipe(request, build_id, recipe_id, active_tab="1"): | 604 | def recipe(request, build_id, recipe_id, active_tab="1"): |
597 | template = "recipe.html" | 605 | template = "recipe.html" |
@@ -618,7 +626,7 @@ def recipe(request, build_id, recipe_id, active_tab="1"): | |||
618 | 'package_count' : package_count, | 626 | 'package_count' : package_count, |
619 | 'tab_states' : tab_states, | 627 | 'tab_states' : tab_states, |
620 | } | 628 | } |
621 | return render(request, template, context) | 629 | return toaster_render(request, template, context) |
622 | 630 | ||
623 | def recipe_packages(request, build_id, recipe_id): | 631 | def recipe_packages(request, build_id, recipe_id): |
624 | template = "recipe_packages.html" | 632 | template = "recipe_packages.html" |
@@ -663,7 +671,7 @@ def recipe_packages(request, build_id, recipe_id): | |||
663 | }, | 671 | }, |
664 | ] | 672 | ] |
665 | } | 673 | } |
666 | response = render(request, template, context) | 674 | response = toaster_render(request, template, context) |
667 | _set_parameters_values(pagesize, orderby, request) | 675 | _set_parameters_values(pagesize, orderby, request) |
668 | return response | 676 | return response |
669 | 677 | ||
@@ -785,7 +793,7 @@ def dirinfo(request, build_id, target_id, file_path=None): | |||
785 | 'dir_list': dir_list, | 793 | 'dir_list': dir_list, |
786 | 'file_path': file_path, | 794 | 'file_path': file_path, |
787 | } | 795 | } |
788 | return render(request, template, context) | 796 | return toaster_render(request, template, context) |
789 | 797 | ||
790 | def _find_task_dep(task_object): | 798 | def _find_task_dep(task_object): |
791 | tdeps = Task_Dependency.objects.filter(task=task_object).filter(depends_on__order__gt=0) | 799 | tdeps = Task_Dependency.objects.filter(task=task_object).filter(depends_on__order__gt=0) |
@@ -837,7 +845,7 @@ def configuration(request, build_id): | |||
837 | 'build': build, | 845 | 'build': build, |
838 | 'project': build.project, | 846 | 'project': build.project, |
839 | 'targets': Target.objects.filter(build=build_id)}) | 847 | 'targets': Target.objects.filter(build=build_id)}) |
840 | return render(request, template, context) | 848 | return toaster_render(request, template, context) |
841 | 849 | ||
842 | 850 | ||
843 | def configvars(request, build_id): | 851 | def configvars(request, build_id): |
@@ -926,7 +934,7 @@ def configvars(request, build_id): | |||
926 | ], | 934 | ], |
927 | } | 935 | } |
928 | 936 | ||
929 | response = render(request, template, context) | 937 | response = toaster_render(request, template, context) |
930 | _set_parameters_values(pagesize, orderby, request) | 938 | _set_parameters_values(pagesize, orderby, request) |
931 | return response | 939 | return response |
932 | 940 | ||
@@ -939,7 +947,7 @@ def bfile(request, build_id, package_id): | |||
939 | 'project': build.project, | 947 | 'project': build.project, |
940 | 'objects' : files | 948 | 'objects' : files |
941 | } | 949 | } |
942 | return render(request, template, context) | 950 | return toaster_render(request, template, context) |
943 | 951 | ||
944 | 952 | ||
945 | # A set of dependency types valid for both included and built package views | 953 | # A set of dependency types valid for both included and built package views |
@@ -1092,7 +1100,7 @@ def package_built_detail(request, build_id, package_id): | |||
1092 | if paths.all().count() < 2: | 1100 | if paths.all().count() < 2: |
1093 | context['disable_sort'] = True; | 1101 | context['disable_sort'] = True; |
1094 | 1102 | ||
1095 | response = render(request, template, context) | 1103 | response = toaster_render(request, template, context) |
1096 | _set_parameters_values(pagesize, orderby, request) | 1104 | _set_parameters_values(pagesize, orderby, request) |
1097 | return response | 1105 | return response |
1098 | 1106 | ||
@@ -1111,7 +1119,7 @@ def package_built_dependencies(request, build_id, package_id): | |||
1111 | 'other_deps' : dependencies['other_deps'], | 1119 | 'other_deps' : dependencies['other_deps'], |
1112 | 'dependency_count' : _get_package_dependency_count(package, -1, False) | 1120 | 'dependency_count' : _get_package_dependency_count(package, -1, False) |
1113 | } | 1121 | } |
1114 | return render(request, template, context) | 1122 | return toaster_render(request, template, context) |
1115 | 1123 | ||
1116 | 1124 | ||
1117 | def package_included_detail(request, build_id, target_id, package_id): | 1125 | def package_included_detail(request, build_id, target_id, package_id): |
@@ -1157,7 +1165,7 @@ def package_included_detail(request, build_id, target_id, package_id): | |||
1157 | } | 1165 | } |
1158 | if paths.all().count() < 2: | 1166 | if paths.all().count() < 2: |
1159 | context['disable_sort'] = True | 1167 | context['disable_sort'] = True |
1160 | response = render(request, template, context) | 1168 | response = toaster_render(request, template, context) |
1161 | _set_parameters_values(pagesize, orderby, request) | 1169 | _set_parameters_values(pagesize, orderby, request) |
1162 | return response | 1170 | return response |
1163 | 1171 | ||
@@ -1181,7 +1189,7 @@ def package_included_dependencies(request, build_id, target_id, package_id): | |||
1181 | 'reverse_count' : _get_package_reverse_dep_count(package, target_id), | 1189 | 'reverse_count' : _get_package_reverse_dep_count(package, target_id), |
1182 | 'dependency_count' : _get_package_dependency_count(package, target_id, True) | 1190 | 'dependency_count' : _get_package_dependency_count(package, target_id, True) |
1183 | } | 1191 | } |
1184 | return render(request, template, context) | 1192 | return toaster_render(request, template, context) |
1185 | 1193 | ||
1186 | def package_included_reverse_dependencies(request, build_id, target_id, package_id): | 1194 | def package_included_reverse_dependencies(request, build_id, target_id, package_id): |
1187 | template = "package_included_reverse_dependencies.html" | 1195 | template = "package_included_reverse_dependencies.html" |
@@ -1232,7 +1240,7 @@ def package_included_reverse_dependencies(request, build_id, target_id, package_ | |||
1232 | } | 1240 | } |
1233 | if objects.all().count() < 2: | 1241 | if objects.all().count() < 2: |
1234 | context['disable_sort'] = True | 1242 | context['disable_sort'] = True |
1235 | response = render(request, template, context) | 1243 | response = toaster_render(request, template, context) |
1236 | _set_parameters_values(pagesize, orderby, request) | 1244 | _set_parameters_values(pagesize, orderby, request) |
1237 | return response | 1245 | return response |
1238 | 1246 | ||
@@ -1365,6 +1373,9 @@ if True: | |||
1365 | 1373 | ||
1366 | # new project | 1374 | # new project |
1367 | def newproject(request): | 1375 | def newproject(request): |
1376 | if not project_enable: | ||
1377 | return redirect( landing ) | ||
1378 | |||
1368 | template = "newproject.html" | 1379 | template = "newproject.html" |
1369 | context = { | 1380 | context = { |
1370 | 'email': request.user.email if request.user.is_authenticated() else '', | 1381 | 'email': request.user.email if request.user.is_authenticated() else '', |
@@ -1379,7 +1390,7 @@ if True: | |||
1379 | 1390 | ||
1380 | if request.method == "GET": | 1391 | if request.method == "GET": |
1381 | # render new project page | 1392 | # render new project page |
1382 | return render(request, template, context) | 1393 | return toaster_render(request, template, context) |
1383 | elif request.method == "POST": | 1394 | elif request.method == "POST": |
1384 | mandatory_fields = ['projectname', 'ptype'] | 1395 | mandatory_fields = ['projectname', 'ptype'] |
1385 | try: | 1396 | try: |
@@ -1419,7 +1430,7 @@ if True: | |||
1419 | context['alert'] = "Your chosen username is already used" | 1430 | context['alert'] = "Your chosen username is already used" |
1420 | else: | 1431 | else: |
1421 | context['alert'] = str(e) | 1432 | context['alert'] = str(e) |
1422 | return render(request, template, context) | 1433 | return toaster_render(request, template, context) |
1423 | 1434 | ||
1424 | raise Exception("Invalid HTTP method for this page") | 1435 | raise Exception("Invalid HTTP method for this page") |
1425 | 1436 | ||
@@ -1427,7 +1438,7 @@ if True: | |||
1427 | def project(request, pid): | 1438 | def project(request, pid): |
1428 | project = Project.objects.get(pk=pid) | 1439 | project = Project.objects.get(pk=pid) |
1429 | context = {"project": project} | 1440 | context = {"project": project} |
1430 | return render(request, "project.html", context) | 1441 | return toaster_render(request, "project.html", context) |
1431 | 1442 | ||
1432 | def jsunittests(request): | 1443 | def jsunittests(request): |
1433 | """ Provides a page for the js unit tests """ | 1444 | """ Provides a page for the js unit tests """ |
@@ -1453,7 +1464,7 @@ if True: | |||
1453 | name="MACHINE", | 1464 | name="MACHINE", |
1454 | value="qemux86") | 1465 | value="qemux86") |
1455 | context = {'project': new_project} | 1466 | context = {'project': new_project} |
1456 | return render(request, "js-unit-tests.html", context) | 1467 | return toaster_render(request, "js-unit-tests.html", context) |
1457 | 1468 | ||
1458 | from django.views.decorators.csrf import csrf_exempt | 1469 | from django.views.decorators.csrf import csrf_exempt |
1459 | @csrf_exempt | 1470 | @csrf_exempt |
@@ -1588,7 +1599,7 @@ if True: | |||
1588 | context = { | 1599 | context = { |
1589 | 'project': Project.objects.get(id=pid), | 1600 | 'project': Project.objects.get(id=pid), |
1590 | } | 1601 | } |
1591 | return render(request, template, context) | 1602 | return toaster_render(request, template, context) |
1592 | 1603 | ||
1593 | def layerdetails(request, pid, layerid): | 1604 | def layerdetails(request, pid, layerid): |
1594 | project = Project.objects.get(pk=pid) | 1605 | project = Project.objects.get(pk=pid) |
@@ -1617,7 +1628,7 @@ if True: | |||
1617 | 'projectlayers': list(project_layers) | 1628 | 'projectlayers': list(project_layers) |
1618 | } | 1629 | } |
1619 | 1630 | ||
1620 | return render(request, 'layerdetails.html', context) | 1631 | return toaster_render(request, 'layerdetails.html', context) |
1621 | 1632 | ||
1622 | 1633 | ||
1623 | def get_project_configvars_context(): | 1634 | def get_project_configvars_context(): |
@@ -1707,7 +1718,7 @@ if True: | |||
1707 | except (ProjectVariable.DoesNotExist, BuildEnvironment.DoesNotExist): | 1718 | except (ProjectVariable.DoesNotExist, BuildEnvironment.DoesNotExist): |
1708 | pass | 1719 | pass |
1709 | 1720 | ||
1710 | return render(request, "projectconf.html", context) | 1721 | return toaster_render(request, "projectconf.html", context) |
1711 | 1722 | ||
1712 | def _file_names_for_artifact(build, artifact_type, artifact_id): | 1723 | def _file_names_for_artifact(build, artifact_type, artifact_id): |
1713 | """ | 1724 | """ |
@@ -1774,7 +1785,7 @@ if True: | |||
1774 | 1785 | ||
1775 | return response | 1786 | return response |
1776 | else: | 1787 | else: |
1777 | return render(request, "unavailable_artifact.html") | 1788 | return toaster_render(request, "unavailable_artifact.html") |
1778 | except (ObjectDoesNotExist, IOError): | 1789 | except (ObjectDoesNotExist, IOError): |
1779 | return render(request, "unavailable_artifact.html") | 1790 | return toaster_render(request, "unavailable_artifact.html") |
1780 | 1791 | ||
diff --git a/bitbake/lib/toaster/toastergui/widgets.py b/bitbake/lib/toaster/toastergui/widgets.py index 67c1ff9615..a1792d997f 100644 --- a/bitbake/lib/toaster/toastergui/widgets.py +++ b/bitbake/lib/toaster/toastergui/widgets.py | |||
@@ -41,6 +41,7 @@ import types | |||
41 | import json | 41 | import json |
42 | import collections | 42 | import collections |
43 | import re | 43 | import re |
44 | import os | ||
44 | 45 | ||
45 | from toastergui.tablefilter import TableFilterMap | 46 | from toastergui.tablefilter import TableFilterMap |
46 | 47 | ||
@@ -86,6 +87,9 @@ class ToasterTable(TemplateView): | |||
86 | context['table_name'] = type(self).__name__.lower() | 87 | context['table_name'] = type(self).__name__.lower() |
87 | context['empty_state'] = self.empty_state | 88 | context['empty_state'] = self.empty_state |
88 | 89 | ||
90 | # global variables | ||
91 | context['project_enable'] = ('1' == os.environ.get('TOASTER_BUILDSERVER')) | ||
92 | |||
89 | return context | 93 | return context |
90 | 94 | ||
91 | def get(self, request, *args, **kwargs): | 95 | def get(self, request, *args, **kwargs): |