summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui
diff options
context:
space:
mode:
authorEd Bartosh <ed.bartosh@linux.intel.com>2015-09-28 21:45:22 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-09-29 14:11:37 +0100
commita3ff4b28baa9f4cc76ec4993f862f2ed7bd20f65 (patch)
treed85c61a3e432146f17351c5fc6a3bd1e39588da9 /bitbake/lib/toaster/toastergui
parent28153acb0aadce9e42ab5eac02f9b68921a9563f (diff)
downloadpoky-a3ff4b28baa9f4cc76ec4993f862f2ed7bd20f65.tar.gz
bitbake: toaster: Add new ReST API for Image Customisation feature
Implemented xhr_customrecipe API. To create a custom recipe from a base recipe. Implemented xhr_customrecipe_packages API to add/remove packages to/from custom recipe. co-authored see Signed-off-by (Bitbake rev: 84be400237173970716616eeab6a37d776aa011b) Signed-off-by: Ed Bartosh <ed.bartosh@linux.intel.com> Signed-off-by: Elliot Smith <elliot.smith@intel.com> Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: brian avery <avery.brian@gmail.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/toastergui')
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py10
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py152
2 files changed, 159 insertions, 3 deletions
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index 55f325d0d6..b47a161687 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -152,6 +152,14 @@ urlpatterns = patterns('toastergui.views',
152 # JS Unit tests 152 # JS Unit tests
153 url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'), 153 url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
154 154
155 # default redirection 155 # image customisation functionality
156 url(r'^xhr_customrecipe/(?P<recipe_id>\d+)/packages/(?P<package_id>\d+|)$',
157 'xhr_customrecipe_packages', name='xhr_customrecipe_packages'),
158 url(r'^xhr_customrecipe/(?P<recipe_id>\d+)$', 'xhr_customrecipe_id',
159 name='xhr_customrecipe_id'),
160 url(r'^xhr_customrecipe/', 'xhr_customrecipe',
161 name='xhr_customrecipe'),
162
163 # default redirection
156 url(r'^$', RedirectView.as_view( url= 'landing')), 164 url(r'^$', RedirectView.as_view( url= 'landing')),
157) 165)
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 5ea6122a02..392e56da2a 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -26,12 +26,12 @@
26import operator,re 26import operator,re
27 27
28from django.db.models import F, Q, Sum, Count, Max 28from django.db.models import F, Q, Sum, Count, Max
29from django.db import IntegrityError 29from django.db import IntegrityError, Error
30from django.shortcuts import render, redirect 30from django.shortcuts import render, redirect
31from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable 31from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe, LogMessage, Variable
32from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency 32from orm.models import Task_Dependency, Recipe_Dependency, Package, Package_File, Package_Dependency
33from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact 33from orm.models import Target_Installed_Package, Target_File, Target_Image_File, BuildArtifact
34from orm.models import BitbakeVersion 34from orm.models import BitbakeVersion, CustomImageRecipe
35from bldcontrol import bbcontroller 35from bldcontrol import bbcontroller
36from django.views.decorators.cache import cache_control 36from django.views.decorators.cache import cache_control
37from django.core.urlresolvers import reverse, resolve 37from django.core.urlresolvers import reverse, resolve
@@ -2596,7 +2596,155 @@ if True:
2596 2596
2597 return HttpResponse(jsonfilter({"error": "ok",}), content_type = "application/json") 2597 return HttpResponse(jsonfilter({"error": "ok",}), content_type = "application/json")
2598 2598
2599 @xhr_response
2600 def xhr_customrecipe(request):
2601 """
2602 Custom image recipe REST API
2603
2604 Entry point: /xhr_customrecipe/
2605 Method: POST
2606
2607 Args:
2608 name: name of custom recipe to create
2609 project: target project id of orm.models.Project
2610 base: base recipe id of orm.models.Recipe
2611
2612 Returns:
2613 {"error": "ok",
2614 "url": <url of the created recipe>}
2615 or
2616 {"error": <error message>}
2617 """
2618 # check if request has all required parameters
2619 for param in ('name', 'project', 'base'):
2620 if param not in request.POST:
2621 return {"error": "Missing parameter '%s'" % param}
2622
2623 # get project and baserecipe objects
2624 params = {}
2625 for name, model in [("project", Project),
2626 ("base", Recipe)]:
2627 value = request.POST[name]
2628 try:
2629 params[name] = model.objects.get(id=value)
2630 except model.DoesNotExist:
2631 return {"error": "Invalid %s id %s" % (name, value)}
2632
2633 # create custom recipe
2634 try:
2635 recipe = CustomImageRecipe.objects.create(
2636 name=request.POST["name"],
2637 base_recipe=params["base"],
2638 project=params["project"])
2639 except Error as err:
2640 return {"error": "Can't create custom recipe: %s" % err}
2641
2642 # Find the package list from the last build of this recipe/target
2643 build = Build.objects.filter(target__target=params['base'].name,
2644 project=params['project']).last()
2645
2646 if build:
2647 # Copy in every package
2648 # We don't want these packages to be linked to anything because
2649 # that underlying data may change e.g. delete a build
2650 for package in build.package_set.all():
2651 # Create the duplicate
2652 package.pk = None
2653 package.save()
2654 # Disassociate the package from the build
2655 package.build = None
2656 package.save()
2657 recipe.packages.add(package)
2658 else:
2659 logger.warn("No packages found for this base recipe")
2660
2661 return {"error": "ok",
2662 "url": reverse('customrecipe', args=(params['project'].pk,
2663 recipe.id))}
2664
2665 @xhr_response
2666 def xhr_customrecipe_id(request, recipe_id):
2667 """
2668 Set of ReST API processors working with recipe id.
2669
2670 Entry point: /xhr_customrecipe/<recipe_id>
2671
2672 Methods:
2673 GET - Get details of custom image recipe
2674 DELETE - Delete custom image recipe
2675
2676 Returns:
2677 GET:
2678 {"error": "ok",
2679 "info": dictionary of field name -> value pairs
2680 of the CustomImageRecipe model}
2681 DELETE:
2682 {"error": "ok"}
2683 or
2684 {"error": <error message>}
2685 """
2686 objects = CustomImageRecipe.objects.filter(id=recipe_id)
2687 if not objects:
2688 return {"error": "Custom recipe with id=%s "
2689 "not found" % recipe_id}
2690 if request.method == 'GET':
2691 values = CustomImageRecipe.objects.filter(id=recipe_id).values()
2692 if values:
2693 return {"error": "ok", "info": values[0]}
2694 else:
2695 return {"error": "Custom recipe with id=%s "
2696 "not found" % recipe_id}
2697 return {"error": "ok", "info": objects.values()[0]}
2698 elif request.method == 'DELETE':
2699 objects.delete()
2700 return {"error": "ok"}
2701 else:
2702 return {"error": "Method %s is not supported" % request.method}
2703
2704 @xhr_response
2705 def xhr_customrecipe_packages(request, recipe_id, package_id):
2706 """
2707 ReST API to add/remove packages to/from custom recipe.
2599 2708
2709 Entry point: /xhr_customrecipe/<recipe_id>/packages/
2710
2711 Methods:
2712 PUT - Add package to the recipe
2713 DELETE - Delete package from the recipe
2714
2715 Returns:
2716 {"error": "ok"}
2717 or
2718 {"error": <error message>}
2719 """
2720 try:
2721 recipe = CustomImageRecipe.objects.get(id=recipe_id)
2722 except CustomImageRecipe.DoesNotExist:
2723 return {"error": "Custom recipe with id=%s "
2724 "not found" % recipe_id}
2725
2726 if request.method == 'GET' and not package_id:
2727 return {"error": "ok",
2728 "packages": list(recipe.packages.values_list('id'))}
2729
2730 try:
2731 package = Package.objects.get(id=package_id)
2732 except Package.DoesNotExist:
2733 return {"error": "Package with id=%s "
2734 "not found" % package_id}
2735
2736 if request.method == 'PUT':
2737 recipe.packages.add(package)
2738 return {"error": "ok"}
2739 elif request.method == 'DELETE':
2740 if package in recipe.packages.all():
2741 recipe.packages.remove(package)
2742 return {"error": "ok"}
2743 else:
2744 return {"error": "Package '%s' is not in the recipe '%s'" % \
2745 (package.name, recipe.name)}
2746 else:
2747 return {"error": "Method %s is not supported" % request.method}
2600 2748
2601 def importlayer(request, pid): 2749 def importlayer(request, pid):
2602 template = "importlayer.html" 2750 template = "importlayer.html"