Merge lp:~milo/linaro-ci-dashboard/lava-data-model into lp:linaro-ci-dashboard

Proposed by Milo Casagrande
Status: Merged
Merged at revision: 67
Proposed branch: lp:~milo/linaro-ci-dashboard/lava-data-model
Merge into: lp:linaro-ci-dashboard
Diff against target: 1083 lines (+865/-7) (has conflicts)
22 files modified
Makefile (+2/-0)
dashboard/frontend/forms/loop_form.py (+6/-3)
dashboard/frontend/migrations/0007_auto__add_field_loopbuild_lava_test_status.py (+52/-0)
dashboard/frontend/migrations/0008_auto__add_field_loop_lava_tests.py (+53/-0)
dashboard/frontend/models/loop.py (+1/-0)
dashboard/frontend/models/loop_build.py (+3/-0)
dashboard/frontend/templates/loop_detail.html (+2/-2)
dashboard/js/lava/lava_test_select.js (+28/-0)
dashboard/lava/lib/lavalib.py (+249/-0)
dashboard/lava/migrations/0001_initial.py (+65/-0)
dashboard/lava/models/__init__.py (+1/-0)
dashboard/lava/models/lava.py (+37/-0)
dashboard/lava/templates/lava_select.html (+66/-0)
dashboard/lava/templates/tests_list.html (+7/-0)
dashboard/lava/tests/__init__.py (+23/-0)
dashboard/lava/tests/test_lavalib.py (+70/-0)
dashboard/lava/urls.py (+29/-0)
dashboard/lava/views/lava_select_test_names.py (+58/-0)
dashboard/lava/views/lava_select_view.py (+46/-0)
dashboard/lava/widgets/lava_test_select_widget.py (+54/-0)
dashboard/settings.py (+8/-0)
dashboard/urls.py (+5/-2)
Text conflict in dashboard/settings.py
To merge this branch: bzr merge lp:~milo/linaro-ci-dashboard/lava-data-model
Reviewer Review Type Date Requested Status
Stevan Radaković Pending
Review via email: mp+125162@code.launchpad.net

Description of the change

Merge proposal to keep track and discuss the LAVA model and other implementation details.

Discussin with Danilo we thought about creating a separate app for the ci-dashboard, more or less as jenkinsserver.
In this first implmentation there is the structure of the app, initial implementation for the model, and a lib subdirectory ofr a library to interact with LAVA XML-RPC.

To post a comment you must log in.
53. By Milo Casagrande

Merged from trunk.

Revision history for this message
Stevan Radaković (stevanr) wrote :

