All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michael Wood <michael.g.wood@intel.com>
To: toaster@yoctoproject.org
Subject: [PATCH 12/21] toaster: Add new ReST API for Image Customisation feature
Date: Fri, 25 Sep 2015 19:07:23 +0100	[thread overview]
Message-ID: <1443204452-32244-13-git-send-email-michael.g.wood@intel.com> (raw)
In-Reply-To: <1443204452-32244-1-git-send-email-michael.g.wood@intel.com>

From: Ed Bartosh <ed.bartosh@linux.intel.com>

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

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>
---
 bitbake/lib/toaster/toastergui/urls.py  |  10 ++-
 bitbake/lib/toaster/toastergui/views.py | 152 +++++++++++++++++++++++++++++++-
 2 files changed, 159 insertions(+), 3 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index 55f325d..b47a161 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -152,6 +152,14 @@ urlpatterns = patterns('toastergui.views',
         # JS Unit tests
         url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
 
-        # default redirection
+        # image customisation functionality
+        url(r'^xhr_customrecipe/(?P<recipe_id>\d+)/packages/(?P<package_id>\d+|)$',
+            'xhr_customrecipe_packages', name='xhr_customrecipe_packages'),
+        url(r'^xhr_customrecipe/(?P<recipe_id>\d+)$', 'xhr_customrecipe_id',
+            name='xhr_customrecipe_id'),
+        url(r'^xhr_customrecipe/', 'xhr_customrecipe',
+            name='xhr_customrecipe'),
+
+          # default redirection
         url(r'^$', RedirectView.as_view( url= 'landing')),
 )
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 5ea6122..392e56d 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -26,12 +26,12 @@
 import operator,re
 
 from django.db.models import F, Q, Sum, Count, Max
-from django.db import IntegrityError
+from django.db import IntegrityError, Error
 from django.shortcuts import render, redirect
 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, Target_File, Target_Image_File, BuildArtifact
-from orm.models import BitbakeVersion
+from orm.models import BitbakeVersion, CustomImageRecipe
 from bldcontrol import bbcontroller
 from django.views.decorators.cache import cache_control
 from django.core.urlresolvers import reverse, resolve
@@ -2596,7 +2596,155 @@ if True:
 
         return HttpResponse(jsonfilter({"error": "ok",}), content_type = "application/json")
 
+    @xhr_response
+    def xhr_customrecipe(request):
+        """
+        Custom image recipe REST API
+
+        Entry point: /xhr_customrecipe/
+        Method: POST
+
+        Args:
+            name: name of custom recipe to create
+            project: target project id of orm.models.Project
+            base: base recipe id of orm.models.Recipe
+
+        Returns:
+            {"error": "ok",
+             "url": <url of the created recipe>}
+            or
+            {"error": <error message>}
+        """
+        # check if request has all required parameters
+        for param in ('name', 'project', 'base'):
+            if param not in request.POST:
+                return {"error": "Missing parameter '%s'" % param}
+
+        # get project and baserecipe objects
+        params = {}
+        for name, model in [("project", Project),
+                            ("base", Recipe)]:
+            value = request.POST[name]
+            try:
+                params[name] = model.objects.get(id=value)
+            except model.DoesNotExist:
+                return {"error": "Invalid %s id %s" % (name, value)}
+
+        # create custom recipe
+        try:
+            recipe = CustomImageRecipe.objects.create(
+                         name=request.POST["name"],
+                         base_recipe=params["base"],
+                         project=params["project"])
+        except Error as err:
+            return {"error": "Can't create custom recipe: %s" % err}
+
+        # Find the package list from the last build of this recipe/target
+        build = Build.objects.filter(target__target=params['base'].name,
+                    project=params['project']).last()
+
+        if build:
+            # Copy in every package
+            # We don't want these packages to be linked to anything because
+            # that underlying data may change e.g. delete a build
+            for package in build.package_set.all():
+                # Create the duplicate
+                package.pk = None
+                package.save()
+                # Disassociate the package from the build
+                package.build = None
+                package.save()
+                recipe.packages.add(package)
+        else:
+            logger.warn("No packages found for this base recipe")
+
+        return {"error": "ok",
+                "url": reverse('customrecipe', args=(params['project'].pk,
+                                                     recipe.id))}
+
+    @xhr_response
+    def xhr_customrecipe_id(request, recipe_id):
+        """
+        Set of ReST API processors working with recipe id.
+
+        Entry point: /xhr_customrecipe/<recipe_id>
+
+        Methods:
+            GET - Get details of custom image recipe
+            DELETE - Delete custom image recipe
+
+        Returns:
+            GET:
+            {"error": "ok",
+             "info": dictionary of field name -> value pairs
+                     of the CustomImageRecipe model}
+            DELETE:
+            {"error": "ok"}
+            or
+            {"error": <error message>}
+        """
+        objects = CustomImageRecipe.objects.filter(id=recipe_id)
+        if not objects:
+            return {"error": "Custom recipe with id=%s "
+                             "not found" % recipe_id}
+        if request.method == 'GET':
+            values = CustomImageRecipe.objects.filter(id=recipe_id).values()
+            if values:
+                return {"error": "ok", "info": values[0]}
+            else:
+                return {"error": "Custom recipe with id=%s "
+                                 "not found" % recipe_id}
+            return {"error": "ok", "info": objects.values()[0]}
+        elif request.method == 'DELETE':
+            objects.delete()
+            return {"error": "ok"}
+        else:
+            return {"error": "Method %s is not supported" % request.method}
+
+    @xhr_response
+    def xhr_customrecipe_packages(request, recipe_id, package_id):
+        """
+        ReST API to add/remove packages to/from custom recipe.
 
+        Entry point: /xhr_customrecipe/<recipe_id>/packages/
+
+        Methods:
+            PUT - Add package to the recipe
+            DELETE - Delete package from the recipe
+
+        Returns:
+            {"error": "ok"}
+            or
+            {"error": <error message>}
+        """
+        try:
+            recipe = CustomImageRecipe.objects.get(id=recipe_id)
+        except CustomImageRecipe.DoesNotExist:
+            return {"error": "Custom recipe with id=%s "
+                             "not found" % recipe_id}
+
+        if request.method == 'GET' and not package_id:
+            return {"error": "ok",
+                    "packages": list(recipe.packages.values_list('id'))}
+
+        try:
+            package = Package.objects.get(id=package_id)
+        except Package.DoesNotExist:
+            return {"error": "Package with id=%s "
+                             "not found" % package_id}
+
+        if request.method == 'PUT':
+            recipe.packages.add(package)
+            return {"error": "ok"}
+        elif request.method == 'DELETE':
+            if package in recipe.packages.all():
+                recipe.packages.remove(package)
+                return {"error": "ok"}
+            else:
+                return {"error": "Package '%s' is not in the recipe '%s'" % \
+                                 (package.name, recipe.name)}
+        else:
+            return {"error": "Method %s is not supported" % request.method}
 
     def importlayer(request, pid):
         template = "importlayer.html"
