diff options
| -rw-r--r-- | bitbake/lib/toaster/bldcontrol/models.py | 13 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/templates/builddashboard.html | 4 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/templates/task.html | 4 | ||||
| -rw-r--r-- | bitbake/lib/toaster/toastergui/urls.py | 5 | ||||
| -rwxr-xr-x | bitbake/lib/toaster/toastergui/views.py | 40 |
5 files changed, 65 insertions, 1 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/models.py b/bitbake/lib/toaster/bldcontrol/models.py index df3635b331..15270c3a57 100644 --- a/bitbake/lib/toaster/bldcontrol/models.py +++ b/bitbake/lib/toaster/bldcontrol/models.py | |||
| @@ -40,6 +40,19 @@ class BuildEnvironment(models.Model): | |||
| 40 | updated = models.DateTimeField(auto_now = True) | 40 | updated = models.DateTimeField(auto_now = True) |
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | def get_artifact_type(self, path): | ||
| 44 | if self.betype == BuildEnvironment.TYPE_LOCAL: | ||
| 45 | import magic | ||
| 46 | m = magic.open(magic.MAGIC_MIME_TYPE) | ||
| 47 | m.load() | ||
| 48 | return m.file(path) | ||
| 49 | raise Exception("FIXME: not implemented") | ||
| 50 | |||
| 51 | def get_artifact(self, path): | ||
| 52 | if self.betype == BuildEnvironment.TYPE_LOCAL: | ||
| 53 | return open(path, "r") | ||
| 54 | raise Exception("FIXME: not implemented") | ||
| 55 | |||
| 43 | # a BuildRequest is a request that the scheduler will build using a BuildEnvironment | 56 | # a BuildRequest is a request that the scheduler will build using a BuildEnvironment |
| 44 | # the build request queue is the table itself, ordered by state | 57 | # the build request queue is the table itself, ordered by state |
| 45 | 58 | ||
diff --git a/bitbake/lib/toaster/toastergui/templates/builddashboard.html b/bitbake/lib/toaster/toastergui/templates/builddashboard.html index 8a6709cfe1..2aa7b6bcfb 100644 --- a/bitbake/lib/toaster/toastergui/templates/builddashboard.html +++ b/bitbake/lib/toaster/toastergui/templates/builddashboard.html | |||
| @@ -58,7 +58,11 @@ | |||
| 58 | <div class="span10"> | 58 | <div class="span10"> |
| 59 | {% for error in logmessages %}{% if error.level == 2 %} | 59 | {% for error in logmessages %}{% if error.level == 2 %} |
| 60 | <div class="alert alert-error"> | 60 | <div class="alert alert-error"> |
| 61 | {% if MANAGED and error.pathname %} | ||
| 62 | <pre><a href="{% url 'build_artifact' build.pk 'logmessagefile' error.pk %}" target="_blanc">{{error.message}}</pre> | ||
| 63 | {% else %} | ||
| 61 | <pre>{{error.message}}</pre> | 64 | <pre>{{error.message}}</pre> |
| 65 | {% endif %} | ||
| 62 | </div> | 66 | </div> |
| 63 | {% endif %}{% endfor %} | 67 | {% endif %}{% endfor %} |
| 64 | </div> | 68 | </div> |
diff --git a/bitbake/lib/toaster/toastergui/templates/task.html b/bitbake/lib/toaster/toastergui/templates/task.html index d7e2619f5f..1b270420db 100644 --- a/bitbake/lib/toaster/toastergui/templates/task.html +++ b/bitbake/lib/toaster/toastergui/templates/task.html | |||
| @@ -28,7 +28,11 @@ | |||
| 28 | <i class="icon-question-sign get-help" title="Path the task log file"></i> Log file | 28 | <i class="icon-question-sign get-help" title="Path the task log file"></i> Log file |
| 29 | </dt> | 29 | </dt> |
| 30 | <dd> | 30 | <dd> |
| 31 | {% if MANAGED %} | ||
| 32 | <code><a href="{% url 'build_artifact' build.pk 'tasklogfile' task.pk %}" target="_blanc">{{task.logfile}}</a></code> | ||
| 33 | {% else %} | ||
| 31 | <code>{{task.logfile}}</code> | 34 | <code>{{task.logfile}}</code> |
| 35 | {% endif %} | ||
| 32 | </dd> | 36 | </dd> |
| 33 | {% endif %} | 37 | {% endif %} |
| 34 | {# show stack trace for failed task #} | 38 | {# show stack trace for failed task #} |
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py index 07821b6036..f43bb64653 100644 --- a/bitbake/lib/toaster/toastergui/urls.py +++ b/bitbake/lib/toaster/toastergui/urls.py | |||
| @@ -59,11 +59,14 @@ urlpatterns = patterns('toastergui.views', | |||
| 59 | url(r'^build/(?P<build_id>\d+)/cpuusage$', 'cpuusage', name='cpuusage'), | 59 | url(r'^build/(?P<build_id>\d+)/cpuusage$', 'cpuusage', name='cpuusage'), |
| 60 | url(r'^build/(?P<build_id>\d+)/diskio$', 'diskio', name='diskio'), | 60 | url(r'^build/(?P<build_id>\d+)/diskio$', 'diskio', name='diskio'), |
| 61 | 61 | ||
| 62 | # image information dir - not yet implemented | 62 | # image information dir |
| 63 | url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/packagefile/(?P<packagefile_id>\d+)$', | 63 | url(r'^build/(?P<build_id>\d+)/target/(?P<target_id>\d+)/packagefile/(?P<packagefile_id>\d+)$', |
| 64 | 'image_information_dir', name='image_information_dir'), | 64 | 'image_information_dir', name='image_information_dir'), |
| 65 | 65 | ||
| 66 | 66 | ||
| 67 | # build download artifact | ||
| 68 | url(r'^build/(?P<build_id>\d+)/artifact/(?P<artifact_type>\w+)/id/(?P<artifact_id>\w+)', 'build_artifact', name="build_artifact"), | ||
| 69 | |||
| 67 | # urls not linked from the dashboard | 70 | # urls not linked from the dashboard |
| 68 | url(r'^layerversions/(?P<layerversion_id>\d+)/recipes/.*$', 'layer_versions_recipes', name='layer_versions_recipes'), | 71 | url(r'^layerversions/(?P<layerversion_id>\d+)/recipes/.*$', 'layer_versions_recipes', name='layer_versions_recipes'), |
| 69 | 72 | ||
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 38d67e378f..e568ee70ed 100755 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
| @@ -2603,6 +2603,43 @@ if toastermain.settings.MANAGED: | |||
| 2603 | 2603 | ||
| 2604 | 2604 | ||
| 2605 | 2605 | ||
| 2606 | def build_artifact(request, build_id, artifact_type, artifact_id): | ||
| 2607 | try: | ||
| 2608 | b = Build.objects.get(pk=build_id) | ||
| 2609 | if b.buildrequest is None or b.buildrequest.environment is None: | ||
| 2610 | raise Exception("Cannot download file") | ||
| 2611 | |||
| 2612 | file_name = None | ||
| 2613 | fsock = None | ||
| 2614 | content_type='application/force-download' | ||
| 2615 | # Target_Image_File file_name | ||
| 2616 | # Task logfile | ||
| 2617 | if artifact_type == "tasklogfile": | ||
| 2618 | file_name = Task.objects.get(build = b, pk = artifact_id).logfile | ||
| 2619 | |||
| 2620 | # Task path_to_sstate_obj | ||
| 2621 | # Package_File path | ||
| 2622 | # Recipe file_path | ||
| 2623 | # VariableHistory file_name | ||
| 2624 | # LogMessage pathname | ||
| 2625 | if artifact_type == "logmessagefile": | ||
| 2626 | file_name = LogMessage.objects.get(build = b, pk = artifact_id).pathname | ||
| 2627 | |||
| 2628 | if file_name is not None: | ||
| 2629 | content_type = b.buildrequest.environment.get_artifact_type(file_name) | ||
| 2630 | fsock = b.buildrequest.environment.get_artifact(file_name) | ||
| 2631 | file_name = os.path.basename(file_name) | ||
| 2632 | |||
| 2633 | response = HttpResponse(fsock, content_type = content_type) | ||
| 2634 | |||
| 2635 | # returns a file from the environment | ||
| 2636 | response['Content-Disposition'] = 'attachment; filename=' + file_name | ||
| 2637 | return response | ||
| 2638 | except: | ||
| 2639 | raise | ||
| 2640 | |||
| 2641 | |||
| 2642 | |||
| 2606 | def projects(request): | 2643 | def projects(request): |
| 2607 | template="projects.html" | 2644 | template="projects.html" |
| 2608 | 2645 | ||
| @@ -2725,5 +2762,8 @@ else: | |||
| 2725 | def projectbuilds(request): | 2762 | def projectbuilds(request): |
| 2726 | raise Exception("page not available in interactive mode") | 2763 | raise Exception("page not available in interactive mode") |
| 2727 | 2764 | ||
| 2765 | def build_artifact(request, build_id, artifact_type, artifact_id): | ||
| 2766 | raise Exception("page not available in interactive mode") | ||
| 2767 | |||
| 2728 | def projects(request): | 2768 | def projects(request): |
| 2729 | raise Exception("page not available in interactive mode") | 2769 | raise Exception("page not available in interactive mode") |
