* [PATCH 00/11] Toaster improvements (BitBake part)
@ 2013-12-09 19:07 Paul Eggleton
2013-12-09 19:07 ` [PATCH 01/11] toaster: Analysis API variablehistory update Paul Eggleton
` (10 more replies)
0 siblings, 11 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
Note: this should be merged into BitBake at the same time that the
corresponding changes to toaster.bbclass are merged in OE-Core.
The following changes since commit 8f453bb11d72afc90a986ac604b3477d97eaf9a8:
data: Ensure we add the contains keys in a particular order (2013-12-09 10:25:41 +0000)
are available in the git repository at:
git://git.yoctoproject.org/poky-contrib paule/toaster-bb
http://git.yoctoproject.org/cgit.cgi/poky-contrib/log/?h=paule/toaster-bb
Alexandru DAMIAN (11):
toaster: Analysis API variablehistory update
toaster: remove Author field in SimpleUI
toaster: move layer information reading code
toaster: update build stats reading
toaster: change package storage model
toasterui: fix version numbers for no PE specified
toasterui: do not link non-image targets
toaster: update to Django 1.5
toaster: migrate orm models to South
toaster: add pagination to the Simple UI
toaster: Add more information for tasks in Simple UI
bin/toaster | 20 +-
lib/bb/ui/buildinfohelper.py | 319 ++++++----------
lib/bb/ui/toasterui.py | 9 +-
lib/toaster/bldviewer/api.py | 1 +
lib/toaster/bldviewer/templates/base.html | 4 +-
lib/toaster/bldviewer/templates/basebuildpage.html | 8 +-
lib/toaster/bldviewer/templates/basetable.html | 22 +-
lib/toaster/bldviewer/templates/bfile.html | 6 +-
lib/toaster/bldviewer/templates/bpackage.html | 12 +-
lib/toaster/bldviewer/templates/build.html | 6 +-
lib/toaster/bldviewer/templates/configuration.html | 2 +-
lib/toaster/bldviewer/templates/layer.html | 4 +-
lib/toaster/bldviewer/templates/package.html | 8 +-
lib/toaster/bldviewer/templates/recipe.html | 3 +-
lib/toaster/bldviewer/templates/task.html | 18 +-
lib/toaster/bldviewer/urls.py | 4 +-
lib/toaster/bldviewer/views.py | 70 ++--
lib/toaster/orm/migrations/0001_initial.py | 400 +++++++++++++++++++++
lib/toaster/orm/migrations/__init__.py | 0
lib/toaster/orm/models.py | 51 +--
lib/toaster/toastermain/settings.py | 1 +
lib/toaster/toastermain/urls.py | 4 +-
22 files changed, 659 insertions(+), 313 deletions(-)
create mode 100644 lib/toaster/orm/migrations/0001_initial.py
create mode 100644 lib/toaster/orm/migrations/__init__.py
--
1.8.1.2
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 01/11] toaster: Analysis API variablehistory update
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 02/11] toaster: remove Author field in SimpleUI Paul Eggleton
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
This patch updates the Analysis REST API to expose
the variablehistory information. A UI tool can query
this API to get a picture on how a variable value got
to its final form.
The documentation for VariableHistory is updated on
Wiki https://wiki.yoctoproject.org/wiki/Analysis_REST_API_Contracts
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/bldviewer/api.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/toaster/bldviewer/api.py b/lib/toaster/bldviewer/api.py
index f761ba6..a586734 100644
--- a/lib/toaster/bldviewer/api.py
+++ b/lib/toaster/bldviewer/api.py
@@ -33,5 +33,6 @@ urlpatterns = patterns('bldviewer.views',
url(r'^recipes$', 'model_explorer', {'model_name':'recipe'}, name='recipe'),
url(r'^recipe_dependencies$', 'model_explorer', {'model_name':'recipe_dependency'}, name='recipe_dependencies'),
url(r'^variables$', 'model_explorer', {'model_name':'variable'}, name='variables'),
+ url(r'^variableshistory$', 'model_explorer', {'model_name':'variablehistory'}, name='variablehistory'),
url(r'^logmessages$', 'model_explorer', {'model_name':'logmessage'}, name='logmessages'),
)
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/11] toaster: remove Author field in SimpleUI
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
2013-12-09 19:07 ` [PATCH 01/11] toaster: Analysis API variablehistory update Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 03/11] toaster: move layer information reading code Paul Eggleton
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
Removes a left-over Author field in the Simple UI
recipe page.
[YOCTO #5449]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/bldviewer/templates/recipe.html | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/toaster/bldviewer/templates/recipe.html b/lib/toaster/bldviewer/templates/recipe.html
index e9a1c10..7d5fbf4 100644
--- a/lib/toaster/bldviewer/templates/recipe.html
+++ b/lib/toaster/bldviewer/templates/recipe.html
@@ -21,7 +21,6 @@
<th>License file</th>
<th>Homepage</th>
<th>Bugtracker</th>
- <th>Author</th>
<th>File_path</th>
<th style="width: 30em">Recipe Dependency</th>
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/11] toaster: move layer information reading code
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
2013-12-09 19:07 ` [PATCH 01/11] toaster: Analysis API variablehistory update Paul Eggleton
2013-12-09 19:07 ` [PATCH 02/11] toaster: remove Author field in SimpleUI Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 04/11] toaster: update build stats reading Paul Eggleton
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
In the processes of removing local system accesses
from toaster UI, we remove the layer data reading
code that was moved to toaster.bbclass, and
adapt the database writing code to read the data
from event sent by the toaster.bbclass
[YOCTO #5604]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/bb/ui/buildinfohelper.py | 88 ++++++++------------------------------------
lib/bb/ui/toasterui.py | 4 +-
lib/toaster/orm/models.py | 1 +
3 files changed, 19 insertions(+), 74 deletions(-)
diff --git a/lib/bb/ui/buildinfohelper.py b/lib/bb/ui/buildinfohelper.py
index c99a511..b2e21ef 100644
--- a/lib/bb/ui/buildinfohelper.py
+++ b/lib/bb/ui/buildinfohelper.py
@@ -20,8 +20,6 @@ import datetime
import sys
import bb
import re
-import subprocess
-
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "toaster.toastermain.settings")
@@ -125,10 +123,11 @@ class ORMWrapper(object):
return recipe_object
- def get_layer_version_object(self, layer_version_information):
+ def get_update_layer_version_object(self, build_obj, layer_obj, layer_version_information):
layer_version_object = Layer_Version.objects.get_or_create(
- layer = layer_version_information['layer'],
+ build = build_obj,
+ layer = layer_obj,
branch = layer_version_information['branch'],
commit = layer_version_information['commit'],
priority = layer_version_information['priority']
@@ -274,60 +273,6 @@ class BuildInfoHelper(object):
###################
## methods to convert event/external info into objects that the ORM layer uses
- def _get_layer_dict(self, layer_path):
-
- layer_info = {}
- layer_name = layer_path.split('/')[-1]
- layer_url = 'http://layers.openembedded.org/layerindex/layer/{layer}/'
- layer_url_name = self._get_url_map_name(layer_name)
-
- layer_info['name'] = layer_name
- layer_info['local_path'] = layer_path
- layer_info['layer_index_url'] = layer_url.format(layer=layer_url_name)
-
- return layer_info
-
- def _get_url_map_name(self, layer_name):
- """ Some layers have a different name on openembedded.org site,
- this method returns the correct name to use in the URL
- """
-
- url_name = layer_name
- url_mapping = {'meta': 'openembedded-core'}
-
- for key in url_mapping.keys():
- if key == layer_name:
- url_name = url_mapping[key]
-
- return url_name
-
- def _get_layer_information(self):
-
- layer_info = {}
-
- return layer_info
-
- def _get_layer_version_information(self, layer_object):
-
- layer_version_info = {}
- layer_version_info['build'] = self.internal_state['build']
- layer_version_info['layer'] = layer_object
- layer_version_info['branch'] = self._get_git_branch(layer_object.local_path)
- layer_version_info['commit'] = self._get_git_revision(layer_object.local_path)
- layer_version_info['priority'] = 0
-
- return layer_version_info
-
-
- def _get_git_branch(self, layer_path):
- branch = subprocess.Popen("git symbolic-ref HEAD 2>/dev/null ", cwd=layer_path, shell=True, stdout=subprocess.PIPE).communicate()[0]
- branch = branch.replace('refs/heads/', '').rstrip()
- return branch
-
- def _get_git_revision(self, layer_path):
- revision = subprocess.Popen("git rev-parse HEAD 2>/dev/null ", cwd=layer_path, shell=True, stdout=subprocess.PIPE).communicate()[0].rstrip()
- return revision
-
def _get_build_information(self):
build_info = {}
@@ -366,7 +311,7 @@ class BuildInfoHelper(object):
# Heuristics: we always match recipe to the deepest layer path that
# we can match to the recipe file path
- for bl in sorted(self.internal_state['layer_versions'], reverse=True, key=_slkey):
+ for bl in sorted(Layer_Version.objects.filter(build = self.internal_state['build']), reverse=True, key=_slkey):
if (path.startswith(bl.layer.local_path)):
return bl
@@ -452,12 +397,12 @@ class BuildInfoHelper(object):
################################
## external available methods to store information
- def store_layer_info(self):
- layers = self.server.runCommand(["getVariable", "BBLAYERS"])[0].strip().split(" ")
- self.internal_state['layers'] = []
- for layer_path in { l for l in layers if len(l) }:
- layer_information = self._get_layer_dict(layer_path)
- self.internal_state['layers'].append(self.orm_wrapper.get_update_layer_object(layer_information))
+ def store_layer_info(self, event):
+ layerinfos = event.data
+ self.internal_state['lvs'] = {}
+ for layer in layerinfos:
+ self.internal_state['lvs'][self.orm_wrapper.get_update_layer_object(layerinfos[layer])] = layerinfos[layer]['version']
+
def store_started_build(self, event):
@@ -466,6 +411,12 @@ class BuildInfoHelper(object):
build_obj = self.orm_wrapper.create_build_object(build_information)
self.internal_state['build'] = build_obj
+ # save layer version information for this build
+ for layer_obj in self.internal_state['lvs']:
+ self.orm_wrapper.get_update_layer_version_object(build_obj, layer_obj, self.internal_state['lvs'][layer_obj])
+
+ del self.internal_state['lvs']
+
# create target information
target_information = {}
target_information['targets'] = event.getPkgs()
@@ -473,13 +424,6 @@ class BuildInfoHelper(object):
self.internal_state['targets'] = self.orm_wrapper.create_target_objects(target_information)
- # Load layer information for the build
- self.internal_state['layer_versions'] = []
- for layer_object in self.internal_state['layers']:
- layer_version_information = self._get_layer_version_information(layer_object)
- self.internal_state['layer_versions'].append(self.orm_wrapper.get_layer_version_object(layer_version_information))
-
- del self.internal_state['layers']
# Save build configuration
self.orm_wrapper.save_build_variables(build_obj, self.server.runCommand(["getAllKeysWithFlags", ["doc", "func"]])[0])
diff --git a/lib/bb/ui/toasterui.py b/lib/bb/ui/toasterui.py
index 8e30a91..50493e7 100644
--- a/lib/bb/ui/toasterui.py
+++ b/lib/bb/ui/toasterui.py
@@ -93,7 +93,6 @@ def main(server, eventHandler, params ):
taskfailures = []
buildinfohelper = BuildInfoHelper(server, build_history_enabled)
- buildinfohelper.store_layer_info()
while True:
@@ -232,12 +231,13 @@ def main(server, eventHandler, params ):
warnings = 0
taskfailures = []
buildinfohelper = BuildInfoHelper(server, build_history_enabled)
- buildinfohelper.store_layer_info()
continue
if isinstance(event, bb.event.MetadataEvent):
if event.type == "SinglePackageInfo":
buildinfohelper.store_build_package_information(event)
+ if event.type == "LayerInfo":
+ buildinfohelper.store_layer_info(event)
continue
# ignore
diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index cac8367..0bb048c 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -229,6 +229,7 @@ class Layer(models.Model):
class Layer_Version(models.Model):
+ build = models.ForeignKey(Build, related_name='layer_version_build')
layer = models.ForeignKey(Layer, related_name='layer_version_layer')
branch = models.CharField(max_length=50)
commit = models.CharField(max_length=100)
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/11] toaster: update build stats reading
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (2 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 03/11] toaster: move layer information reading code Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 05/11] toaster: change package storage model Paul Eggleton
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
In the processes of removing local system accesses
from toaster UI, we remove the build stats
code that was moved to toaster.bbclass, and
adapt the database writing code to read the data
from BuildStatsList event sent by the toaster.bbclass
[YOCTO #5604]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/bb/ui/buildinfohelper.py | 64 +++++++++++++-------------------------------
lib/bb/ui/toasterui.py | 2 ++
2 files changed, 21 insertions(+), 45 deletions(-)
diff --git a/lib/bb/ui/buildinfohelper.py b/lib/bb/ui/buildinfohelper.py
index b2e21ef..fef849d 100644
--- a/lib/bb/ui/buildinfohelper.py
+++ b/lib/bb/ui/buildinfohelper.py
@@ -319,23 +319,16 @@ class BuildInfoHelper(object):
assert False
return None
- def _get_recipe_information_from_build_event(self, event):
+ def _get_recipe_information_from_taskfile(self, taskfile):
- layer_version_obj = self._get_layer_version_for_path(re.split(':', event.taskfile)[-1])
+ layer_version_obj = self._get_layer_version_for_path(re.split(':', taskfile)[-1])
recipe_info = {}
recipe_info['layer_version'] = layer_version_obj
- recipe_info['file_path'] = re.split(':', event.taskfile)[-1]
+ recipe_info['file_path'] = re.split(':', taskfile)[-1]
return recipe_info
- def _get_task_build_stats(self, task_object):
- bs_path = self._get_path_information(task_object)
- for bp in bs_path: # TODO: split for each target
- task_build_stats = self._get_build_stats_from_file(bp, task_object.task_name)
-
- return task_build_stats
-
def _get_path_information(self, task_object):
build_stats_format = "{tmpdir}/buildstats/{target}-{machine}/{buildname}/{package}/"
build_stats_path = []
@@ -356,36 +349,6 @@ class BuildInfoHelper(object):
return build_stats_path
- def _get_build_stats_from_file(self, bs_path, task_name):
-
- task_bs_filename = str(bs_path) + str(task_name)
- task_bs = open(task_bs_filename, 'r')
-
- cpu_usage = 0
- disk_io = 0
- startio = ''
- endio = ''
-
- for line in task_bs.readlines():
- if line.startswith('CPU usage: '):
- cpu_usage = line[11:]
- elif line.startswith('EndTimeIO: '):
- endio = line[11:]
- elif line.startswith('StartTimeIO: '):
- startio = line[13:]
-
- task_bs.close()
-
- if startio and endio:
- disk_io = int(endio.strip('\n ')) - int(startio.strip('\n '))
-
- if cpu_usage:
- cpu_usage = float(cpu_usage.strip('% \n'))
-
- task_build_stats = {'cpu_usage': cpu_usage, 'disk_io': disk_io}
-
- return task_build_stats
-
def _remove_redundant(self, string):
ret = []
for i in string.split():
@@ -435,7 +398,7 @@ class BuildInfoHelper(object):
def store_started_task(self, event):
identifier = event.taskfile + event.taskname
- recipe_information = self._get_recipe_information_from_build_event(event)
+ recipe_information = self._get_recipe_information_from_taskfile(event.taskfile)
recipe = self.orm_wrapper.get_update_recipe_object(recipe_information)
task_information = self._get_task_information(event, recipe)
@@ -458,9 +421,23 @@ class BuildInfoHelper(object):
self.internal_state[identifier] = {'start_time': datetime.datetime.now()}
+
+ def store_tasks_stats(self, event):
+ for (taskfile, taskname, taskstats) in event.data:
+ recipe_information = self._get_recipe_information_from_taskfile(taskfile)
+ recipe = self.orm_wrapper.get_update_recipe_object(recipe_information)
+
+ task_information = {}
+ task_information['build'] = self.internal_state['build']
+ task_information['recipe'] = recipe
+ task_information['task_name'] = taskname
+ task_information['cpu_usage'] = taskstats['cpu_usage']
+ task_information['disk_io'] = taskstats['disk_io']
+ task_obj = self.orm_wrapper.get_update_task_object(task_information)
+
def update_and_store_task(self, event):
identifier = event.taskfile + event.taskname
- recipe_information = self._get_recipe_information_from_build_event(event)
+ recipe_information = self._get_recipe_information_from_taskfile(event.taskfile)
recipe = self.orm_wrapper.get_update_recipe_object(recipe_information)
task_information = self._get_task_information(event,recipe)
try:
@@ -483,9 +460,6 @@ class BuildInfoHelper(object):
if isinstance(event, (bb.runqueue.runQueueTaskCompleted, bb.runqueue.sceneQueueTaskCompleted)):
task_information['outcome'] = Task.OUTCOME_SUCCESS
- task_build_stats = self._get_task_build_stats(self.orm_wrapper.get_update_task_object(task_information))
- task_information['cpu_usage'] = task_build_stats['cpu_usage']
- task_information['disk_io'] = task_build_stats['disk_io']
del self.internal_state[identifier]
if isinstance(event, (bb.runqueue.runQueueTaskFailed, bb.runqueue.sceneQueueTaskFailed)):
diff --git a/lib/bb/ui/toasterui.py b/lib/bb/ui/toasterui.py
index 50493e7..318fc28 100644
--- a/lib/bb/ui/toasterui.py
+++ b/lib/bb/ui/toasterui.py
@@ -238,6 +238,8 @@ def main(server, eventHandler, params ):
buildinfohelper.store_build_package_information(event)
if event.type == "LayerInfo":
buildinfohelper.store_layer_info(event)
+ if event.type == "BuildStatsList":
+ buildinfohelper.store_tasks_stats(event)
continue
# ignore
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/11] toaster: change package storage model
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (3 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 04/11] toaster: update build stats reading Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 06/11] toasterui: fix version numbers for no PE specified Paul Eggleton
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
Up until this patch, package information lived in two
places - one table for build packages and one table for
target installed packaged. This situation leads to
two problems: there is no direct link between a build
package and a installed package, and a lot of data is duplicated.
This change unifies all package types in a single table.
The SimpleUI remains the same for continuity sake,
but the REST API will be changed in a future patch.
The package dependencies and package files are now
kept in a single table.
Since we collect target installed package information at all times,
we need to expand it to supplement missing information if a
package is not actually built in the current build.
Small changes to the Simple UI reflect the updated database schema.
[YOCTO #5565]
[YOCTO #5269]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/bb/ui/buildinfohelper.py | 165 ++++++++++++--------------
lib/bb/ui/toasterui.py | 3 +-
lib/toaster/bldviewer/templates/bpackage.html | 6 +-
lib/toaster/bldviewer/templates/package.html | 2 +-
lib/toaster/bldviewer/views.py | 25 ++--
lib/toaster/orm/models.py | 50 +++-----
6 files changed, 108 insertions(+), 143 deletions(-)
diff --git a/lib/bb/ui/buildinfohelper.py b/lib/bb/ui/buildinfohelper.py
index fef849d..0252efd 100644
--- a/lib/bb/ui/buildinfohelper.py
+++ b/lib/bb/ui/buildinfohelper.py
@@ -20,15 +20,16 @@ import datetime
import sys
import bb
import re
+import ast
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "toaster.toastermain.settings")
import toaster.toastermain.settings as toaster_django_settings
from toaster.orm.models import Build, Task, Recipe, Layer_Version, Layer, Target, LogMessage
from toaster.orm.models import Variable, VariableHistory
-from toaster.orm.models import Target_Package, Build_Package, Build_File
-from toaster.orm.models import Task_Dependency, Build_Package_Dependency
-from toaster.orm.models import Target_Package_Dependency, Recipe_Dependency
+from toaster.orm.models import Package, Package_File, Target_Installed_Package
+from toaster.orm.models import Task_Dependency, Package_Dependency
+from toaster.orm.models import Recipe_Dependency
from bb.msg import BBLogFormatter as format
class ORMWrapper(object):
@@ -148,21 +149,48 @@ class ORMWrapper(object):
return layer_object[0]
- def save_target_package_information(self, target_obj, packagedict, bldpkgs, recipes):
+ def save_target_package_information(self, build_obj, target_obj, packagedict, pkgpnmap, recipes):
for p in packagedict:
- packagedict[p]['object'] = Target_Package.objects.create( target = target_obj,
- name = p,
- size = packagedict[p]['size'])
- if p in bldpkgs:
- packagedict[p]['object'].version = bldpkgs[p]['version']
- packagedict[p]['object'].recipe = recipes[bldpkgs[p]['pn']]
- packagedict[p]['object'].save()
+ packagedict[p]['object'], created = Package.objects.get_or_create( build = build_obj, name = p )
+ if created:
+ # package was not build in the current build, but
+ # fill in everything we can from the runtime-reverse package data
+ try:
+ packagedict[p]['object'].recipe = recipes[pkgpnmap[p]['PN']]
+ packagedict[p]['object'].version = pkgpnmap[p]['PV']
+ packagedict[p]['object'].revision = pkgpnmap[p]['PR']
+ packagedict[p]['object'].license = pkgpnmap[p]['LICENSE']
+ packagedict[p]['object'].section = pkgpnmap[p]['SECTION']
+ packagedict[p]['object'].summary = pkgpnmap[p]['SUMMARY']
+ packagedict[p]['object'].description = pkgpnmap[p]['DESCRIPTION']
+ packagedict[p]['object'].size = int(pkgpnmap[p]['PKGSIZE'])
+
+ # no files recorded for this package, so save files info
+ for targetpath in pkgpnmap[p]['FILES_INFO']:
+ targetfilesize = pkgpnmap[p]['FILES_INFO'][targetpath]
+ Package_File.objects.create( package = packagedict[p]['object'],
+ path = targetpath,
+ size = targetfilesize)
+ except KeyError as e:
+ print "Key error, package", p, "key", e
+
+ # save disk installed size
+ packagedict[p]['object'].installed_size = packagedict[p]['size']
+ packagedict[p]['object'].save()
+
+ Target_Installed_Package.objects.create(target = target_obj, package = packagedict[p]['object'])
for p in packagedict:
for (px,deptype) in packagedict[p]['depends']:
- Target_Package_Dependency.objects.create( package = packagedict[p]['object'],
+ if deptype == 'depends':
+ tdeptype = Package_Dependency.TYPE_TRDEPENDS
+ elif deptype == 'recommends':
+ tdeptype = Package_Dependency.TYPE_TRECOMMENDS
+
+ Package_Dependency.objects.create( package = packagedict[p]['object'],
depends_on = packagedict[px]['object'],
- dep_type = deptype);
+ dep_type = tdeptype,
+ target = target_obj);
def create_logmessage(self, log_information):
@@ -180,48 +208,53 @@ class ORMWrapper(object):
def save_build_package_information(self, build_obj, package_info, recipes):
# create and save the object
- bp_object = Build_Package.objects.create( build = build_obj,
- recipe = recipes[package_info['PN']],
- name = package_info['PKG'],
- version = package_info['PKGV'],
- revision = package_info['PKGR'],
- summary = package_info['SUMMARY'],
- description = package_info['DESCRIPTION'],
- size = int(package_info['PKGSIZE']),
- section = package_info['SECTION'],
- license = package_info['LICENSE'],
- )
+ bp_object, created = Package.objects.get_or_create( build = build_obj,
+ name = package_info['PKG'] )
+
+ bp_object.recipe = recipes[package_info['PN']]
+ bp_object.version = package_info['PKGV']
+ bp_object.revision = package_info['PKGR']
+ bp_object.summary = package_info['SUMMARY']
+ bp_object.description = package_info['DESCRIPTION']
+ bp_object.size = int(package_info['PKGSIZE'])
+ bp_object.section = package_info['SECTION']
+ bp_object.license = package_info['LICENSE']
+ bp_object.save()
+
# save any attached file information
for path in package_info['FILES_INFO']:
- fo = Build_File.objects.create( bpackage = bp_object,
+ fo = Package_File.objects.create( package = bp_object,
path = path,
size = package_info['FILES_INFO'][path] )
+ def _po_byname(p):
+ return Package.objects.get_or_create(build = build_obj, name = p)[0]
+
# save soft dependency information
if 'RDEPENDS' in package_info and package_info['RDEPENDS']:
for p in bb.utils.explode_deps(package_info['RDEPENDS']):
- Build_Package_Dependency.objects.get_or_create( package = bp_object,
- depends_on = p, dep_type = Build_Package_Dependency.TYPE_RDEPENDS)
+ Package_Dependency.objects.get_or_create( package = bp_object,
+ depends_on = _po_byname(p), dep_type = Package_Dependency.TYPE_RDEPENDS)
if 'RPROVIDES' in package_info and package_info['RPROVIDES']:
for p in bb.utils.explode_deps(package_info['RPROVIDES']):
- Build_Package_Dependency.objects.get_or_create( package = bp_object,
- depends_on = p, dep_type = Build_Package_Dependency.TYPE_RPROVIDES)
+ Package_Dependency.objects.get_or_create( package = bp_object,
+ depends_on = _po_byname(p), dep_type = Package_Dependency.TYPE_RPROVIDES)
if 'RRECOMMENDS' in package_info and package_info['RRECOMMENDS']:
for p in bb.utils.explode_deps(package_info['RRECOMMENDS']):
- Build_Package_Dependency.objects.get_or_create( package = bp_object,
- depends_on = p, dep_type = Build_Package_Dependency.TYPE_RRECOMMENDS)
+ Package_Dependency.objects.get_or_create( package = bp_object,
+ depends_on = _po_byname(p), dep_type = Package_Dependency.TYPE_RRECOMMENDS)
if 'RSUGGESTS' in package_info and package_info['RSUGGESTS']:
for p in bb.utils.explode_deps(package_info['RSUGGESTS']):
- Build_Package_Dependency.objects.get_or_create( package = bp_object,
- depends_on = p, dep_type = Build_Package_Dependency.TYPE_RSUGGESTS)
+ Package_Dependency.objects.get_or_create( package = bp_object,
+ depends_on = _po_byname(p), dep_type = Package_Dependency.TYPE_RSUGGESTS)
if 'RREPLACES' in package_info and package_info['RREPLACES']:
for p in bb.utils.explode_deps(package_info['RREPLACES']):
- Build_Package_Dependency.objects.get_or_create( package = bp_object,
- depends_on = p, dep_type = Build_Package_Dependency.TYPE_RREPLACES)
+ Package_Dependency.objects.get_or_create( package = bp_object,
+ depends_on = _po_byname(p), dep_type = Package_Dependency.TYPE_RREPLACES)
if 'RCONFLICTS' in package_info and package_info['RCONFLICTS']:
for p in bb.utils.explode_deps(package_info['RCONFLICTS']):
- Build_Package_Dependency.objects.get_or_create( package = bp_object,
- depends_on = p, dep_type = Build_Package_Dependency.TYPE_RCONFLICTS)
+ Package_Dependency.objects.get_or_create( package = bp_object,
+ depends_on = _po_byname(p), dep_type = Package_Dependency.TYPE_RCONFLICTS)
return bp_object
@@ -469,54 +502,13 @@ class BuildInfoHelper(object):
self.orm_wrapper.get_update_task_object(task_information)
- def read_target_package_dep_data(self, event):
- # for all targets
+ def store_target_package_data(self, event):
+ # for all image targets
for target in self.internal_state['targets']:
- # verify that we have something to read
- if not target.is_image or not self.has_build_history:
- print "not collecting package info ", target.is_image, self.has_build_history
- break
-
- # TODO this is a temporary replication of the code in buildhistory.bbclass
- # This MUST be changed to query the actual BUILD_DIR_IMAGE in the target context when
- # the capability will be implemented in Bitbake
-
- MACHINE_ARCH, error = self.server.runCommand(['getVariable', 'MACHINE_ARCH'])
- TCLIBC, error = self.server.runCommand(['getVariable', 'TCLIBC'])
- BUILDHISTORY_DIR, error = self.server.runCommand(['getVariable', 'BUILDHISTORY_DIR'])
- BUILDHISTORY_DIR_IMAGE = "%s/images/%s/%s/%s" % (BUILDHISTORY_DIR, MACHINE_ARCH, TCLIBC, target.target)
-
- self.internal_state['packages'] = {}
-
- with open("%s/installed-package-sizes.txt" % BUILDHISTORY_DIR_IMAGE, "r") as fin:
- for line in fin:
- line = line.rstrip(";")
- psize, px = line.split("\t")
- punit, pname = px.split(" ")
- self.internal_state['packages'][pname.strip()] = {'size':int(psize)*1024, 'depends' : []}
-
- with open("%s/depends.dot" % BUILDHISTORY_DIR_IMAGE, "r") as fin:
- p = re.compile(r' -> ')
- dot = re.compile(r'.*style=dotted')
- for line in fin:
- line = line.rstrip(';')
- linesplit = p.split(line)
- if len(linesplit) == 2:
- pname = linesplit[0].rstrip('"').strip('"')
- dependsname = linesplit[1].split(" ")[0].strip().strip(";").strip('"').rstrip('"')
- deptype = Target_Package_Dependency.TYPE_DEPENDS
- if dot.match(line):
- deptype = Target_Package_Dependency.TYPE_RECOMMENDS
- if not pname in self.internal_state['packages']:
- self.internal_state['packages'][pname] = {'size': 0, 'depends' : []}
- if not dependsname in self.internal_state['packages']:
- self.internal_state['packages'][dependsname] = {'size': 0, 'depends' : []}
- self.internal_state['packages'][pname]['depends'].append((dependsname, deptype))
-
- self.orm_wrapper.save_target_package_information(target,
- self.internal_state['packages'],
- self.internal_state['bldpkgs'], self.internal_state['recipes'])
-
+ if target.is_image:
+ pkgdata = event.data['pkgdata']
+ imgdata = event.data['imgdata'][target.target]
+ self.orm_wrapper.save_target_package_information(self.internal_state['build'], target, imgdata, pkgdata, self.internal_state['recipes'])
def store_dependency_information(self, event):
# save layer version priorities
@@ -528,11 +520,6 @@ class BuildInfoHelper(object):
layer_version_obj.priority = priority
layer_version_obj.save()
- # save build time package information
- self.internal_state['bldpkgs'] = {}
- for pkg in event._depgraph['packages']:
- self.internal_state['bldpkgs'][pkg] = event._depgraph['packages'][pkg]
-
# save recipe information
self.internal_state['recipes'] = {}
for pn in event._depgraph['pn']:
diff --git a/lib/bb/ui/toasterui.py b/lib/bb/ui/toasterui.py
index 318fc28..e469d93 100644
--- a/lib/bb/ui/toasterui.py
+++ b/lib/bb/ui/toasterui.py
@@ -209,7 +209,6 @@ def main(server, eventHandler, params ):
continue
if isinstance(event, (bb.event.BuildCompleted)):
- buildinfohelper.read_target_package_dep_data(event)
buildinfohelper.update_build_information(event, errors, warnings, taskfailures)
continue
@@ -240,6 +239,8 @@ def main(server, eventHandler, params ):
buildinfohelper.store_layer_info(event)
if event.type == "BuildStatsList":
buildinfohelper.store_tasks_stats(event)
+ if event.type == "ImagePkgList":
+ buildinfohelper.store_target_package_data(event)
continue
# ignore
diff --git a/lib/toaster/bldviewer/templates/bpackage.html b/lib/toaster/bldviewer/templates/bpackage.html
index 4e6d9c6..ca092ca 100644
--- a/lib/toaster/bldviewer/templates/bpackage.html
+++ b/lib/toaster/bldviewer/templates/bpackage.html
@@ -23,7 +23,7 @@
<tr class="data">
<td><a name="#{{package.name}}" href="{% url bfile build.pk package.pk %}">{{package.name}} ({{package.filelist_bpackage.count}} files)</a></td>
<td>{{package.version}}-{{package.revision}}</td>
- <td><a href="{% url layer_versions_recipes package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a></td>
+ <td>{%if package.recipe%}<a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
<td>{{package.summary}}</td>
<td>{{package.section}}</td>
@@ -32,8 +32,8 @@
<td>{{package.license}}</td>
<td>
<div style="height: 3em; overflow:auto">
- {% for bpd in package.bpackage_dependencies_package.all %}
- {{bpd.dep_type}}: {{bpd.depends_on}} <br/>
+ {% for bpd in package.package_dependencies_source.all %}
+ {{bpd.dep_type}}: {{bpd.depends_on.name}} <br/>
{% endfor %}
</div>
</td>
diff --git a/lib/toaster/bldviewer/templates/package.html b/lib/toaster/bldviewer/templates/package.html
index c22e988..b1246e7 100644
--- a/lib/toaster/bldviewer/templates/package.html
+++ b/lib/toaster/bldviewer/templates/package.html
@@ -23,7 +23,7 @@
<a href="{% url layer_versions_recipes package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
<td>
<div style="height: 4em; overflow:auto">
- {% for d in package.tpackage_dependencies_package.all %}
+ {% for d in package.package_dependencies_source.all %}
<a href="#{{d.name}}">{{d.depends_on.name}}</a><br/>
{% endfor %}
</div>
diff --git a/lib/toaster/bldviewer/views.py b/lib/toaster/bldviewer/views.py
index 7be4d4b..3eb785b 100644
--- a/lib/toaster/bldviewer/views.py
+++ b/lib/toaster/bldviewer/views.py
@@ -20,8 +20,9 @@ import operator
from django.db.models import Q
from django.shortcuts import render
-from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, Target_Package, LogMessage, Variable
-from orm.models import Task_Dependency, Recipe_Dependency, Build_Package, Build_File, Build_Package_Dependency
+from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
+from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
+from orm.models import Target_Installed_Package
from django.views.decorators.cache import cache_control
@cache_control(no_store=True)
@@ -78,23 +79,20 @@ def configuration(request, build_id):
def bpackage(request, build_id):
template = 'bpackage.html'
- packages = Build_Package.objects.filter(build = build_id)
+ packages = Package.objects.filter(build = build_id)
context = {'build': Build.objects.filter(pk=build_id)[0], 'packages' : packages}
return render(request, template, context)
def bfile(request, build_id, package_id):
template = 'bfile.html'
- files = Build_File.objects.filter(bpackage = package_id)
+ files = Package_File.objects.filter(package = package_id)
context = {'build': Build.objects.filter(pk=build_id)[0], 'files' : files}
return render(request, template, context)
def tpackage(request, build_id, target_id):
template = 'package.html'
-
- packages = Target_Package.objects.filter(target=target_id)
-
- context = {'build' : Build.objects.filter(pk=build_id)[0],'packages': packages}
-
+ packages = map(lambda x: x.package, list(Target_Installed_Package.objects.filter(target=target_id)))
+ context = {'build': Build.objects.filter(pk=build_id)[0], 'packages' : packages}
return render(request, template, context)
def layer(request):
@@ -135,17 +133,16 @@ def model_explorer(request, model_name):
model_mapping = {
'build': Build,
'target': Target,
- 'target_package': Target_Package,
'task': Task,
'task_dependency': Task_Dependency,
- 'package': Build_Package,
+ 'package': Package,
'layer': Layer,
'layerversion': Layer_Version,
'recipe': Recipe,
'recipe_dependency': Recipe_Dependency,
- 'build_package': Build_Package,
- 'build_package_dependency': Build_Package_Dependency,
- 'build_file': Build_File,
+ 'package': Package,
+ 'package_dependency': Package_Dependency,
+ 'build_file': Package_File,
'variable': Variable,
'logmessage': LogMessage,
}
diff --git a/lib/toaster/orm/models.py b/lib/toaster/orm/models.py
index 0bb048c..b30e405 100644
--- a/lib/toaster/orm/models.py
+++ b/lib/toaster/orm/models.py
@@ -130,7 +130,7 @@ class Task_Dependency(models.Model):
depends_on = models.ForeignKey(Task, related_name='task_dependencies_depends')
-class Build_Package(models.Model):
+class Package(models.Model):
build = models.ForeignKey('Build')
recipe = models.ForeignKey('Recipe', null=True)
name = models.CharField(max_length=100)
@@ -139,16 +139,19 @@ class Build_Package(models.Model):
summary = models.CharField(max_length=200, blank=True)
description = models.CharField(max_length=200, blank=True)
size = models.IntegerField(default=0)
+ installed_size = models.IntegerField(default=0)
section = models.CharField(max_length=80, blank=True)
license = models.CharField(max_length=80, blank=True)
-class Build_Package_Dependency(models.Model):
+class Package_Dependency(models.Model):
TYPE_RDEPENDS = 0
TYPE_RPROVIDES = 1
TYPE_RRECOMMENDS = 2
TYPE_RSUGGESTS = 3
TYPE_RREPLACES = 4
TYPE_RCONFLICTS = 5
+ TYPE_TRDEPENDS = 6
+ TYPE_TRECOMMENDS = 7
DEPENDS_TYPE = (
(TYPE_RDEPENDS, "rdepends"),
(TYPE_RPROVIDES, "rprovides"),
@@ -156,46 +159,23 @@ class Build_Package_Dependency(models.Model):
(TYPE_RSUGGESTS, "rsuggests"),
(TYPE_RREPLACES, "rreplaces"),
(TYPE_RCONFLICTS, "rconflicts"),
+ (TYPE_TRDEPENDS, "trdepends"),
+ (TYPE_TRECOMMENDS, "trecommends"),
)
- package = models.ForeignKey(Build_Package, related_name='bpackage_dependencies_package')
- depends_on = models.CharField(max_length=100) # soft dependency
+ package = models.ForeignKey(Package, related_name='package_dependencies_source')
+ depends_on = models.ForeignKey(Package, related_name='package_dependencies_target') # soft dependency
dep_type = models.IntegerField(choices=DEPENDS_TYPE)
+ target = models.ForeignKey(Target, null=True)
+class Target_Installed_Package(models.Model):
+ target = models.ForeignKey(Target)
+ package = models.ForeignKey(Package)
-class Target_Package(models.Model):
- target = models.ForeignKey('Target')
- recipe = models.ForeignKey('Recipe', null=True)
- name = models.CharField(max_length=100)
- version = models.CharField(max_length=100, blank=True)
- size = models.IntegerField()
-
-
-class Target_Package_Dependency(models.Model):
- TYPE_DEPENDS = 0
- TYPE_RDEPENDS = 1
- TYPE_RECOMMENDS = 2
-
- DEPENDS_TYPE = (
- (TYPE_DEPENDS, "depends"),
- (TYPE_RDEPENDS, "rdepends"),
- (TYPE_RECOMMENDS, "recommends"),
- )
- package = models.ForeignKey(Target_Package, related_name='tpackage_dependencies_package')
- depends_on = models.ForeignKey(Target_Package, related_name='tpackage_dependencies_depends')
- dep_type = models.IntegerField(choices=DEPENDS_TYPE)
-
-
-class Build_File(models.Model):
- bpackage = models.ForeignKey(Build_Package, related_name='filelist_bpackage')
+class Package_File(models.Model):
+ package = models.ForeignKey(Package, related_name='buildfilelist_package')
path = models.FilePathField(max_length=255, blank=True)
size = models.IntegerField()
-class Target_File(models.Model):
- tpackage = models.ForeignKey(Target_Package, related_name='filelist_tpackage')
- path = models.FilePathField(max_length=255, blank=True)
- size = models.IntegerField()
-
-
class Recipe(models.Model):
name = models.CharField(max_length=100, blank=True)
version = models.CharField(max_length=100, blank=True)
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/11] toasterui: fix version numbers for no PE specified
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (4 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 05/11] toaster: change package storage model Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 07/11] toasterui: do not link non-image targets Paul Eggleton
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
PE is an optional field in recipes specifiying the epoch
for the recipe. The canonical form for the
full recipe version string is: PE:PV-PR
If no PE is specified, we shouldn't store the initial ":"
character, as it leads to inconsistency with how the
version string is used elsewhere. This patch drops the leading ":"
[YOCTO #5459]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/bb/ui/buildinfohelper.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/bb/ui/buildinfohelper.py b/lib/bb/ui/buildinfohelper.py
index 0252efd..3d5f1c8 100644
--- a/lib/bb/ui/buildinfohelper.py
+++ b/lib/bb/ui/buildinfohelper.py
@@ -531,7 +531,7 @@ class BuildInfoHelper(object):
recipe_info = {}
recipe_info['name'] = pn
- recipe_info['version'] = event._depgraph['pn'][pn]['version']
+ recipe_info['version'] = event._depgraph['pn'][pn]['version'].lstrip(":")
recipe_info['layer_version'] = layer_version_obj
recipe_info['summary'] = event._depgraph['pn'][pn]['summary']
recipe_info['license'] = event._depgraph['pn'][pn]['license']
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/11] toasterui: do not link non-image targets
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (5 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 06/11] toasterui: fix version numbers for no PE specified Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 08/11] toaster: update to Django 1.5 Paul Eggleton
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
In the Simple UI, builds table, targets that are images
have link to the list of installed packages.
There is no point in having links enabled for the non-image
targets, so we don't link in this case.
[YOCTO #5366]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/bldviewer/templates/build.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/toaster/bldviewer/templates/build.html b/lib/toaster/bldviewer/templates/build.html
index ab6e196..5f62350 100644
--- a/lib/toaster/bldviewer/templates/build.html
+++ b/lib/toaster/bldviewer/templates/build.html
@@ -26,7 +26,7 @@
<td><a href="{% url configuration build.id %}">{{build.get_outcome_display}}</a></td>
<td>{{build.started_on}}</td>
<td>{{build.completed_on}}</td>
- <td>{% for t in build.target_set.all %}<a href="{% url tpackage build.id t.id %}">{{t.target}}</a>{% if t.is_image %} (Img){% endif %}<br/>{% endfor %}</td>
+ <td>{% for t in build.target_set.all %}{%if t.is_image %}<a href="{% url tpackage build.id t.id %}">{% endif %}{{t.target}}{% if t.is_image %}</a>{% endif %}<br/>{% endfor %}</td>
<td>{{build.machine}}</td>
<td>{% time_difference build.started_on build.completed_on %}</td>
<td>{{build.errors_no}}:{% if build.errors_no %}{% for error in logs %}{% if error.build == build %}{% if error.level == 2 %}<p>{{error.message}}</p>{% endif %}{% endif %}{% endfor %}{% else %}None{% endif %}</td>
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/11] toaster: update to Django 1.5
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (6 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 07/11] toasterui: do not link non-image targets Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 09/11] toaster: migrate orm models to South Paul Eggleton
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
In order to remain up to date with the relevant technologies,
Toaster is updated with this patch to Django 1.5. This also
makes headways to allow usage of emerging
Django-related technologies.
Changes include the startup script Django version check, usage
of TemplateView instead of deprecated simple function to do
redirects, and update to the new form of the _url_ template tag.
Support for Django 1.4.5 is now deprecated.
[YOCTO #5558]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
bin/toaster | 4 ++--
lib/toaster/bldviewer/templates/base.html | 4 ++--
lib/toaster/bldviewer/templates/basebuildpage.html | 8 ++++----
lib/toaster/bldviewer/templates/bpackage.html | 4 ++--
lib/toaster/bldviewer/templates/build.html | 4 ++--
lib/toaster/bldviewer/templates/layer.html | 2 +-
lib/toaster/bldviewer/templates/package.html | 2 +-
lib/toaster/bldviewer/templates/task.html | 2 +-
lib/toaster/bldviewer/urls.py | 4 ++--
lib/toaster/toastermain/urls.py | 4 ++--
10 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/bin/toaster b/bin/toaster
index d4715fa..7e51014 100755
--- a/bin/toaster
+++ b/bin/toaster
@@ -87,8 +87,8 @@ BBBASEDIR=`dirname ${BASH_SOURCE}`/..
# Verify prerequisites
-if ! echo "import django; print (1,4,5) == django.VERSION[0:3]" | python 2>/dev/null | grep True >/dev/null; then
- echo -e "This program needs Django 1.4.5. Please install with\n\nsudo pip install django==1.4.5"
+if ! echo "import django; print (1,5) == django.VERSION[0:2]" | python 2>/dev/null | grep True >/dev/null; then
+ echo -e "This program needs Django 1.5. Please install with\n\nsudo pip install django==1.5"
return 2
fi
diff --git a/lib/toaster/bldviewer/templates/base.html b/lib/toaster/bldviewer/templates/base.html
index 101880d..d58cbea 100644
--- a/lib/toaster/bldviewer/templates/base.html
+++ b/lib/toaster/bldviewer/templates/base.html
@@ -14,8 +14,8 @@
<div style="width:100%; height: 100%; position:absolute">
<div style="width: 100%; height: 3em" class="nav">
<ul class="nav nav-tabs">
- <li><a href="{% url all-builds %}">All Builds</a></li>
- <li><a href="{% url all-layers %}">All Layers</a></li>
+ <li><a href="{% url "all-builds" %}">All Builds</a></li>
+ <li><a href="{% url "all-layers" %}">All Layers</a></li>
</ul>
</div>
diff --git a/lib/toaster/bldviewer/templates/basebuildpage.html b/lib/toaster/bldviewer/templates/basebuildpage.html
index 873f271..d590f28 100644
--- a/lib/toaster/bldviewer/templates/basebuildpage.html
+++ b/lib/toaster/bldviewer/templates/basebuildpage.html
@@ -3,14 +3,14 @@
{% block pagename %}
<ul class="nav nav-tabs" style="display: inline-block">
<li><a>Build {{build.target_set.all|join:" "}} at {{build.started_on}} : </a></li>
- <li><a href="{% url task build.id %}"> Tasks </a></li>
- <li><a href="{% url bpackage build.id %}"> Build Packages </a></li>
+ <li><a href="{% url "task" build.id %}"> Tasks </a></li>
+ <li><a href="{% url "bpackage" build.id %}"> Build Packages </a></li>
{% for t in build.target_set.all %}
{% if t.is_image %}
- <li><a href="{% url tpackage build.id t.pk %}"> Packages for {{t.target}} </a> </li>
+ <li><a href="{% url "tpackage" build.id t.pk %}"> Packages for {{t.target}} </a> </li>
{% endif %}
{% endfor %}
- <li><a href="{% url configuration build.id %}"> Configuration </a> </li>
+ <li><a href="{% url "configuration" build.id %}"> Configuration </a> </li>
</ul>
<h1>Toaster - Build {% block pagetitle %} {% endblock %}</h1>
{% endblock %}
diff --git a/lib/toaster/bldviewer/templates/bpackage.html b/lib/toaster/bldviewer/templates/bpackage.html
index ca092ca..07d0792 100644
--- a/lib/toaster/bldviewer/templates/bpackage.html
+++ b/lib/toaster/bldviewer/templates/bpackage.html
@@ -21,9 +21,9 @@
{% for package in packages %}
<tr class="data">
- <td><a name="#{{package.name}}" href="{% url bfile build.pk package.pk %}">{{package.name}} ({{package.filelist_bpackage.count}} files)</a></td>
+ <td><a name="#{{package.name}}" href="{% url "bfile" build.pk package.pk %}">{{package.name}} ({{package.filelist_bpackage.count}} files)</a></td>
<td>{{package.version}}-{{package.revision}}</td>
- <td>{%if package.recipe%}<a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
+ <td><a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a></td>
<td>{{package.summary}}</td>
<td>{{package.section}}</td>
diff --git a/lib/toaster/bldviewer/templates/build.html b/lib/toaster/bldviewer/templates/build.html
index 5f62350..5653cca 100644
--- a/lib/toaster/bldviewer/templates/build.html
+++ b/lib/toaster/bldviewer/templates/build.html
@@ -23,10 +23,10 @@
</tr>
{% for build in builds %}
<tr class="data">
- <td><a href="{% url configuration build.id %}">{{build.get_outcome_display}}</a></td>
+ <td><a href="{% url "configuration" build.id %}">{{build.get_outcome_display}}</a></td>
<td>{{build.started_on}}</td>
<td>{{build.completed_on}}</td>
- <td>{% for t in build.target_set.all %}{%if t.is_image %}<a href="{% url tpackage build.id t.id %}">{% endif %}{{t.target}}{% if t.is_image %}</a>{% endif %}<br/>{% endfor %}</td>
+ <td>{% for t in build.target_set.all %}{%if t.is_image %}<a href="{% url "tpackage" build.id t.id %}">{% endif %}{{t.target}}{% if t.is_image %}</a>{% endif %}<br/>{% endfor %}</td>
<td>{{build.machine}}</td>
<td>{% time_difference build.started_on build.completed_on %}</td>
<td>{{build.errors_no}}:{% if build.errors_no %}{% for error in logs %}{% if error.build == build %}{% if error.level == 2 %}<p>{{error.message}}</p>{% endif %}{% endif %}{% endfor %}{% else %}None{% endif %}</td>
diff --git a/lib/toaster/bldviewer/templates/layer.html b/lib/toaster/bldviewer/templates/layer.html
index fa4fd9b..c5034de 100644
--- a/lib/toaster/bldviewer/templates/layer.html
+++ b/lib/toaster/bldviewer/templates/layer.html
@@ -23,7 +23,7 @@
<td><table>
{% for lv in layer.versions %}
<tr><td>
- <a href="{% url layer_versions_recipes lv.id %}">({{lv.priority}}){{lv.branch}}:{{lv.commit}} ({{lv.count}} recipes)</a>
+ <a href="{% url "layer_versions_recipes" lv.id %}">({{lv.priority}}){{lv.branch}}:{{lv.commit}} ({{lv.count}} recipes)</a>
</td></tr>
{% endfor %}
</table></td>
diff --git a/lib/toaster/bldviewer/templates/package.html b/lib/toaster/bldviewer/templates/package.html
index b1246e7..fda9dab 100644
--- a/lib/toaster/bldviewer/templates/package.html
+++ b/lib/toaster/bldviewer/templates/package.html
@@ -20,7 +20,7 @@
<td>{{package.version}}</td>
<td>{{package.size}}</td>
<td>{%if package.recipe %}<a name="{{package.recipe.name}}.{{package.package_name}}">
- <a href="{% url layer_versions_recipes package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
+ <a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
<td>
<div style="height: 4em; overflow:auto">
{% for d in package.package_dependencies_source.all %}
diff --git a/lib/toaster/bldviewer/templates/task.html b/lib/toaster/bldviewer/templates/task.html
index e725369..5d9887e 100644
--- a/lib/toaster/bldviewer/templates/task.html
+++ b/lib/toaster/bldviewer/templates/task.html
@@ -28,7 +28,7 @@
<tr class="data">
<td>{{task.order}}</td>
<td><a name="{{task.recipe.name}}.{{task.task_name}}">
- <a href="{% url layer_versions_recipes task.recipe.layer_version_id %}#{{task.recipe.name}}">{{task.recipe.name}}</a>.{{task.task_name}}</a></td>
+ <a href="{% url "layer_versions_recipes" task.recipe.layer_version_id %}#{{task.recipe.name}}">{{task.recipe.name}}</a>.{{task.task_name}}</a></td>
<td>{{task.recipe.version}}</td>
{% if task.task_executed %}
diff --git a/lib/toaster/bldviewer/urls.py b/lib/toaster/bldviewer/urls.py
index becc679..b84c95f 100644
--- a/lib/toaster/bldviewer/urls.py
+++ b/lib/toaster/bldviewer/urls.py
@@ -17,7 +17,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from django.conf.urls import patterns, include, url
-from django.views.generic.simple import redirect_to
+from django.views.generic import RedirectView
urlpatterns = patterns('bldviewer.views',
url(r'^builds/$', 'build', name='all-builds'),
@@ -28,5 +28,5 @@ urlpatterns = patterns('bldviewer.views',
url(r'^build/(?P<build_id>\d+)/configuration/$', 'configuration', name='configuration'),
url(r'^layers/$', 'layer', name='all-layers'),
url(r'^layerversions/(?P<layerversion_id>\d+)/recipes/.*$', 'layer_versions_recipes', name='layer_versions_recipes'),
- url(r'^$', redirect_to, {'url': 'builds/'}),
+ url(r'^$', RedirectView.as_view( url= 'builds/')),
)
diff --git a/lib/toaster/toastermain/urls.py b/lib/toaster/toastermain/urls.py
index d0606bc..a696a0b 100644
--- a/lib/toaster/toastermain/urls.py
+++ b/lib/toaster/toastermain/urls.py
@@ -17,7 +17,7 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
from django.conf.urls import patterns, include, url
-from django.views.generic.simple import redirect_to
+from django.views.generic import RedirectView
from django.views.decorators.cache import never_cache
@@ -29,7 +29,7 @@ urlpatterns = patterns('',
url(r'^simple/', include('bldviewer.urls')),
url(r'^api/1.0/', include('bldviewer.api')),
url(r'^gui/', include('toastergui.urls')),
- url(r'^$', never_cache(redirect_to), {'url': '/simple/'}),
+ url(r'^$', never_cache(RedirectView.as_view(url='/simple/'))),
# Examples:
# url(r'^toaster/', include('toaster.foo.urls')),
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/11] toaster: migrate orm models to South
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (7 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 08/11] toaster: update to Django 1.5 Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 10/11] toaster: add pagination to the Simple UI Paul Eggleton
2013-12-09 19:07 ` [PATCH 11/11] toaster: Add more information for tasks in " Paul Eggleton
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
As Toaster advances, database schema alteration
will force users to delete old versions and lose
all data collected.
In order to prevent this, and to allow database
updates to happen without having to delete old data,
we use South to handle migrations for the ORM
application which stores the Toaster data.
[YOCTO #5559]
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
bin/toaster | 16 +-
lib/toaster/orm/migrations/0001_initial.py | 400 +++++++++++++++++++++++++++++
lib/toaster/orm/migrations/__init__.py | 0
lib/toaster/toastermain/settings.py | 1 +
4 files changed, 416 insertions(+), 1 deletion(-)
create mode 100644 lib/toaster/orm/migrations/0001_initial.py
create mode 100644 lib/toaster/orm/migrations/__init__.py
diff --git a/bin/toaster b/bin/toaster
index 7e51014..fc59fe5 100755
--- a/bin/toaster
+++ b/bin/toaster
@@ -40,9 +40,16 @@ function webserverStartAll()
{
retval=0
python $BBBASEDIR/lib/toaster/manage.py syncdb || retval=1
+ python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=2
if [ $retval -eq 1 ]; then
echo "Failed db sync, stopping system start" 1>&2
- else
+ elif [ $retval -eq 2 ]; then
+ echo -e "\nError on migration, trying to recover... \n"
+ python $BBBASEDIR/lib/toaster/manage.py migrate orm 0001_initial --fake
+ retval=0
+ python $BBBASEDIR/lib/toaster/manage.py migrate orm || retval=1
+ fi
+ if [ $retval -eq 0 ]; then
python $BBBASEDIR/lib/toaster/manage.py runserver 0.0.0.0:8000 </dev/null >${BUILDDIR}/toaster_web.log 2>&1 & echo $! >${BUILDDIR}/.toastermain.pid
fi
return $retval
@@ -92,6 +99,13 @@ if ! echo "import django; print (1,5) == django.VERSION[0:2]" | python 2>/dev/nu
return 2
fi
+if ! echo "import south; print [0,8,4] == map(int,south.__version__.split(\".\"))" | python 2>/dev/null | grep True >/dev/null; then
+ echo -e "This program needs South 0.8.4. Please install with\n\nsudo pip install south==0.8.4"
+ return 2
+fi
+
+
+
# Determine the action. If specified by arguments, fine, if not, toggle it
diff --git a/lib/toaster/orm/migrations/0001_initial.py b/lib/toaster/orm/migrations/0001_initial.py
new file mode 100644
index 0000000..3b606cb
--- /dev/null
+++ b/lib/toaster/orm/migrations/0001_initial.py
@@ -0,0 +1,400 @@
+# -*- coding: utf-8 -*-
+from south.utils import datetime_utils as datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'Build'
+ db.create_table(u'orm_build', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('machine', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('image_fstypes', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('distro', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('distro_version', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('started_on', self.gf('django.db.models.fields.DateTimeField')()),
+ ('completed_on', self.gf('django.db.models.fields.DateTimeField')()),
+ ('outcome', self.gf('django.db.models.fields.IntegerField')(default=2)),
+ ('errors_no', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('warnings_no', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('cooker_log_path', self.gf('django.db.models.fields.CharField')(max_length=500)),
+ ('build_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('bitbake_version', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ))
+ db.send_create_signal(u'orm', ['Build'])
+
+ # Adding model 'Target'
+ db.create_table(u'orm_target', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
+ ('target', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('is_image', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('file_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('file_size', self.gf('django.db.models.fields.IntegerField')()),
+ ))
+ db.send_create_signal(u'orm', ['Target'])
+
+ # Adding model 'Task'
+ db.create_table(u'orm_task', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='task_build', to=orm['orm.Build'])),
+ ('order', self.gf('django.db.models.fields.IntegerField')(null=True)),
+ ('task_executed', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('outcome', self.gf('django.db.models.fields.IntegerField')(default=5)),
+ ('sstate_checksum', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('path_to_sstate_obj', self.gf('django.db.models.fields.FilePathField')(max_length=500, blank=True)),
+ ('recipe', self.gf('django.db.models.fields.related.ForeignKey')(related_name='build_recipe', to=orm['orm.Recipe'])),
+ ('task_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('source_url', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
+ ('work_directory', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
+ ('script_type', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('line_number', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('disk_io', self.gf('django.db.models.fields.IntegerField')(null=True)),
+ ('cpu_usage', self.gf('django.db.models.fields.DecimalField')(null=True, max_digits=6, decimal_places=2)),
+ ('elapsed_time', self.gf('django.db.models.fields.CharField')(default=0, max_length=50)),
+ ('sstate_result', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('message', self.gf('django.db.models.fields.CharField')(max_length=240)),
+ ('logfile', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
+ ))
+ db.send_create_signal(u'orm', ['Task'])
+
+ # Adding model 'Task_Dependency'
+ db.create_table(u'orm_task_dependency', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('task', self.gf('django.db.models.fields.related.ForeignKey')(related_name='task_dependencies_task', to=orm['orm.Task'])),
+ ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='task_dependencies_depends', to=orm['orm.Task'])),
+ ))
+ db.send_create_signal(u'orm', ['Task_Dependency'])
+
+ # Adding model 'Package'
+ db.create_table(u'orm_package', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
+ ('recipe', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Recipe'], null=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('version', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('revision', self.gf('django.db.models.fields.CharField')(max_length=32, blank=True)),
+ ('summary', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
+ ('description', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
+ ('size', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('installed_size', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('section', self.gf('django.db.models.fields.CharField')(max_length=80, blank=True)),
+ ('license', self.gf('django.db.models.fields.CharField')(max_length=80, blank=True)),
+ ))
+ db.send_create_signal(u'orm', ['Package'])
+
+ # Adding model 'Package_Dependency'
+ db.create_table(u'orm_package_dependency', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('package', self.gf('django.db.models.fields.related.ForeignKey')(related_name='package_dependencies_source', to=orm['orm.Package'])),
+ ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='package_dependencies_target', to=orm['orm.Package'])),
+ ('dep_type', self.gf('django.db.models.fields.IntegerField')()),
+ ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target'], null=True)),
+ ))
+ db.send_create_signal(u'orm', ['Package_Dependency'])
+
+ # Adding model 'Target_Installed_Package'
+ db.create_table(u'orm_target_installed_package', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('target', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Target'])),
+ ('package', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Package'])),
+ ))
+ db.send_create_signal(u'orm', ['Target_Installed_Package'])
+
+ # Adding model 'Package_File'
+ db.create_table(u'orm_package_file', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('package', self.gf('django.db.models.fields.related.ForeignKey')(related_name='buildfilelist_package', to=orm['orm.Package'])),
+ ('path', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
+ ('size', self.gf('django.db.models.fields.IntegerField')()),
+ ))
+ db.send_create_signal(u'orm', ['Package_File'])
+
+ # Adding model 'Recipe'
+ db.create_table(u'orm_recipe', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('version', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('layer_version', self.gf('django.db.models.fields.related.ForeignKey')(related_name='recipe_layer_version', to=orm['orm.Layer_Version'])),
+ ('summary', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('description', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('section', self.gf('django.db.models.fields.CharField')(max_length=100, blank=True)),
+ ('license', self.gf('django.db.models.fields.CharField')(max_length=200, blank=True)),
+ ('licensing_info', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ('homepage', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
+ ('bugtracker', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
+ ('file_path', self.gf('django.db.models.fields.FilePathField')(max_length=255)),
+ ))
+ db.send_create_signal(u'orm', ['Recipe'])
+
+ # Adding model 'Recipe_Dependency'
+ db.create_table(u'orm_recipe_dependency', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('recipe', self.gf('django.db.models.fields.related.ForeignKey')(related_name='r_dependencies_recipe', to=orm['orm.Recipe'])),
+ ('depends_on', self.gf('django.db.models.fields.related.ForeignKey')(related_name='r_dependencies_depends', to=orm['orm.Recipe'])),
+ ('dep_type', self.gf('django.db.models.fields.IntegerField')()),
+ ))
+ db.send_create_signal(u'orm', ['Recipe_Dependency'])
+
+ # Adding model 'Layer'
+ db.create_table(u'orm_layer', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('local_path', self.gf('django.db.models.fields.FilePathField')(max_length=255)),
+ ('layer_index_url', self.gf('django.db.models.fields.URLField')(max_length=200)),
+ ))
+ db.send_create_signal(u'orm', ['Layer'])
+
+ # Adding model 'Layer_Version'
+ db.create_table(u'orm_layer_version', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='layer_version_build', to=orm['orm.Build'])),
+ ('layer', self.gf('django.db.models.fields.related.ForeignKey')(related_name='layer_version_layer', to=orm['orm.Layer'])),
+ ('branch', self.gf('django.db.models.fields.CharField')(max_length=50)),
+ ('commit', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('priority', self.gf('django.db.models.fields.IntegerField')()),
+ ))
+ db.send_create_signal(u'orm', ['Layer_Version'])
+
+ # Adding model 'Variable'
+ db.create_table(u'orm_variable', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('build', self.gf('django.db.models.fields.related.ForeignKey')(related_name='variable_build', to=orm['orm.Build'])),
+ ('variable_name', self.gf('django.db.models.fields.CharField')(max_length=100)),
+ ('variable_value', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ('changed', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('human_readable_name', self.gf('django.db.models.fields.CharField')(max_length=200)),
+ ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ))
+ db.send_create_signal(u'orm', ['Variable'])
+
+ # Adding model 'VariableHistory'
+ db.create_table(u'orm_variablehistory', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('variable', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Variable'])),
+ ('file_name', self.gf('django.db.models.fields.FilePathField')(max_length=255)),
+ ('line_number', self.gf('django.db.models.fields.IntegerField')(null=True)),
+ ('operation', self.gf('django.db.models.fields.CharField')(max_length=16)),
+ ))
+ db.send_create_signal(u'orm', ['VariableHistory'])
+
+ # Adding model 'LogMessage'
+ db.create_table(u'orm_logmessage', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('build', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['orm.Build'])),
+ ('level', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ('message', self.gf('django.db.models.fields.CharField')(max_length=240)),
+ ('pathname', self.gf('django.db.models.fields.FilePathField')(max_length=255, blank=True)),
+ ('lineno', self.gf('django.db.models.fields.IntegerField')(null=True)),
+ ))
+ db.send_create_signal(u'orm', ['LogMessage'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'Build'
+ db.delete_table(u'orm_build')
+
+ # Deleting model 'Target'
+ db.delete_table(u'orm_target')
+
+ # Deleting model 'Task'
+ db.delete_table(u'orm_task')
+
+ # Deleting model 'Task_Dependency'
+ db.delete_table(u'orm_task_dependency')
+
+ # Deleting model 'Package'
+ db.delete_table(u'orm_package')
+
+ # Deleting model 'Package_Dependency'
+ db.delete_table(u'orm_package_dependency')
+
+ # Deleting model 'Target_Installed_Package'
+ db.delete_table(u'orm_target_installed_package')
+
+ # Deleting model 'Package_File'
+ db.delete_table(u'orm_package_file')
+
+ # Deleting model 'Recipe'
+ db.delete_table(u'orm_recipe')
+
+ # Deleting model 'Recipe_Dependency'
+ db.delete_table(u'orm_recipe_dependency')
+
+ # Deleting model 'Layer'
+ db.delete_table(u'orm_layer')
+
+ # Deleting model 'Layer_Version'
+ db.delete_table(u'orm_layer_version')
+
+ # Deleting model 'Variable'
+ db.delete_table(u'orm_variable')
+
+ # Deleting model 'VariableHistory'
+ db.delete_table(u'orm_variablehistory')
+
+ # Deleting model 'LogMessage'
+ db.delete_table(u'orm_logmessage')
+
+
+ models = {
+ u'orm.build': {
+ 'Meta': {'object_name': 'Build'},
+ 'bitbake_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'build_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'completed_on': ('django.db.models.fields.DateTimeField', [], {}),
+ 'cooker_log_path': ('django.db.models.fields.CharField', [], {'max_length': '500'}),
+ 'distro': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'distro_version': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'errors_no': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image_fstypes': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'machine': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '2'}),
+ 'started_on': ('django.db.models.fields.DateTimeField', [], {}),
+ 'warnings_no': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+ },
+ u'orm.layer': {
+ 'Meta': {'object_name': 'Layer'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'layer_index_url': ('django.db.models.fields.URLField', [], {'max_length': '200'}),
+ 'local_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ u'orm.layer_version': {
+ 'Meta': {'object_name': 'Layer_Version'},
+ 'branch': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
+ 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_build'", 'to': u"orm['orm.Build']"}),
+ 'commit': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'layer': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'layer_version_layer'", 'to': u"orm['orm.Layer']"}),
+ 'priority': ('django.db.models.fields.IntegerField', [], {})
+ },
+ u'orm.logmessage': {
+ 'Meta': {'object_name': 'LogMessage'},
+ 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'level': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'lineno': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+ 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
+ 'pathname': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
+ },
+ u'orm.package': {
+ 'Meta': {'object_name': 'Package'},
+ 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'installed_size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Recipe']", 'null': 'True'}),
+ 'revision': ('django.db.models.fields.CharField', [], {'max_length': '32', 'blank': 'True'}),
+ 'section': ('django.db.models.fields.CharField', [], {'max_length': '80', 'blank': 'True'}),
+ 'size': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
+ 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
+ },
+ u'orm.package_dependency': {
+ 'Meta': {'object_name': 'Package_Dependency'},
+ 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
+ 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_target'", 'to': u"orm['orm.Package']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'package_dependencies_source'", 'to': u"orm['orm.Package']"}),
+ 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']", 'null': 'True'})
+ },
+ u'orm.package_file': {
+ 'Meta': {'object_name': 'Package_File'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'package': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'buildfilelist_package'", 'to': u"orm['orm.Package']"}),
+ 'path': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
+ 'size': ('django.db.models.fields.IntegerField', [], {})
+ },
+ u'orm.recipe': {
+ 'Meta': {'object_name': 'Recipe'},
+ 'bugtracker': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'description': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'file_path': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
+ 'homepage': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'layer_version': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'recipe_layer_version'", 'to': u"orm['orm.Layer_Version']"}),
+ 'license': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}),
+ 'licensing_info': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'section': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'summary': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'version': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'})
+ },
+ u'orm.recipe_dependency': {
+ 'Meta': {'object_name': 'Recipe_Dependency'},
+ 'dep_type': ('django.db.models.fields.IntegerField', [], {}),
+ 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_depends'", 'to': u"orm['orm.Recipe']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'r_dependencies_recipe'", 'to': u"orm['orm.Recipe']"})
+ },
+ u'orm.target': {
+ 'Meta': {'object_name': 'Target'},
+ 'build': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Build']"}),
+ 'file_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'file_size': ('django.db.models.fields.IntegerField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'is_image': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'target': ('django.db.models.fields.CharField', [], {'max_length': '100'})
+ },
+ u'orm.target_installed_package': {
+ 'Meta': {'object_name': 'Target_Installed_Package'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'package': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Package']"}),
+ 'target': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Target']"})
+ },
+ u'orm.task': {
+ 'Meta': {'ordering': "('order', 'recipe')", 'object_name': 'Task'},
+ 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_build'", 'to': u"orm['orm.Build']"}),
+ 'cpu_usage': ('django.db.models.fields.DecimalField', [], {'null': 'True', 'max_digits': '6', 'decimal_places': '2'}),
+ 'disk_io': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+ 'elapsed_time': ('django.db.models.fields.CharField', [], {'default': '0', 'max_length': '50'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'line_number': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'logfile': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
+ 'message': ('django.db.models.fields.CharField', [], {'max_length': '240'}),
+ 'order': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+ 'outcome': ('django.db.models.fields.IntegerField', [], {'default': '5'}),
+ 'path_to_sstate_obj': ('django.db.models.fields.FilePathField', [], {'max_length': '500', 'blank': 'True'}),
+ 'recipe': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'build_recipe'", 'to': u"orm['orm.Recipe']"}),
+ 'script_type': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'source_url': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'}),
+ 'sstate_checksum': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
+ 'sstate_result': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
+ 'task_executed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'task_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'work_directory': ('django.db.models.fields.FilePathField', [], {'max_length': '255', 'blank': 'True'})
+ },
+ u'orm.task_dependency': {
+ 'Meta': {'object_name': 'Task_Dependency'},
+ 'depends_on': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_depends'", 'to': u"orm['orm.Task']"}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'task': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'task_dependencies_task'", 'to': u"orm['orm.Task']"})
+ },
+ u'orm.variable': {
+ 'Meta': {'object_name': 'Variable'},
+ 'build': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'variable_build'", 'to': u"orm['orm.Build']"}),
+ 'changed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'human_readable_name': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'variable_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'variable_value': ('django.db.models.fields.TextField', [], {'blank': 'True'})
+ },
+ u'orm.variablehistory': {
+ 'Meta': {'object_name': 'VariableHistory'},
+ 'file_name': ('django.db.models.fields.FilePathField', [], {'max_length': '255'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'line_number': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
+ 'operation': ('django.db.models.fields.CharField', [], {'max_length': '16'}),
+ 'variable': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['orm.Variable']"})
+ }
+ }
+
+ complete_apps = ['orm']
\ No newline at end of file
diff --git a/lib/toaster/orm/migrations/__init__.py b/lib/toaster/orm/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/toaster/toastermain/settings.py b/lib/toaster/toastermain/settings.py
index 9435087..c6ede68 100644
--- a/lib/toaster/toastermain/settings.py
+++ b/lib/toaster/toastermain/settings.py
@@ -148,6 +148,7 @@ INSTALLED_APPS = (
'toastermain',
'bldviewer',
'toastergui',
+ 'south',
)
# A sample logging configuration. The only tangible logging
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 10/11] toaster: add pagination to the Simple UI
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (8 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 09/11] toaster: migrate orm models to South Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
2013-12-09 19:07 ` [PATCH 11/11] toaster: Add more information for tasks in " Paul Eggleton
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
In an effort to make the Simple UI more usable and
reponsive, this patch adds pagination support for the
pages with lots of entries: Builds, Configuration and
Tasks.
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/bldviewer/templates/basetable.html | 22 +++++++++-
lib/toaster/bldviewer/templates/bfile.html | 6 +--
lib/toaster/bldviewer/templates/bpackage.html | 6 +--
lib/toaster/bldviewer/templates/build.html | 2 +-
lib/toaster/bldviewer/templates/configuration.html | 2 +-
lib/toaster/bldviewer/templates/layer.html | 2 +-
lib/toaster/bldviewer/templates/package.html | 4 +-
lib/toaster/bldviewer/templates/recipe.html | 2 +-
lib/toaster/bldviewer/templates/task.html | 4 +-
lib/toaster/bldviewer/views.py | 47 ++++++++++++++++------
10 files changed, 69 insertions(+), 28 deletions(-)
diff --git a/lib/toaster/bldviewer/templates/basetable.html b/lib/toaster/bldviewer/templates/basetable.html
index 083bcb8..16628ea 100644
--- a/lib/toaster/bldviewer/templates/basetable.html
+++ b/lib/toaster/bldviewer/templates/basetable.html
@@ -26,7 +26,7 @@ function filterTableRows(test) {
{% block pagename %}
{% endblock %}
- <div align="left" style="display:inline-block; width: 40%; margin-left: 2em"> Search: <input type="search" id="filterstring" style="width: 80%" onkeyup="filterTableRows($('#filterstring').val())" autocomplete="off">
+ <div align="left" style="display:inline-block; width: 40%; margin-left: 2em"> Filter: <input type="search" id="filterstring" style="width: 80%" onkeyup="filterTableRows($('#filterstring').val())" autocomplete="off">
</div>
{% if hideshowcols %}
<div align="right" style="display: inline-block; width: 40%">Show/Hide columns:
@@ -36,7 +36,25 @@ function filterTableRows(test) {
</div>
{% endif %}
</div>
-<div>
+
+ <div style="display: block; float:right; margin-left: auto; margin-right:5em"><span class="pagination" style="vertical-align: top; margin-right: 3em">Showing {{objects.start_index}} to {{objects.end_index}} out of {{objects.paginator.count}} entries. </span>
+ <ul class="pagination" style="display: block-inline">
+{%if objects.has_previous %}
+ <li><a href="?page={{objects.previous_page_number}}">«</a></li>
+{%else%}
+ <li class="disabled"><a href="#">«</a></li>
+{%endif%}
+{% for i in objects.page_range %}
+ <li{%if i == objects.number %} class="active" {%endif%}><a href="?page={{i}}">{{i}}</a></li>
+{% endfor %}
+{%if objects.has_next%}
+ <li><a href="?page={{objects.next_page_number}}">»</a></li>
+{%else%}
+ <li class="disabled"><a href="#">»</a></li>
+{%endif%}
+ </ul>
+</div>
+
<table class="table table-striped table-condensed" style="width:95%">
{% block pagetable %}
{% endblock %}
diff --git a/lib/toaster/bldviewer/templates/bfile.html b/lib/toaster/bldviewer/templates/bfile.html
index d90f4fb..c7f5943 100644
--- a/lib/toaster/bldviewer/templates/bfile.html
+++ b/lib/toaster/bldviewer/templates/bfile.html
@@ -1,8 +1,8 @@
{% extends "basebuildpage.html" %}
-{% block pagetitle %}Files for package {{files.0.bpackage.name}} {% endblock %}
+{% block pagetitle %}Files for package {{objects.0.bpackage.name}} {% endblock %}
{% block pagetable %}
- {% if not files %}
+ {% if not objects %}
<p>No files were recorded for this package!</p>
{% else %}
@@ -11,7 +11,7 @@
<th>Size (Bytes)</th>
</tr>
- {% for file in files %}
+ {% for file in objects %}
<tr class="data">
<td>{{file.path}}</td>
diff --git a/lib/toaster/bldviewer/templates/bpackage.html b/lib/toaster/bldviewer/templates/bpackage.html
index 07d0792..67fc65c 100644
--- a/lib/toaster/bldviewer/templates/bpackage.html
+++ b/lib/toaster/bldviewer/templates/bpackage.html
@@ -2,7 +2,7 @@
{% block pagetitle %}Packages{% endblock %}
{% block pagetable %}
- {% if not packages %}
+ {% if not objects %}
<p>No packages were recorded for this target!</p>
{% else %}
@@ -18,12 +18,12 @@
<th>Dependencies List (all)</th>
</tr>
- {% for package in packages %}
+ {% for package in objects %}
<tr class="data">
<td><a name="#{{package.name}}" href="{% url "bfile" build.pk package.pk %}">{{package.name}} ({{package.filelist_bpackage.count}} files)</a></td>
<td>{{package.version}}-{{package.revision}}</td>
- <td><a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a></td>
+ <td>{%if package.recipe%}<a href="{% url "layer_versions_recipes" package.recipe.layer_version_id %}#{{package.recipe.name}}">{{package.recipe.name}}</a>{{package.package_name}}</a>{%endif%}</td>
<td>{{package.summary}}</td>
<td>{{package.section}}</td>
diff --git a/lib/toaster/bldviewer/templates/build.html b/lib/toaster/bldviewer/templates/build.html
index 5653cca..4fa87d5 100644
--- a/lib/toaster/bldviewer/templates/build.html
+++ b/lib/toaster/bldviewer/templates/build.html
@@ -21,7 +21,7 @@
<th>Bitbake Version</th>
<th>Build Name</th>
</tr>
- {% for build in builds %}
+ {% for build in objects %}
<tr class="data">
<td><a href="{% url "configuration" build.id %}">{{build.get_outcome_display}}</a></td>
<td>{{build.started_on}}</td>
diff --git a/lib/toaster/bldviewer/templates/configuration.html b/lib/toaster/bldviewer/templates/configuration.html
index 8db35e0..521620f 100644
--- a/lib/toaster/bldviewer/templates/configuration.html
+++ b/lib/toaster/bldviewer/templates/configuration.html
@@ -10,7 +10,7 @@
<th>Value</th>
</tr>
- {% for variable in configuration %}
+ {% for variable in objects %}
<tr class="data">
<td>{{variable.variable_name}}</td>
diff --git a/lib/toaster/bldviewer/templates/layer.html b/lib/toaster/bldviewer/templates/layer.html
index c5034de..410d766 100644
--- a/lib/toaster/bldviewer/templates/layer.html
+++ b/lib/toaster/bldviewer/templates/layer.html
@@ -14,7 +14,7 @@
<th>Known Versions</th>
</tr>
- {% for layer in layers %}
+ {% for layer in objects %}
<tr class="data">
<td>{{layer.name}}</td>
diff --git a/lib/toaster/bldviewer/templates/package.html b/lib/toaster/bldviewer/templates/package.html
index fda9dab..1ba3726 100644
--- a/lib/toaster/bldviewer/templates/package.html
+++ b/lib/toaster/bldviewer/templates/package.html
@@ -1,7 +1,7 @@
{% extends "basebuildpage.html" %}
{% block pagetable %}
- {% if not packages %}
+ {% if not objects %}
<p>No packages were recorded for this target!</p>
{% else %}
@@ -13,7 +13,7 @@
<th>Depends on</th>
</tr>
- {% for package in packages %}
+ {% for package in objects %}
<tr class="data">
<td><a name="#{{package.name}}">{{package.name}}</a></td>
diff --git a/lib/toaster/bldviewer/templates/recipe.html b/lib/toaster/bldviewer/templates/recipe.html
index 7d5fbf4..d7f57eb 100644
--- a/lib/toaster/bldviewer/templates/recipe.html
+++ b/lib/toaster/bldviewer/templates/recipe.html
@@ -25,7 +25,7 @@
<th style="width: 30em">Recipe Dependency</th>
- {% for recipe in recipes %}
+ {% for recipe in objects %}
<tr class="data">
<td><a name="{{recipe.name}}">{{recipe.name}}</a></td>
diff --git a/lib/toaster/bldviewer/templates/task.html b/lib/toaster/bldviewer/templates/task.html
index 5d9887e..6a9979e 100644
--- a/lib/toaster/bldviewer/templates/task.html
+++ b/lib/toaster/bldviewer/templates/task.html
@@ -2,7 +2,7 @@
{% block pagetitle %}Tasks{% endblock %}
{% block pagetable %}
- {% if not tasks %}
+ {% if not objects %}
<p>No tasks were executed in this build!</p>
{% else %}
@@ -23,7 +23,7 @@
<th>Depends</th>
</tr>
- {% for task in tasks %}
+ {% for task in objects %}
<tr class="data">
<td>{{task.order}}</td>
diff --git a/lib/toaster/bldviewer/views.py b/lib/toaster/bldviewer/views.py
index 3eb785b..7cb9b42 100644
--- a/lib/toaster/bldviewer/views.py
+++ b/lib/toaster/bldviewer/views.py
@@ -24,15 +24,38 @@ from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMes
from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
from orm.models import Target_Installed_Package
from django.views.decorators.cache import cache_control
+from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
+
+
+def _build_page_range(paginator, index = 1):
+ try:
+ page = paginator.page(index)
+ except PageNotAnInteger:
+ page = paginator.page(1)
+ except EmptyPage:
+ page = paginator.page(paginator.num_pages)
+
+ page.page_range = [page.number]
+ crt_range = 0
+ for i in range(1,5):
+ if (page.number + i) <= paginator.num_pages:
+ page.page_range = page.page_range + [ page.number + i]
+ crt_range +=1
+ if (page.number - i) > 0:
+ page.page_range = [page.number -i] + page.page_range
+ crt_range +=1
+ if crt_range == 4:
+ break
+ return page
@cache_control(no_store=True)
def build(request):
template = 'build.html'
- build_info = Build.objects.all()
-
logs = LogMessage.objects.all()
- context = {'builds': build_info, 'logs': logs ,
+ build_info = _build_page_range(Paginator(Build.objects.order_by("-id"), 10),request.GET.get('page', 1))
+
+ context = {'objects': build_info, 'logs': logs ,
'hideshowcols' : [
{'name': 'Output', 'order':10},
{'name': 'Log', 'order':11},
@@ -61,38 +84,38 @@ def _find_task_provider(task):
def task(request, build_id):
template = 'task.html'
- tasks = Task.objects.filter(build=build_id)
+ tasks = _build_page_range(Paginator(Task.objects.filter(build=build_id), 100),request.GET.get('page', 1))
for t in tasks:
if t.outcome == Task.OUTCOME_COVERED:
t.provider = _find_task_provider(t)
- context = {'build': Build.objects.filter(pk=build_id)[0], 'tasks': tasks}
+ context = {'build': Build.objects.filter(pk=build_id)[0], 'objects': tasks}
return render(request, template, context)
def configuration(request, build_id):
template = 'configuration.html'
- variables = Variable.objects.filter(build=build_id)
- context = {'build': Build.objects.filter(pk=build_id)[0], 'configuration' : variables}
+ variables = _build_page_range(Paginator(Variable.objects.filter(build=build_id), 50), request.GET.get('page', 1))
+ context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : variables}
return render(request, template, context)
def bpackage(request, build_id):
template = 'bpackage.html'
packages = Package.objects.filter(build = build_id)
- context = {'build': Build.objects.filter(pk=build_id)[0], 'packages' : packages}
+ context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : packages}
return render(request, template, context)
def bfile(request, build_id, package_id):
template = 'bfile.html'
files = Package_File.objects.filter(package = package_id)
- context = {'build': Build.objects.filter(pk=build_id)[0], 'files' : files}
+ context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : files}
return render(request, template, context)
def tpackage(request, build_id, target_id):
template = 'package.html'
packages = map(lambda x: x.package, list(Target_Installed_Package.objects.filter(target=target_id)))
- context = {'build': Build.objects.filter(pk=build_id)[0], 'packages' : packages}
+ context = {'build': Build.objects.filter(pk=build_id)[0], 'objects' : packages}
return render(request, template, context)
def layer(request):
@@ -104,7 +127,7 @@ def layer(request):
for liv in li.versions:
liv.count = Recipe.objects.filter(layer_version__id = liv.id).count()
- context = {'layers': layer_info}
+ context = {'objects': layer_info}
return render(request, template, context)
@@ -113,7 +136,7 @@ def layer_versions_recipes(request, layerversion_id):
template = 'recipe.html'
recipes = Recipe.objects.filter(layer_version__id = layerversion_id)
- context = {'recipes': recipes,
+ context = {'objects': recipes,
'layer_version' : Layer_Version.objects.filter( id = layerversion_id )[0]
}
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 11/11] toaster: Add more information for tasks in Simple UI
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
` (9 preceding siblings ...)
2013-12-09 19:07 ` [PATCH 10/11] toaster: add pagination to the Simple UI Paul Eggleton
@ 2013-12-09 19:07 ` Paul Eggleton
10 siblings, 0 replies; 12+ messages in thread
From: Paul Eggleton @ 2013-12-09 19:07 UTC (permalink / raw)
To: bitbake-devel
From: Alexandru DAMIAN <alexandru.damian@intel.com>
This patch adds more information about Tasks in the Simple UI:
* all local file system information is not listed in a single
column, showing the common relationship
* adding the display for the location of the task source
* we display the work directory for each task
Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com>
---
lib/toaster/bldviewer/templates/task.html | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/lib/toaster/bldviewer/templates/task.html b/lib/toaster/bldviewer/templates/task.html
index 6a9979e..de965ab 100644
--- a/lib/toaster/bldviewer/templates/task.html
+++ b/lib/toaster/bldviewer/templates/task.html
@@ -14,12 +14,11 @@
<th>Checksum</th>
<th>Outcome</th>
<th>Message</th>
- <th>Logfile</th>
<th>Time</th>
<th>CPU usage</th>
<th>Disk I/O</th>
<th>Script type</th>
- <th>File path</th>
+ <th>Filesystem</th>
<th>Depends</th>
</tr>
@@ -40,12 +39,17 @@
<td>{{task.sstate_checksum}}</td>
<td>{{task.get_outcome_display}}{% if task.provider %}</br>(by <a href="#{{task.provider.recipe.name}}.{{task.provider.task_name}}">{{task.provider.recipe.name}}.{{task.provider.task_name}}</a>){% endif %}</td>
<td><p>{{task.message}}</td>
- <td><a target="_fileview" href="file:///{{task.logfile}}">{{task.logfile}}</a></td>
<td>{{task.elapsed_time}}</td>
<td>{{task.cpu_usage}}</td>
<td>{{task.disk_io}}</td>
<td>{{task.get_script_type_display}}</td>
- <td><a target="_fileview" href="file:///{{task.recipe.file_path}}">{{task.recipe.file_path}}</a></td>
+ <td> <table>
+<tr><td> Recipe</td><td><a target="_fileview" href="file:///{{task.recipe.file_path}}">{{task.recipe.file_path}}</a></td></tr>
+<tr><td> Source</td><td><a target="_fileview" href="file:///{{task.file_name}}">{{task.file_name}}:{{task.line_number}}</a></td></tr>
+<tr><td> Workdir</td><td><a target="_fileview" href="file:///{{task.work_directory}}">{{task.work_directory}}</a></td></tr>
+<tr><td> Log</td><td><a target="_fileview" href="file:///{{task.logfile}}">{{task.logfile}}</a><br/></td></tr>
+</table>
+ </td>
<td>
<div style="height: 3em; overflow:auto">
{% for tt in task.task_dependencies_task.all %}
--
1.8.1.2
^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-12-09 19:07 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-09 19:07 [PATCH 00/11] Toaster improvements (BitBake part) Paul Eggleton
2013-12-09 19:07 ` [PATCH 01/11] toaster: Analysis API variablehistory update Paul Eggleton
2013-12-09 19:07 ` [PATCH 02/11] toaster: remove Author field in SimpleUI Paul Eggleton
2013-12-09 19:07 ` [PATCH 03/11] toaster: move layer information reading code Paul Eggleton
2013-12-09 19:07 ` [PATCH 04/11] toaster: update build stats reading Paul Eggleton
2013-12-09 19:07 ` [PATCH 05/11] toaster: change package storage model Paul Eggleton
2013-12-09 19:07 ` [PATCH 06/11] toasterui: fix version numbers for no PE specified Paul Eggleton
2013-12-09 19:07 ` [PATCH 07/11] toasterui: do not link non-image targets Paul Eggleton
2013-12-09 19:07 ` [PATCH 08/11] toaster: update to Django 1.5 Paul Eggleton
2013-12-09 19:07 ` [PATCH 09/11] toaster: migrate orm models to South Paul Eggleton
2013-12-09 19:07 ` [PATCH 10/11] toaster: add pagination to the Simple UI Paul Eggleton
2013-12-09 19:07 ` [PATCH 11/11] toaster: Add more information for tasks in " Paul Eggleton
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.