diff options
Diffstat (limited to 'bitbake/lib/toaster/toastergui/views.py')
| -rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 168 |
1 files changed, 101 insertions, 67 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 8301f6ce66..736de784a3 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -27,7 +27,7 @@ from django.db import IntegrityError | |||
| 27 | from django.shortcuts import render, redirect | 27 | from django.shortcuts import render, redirect |
| 28 | from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable | 28 | from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable |
| 29 | from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency | 29 | from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency |
| 30 | from orm.models import Target_Installed_Package, Target_File, Target_Image_File | 30 | from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact |
| 31 | from django.views.decorators.cache import cache_control | 31 | from django.views.decorators.cache import cache_control |
| 32 | from django.core.urlresolvers import reverse | 32 | from django.core.urlresolvers import reverse |
| 33 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | 33 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
| @@ -421,30 +421,36 @@ def builds(request): | |||
| 421 | 'ordericon':_get_toggle_order_icon(request, "timespent"), | 421 | 'ordericon':_get_toggle_order_icon(request, "timespent"), |
| 422 | 'orderkey' : 'timespent', | 422 | 'orderkey' : 'timespent', |
| 423 | }, | 423 | }, |
| 424 | {'name': 'Log', | 424 | {'name': 'Image files', 'clclass': 'output', |
| 425 | 'qhelp': "The root file system types produced by the build. You can find them in your <code>/build/tmp/deploy/images/</code> directory", | ||
| 426 | # TODO: compute image fstypes from Target_Image_File | ||
| 427 | }, | ||
| 428 | ] | ||
| 429 | } | ||
| 430 | |||
| 431 | if not toastermain.settings.MANAGED: | ||
| 432 | context['tablecols'].insert(-2, | ||
| 433 | {'name': 'Log1', | ||
| 425 | 'dclass': "span4", | 434 | 'dclass': "span4", |
| 426 | 'qhelp': "Path to the build main log file", | 435 | 'qhelp': "Path to the build main log file", |
| 427 | 'clclass': 'log', 'hidden': 1, | 436 | 'clclass': 'log', 'hidden': 1, |
| 428 | 'orderfield': _get_toggle_order(request, "cooker_log_path"), | 437 | 'orderfield': _get_toggle_order(request, "cooker_log_path"), |
| 429 | 'ordericon':_get_toggle_order_icon(request, "cooker_log_path"), | 438 | 'ordericon':_get_toggle_order_icon(request, "cooker_log_path"), |
| 430 | 'orderkey' : 'cooker_log_path', | 439 | 'orderkey' : 'cooker_log_path', |
| 431 | }, | 440 | } |
| 432 | {'name': 'Output', 'clclass': 'output', | 441 | ) |
| 433 | 'qhelp': "The root file system types produced by the build. You can find them in your <code>/build/tmp/deploy/images/</code> directory", | 442 | |
| 434 | # TODO: compute image fstypes from Target_Image_File | ||
| 435 | }, | ||
| 436 | ] | ||
| 437 | } | ||
| 438 | 443 | ||
| 439 | if toastermain.settings.MANAGED: | 444 | if toastermain.settings.MANAGED: |
| 440 | context['tablecols'].append( | 445 | context['tablecols'].append( |
| 441 | {'name': 'Project', 'clclass': 'project', | 446 | {'name': 'Project', 'clclass': 'project', |
| 442 | 'filter': {'class': 'project', | 447 | 'filter': {'class': 'project', |
| 443 | 'label': 'Project:', | 448 | 'label': 'Project:', |
| 444 | 'options': map(lambda x: (x.name,'',x.build_set.filter(outcome__lt=Build.IN_PROGRESS).count()), Project.objects.all()), | 449 | 'options': map(lambda x: (x.name,'',x.build_set.filter(outcome__lt=Build.IN_PROGRESS).count()), Project.objects.all()), |
| 445 | 450 | ||
| 446 | } | 451 | } |
| 447 | }) | 452 | } |
| 453 | ) | ||
| 448 | 454 | ||
| 449 | 455 | ||
| 450 | response = render(request, template, context) | 456 | response = render(request, template, context) |
| @@ -481,12 +487,8 @@ def builddashboard( request, build_id ): | |||
| 481 | hasImages = True | 487 | hasImages = True |
| 482 | npkg = 0 | 488 | npkg = 0 |
| 483 | pkgsz = 0 | 489 | pkgsz = 0 |
| 484 | pid= 0 | ||
| 485 | tp = Target_Installed_Package.objects.filter( target_id = t.id ) | ||
| 486 | package = None | 490 | package = None |
| 487 | for p in tp: | 491 | for package in Package.objects.filter(id__in = [x.package_id for x in t.target_installed_package_set.all()]): |
| 488 | pid = p.package_id | ||
| 489 | package = Package.objects.get( pk = p.package_id ) | ||
| 490 | pkgsz = pkgsz + package.size | 492 | pkgsz = pkgsz + package.size |
| 491 | if ( package.installed_name ): | 493 | if ( package.installed_name ): |
| 492 | npkg = npkg + 1 | 494 | npkg = npkg + 1 |
| @@ -499,7 +501,7 @@ def builddashboard( request, build_id ): | |||
| 499 | if ( ndx < 0 ): | 501 | if ( ndx < 0 ): |
| 500 | ndx = 0; | 502 | ndx = 0; |
| 501 | f = i.file_name[ ndx + 1: ] | 503 | f = i.file_name[ ndx + 1: ] |
| 502 | imageFiles.append({ 'path': f, 'size' : i.file_size }) | 504 | imageFiles.append({ 'id': i.id, 'path': f, 'size' : i.file_size }) |
| 503 | if ( t.is_image and | 505 | if ( t.is_image and |
| 504 | (( len( imageFiles ) <= 0 ) or ( len( t.license_manifest_path ) <= 0 ))): | 506 | (( len( imageFiles ) <= 0 ) or ( len( t.license_manifest_path ) <= 0 ))): |
| 505 | targetHasNoImages = True | 507 | targetHasNoImages = True |
| @@ -517,6 +519,8 @@ def builddashboard( request, build_id ): | |||
| 517 | if ( p.installed_name ): | 519 | if ( p.installed_name ): |
| 518 | packageCount = packageCount + 1 | 520 | packageCount = packageCount + 1 |
| 519 | 521 | ||
| 522 | logmessages = list(LogMessage.objects.filter( build = build_id )) | ||
| 523 | |||
| 520 | context = { | 524 | context = { |
| 521 | 'build' : build, | 525 | 'build' : build, |
| 522 | 'hasImages' : hasImages, | 526 | 'hasImages' : hasImages, |
| @@ -524,7 +528,7 @@ def builddashboard( request, build_id ): | |||
| 524 | 'targets' : targets, | 528 | 'targets' : targets, |
| 525 | 'recipecount' : recipeCount, | 529 | 'recipecount' : recipeCount, |
| 526 | 'packagecount' : packageCount, | 530 | 'packagecount' : packageCount, |
| 527 | 'logmessages' : LogMessage.objects.filter( build = build_id ), | 531 | 'logmessages' : logmessages, |
| 528 | } | 532 | } |
| 529 | return render( request, template, context ) | 533 | return render( request, template, context ) |
| 530 | 534 | ||
| @@ -637,6 +641,9 @@ def target_common( request, build_id, target_id, variant ): | |||
| 637 | Package, queryset, filter_string, search_term, ordering_string, 'name' ) | 641 | Package, queryset, filter_string, search_term, ordering_string, 'name' ) |
| 638 | packages = _build_page_range( Paginator(queryset, pagesize), request.GET.get( 'page', 1 )) | 642 | packages = _build_page_range( Paginator(queryset, pagesize), request.GET.get( 'page', 1 )) |
| 639 | 643 | ||
| 644 | |||
| 645 | build = Build.objects.get( pk = build_id ) | ||
| 646 | |||
| 640 | # bring in package dependencies | 647 | # bring in package dependencies |
| 641 | for p in packages.object_list: | 648 | for p in packages.object_list: |
| 642 | p.runtime_dependencies = p.package_dependencies_source.filter( | 649 | p.runtime_dependencies = p.package_dependencies_source.filter( |
| @@ -697,8 +704,7 @@ eans multiple licenses exist that cover different parts of the source', | |||
| 697 | tc_dependencies[ "hidden" ] = 1 | 704 | tc_dependencies[ "hidden" ] = 1 |
| 698 | tc_rdependencies = { | 705 | tc_rdependencies = { |
| 699 | 'name' : 'Reverse dependencies', | 706 | 'name' : 'Reverse dependencies', |
| 700 | 'qhelp' : 'Package run-time reverse dependencies (i.e. which other packages depend on t\ | 707 | 'qhelp' : 'Package run-time reverse dependencies (i.e. which other packages depend on this package', |
| 701 | his package', | ||
| 702 | 'clclass' : 'brought_in_by', | 708 | 'clclass' : 'brought_in_by', |
| 703 | } | 709 | } |
| 704 | if ( variant == 'target' ): | 710 | if ( variant == 'target' ): |
| @@ -741,18 +747,10 @@ his package', | |||
| 741 | 'clclass' : 'layer_commit', | 747 | 'clclass' : 'layer_commit', |
| 742 | 'hidden' : 1, | 748 | 'hidden' : 1, |
| 743 | } | 749 | } |
| 744 | tc_layerDir = { | 750 | |
| 745 | 'name':'Layer directory', | ||
| 746 | 'qhelp':'Location in disk of the layer providing the recipe that builds the package', | ||
| 747 | 'orderfield' : _get_toggle_order( request, "recipe__layer_version__layer__local_path" ), | ||
| 748 | 'ordericon' : _get_toggle_order_icon( request, "recipe__layer_version__layer__local_path" )\ | ||
| 749 | , | ||
| 750 | 'clclass' : 'layer_directory', | ||
| 751 | 'hidden' : 1, | ||
| 752 | } | ||
| 753 | context = { | 751 | context = { |
| 754 | 'objectname': variant, | 752 | 'objectname': variant, |
| 755 | 'build' : Build.objects.filter( pk = build_id )[ 0 ], | 753 | 'build' : build, |
| 756 | 'target' : Target.objects.filter( pk = target_id )[ 0 ], | 754 | 'target' : Target.objects.filter( pk = target_id )[ 0 ], |
| 757 | 'objects' : packages, | 755 | 'objects' : packages, |
| 758 | 'packages_sum' : packages_sum[ 'installed_size__sum' ], | 756 | 'packages_sum' : packages_sum[ 'installed_size__sum' ], |
| @@ -771,10 +769,21 @@ his package', | |||
| 771 | tc_layer, | 769 | tc_layer, |
| 772 | tc_layerBranch, | 770 | tc_layerBranch, |
| 773 | tc_layerCommit, | 771 | tc_layerCommit, |
| 774 | tc_layerDir, | ||
| 775 | ] | 772 | ] |
| 776 | } | 773 | } |
| 777 | 774 | ||
| 775 | if not toastermain.settings.MANAGED or build.project is None: | ||
| 776 | |||
| 777 | tc_layerDir = { | ||
| 778 | 'name':'Layer directory', | ||
| 779 | 'qhelp':'Location in disk of the layer providing the recipe that builds the package', | ||
| 780 | 'orderfield' : _get_toggle_order( request, "recipe__layer_version__layer__local_path" ), | ||
| 781 | 'ordericon' : _get_toggle_order_icon( request, "recipe__layer_version__layer__local_path" ), | ||
| 782 | 'clclass' : 'layer_directory', | ||
| 783 | 'hidden' : 1, | ||
| 784 | } | ||
| 785 | context['tablecols'].append(tc_layerDir) | ||
| 786 | |||
| 778 | response = render(request, template, context) | 787 | response = render(request, template, context) |
| 779 | _save_parameters_cookies(response, pagesize, orderby, request) | 788 | _save_parameters_cookies(response, pagesize, orderby, request) |
| 780 | return response | 789 | return response |
| @@ -1136,12 +1145,13 @@ def tasks_common(request, build_id, variant, task_anchor): | |||
| 1136 | } | 1145 | } |
| 1137 | if 'diskio' == variant: tc_diskio['hidden']='0'; del tc_diskio['clclass']; tc_cache['hidden']='1'; | 1146 | if 'diskio' == variant: tc_diskio['hidden']='0'; del tc_diskio['clclass']; tc_cache['hidden']='1'; |
| 1138 | 1147 | ||
| 1148 | build = Build.objects.get(pk=build_id) | ||
| 1139 | 1149 | ||
| 1140 | context = { 'objectname': variant, | 1150 | context = { 'objectname': variant, |
| 1141 | 'object_search_display': object_search_display, | 1151 | 'object_search_display': object_search_display, |
| 1142 | 'filter_search_display': filter_search_display, | 1152 | 'filter_search_display': filter_search_display, |
| 1143 | 'title': title_variant, | 1153 | 'title': title_variant, |
| 1144 | 'build': Build.objects.get(pk=build_id), | 1154 | 'build': build, |
| 1145 | 'objects': tasks, | 1155 | 'objects': tasks, |
| 1146 | 'default_orderby' : orderby, | 1156 | 'default_orderby' : orderby, |
| 1147 | 'search_term': search_term, | 1157 | 'search_term': search_term, |
| @@ -1157,9 +1167,12 @@ def tasks_common(request, build_id, variant, task_anchor): | |||
| 1157 | tc_time, | 1167 | tc_time, |
| 1158 | tc_cpu, | 1168 | tc_cpu, |
| 1159 | tc_diskio, | 1169 | tc_diskio, |
| 1160 | tc_log, | ||
| 1161 | ]} | 1170 | ]} |
| 1162 | 1171 | ||
| 1172 | |||
| 1173 | if not toastermain.settings.MANAGED or build.project is None: | ||
| 1174 | context['tablecols'].append(tc_log) | ||
| 1175 | |||
| 1163 | response = render(request, template, context) | 1176 | response = render(request, template, context) |
| 1164 | _save_parameters_cookies(response, pagesize, orderby, request) | 1177 | _save_parameters_cookies(response, pagesize, orderby, request) |
| 1165 | return response | 1178 | return response |
| @@ -1206,9 +1219,11 @@ def recipes(request, build_id): | |||
| 1206 | revlist.append(recipe_dep) | 1219 | revlist.append(recipe_dep) |
| 1207 | revs[recipe.id] = revlist | 1220 | revs[recipe.id] = revlist |
| 1208 | 1221 | ||
| 1222 | build = Build.objects.get(pk=build_id) | ||
| 1223 | |||
| 1209 | context = { | 1224 | context = { |
| 1210 | 'objectname': 'recipes', | 1225 | 'objectname': 'recipes', |
| 1211 | 'build': Build.objects.get(pk=build_id), | 1226 | 'build': build, |
| 1212 | 'objects': recipes, | 1227 | 'objects': recipes, |
| 1213 | 'default_orderby' : 'name:+', | 1228 | 'default_orderby' : 'name:+', |
| 1214 | 'recipe_deps' : deps, | 1229 | 'recipe_deps' : deps, |
| @@ -1279,6 +1294,11 @@ def recipes(request, build_id): | |||
| 1279 | 'qhelp':'The Git commit of the layer providing the recipe', | 1294 | 'qhelp':'The Git commit of the layer providing the recipe', |
| 1280 | 'clclass': 'layer_version__layer__commit', 'hidden': 1, | 1295 | 'clclass': 'layer_version__layer__commit', 'hidden': 1, |
| 1281 | }, | 1296 | }, |
| 1297 | ] | ||
| 1298 | } | ||
| 1299 | |||
| 1300 | if not toastermain.settings.MANAGED or build.project is None: | ||
| 1301 | context['tablecols'].append( | ||
| 1282 | { | 1302 | { |
| 1283 | 'name':'Layer directory', | 1303 | 'name':'Layer directory', |
| 1284 | 'qhelp':'Path to the layer prodiving the recipe', | 1304 | 'qhelp':'Path to the layer prodiving the recipe', |
| @@ -1286,9 +1306,8 @@ def recipes(request, build_id): | |||
| 1286 | 'ordericon':_get_toggle_order_icon(request, "layer_version__layer__local_path"), | 1306 | 'ordericon':_get_toggle_order_icon(request, "layer_version__layer__local_path"), |
| 1287 | 'orderkey' : 'layer_version__layer__local_path', | 1307 | 'orderkey' : 'layer_version__layer__local_path', |
| 1288 | 'clclass': 'layer_version__layer__local_path', 'hidden': 1, | 1308 | 'clclass': 'layer_version__layer__local_path', 'hidden': 1, |
| 1289 | }, | 1309 | }) |
| 1290 | ] | 1310 | |
| 1291 | } | ||
| 1292 | 1311 | ||
| 1293 | response = render(request, template, context) | 1312 | response = render(request, template, context) |
| 1294 | _save_parameters_cookies(response, pagesize, orderby, request) | 1313 | _save_parameters_cookies(response, pagesize, orderby, request) |
| @@ -2685,41 +2704,53 @@ if toastermain.settings.MANAGED: | |||
| 2685 | return render(request, template, context) | 2704 | return render(request, template, context) |
| 2686 | 2705 | ||
| 2687 | 2706 | ||
| 2707 | def _file_name_for_artifact(b, artifact_type, artifact_id): | ||
| 2708 | file_name = None | ||
| 2709 | # Target_Image_File file_name | ||
| 2710 | if artifact_type == "imagefile": | ||
| 2711 | file_name = Target_Image_File.objects.get(target__build = b, pk = artifact_id).file_name | ||
| 2688 | 2712 | ||
| 2689 | def build_artifact(request, build_id, artifact_type, artifact_id): | 2713 | elif artifact_type == "cookerlog": |
| 2690 | try: | 2714 | file_name = b.cooker_log_path |
| 2691 | b = Build.objects.get(pk=build_id) | 2715 | |
| 2692 | if b.buildrequest is None or b.buildrequest.environment is None: | 2716 | elif artifact_type == "buildartifact": |
| 2693 | raise Exception("Cannot download file") | 2717 | file_name = BuildArtifact.objects.get(build = b, pk = artifact_id).file_name |
| 2694 | 2718 | ||
| 2695 | file_name = None | 2719 | elif artifact_type == "licensemanifest": |
| 2696 | fsock = None | 2720 | file_name = Target.objects.get(build = b, pk = artifact_id).license_manifest_path |
| 2697 | content_type='application/force-download' | ||
| 2698 | # Target_Image_File file_name | ||
| 2699 | # Task logfile | ||
| 2700 | if artifact_type == "tasklogfile": | ||
| 2701 | file_name = Task.objects.get(build = b, pk = artifact_id).logfile | ||
| 2702 | 2721 | ||
| 2703 | # Task path_to_sstate_obj | 2722 | elif artifact_type == "tasklogfile": |
| 2704 | # Package_File path | 2723 | file_name = Task.objects.get(build = b, pk = artifact_id).logfile |
| 2705 | # Recipe file_path | ||
| 2706 | # VariableHistory file_name | ||
| 2707 | # LogMessage pathname | ||
| 2708 | if artifact_type == "logmessagefile": | ||
| 2709 | file_name = LogMessage.objects.get(build = b, pk = artifact_id).pathname | ||
| 2710 | 2724 | ||
| 2711 | if file_name is not None: | 2725 | elif artifact_type == "logmessagefile": |
| 2712 | content_type = b.buildrequest.environment.get_artifact_type(file_name) | 2726 | file_name = LogMessage.objects.get(build = b, pk = artifact_id).pathname |
| 2713 | fsock = b.buildrequest.environment.get_artifact(file_name) | 2727 | else: |
| 2714 | file_name = os.path.basename(file_name) | 2728 | raise Exception("FIXME: artifact type %s not implemented" % (artifact_type)) |
| 2715 | 2729 | ||
| 2716 | response = HttpResponse(fsock, content_type = content_type) | 2730 | return file_name |
| 2717 | 2731 | ||
| 2718 | # returns a file from the environment | 2732 | |
| 2719 | response['Content-Disposition'] = 'attachment; filename=' + file_name | 2733 | def build_artifact(request, build_id, artifact_type, artifact_id): |
| 2720 | return response | 2734 | b = Build.objects.get(pk=build_id) |
| 2721 | except: | 2735 | if b.buildrequest is None or b.buildrequest.environment is None: |
| 2722 | raise | 2736 | raise Exception("Artifact not available for download (missing build request or build environment)") |
| 2737 | |||
| 2738 | file_name = _file_name_for_artifact(b, artifact_type, artifact_id) | ||
| 2739 | fsock = None | ||
| 2740 | content_type='application/force-download' | ||
| 2741 | |||
| 2742 | if file_name is None: | ||
| 2743 | raise Exception("Could not handle artifact %s id %s" % (artifact_type, artifact_id)) | ||
| 2744 | else: | ||
| 2745 | content_type = b.buildrequest.environment.get_artifact_type(file_name) | ||
| 2746 | fsock = b.buildrequest.environment.get_artifact(file_name) | ||
| 2747 | file_name = os.path.basename(file_name) # we assume that the build environment system has the same path conventions as host | ||
| 2748 | |||
| 2749 | response = HttpResponse(fsock, content_type = content_type) | ||
| 2750 | |||
| 2751 | # returns a file from the environment | ||
| 2752 | response['Content-Disposition'] = 'attachment; filename=' + file_name | ||
| 2753 | return response | ||
| 2723 | 2754 | ||
| 2724 | 2755 | ||
| 2725 | 2756 | ||
| @@ -2856,3 +2887,6 @@ else: | |||
| 2856 | 2887 | ||
| 2857 | def projects(request): | 2888 | def projects(request): |
| 2858 | raise Exception("page not available in interactive mode") | 2889 | raise Exception("page not available in interactive mode") |
| 2890 | |||
| 2891 | def xhr_importlayer(request): | ||
| 2892 | raise Exception("page not available in interactive mode") | ||