This looks OK for now.
I guess you already have these things in mind, but I'm going to list additional things to be extended here:
1. Extend the test status to match all available status results as in LAVA and move the status choices list to i.e. settings so it can be used in both loop_build and lavatest classes.
2. Add the unit tests for lava library.
3. I noticed in LAVA that each test contain multiple entries (i don't know what entity is this you can see in https://validation.linaro.org/lava-server/dashboard/tests/lava/ ) which that have Total results and total failures and stuff like that. So how do we plan to cover this, or do we want to do it at all?

Revision history for this message
Milo Casagrande (milo) wrote :

On Wed, Sep 19, 2012 at 3:46 PM, Stevan Radaković
<email address hidden> wrote:
> This looks OK for now.
> I guess you already have these things in mind, but I'm going to list additional things to be extended here:
> 1. Extend the test status to match all available status results as in LAVA and move the status choices list to i.e. settings so it can be used in both loop_build and lavatest classes.

Yeah, I was thinking where to move those values, and settings.py is a
good place to store the all for both of them.

> 2. Add the unit tests for lava library.

Sure, that is way needed. Didn't insert it at the moment, need to
clear some things out first.

> 3. I noticed in LAVA that each test contain multiple entries (i don't know what entity is this you can see in https://validation.linaro.org/lava-server/dashboard/tests/lava/ ) which that have Total results and total failures and stuff like that. So how do we plan to cover this, or do we want to do it at all?

I think we might not cover that at the moment. That is the total
number of runs for that test. Indipendently of the
board/build/whatever. It is just a big total of how many times that
test has been used, not really relevant to what we are doing.

The other thing I'm looking into, is how to best retrieve information
out from LAVA, even server side in an asynchronous way, without having
to deal with cron job. I was thinking about using RabbitMQ/Celery for
this: schedule the necessary tasks, and let the queue handle them. But
those are two new dependencies we have to deal with (maybe good to
start discussion on the mailing list).

Thanks for taking a look!

--
Milo Casagrande
Infrastructure Engineer
Linaro.org <www.linaro.org> │ Open source software for ARM SoCs

54. By Milo Casagrande

Added initial tests selection view.

55. By Milo Casagrande

Added field to store list of tests for each loop, needs custom widget.

56. By Milo Casagrande

Added LAVA widget for test selection.

57. By Milo Casagrande

Merged from trunk.

58. By Milo Casagrande

Added OK button to dialog.

59. By Milo Casagrande

Clean up and fixes.

60. By Milo Casagrande

Added hard-coded test names.

61. By Milo Casagrande

Added lavalib tests, started porting of linaro-android-tools.

62. By Milo Casagrande

Added placeholder for new method.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile'
--- Makefile 2012-09-14 13:44:53 +0000
+++ Makefile 2012-09-21 15:30:40 +0000
@@ -12,6 +12,8 @@
12 echo "No changes to frontend models."12 echo "No changes to frontend models."
13 python dashboard/manage.py schemamigration jenkinsserver --auto || \13 python dashboard/manage.py schemamigration jenkinsserver --auto || \
14 echo "No changes to jenkins models."14 echo "No changes to jenkins models."
15 python dashboard/manage.py schemamigration lava --auto || \
16 echo "No changes to lava models."
15 python dashboard/manage.py schemamigration android_build --auto || \17 python dashboard/manage.py schemamigration android_build --auto || \
16 echo "No changes to android_build models."18 echo "No changes to android_build models."
17 python dashboard/manage.py schemamigration kernel_build --auto || \19 python dashboard/manage.py schemamigration kernel_build --auto || \
1820
=== modified file 'dashboard/frontend/forms/loop_form.py'
--- dashboard/frontend/forms/loop_form.py 2012-09-10 14:27:16 +0000
+++ dashboard/frontend/forms/loop_form.py 2012-09-21 15:30:40 +0000
@@ -23,6 +23,7 @@
23 )23 )
24from frontend.models.loop import Loop24from frontend.models.loop import Loop
25from frontend.widgets.chain_loop_widget import ChainLoopWidget25from frontend.widgets.chain_loop_widget import ChainLoopWidget
26from lava.widgets.lava_test_select_widget import LavaTestSelectWidget
2627
2728
28class LoopForm(ModelForm):29class LoopForm(ModelForm):
@@ -31,18 +32,20 @@
31 """32 """
32 class Meta:33 class Meta:
33 model = Loop34 model = Loop
34 exclude = ('server')35 exclude = ('server', 'lava_tests')
3536
36 next_loop = IntegerField(widget=ChainLoopWidget, required=False)37 next_loop = IntegerField(widget=ChainLoopWidget, required=False)
37 type = CharField(widget=HiddenInput, initial=Loop.__name__,38 type = CharField(widget=HiddenInput, initial=Loop.__name__,
38 required=False)39 required=False)
40 lava_tests = CharField(widget=LavaTestSelectWidget, required=False)
3941
40 def save(self, *args, **kwargs):42 def save(self, *args, **kwargs):
41 instance = super(LoopForm, self).save(commit=False)43 instance = super(LoopForm, self).save(commit=False)
42 if self.data["next_loop_0"]:44 if self.data.get("next_loop_0", None):
43 next_loop = Loop.objects.get(id=self.data["next_loop_0"])45 next_loop = Loop.objects.get(id=self.data["next_loop_0"])
44 instance.next_loop = next_loop46 instance.next_loop = next_loop
4547 if self.data.get("lava_tests_0", None):
48 instance.lava_tests = self.data["lava_tests_0"]
46 instance.save()49 instance.save()
4750
48 return instance51 return instance
4952
=== added file 'dashboard/frontend/migrations/0007_auto__add_field_loopbuild_lava_test_status.py'
--- dashboard/frontend/migrations/0007_auto__add_field_loopbuild_lava_test_status.py 1970-01-01 00:00:00 +0000
+++ dashboard/frontend/migrations/0007_auto__add_field_loopbuild_lava_test_status.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,52 @@
1# encoding: utf-8
2import datetime
3from south.db import db
4from south.v2 import SchemaMigration
5from django.db import models
6
7class Migration(SchemaMigration):
8
9 def forwards(self, orm):
10
11 # Adding field 'LoopBuild.lava_test_status'
12 db.add_column('frontend_loopbuild', 'lava_test_status', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True), keep_default=False)
13
14
15 def backwards(self, orm):
16
17 # Deleting field 'LoopBuild.lava_test_status'
18 db.delete_column('frontend_loopbuild', 'lava_test_status')
19
20
21 models = {
22 'frontend.loop': {
23 'Meta': {'object_name': 'Loop'},
24 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
25 'is_official': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
26 'is_restricted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
27 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
28 'next_loop': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'previous_loop'", 'unique': 'True', 'null': 'True', 'to': "orm['frontend.Loop']"}),
29 'server': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['jenkinsserver.JenkinsServer']", 'null': 'True'}),
30 'type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'})
31 },
32 'frontend.loopbuild': {
33 'Meta': {'ordering': "['-id']", 'unique_together': "(('build_number', 'loop'),)", 'object_name': 'LoopBuild'},
34 'build_number': ('django.db.models.fields.IntegerField', [], {'default': 'None'}),
35 'duration': ('django.db.models.fields.DecimalField', [], {'max_digits': '8', 'decimal_places': '2'}),
36 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
37 'lava_test_status': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
38 'loop': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['frontend.Loop']"}),
39 'remote_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
40 'result_xml': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
41 'status': ('django.db.models.fields.CharField', [], {'max_length': '20'})
42 },
43 'jenkinsserver.jenkinsserver': {
44 'Meta': {'object_name': 'JenkinsServer'},
45 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
46 'password': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
47 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
48 'username': ('django.db.models.fields.CharField', [], {'max_length': '100'})
49 }
50 }
51
52 complete_apps = ['frontend']
053
=== added file 'dashboard/frontend/migrations/0008_auto__add_field_loop_lava_tests.py'
--- dashboard/frontend/migrations/0008_auto__add_field_loop_lava_tests.py 1970-01-01 00:00:00 +0000
+++ dashboard/frontend/migrations/0008_auto__add_field_loop_lava_tests.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,53 @@
1# encoding: utf-8
2import datetime
3from south.db import db
4from south.v2 import SchemaMigration
5from django.db import models
6
7class Migration(SchemaMigration):
8
9 def forwards(self, orm):
10
11 # Adding field 'Loop.lava_tests'
12 db.add_column('frontend_loop', 'lava_tests', self.gf('django.db.models.fields.CharField')(max_length=255, null=True, blank=True), keep_default=False)
13
14
15 def backwards(self, orm):
16
17 # Deleting field 'Loop.lava_tests'
18 db.delete_column('frontend_loop', 'lava_tests')
19
20
21 models = {
22 'frontend.loop': {
23 'Meta': {'object_name': 'Loop'},
24 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
25 'is_official': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
26 'is_restricted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
27 'lava_tests': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
28 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
29 'next_loop': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'previous_loop'", 'unique': 'True', 'null': 'True', 'to': "orm['frontend.Loop']"}),
30 'server': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['jenkinsserver.JenkinsServer']", 'null': 'True'}),
31 'type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'})
32 },
33 'frontend.loopbuild': {
34 'Meta': {'ordering': "['-id']", 'unique_together': "(('build_number', 'loop'),)", 'object_name': 'LoopBuild'},
35 'build_number': ('django.db.models.fields.IntegerField', [], {'default': 'None'}),
36 'duration': ('django.db.models.fields.DecimalField', [], {'max_digits': '8', 'decimal_places': '2'}),
37 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
38 'lava_test_status': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
39 'loop': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['frontend.Loop']"}),
40 'remote_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
41 'result_xml': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
42 'status': ('django.db.models.fields.CharField', [], {'max_length': '20'})
43 },
44 'jenkinsserver.jenkinsserver': {
45 'Meta': {'object_name': 'JenkinsServer'},
46 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
47 'password': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
48 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
49 'username': ('django.db.models.fields.CharField', [], {'max_length': '100'})
50 }
51 }
52
53 complete_apps = ['frontend']
054
=== modified file 'dashboard/frontend/models/loop.py'
--- dashboard/frontend/models/loop.py 2012-09-14 11:36:54 +0000
+++ dashboard/frontend/models/loop.py 2012-09-21 15:30:40 +0000
@@ -40,6 +40,7 @@
40 unique=True, on_delete=models.SET_NULL,40 unique=True, on_delete=models.SET_NULL,
41 related_name='previous_loop',41 related_name='previous_loop',
42 verbose_name='Next loop')42 verbose_name='Next loop')
43 lava_tests = models.CharField(max_length=255, blank=True, null=True)
4344
44 def __init__(self, *args, **kwargs):45 def __init__(self, *args, **kwargs):
45 self.log = Logger.getClassLogger(self)46 self.log = Logger.getClassLogger(self)
4647
=== modified file 'dashboard/frontend/models/loop_build.py'
--- dashboard/frontend/models/loop_build.py 2012-09-13 13:56:36 +0000
+++ dashboard/frontend/models/loop_build.py 2012-09-21 15:30:40 +0000
@@ -40,6 +40,7 @@
40 (SUCCESS, 'SUCCESS'),40 (SUCCESS, 'SUCCESS'),
41 (ABORTED, 'ABORTED'),41 (ABORTED, 'ABORTED'),
42 )42 )
43
43 FINISHED_STATUSES = [FAILURE, SUCCESS]44 FINISHED_STATUSES = [FAILURE, SUCCESS]
44 NON_FINISHED_STATUSES = [SCHEDULED, RUNNING]45 NON_FINISHED_STATUSES = [SCHEDULED, RUNNING]
4546
@@ -49,6 +50,8 @@
49 status = models.CharField(max_length=20, choices=BUILD_STATUS)50 status = models.CharField(max_length=20, choices=BUILD_STATUS)
50 duration = models.DecimalField(max_digits=8, decimal_places=2)51 duration = models.DecimalField(max_digits=8, decimal_places=2)
51 result_xml = models.TextField(null=True, blank=True)52 result_xml = models.TextField(null=True, blank=True)
53 # General status of the LAVA tests for this build.
54 lava_test_status = models.CharField(max_length=20, blank=True, null=True)
5255
53 def save(self, *args, **kwargs):56 def save(self, *args, **kwargs):
54 loop_builds = LoopBuild.objects.filter(loop=self.loop).order_by("-id")57 loop_builds = LoopBuild.objects.filter(loop=self.loop).order_by("-id")
5558
=== modified file 'dashboard/frontend/templates/loop_detail.html'
--- dashboard/frontend/templates/loop_detail.html 2012-09-13 09:13:00 +0000
+++ dashboard/frontend/templates/loop_detail.html 2012-09-21 15:30:40 +0000
@@ -21,8 +21,8 @@
21 </div>21 </div>
22 {% block values %}22 {% block values %}
23 {% comment %}23 {% comment %}
24 This is used in the textfield detail views, to give a spece24 This is used in the textfield detail views, to give a space
25 to represent the key<>value values inserte by the user in a better25 to represent the key<>value values inserted by the user in a better
26 way.26 way.
27 {% endcomment %}27 {% endcomment %}
28 {% endblock values %}28 {% endblock values %}
2929
=== added directory 'dashboard/img'
=== added file 'dashboard/img/loading.gif'
30Binary files dashboard/img/loading.gif 1970-01-01 00:00:00 +0000 and dashboard/img/loading.gif 2012-09-21 15:30:40 +0000 differ30Binary files dashboard/img/loading.gif 1970-01-01 00:00:00 +0000 and dashboard/img/loading.gif 2012-09-21 15:30:40 +0000 differ
=== added directory 'dashboard/js/lava'
=== added file 'dashboard/js/lava/lava_test_select.js'
--- dashboard/js/lava/lava_test_select.js 1970-01-01 00:00:00 +0000
+++ dashboard/js/lava/lava_test_select.js 2012-09-21 15:30:40 +0000
@@ -0,0 +1,28 @@
1$().ready(function () {
2 "use strict";
3 init_lava_dialog();
4 $('#lava_select_link').click(function () {
5 populate_dialog();
6 $('#lava_select_dialog').dialog('open');
7 });
8});
9
10function init_lava_dialog() {
11 "use strict";
12 $('<div id="lava_select_dialog"></div>').dialog({
13 autoOpen: false,
14 title: 'Select LAVA Tests',
15 draggable: false,
16 height: 480,
17 width: 640,
18 modal: true,
19 resizable: false
20 });
21}
22
23function populate_dialog() {
24 "use strict";
25 $.get('/lava/select/', function (data) {
26 $('#lava_select_dialog').html(data);
27 });
28}
029
=== added directory 'dashboard/lava'
=== added file 'dashboard/lava/__init__.py'
=== added directory 'dashboard/lava/forms'
=== added file 'dashboard/lava/forms/__init__.py'
=== added directory 'dashboard/lava/lib'
=== added file 'dashboard/lava/lib/__init__.py'
=== added file 'dashboard/lava/lib/lavalib.py'
--- dashboard/lava/lib/lavalib.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/lib/lavalib.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,249 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18import xmlrpclib
19from lib.logger import Logger
20from dashboard.settings import LAVA_URL
21
22
23# The default delimiter used to separate test names to be executed.
24TEST_PLAN_DELIMITER = ';'
25
26# Map a TARGET_PRODUCT to LAVA parameters.
27PRODUCT_MAP = {
28 "pandaboard": {
29 "test_device_type": "panda",
30 "image_path": "%s%s" % (
31 "target/product/",
32 "pandaboard")},
33 "full_panda": {
34 "test_device_type": "panda",
35 "image_path": "%s%s" % (
36 "target/product/",
37 "panda")},
38 "beagleboard": {
39 "test_device_type": "beaglexm",
40 "image_path": "%s%s" % (
41 "target/product/",
42 "beagleboard")},
43 "snowball": {
44 "test_device_type": "snowball_sd",
45 "image_path": "%s%s" % (
46 "target/product/",
47 "snowball")},
48 "iMX53": {
49 "test_device_type": "mx53loco",
50 "image_path": "%s%s" % (
51 "target/product/",
52 "iMX53")},
53 "origen": {
54 "test_device_type": "origen",
55 "image_path": "%s%s" % (
56 "target/product/",
57 "origen")},
58 "vexpress": {
59 "test_device_type": "vexpress",
60 "image_path": "%s%s" % (
61 "target/product/",
62 "vexpress")},
63 }
64
65OPTION_SUFFIX = "_OPTION"
66TIMEOUT_SUFFIX = "_TIMEOUT"
67
68# Special token for LAVA_TEST_PLAN that allows the build owner to encode a
69# reboot in between test actions.
70REBOOT_TOKEN = '[system-reboot]'
71
72
73class LavaLibException(Exception):
74 """
75 Base class for exception in LAVA lib.
76 """
77
78
79class LavaLib(object):
80 """
81 Library to interact with LAVA XML-RPC.
82 """
83
84 def __init__(self, user=None, token=None, secure=True):
85 """
86 Initialize the LavaLib library to interact with LAVA.
87
88 :param user: The user name to use for interacting with LAVA.
89 :type user str
90 :param token: The token associated with the user.
91 :type token str
92 :param secure: If the connection should be secure or not. Default to
93 True.
94 :type secure bool
95 """
96 super(LavaLib, self).__init__()
97 self.log = Logger.getClassLogger(self)
98 self.user = user
99 self.token = token
100 self.secure = secure
101
102 def _lava_auth(self):
103 """
104 Creates the LAVA authorization string used to talk to LAVA.
105
106 :return A string with user name and token, if they have been specified.
107 """
108 auth_url = ''
109 if self.user is not None and self.token is not None:
110 auth_url = '%(user)s:%(token)s@' % dict(user=self.user,
111 token=self.token)
112 return auth_url
113
114 def _create_server_url(self):
115 """
116 Creates the server URL necessary to interact with the LAVA server.
117
118 :return A string with the URL for the LAVA server.
119 """
120 protocol = 'https'
121 if not self.secure:
122 protocol = 'http'
123
124 lava_auth = self._lava_auth()
125
126 if lava_auth is not '' and not self.secure:
127 self.log.warning('Sending sensible information through an '
128 'insecure channel. Consider using HTTPS.')
129
130 params_dict = dict(protocol=protocol,
131 auth_url=lava_auth,
132 lava_url=LAVA_URL)
133 server_url = ('%(protocol)s://%(auth_url)s%(lava_url)s' % params_dict)
134 return server_url
135
136 def _get_server(self):
137 """
138 Gets a connection to the LAVA server.
139
140 :return A xmlrpclib.ServerProxy object.
141 """
142 return xmlrpclib.ServerProxy(self._create_server_url())
143
144 def get_test_names(self, sort=True):
145 """
146 Get the name of the tests it is possible to run.
147
148 :param sort: If the results should be sorted alphabetically. Default to
149 True.
150 :type sort bool
151 :return A list with all the test names.
152 """
153 # TODO we are faking some data here, since the LAVA server at
154 # validation.linaro.org does not include now the function to get
155 # out the test names.
156 test_names = ['0xbench', 'bluetooth', 'bootchart', 'busybox',
157 'glmark2', 'skia', 'v8', 'mmtest', 'monkey',
158 'monkey_long_run']
159 if sort:
160 test_names.sort()
161 return test_names
162
163 def send_job(self, test_plan):
164 """
165 Sends the test plan to be executed to the LAVA server.
166
167 :param test_plan: The string of tests to be executed.
168 :type test_plan str
169 """
170 config = self._prepare_config(self._split_test_plan(test_plan))
171 try:
172 self._get_server().scheduler.submit_job(config)
173 except:
174 self.log.exception('Impossible to submit LAVA requests.')
175
176 def _split_test_plan(self, test_plan):
177 """
178 Splits the string of tests into single test names. The split happens
179 on the default delimiter set to the variable TEST_PLAN_DELIMITER.
180
181 :param test_plan: The string of tests to be split.
182 :type test_plan str
183 :return A list of test names.
184 """
185 if TEST_PLAN_DELIMITER in test_plan:
186 # Exclude the last element, the test plan we get should have also
187 # the delimiter appended on the last element.
188 tests = test_plan.split(TEST_PLAN_DELIMITER)[:-1]
189
190 # XXX need to check if this test still exists.
191 if "test_android_0xbench" in tests:
192 i = tests.index("test_android_0xbench")
193 tests[i] = "0xbench"
194 else:
195 self.log.exception('Found wrong delimiter in test plan '
196 'definition.')
197 raise LavaLibException('Wrong delimiter in test plan string'
198 'definition.')
199 return tests
200
201 def _prepare_config(self, tests):
202 """
203 :return A JSON representation of the config to be run.
204 """
205 # TODO here should go the biggest part of the main() in
206 # post-build-lava inside linaro-android-build-tools.
207 return {}
208
209 def gen_android_test_actions(self, tests):
210 # TODO this needs to be reworked, need to eliminate env var lookup
211 # Method taken from linaro-android-build-tools.
212 import os
213 actions = []
214 if len(tests) > 0:
215 test_actions = [test for test in tests if test != REBOOT_TOKEN]
216
217 if len(test_actions) > 0:
218 inst_action = {
219 "command": "lava_android_test_install",
220 "parameters": {
221 # ensure only unique test names
222 "tests": list(set(test_actions))
223 }
224 }
225 actions.append(inst_action)
226
227 for test in tests:
228 parameters = {'test_name': test}
229
230 test_option = os.environ.get('%s%s' % (test.upper(),
231 OPTION_SUFFIX))
232 if test_option:
233 parameters['option'] = test_option
234
235 timeout_option = os.environ.get('%s%s' % (test.upper(),
236 TIMEOUT_SUFFIX))
237 if timeout_option:
238 parameters['timeout'] = int(timeout_option)
239
240 if test != REBOOT_TOKEN:
241 run_action = {
242 "command": "lava_android_test_run",
243 "parameters": parameters
244 }
245 actions.append(run_action)
246 else:
247 actions.append({"command": "boot_linaro_android_image"})
248
249 return actions
0250
=== added directory 'dashboard/lava/migrations'
=== added file 'dashboard/lava/migrations/0001_initial.py'
--- dashboard/lava/migrations/0001_initial.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/migrations/0001_initial.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,65 @@
1# encoding: utf-8
2import datetime
3from south.db import db
4from south.v2 import SchemaMigration
5from django.db import models
6
7class Migration(SchemaMigration):
8
9 def forwards(self, orm):
10
11 # Adding model 'LavaTest'
12 db.create_table('lava_lavatest', (
13 ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14 ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['frontend.LoopBuild'])),
15 ('test_name', self.gf('django.db.models.fields.CharField')(max_length=64)),
16 ('test_status', self.gf('django.db.models.fields.CharField')(max_length=20)),
17 ))
18 db.send_create_signal('lava', ['LavaTest'])
19
20
21 def backwards(self, orm):
22
23 # Deleting model 'LavaTest'
24 db.delete_table('lava_lavatest')
25
26
27 models = {
28 'frontend.loop': {
29 'Meta': {'object_name': 'Loop'},
30 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
31 'is_official': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
32 'is_restricted': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
33 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '200'}),
34 'next_loop': ('django.db.models.fields.related.OneToOneField', [], {'blank': 'True', 'related_name': "'previous_loop'", 'unique': 'True', 'null': 'True', 'to': "orm['frontend.Loop']"}),
35 'server': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['jenkinsserver.JenkinsServer']", 'null': 'True'}),
36 'type': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'})
37 },
38 'frontend.loopbuild': {
39 'Meta': {'ordering': "['-id']", 'unique_together': "(('build_number', 'loop'),)", 'object_name': 'LoopBuild'},
40 'build_number': ('django.db.models.fields.IntegerField', [], {'default': 'None'}),
41 'duration': ('django.db.models.fields.DecimalField', [], {'max_digits': '8', 'decimal_places': '2'}),
42 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
43 'lava_test_status': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True', 'blank': 'True'}),
44 'loop': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['frontend.Loop']"}),
45 'remote_number': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'}),
46 'result_xml': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
47 'status': ('django.db.models.fields.CharField', [], {'max_length': '20'})
48 },
49 'jenkinsserver.jenkinsserver': {
50 'Meta': {'object_name': 'JenkinsServer'},
51 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
52 'password': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
53 'url': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
54 'username': ('django.db.models.fields.CharField', [], {'max_length': '100'})
55 },
56 'lava.lavatest': {
57 'Meta': {'object_name': 'LavaTest'},
58 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['frontend.LoopBuild']"}),
59 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
60 'test_name': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
61 'test_status': ('django.db.models.fields.CharField', [], {'max_length': '20'})
62 }
63 }
64
65 complete_apps = ['lava']
066
=== added file 'dashboard/lava/migrations/__init__.py'
=== added directory 'dashboard/lava/models'
=== added file 'dashboard/lava/models/__init__.py'
--- dashboard/lava/models/__init__.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/models/__init__.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,1 @@
1from dashboard.lava.models.lava import LavaTest
02
=== added file 'dashboard/lava/models/lava.py'
--- dashboard/lava/models/lava.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/models/lava.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,37 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18from django.db import models
19from lib.logger import Logger
20from frontend.models.loop_build import LoopBuild
21
22
23class LavaTest(models.Model):
24 class Meta:
25 app_label = 'lava'
26
27 def __init__(self, *args, **kwargs):
28 self.log = Logger.getClassLogger(self)
29 super(LavaTest, self).__init__(*args, **kwargs)
30
31 PENDING = 'pending'
32 RUNNING = 'running'
33 FINISHED = 'finished'
34
35 build = models.ForeignKey(LoopBuild)
36 test_name = models.CharField(max_length=64)
37 test_status = models.CharField(max_length=20)
038
=== added directory 'dashboard/lava/templates'
=== added file 'dashboard/lava/templates/__init__.py'
=== added file 'dashboard/lava/templates/lava_select.html'
--- dashboard/lava/templates/lava_select.html 1970-01-01 00:00:00 +0000
+++ dashboard/lava/templates/lava_select.html 2012-09-21 15:30:40 +0000
@@ -0,0 +1,66 @@
1 <div id="tests_selection">
2 <div id="left_div">
3 <div id="loading_div" class="loading">
4 <img src="/img/loading.gif" alt="Loading test names..." />
5 </div>
6 <select id="available" name="name_available_select" multiple="multiple">
7 {% include "tests_list.html" %}
8 </select>
9 </div>
10 <div id="center_div">
11 <input type="button" id="add_button" value="&#8594;" />
12 <input type="button" id="remove_button" value="&#8592;" />
13 </div>
14 <div id="right_div">
15 <select id="chosen" multiple="multiple">
16 {% comment %}
17 This will be populated moving elements from the previous select
18 element..
19 {% endcomment %}
20 </select>
21 </div>
22 </div>
23 <div><input type="button" id="id_select_button" value="OK"/></div>
24<script type="text/javascript">
25 "use strict";
26 $.ajax({
27 url: "{% if request.is_secure %}https{% else %}http{% endif %}://{{ request.get_host }}{% url LavaSelectTestsNames %}",
28 beforeSend: function () {
29 // Do not show the select element if it is empty, just show the
30 // spinner.
31 $('#available').hide();
32 },
33 success: function (data) {
34 $(data).prependTo($('#available'));
35 $('#available').show();
36 },
37 error: function(data, status, error) {
38 $('#left_div').html('<span class="error"><strong>Oops!</strong> The LAVA server is not responding.</span>')
39 }
40 });
41 $('#loading_div').show().ajaxStop(function () {
42 // Disable the spinner once AJAX is done.
43 $(this).hide();
44 });
45 $('#add_button').click(function () {
46 return !$('#available option:selected').remove().appendTo('#chosen');
47 });
48 $('#remove_button').click(function () {
49 return !$('#chosen option:selected').remove().appendTo('#available');
50 });
51 $('#id_select_button').click(function () {
52 var values = "";
53 $("#chosen > option").each(function() {
54 // We store the values as a semi-colon separated list of names.
55 values += $(this).val() + ";";
56 });
57 $('#id_lava_tests_0').val(values);
58 // Ellipsize the visual representation if it exceeds a prefixed amount
59 // of chars in length, and append an ellipsis.
60 if (values.length > 30) {
61 values = values.substring(0, 27) + "&#8230;";
62 }
63 $('#lava_select_link').html(values);
64 $('#lava_select_dialog').dialog('close');
65 });
66</script>
067
=== added file 'dashboard/lava/templates/tests_list.html'
--- dashboard/lava/templates/tests_list.html 1970-01-01 00:00:00 +0000
+++ dashboard/lava/templates/tests_list.html 2012-09-21 15:30:40 +0000
@@ -0,0 +1,7 @@
1{% comment %}
2This is a basic template used to populate a select element in another view
3through an asynchronous call.
4{% endcomment %}
5{% for test in tests %}
6 <option id="id_{{ test }}" value="{{ test }}">{{ test }}</option>
7{% endfor %}
0\ No newline at end of file8\ No newline at end of file
19
=== added directory 'dashboard/lava/tests'
=== added file 'dashboard/lava/tests/__init__.py'
--- dashboard/lava/tests/__init__.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/tests/__init__.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,23 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18from dashboard.lava.tests.test_lavalib import *
19
20
21__test__ = {
22 'LavalibTest': LavalibTest,
23 }
024
=== added file 'dashboard/lava/tests/test_lavalib.py'
--- dashboard/lava/tests/test_lavalib.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/tests/test_lavalib.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,70 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18from django.test import TestCase
19from dashboard.lava.lib.lavalib import (
20 LavaLib,
21 LavaLibException,
22 LAVA_URL,
23)
24
25
26class LavalibTest(TestCase):
27
28 def setUp(self):
29 self.user = 'auser'
30 self.token = 'atoken'
31 self.lava_lib = LavaLib(self.user, self.token)
32
33 def test_split_test_plan(self):
34 test_plan = 'a;b;c;d;'
35 expected_out = ['a', 'b', 'c', 'd']
36 self.assertEqual(expected_out,
37 self.lava_lib._split_test_plan(test_plan))
38
39 def test_split_test_plan_wrong(self):
40 test_plan = 'a,b,c'
41 self.assertRaises(LavaLibException,
42 self.lava_lib._split_test_plan, test_plan)
43
44 def test_create_lava_auth(self):
45 expected_out = ('%s:%s@' % (self.user, self.token))
46 self.assertEqual(expected_out, self.lava_lib._lava_auth())
47
48 def test_create_lava_auth_empty(self):
49 lava_lib = LavaLib()
50 expected_out = ''
51 self.assertEqual(expected_out, lava_lib._lava_auth())
52
53 def test_create_server_url(self):
54 expected_out = ('https://%s:%s@' + LAVA_URL) % (self.user, self.token)
55 self.assertEqual(expected_out, self.lava_lib._create_server_url())
56
57 def test_create_server_url_no_user(self):
58 expected_out = 'https://' + LAVA_URL
59 lava_lib = LavaLib()
60 self.assertEqual(expected_out, lava_lib._create_server_url())
61
62 def test_create_server_url_not_secure_no_user(self):
63 expected_out = 'http://' + LAVA_URL
64 lava_lib = LavaLib(secure=False)
65 self.assertEqual(expected_out, lava_lib._create_server_url())
66
67 def test_create_server_url_not_secure_with_user(self):
68 expected_out = ('http://%s:%s@' + LAVA_URL) % (self.user, self.token)
69 lava_lib = LavaLib(user=self.user, token=self.token, secure=False)
70 self.assertEqual(expected_out, lava_lib._create_server_url())
071
=== added file 'dashboard/lava/urls.py'
--- dashboard/lava/urls.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/urls.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,29 @@
1#!/usr/bin/env python
2# Copyright (C) 2012 Linaro
3#
4# This file is part of linaro-ci-dashboard.
5#
6# linaro-ci-dashboard is free software: you can redistribute it and/or modify
7# it under the terms of the GNU Affero General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# linaro-ci-dashboard is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU Affero General Public License for more details.
15#
16# You should have received a copy of the GNU Affero General Public License
17# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
18
19from django.conf.urls.defaults import patterns, url
20from dashboard.lava.views.lava_select_view import LavaSelectView
21from dashboard.lava.views.lava_select_test_names import LavaSelectTestNames
22
23
24urlpatterns = patterns('',
25 url(r'^lava/select/$',
26 LavaSelectView.as_view(), name='LavaSelectView'),
27 url(r'^lava/ajax/get-test-names/$',
28 LavaSelectTestNames.as_view(), name='LavaSelectTestsNames'),
29 )
0\ No newline at end of file30\ No newline at end of file
131
=== added directory 'dashboard/lava/views'
=== added file 'dashboard/lava/views/__init__.py'
=== added file 'dashboard/lava/views/lava_select_test_names.py'
--- dashboard/lava/views/lava_select_test_names.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/views/lava_select_test_names.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,58 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18from django.template import RequestContext
19from django.shortcuts import render_to_response
20from django.contrib.auth.decorators import login_required
21from django.views.generic.base import TemplateView
22from django.utils.decorators import method_decorator
23from lava.lib.lavalib import LavaLib
24
25
26class LavaSelectTestNames(TemplateView):
27 """
28 View class used to make asynchronous calls in order to retrieve the list of
29 available test names from a LAVA server through the LAVA library.
30
31 This is not a real view, it is used only to make async call into the
32 ci-dashboard server.
33 """
34 template_name = "tests_list.html"
35
36 @method_decorator(login_required)
37 def dispatch(self, *args, **kwargs):
38 return super(LavaSelectTestNames, self).dispatch(*args, **kwargs)
39
40 def get_lava_tests(self):
41 """
42 Retrieves all the test names from the LAVA server.
43
44 :return A list with all the test names.
45 """
46 lava_server = LavaLib(secure=False)
47 return lava_server.get_test_names()
48
49 def render_to_response(self, context, **response_kwargs):
50 if self.request.is_ajax():
51 data = {
52 "tests": self.get_lava_tests()
53 }
54 return render_to_response(self.template_name, data,
55 context_instance=RequestContext(
56 self.request))
57 else:
58 raise NotImplementedError
059
=== added file 'dashboard/lava/views/lava_select_view.py'
--- dashboard/lava/views/lava_select_view.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/views/lava_select_view.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,46 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18from django.contrib.auth.decorators import login_required
19from django.views.generic.base import TemplateView
20from django.utils.decorators import method_decorator
21from django.shortcuts import render_to_response
22from django.template import RequestContext
23
24
25class LavaSelectView(TemplateView):
26 template_name = 'lava_select.html'
27
28 @method_decorator(login_required)
29 def dispatch(self, *args, **kwargs):
30 return super(LavaSelectView, self).dispatch(*args, **kwargs)
31
32 def get_context_data(self, **kwargs):
33 context = super(LavaSelectView, self).get_context_data(**kwargs)
34 context['request'] = self.request
35 return context
36
37 def render_to_response(self, context, **response_kwargs):
38 data = {
39 "request": self.request
40 }
41 if self.request.is_ajax():
42 return render_to_response(self.template_name, data,
43 context_instance=RequestContext(
44 self.request))
45 else:
46 raise NotImplementedError
047
=== added directory 'dashboard/lava/widgets'
=== added file 'dashboard/lava/widgets/__init__.py'
=== added file 'dashboard/lava/widgets/lava_test_select_widget.py'
--- dashboard/lava/widgets/lava_test_select_widget.py 1970-01-01 00:00:00 +0000
+++ dashboard/lava/widgets/lava_test_select_widget.py 2012-09-21 15:30:40 +0000
@@ -0,0 +1,54 @@
1# Copyright (C) 2012 Linaro
2#
3# This file is part of linaro-ci-dashboard.
4#
5# linaro-ci-dashboard is free software: you can redistribute it and/or modify
6# it under the terms of the GNU Affero General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# linaro-ci-dashboard is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU Affero General Public License for more details.
14#
15# You should have received a copy of the GNU Affero General Public License
16# along with linaro-ci-dashboard. If not, see <http://www.gnu.org/licenses/>.
17
18from django.forms.widgets import (
19 HiddenInput,
20 MultiWidget,
21 Widget
22)
23
24
25class LavaLinkWidget(Widget):
26 def render(self, name, value, attrs=None):
27 from django.utils.safestring import mark_safe
28 if not value:
29 value = "Select Tests"
30 output = ['<span><a href="#" id="lava_select_link">%s</a>'
31 '</span>' % value]
32 return mark_safe(u' '.join(output))
33
34
35class LavaTestSelectWidget(MultiWidget):
36 class Media:
37 js = ("/js/lava/lava_test_select.js",)
38
39 def __init__(self, attrs=None):
40 _widgets = (
41 HiddenInput(attrs=attrs),
42 LavaLinkWidget(attrs=attrs),
43 )
44 super(LavaTestSelectWidget, self).__init__(_widgets, attrs)
45
46 def decompress(self, value):
47 rtn_list = [None, None]
48 return rtn_list
49
50 def format_output(self, rendered_widgets):
51 return u''.join(rendered_widgets)
52
53 def value_from_datadict(self, data, files, name):
54 return data.get("lava_tests_0", None)
055
=== modified file 'dashboard/settings.py'
--- dashboard/settings.py 2012-09-21 09:25:19 +0000
+++ dashboard/settings.py 2012-09-21 15:30:40 +0000
@@ -29,6 +29,7 @@
29DEPS_INSTALL_PATH = os.path.join(ROOT_PATH, "..", "lib")29DEPS_INSTALL_PATH = os.path.join(ROOT_PATH, "..", "lib")
30JS_PATH = os.path.join(ROOT_PATH, "js")30JS_PATH = os.path.join(ROOT_PATH, "js")
31CSS_PATH = os.path.join(ROOT_PATH, "css")31CSS_PATH = os.path.join(ROOT_PATH, "css")
32IMG_PATH = os.path.join(ROOT_PATH, 'img')
3233
33ADMINS = (34ADMINS = (
34 # ('Your Name', 'your_email@example.com'),35 # ('Your Name', 'your_email@example.com'),
@@ -142,6 +143,7 @@
142 'django.contrib.messages',143 'django.contrib.messages',
143 'django.contrib.staticfiles',144 'django.contrib.staticfiles',
144 'django_openid_auth',145 'django_openid_auth',
146 'lava',
145 'jenkinsserver',147 'jenkinsserver',
146 'frontend',148 'frontend',
147 'frontend.android_build',149 'frontend.android_build',
@@ -224,6 +226,12 @@
224JENKINS_HOME = os.path.join(os.getenv('HOME'), ".jenkins_test")226JENKINS_HOME = os.path.join(os.getenv('HOME'), ".jenkins_test")
225JENKINS_LOG_NAME = 'jenkins.log'227JENKINS_LOG_NAME = 'jenkins.log'
226JENKINS_DB_ID = 1228JENKINS_DB_ID = 1
229<<<<<<< TREE
227230
228LAVA_ACCEPTING_ADDRESS = '0.0.0.0'231LAVA_ACCEPTING_ADDRESS = '0.0.0.0'
229LAVA_PORT = '8001'232LAVA_PORT = '8001'
233=======
234
235# LAVA specific values
236LAVA_URL = 'validation.linaro.org/lava-server/RPC2/'
237>>>>>>> MERGE-SOURCE
230238
=== modified file 'dashboard/urls.py'
--- dashboard/urls.py 2012-09-13 10:51:03 +0000
+++ dashboard/urls.py 2012-09-21 15:30:40 +0000
@@ -28,9 +28,12 @@
28 url(r'^admin/', include(admin.site.urls)),28 url(r'^admin/', include(admin.site.urls)),
29 url(r'^logout/$', 'django.contrib.auth.views.logout'),29 url(r'^logout/$', 'django.contrib.auth.views.logout'),
30 url(r'^js/(?P<path>.*)$', 'django.views.static.serve',30 url(r'^js/(?P<path>.*)$', 'django.views.static.serve',
31 {'document_root': settings.JS_PATH}),31 {'document_root': settings.JS_PATH}),
32 url(r'^css/(?P<path>.*)$', 'django.views.static.serve',32 url(r'^css/(?P<path>.*)$', 'django.views.static.serve',
33 {'document_root': settings.CSS_PATH}),33 {'document_root': settings.CSS_PATH}),
34 url(r'^img/(?P<path>.*)$', 'django.views.static.serve',
35 {'document_root': settings.IMG_PATH}),
36 url(r'^', include('dashboard.lava.urls')),
34 url(r'^', include('dashboard.frontend.urls')),37 url(r'^', include('dashboard.frontend.urls')),
35 url(r'^', include('dashboard.frontend.android_build.urls')),38 url(r'^', include('dashboard.frontend.android_build.urls')),
36 url(r'^', include('dashboard.frontend.kernel_build.urls')),39 url(r'^', include('dashboard.frontend.kernel_build.urls')),

Subscribers

People subscribed via source and target branches