summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2014-10-14 13:57:33 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-10-30 13:39:51 +0000
commit298c3d52bab5cf38c37438c54853d6803ca194bd (patch)
tree2113944f04d337bc6a2ddfd2484f95ab7ea2d775
parent2837b110ae8fd5ff0ca3ac5959cadb7d4a5ce6cc (diff)
downloadpoky-298c3d52bab5cf38c37438c54853d6803ca194bd.tar.gz
bitbake: toastergui: provide download file capability
We add, for the localhost environments, the capability to download build artifacts. This is a pontentially dangerous API, because it gives unrestricted read access to the build environment file system - do not expose the functionality directly to the web layer, but use filtering/translation code, such as exemplified in the build_artifact view. The capability for remote build environments is dependent on bug 6835, as to use the collect storage as intermediary storage for serving files. [YOCTO #6834] (Bitbake rev: 5fce7f6e83c6143244faa9618b7ed20c1106e08f) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/toaster/bldcontrol/models.py13
-rw-r--r--bitbake/lib/toaster/toastergui/templates/builddashboard.html4
-rw-r--r--bitbake/lib/toaster/toastergui/templates/task.html4
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py5
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py40
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")