-- 
2.1.4



  parent reply	other threads:[~2015-09-25 18:08 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-25 18:07 [PATCH 00/21] michaelw/toaster/ic-5.0 Michael Wood
2015-09-25 18:07 ` [PATCH 01/21] toaster: make a workaround for old style index Michael Wood
2015-09-25 18:07 ` [PATCH 02/21] toaster: tables Move the title and name into the widget Michael Wood
2015-09-25 18:07 ` [PATCH 03/21] toaster: create custom layer and recipes for Image customisation Michael Wood
2015-09-25 18:07 ` [PATCH 04/21] toaster: widgets ToasterTable add logger to notify when cache hit Michael Wood
2015-09-25 18:07 ` [PATCH 05/21] toaster: widgets ToasterTable Add more info to search field exception Michael Wood
2015-09-25 18:07 ` [PATCH 06/21] toaster: add nocache option to the ToasterTable widget Michael Wood
2015-09-25 18:07 ` [PATCH 07/21] toaster: ToasterTable remove unused class definition Michael Wood
2015-09-25 18:07 ` [PATCH 08/21] toaster: Add CustomImageRecipe model Michael Wood
2015-09-25 18:07 ` [PATCH 09/21] toaster: add toggle for enabling image customisation feeature Michael Wood
2015-09-25 18:07 ` [PATCH 10/21] toaster: implement decorator for REST responses Michael Wood
2015-09-25 18:07 ` [PATCH 11/21] toaster: Fix indentation of jsunittests view Michael Wood
2015-09-25 18:07 ` Michael Wood [this message]
2015-09-25 18:07 ` [PATCH 13/21] toaster: Add ToasterTables for Image customisation feature Michael Wood
2015-09-25 18:07 ` [PATCH 14/21] toaster: Add Image customisation frontend feature Michael Wood
2015-09-25 18:07 ` [PATCH 15/21] toaster: Add test cases for new Image customisation features Michael Wood
2015-09-25 18:07 ` [PATCH 16/21] toaster: Special case the openembedded-core layer to avoid duplicates Michael Wood
2015-09-25 18:07 ` [PATCH 17/21] toaster: Create a relationship between build information and toaster layers Michael Wood
2015-09-25 18:07 ` [PATCH 18/21] toaster: Prioroitise the layer more generic vcs reference over the sha Michael Wood
2015-09-25 18:07 ` [PATCH 19/21] toaster: tables show all recipes in the layerdetails even duplicates Michael Wood
2015-09-25 18:07 ` [PATCH 20/21] toaster: buildinfohelper Create a copy of the built layer and recipe Michael Wood
2015-09-25 18:07 ` [PATCH 21/21] Revert "bitbake: toaster: don't re-create Target objects" Michael Wood
2015-09-28 16:07   ` Additional patch Michael Wood
2015-09-28 16:07     ` [PATCH] toaster: orm remove the complicated querying on the ORM Michael Wood
2015-09-29  4:43     ` Additional patch Brian Avery

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1443204452-32244-13-git-send-email-michael.g.wood@intel.com \
    --to=michael.g.wood@intel.com \
    --cc=toaster@yoctoproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.