All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Build cancellation
@ 2016-02-25 18:21 Michael Wood
  2016-02-25 18:21 ` [PATCH 01/11] toaster: bldcontrol Add forceShutDown function to BitbakeController Michael Wood
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

This is the combination of Sujith's and my work on build cancel. 

Michael Wood (7):
  toaster: Move xhr calls for starting and stopping builds
  toaster: xhr Update the implementation of the build cancellation
    request
  toaster: libtoaster Update implementation of startABuild and
    cancelABuild
  toaster: bldcontrol models Add a cancelling state the BuildRequest
  buildinfohelper: Add handler for cancelling a build
  toaster: mrb_section template Add build cancel button
  toaster: models Exclude the CANCELLED builds from get_number_of_builds

Sujith H (4):
  toaster: bldcontrol Add forceShutDown function to BitbakeController
  toaster: update BuildEnvironmentController and BitbakeController
  toaster: models Add cancelled state to build outcome
  toaster: tables BuildsTable exclude cancelled builds

 bitbake/lib/bb/ui/buildinfohelper.py               |  19 +++-
 bitbake/lib/toaster/bldcontrol/bbcontroller.py     |  29 ++----
 .../toaster/bldcontrol/localhostbecontroller.py    |   6 +-
 .../migrations/0002_add_cancelling_state.py        |  19 ++++
 bitbake/lib/toaster/bldcontrol/models.py           |  27 ++++-
 .../orm/migrations/0006_add_cancelled_state.py     |  19 ++++
 bitbake/lib/toaster/orm/models.py                  |  12 ++-
 bitbake/lib/toaster/toastergui/api.py              | 110 +++++++++++++++++++++
 .../toaster/toastergui/static/js/customrecipe.js   |   4 +-
 .../lib/toaster/toastergui/static/js/layerBtn.js   |   3 +-
 .../lib/toaster/toastergui/static/js/libtoaster.js |  41 +++++---
 .../toaster/toastergui/static/js/projectpage.js    |   4 +-
 .../toaster/toastergui/static/js/projecttopbar.js  |   6 +-
 .../toaster/toastergui/static/js/recipedetails.js  |   4 +-
 bitbake/lib/toaster/toastergui/tables.py           |  48 +--------
 bitbake/lib/toaster/toastergui/templates/base.html |   1 +
 .../toaster/toastergui/templates/mrb_section.html  | 102 +++++++++++++------
 bitbake/lib/toaster/toastergui/urls.py             |   5 +
 18 files changed, 327 insertions(+), 132 deletions(-)
 create mode 100644 bitbake/lib/toaster/bldcontrol/migrations/0002_add_cancelling_state.py
 create mode 100644 bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py
 create mode 100644 bitbake/lib/toaster/toastergui/api.py

-- 
2.1.4



^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 01/11] toaster: bldcontrol Add forceShutDown function to BitbakeController
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 02/11] toaster: Move xhr calls for starting and stopping builds Michael Wood
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

From: Sujith H <sujith.h@gmail.com>

Add forceShutDown function to BitbakeController class. This function
provides a mechanism to cancel the build from toaster. An API which
can be used safely to cancel build and hence shutdown running bitbake
server.

[YOCTO #6787]

Signed-off-by: Sujith H <sujith.h@gmail.com>
---
 bitbake/lib/toaster/bldcontrol/bbcontroller.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/bitbake/lib/toaster/bldcontrol/bbcontroller.py b/bitbake/lib/toaster/bldcontrol/bbcontroller.py
index 1387bda..068b835 100644
--- a/bitbake/lib/toaster/bldcontrol/bbcontroller.py
+++ b/bitbake/lib/toaster/bldcontrol/bbcontroller.py
@@ -63,6 +63,9 @@ class BitbakeController(object):
             task = "build"
         return self._runCommand(["buildTargets", targets, task])
 
+    def forceShutDown(self):
+        return self._runCommand(["stateForceShutdown"])
+
 
 
 def getBuildEnvironmentController(**kwargs):
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 02/11] toaster: Move xhr calls for starting and stopping builds
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
  2016-02-25 18:21 ` [PATCH 01/11] toaster: bldcontrol Add forceShutDown function to BitbakeController Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 03/11] toaster: xhr Update the implementation of the build cancellation request Michael Wood
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

Move the backend xhr implementation of the build request changes
into it's own file and out of the ToasterTable definition.
It used to live in the views.py but in a hope of starting to collate logical
groups of views move this to a new file called api.

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 bitbake/lib/toaster/toastergui/api.py    | 74 ++++++++++++++++++++++++++++++++
 bitbake/lib/toaster/toastergui/tables.py | 43 +------------------
 bitbake/lib/toaster/toastergui/urls.py   |  5 +++
 3 files changed, 80 insertions(+), 42 deletions(-)
 create mode 100644 bitbake/lib/toaster/toastergui/api.py

diff --git a/bitbake/lib/toaster/toastergui/api.py b/bitbake/lib/toaster/toastergui/api.py
new file mode 100644
index 0000000..1b1f598
--- /dev/null
+++ b/bitbake/lib/toaster/toastergui/api.py
@@ -0,0 +1,74 @@
+#
+# BitBake Toaster Implementation
+#
+# Copyright (C) 2016        Intel Corporation
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+# Temporary home for the UI's misc API
+
+from orm.models import Project, ProjectTarget
+from bldcontrol.models import BuildRequest
+from bldcontrol import bbcontroller
+from django.http import HttpResponse, JsonResponse
+from django.views.generic import View
+
+
+class XhrBuildRequest(View):
+
+    def get(self, request, *args, **kwargs):
+        return HttpResponse()
+
+    def post(self, request, *args, **kwargs):
+        """ Process HTTP POSTs which make build requests """
+
+        project = Project.objects.get(pk=kwargs['pid'])
+
+        if 'buildCancel' in request.POST:
+            for i in request.POST['buildCancel'].strip().split(" "):
+                try:
+                    br = BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_QUEUED)
+                    br.state = BuildRequest.REQ_DELETED
+                    br.save()
+                except BuildRequest.DoesNotExist:
+                    pass
+
+        if 'buildDelete' in request.POST:
+            for i in request.POST['buildDelete'].strip().split(" "):
+                try:
+                    BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
+                except BuildRequest.DoesNotExist:
+                    pass
+
+        if 'targets' in request.POST:
+            ProjectTarget.objects.filter(project = project).delete()
+            s = str(request.POST['targets'])
+            for t in s.translate(None, ";%|\"").split(" "):
+                if ":" in t:
+                    target, task = t.split(":")
+                else:
+                    target = t
+                    task = ""
+                ProjectTarget.objects.create(project = project,
+                                             target = target,
+                                             task = task)
+            project.schedule_build()
+
+        # redirect back to builds page so any new builds in progress etc.
+        # are visible
+        response = HttpResponse()
+        response.status_code = 302
+        response['Location'] = request.build_absolute_uri()
+        return response
diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
index 71892e2..0cda459 100644
--- a/bitbake/lib/toaster/toastergui/tables.py
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -22,7 +22,7 @@
 from toastergui.widgets import ToasterTable
 from orm.models import Recipe, ProjectLayer, Layer_Version, Machine, Project
 from orm.models import CustomImageRecipe, Package, Target, Build, LogMessage, Task
-from orm.models import CustomImagePackage, ProjectTarget
+from orm.models import CustomImagePackage
 from django.db.models import Q, Max, Sum, Count, When, Case, Value, IntegerField
 from django.conf.urls import url
 from django.core.urlresolvers import reverse, resolve
@@ -1400,47 +1400,6 @@ class BuildsTable(ToasterTable):
         failed_tasks_filter.add_action(without_failed_tasks_action)
         self.add_filter(failed_tasks_filter)
 
-    def post(self, request, *args, **kwargs):
-        """ Process HTTP POSTs which make build requests """
-
-        project = Project.objects.get(pk=kwargs['pid'])
-
-        if 'buildCancel' in request.POST:
-            for i in request.POST['buildCancel'].strip().split(" "):
-                try:
-                    br = BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_QUEUED)
-                    br.state = BuildRequest.REQ_DELETED
-                    br.save()
-                except BuildRequest.DoesNotExist:
-                    pass
-
-        if 'buildDelete' in request.POST:
-            for i in request.POST['buildDelete'].strip().split(" "):
-                try:
-                    BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
-                except BuildRequest.DoesNotExist:
-                    pass
-
-        if 'targets' in request.POST:
-            ProjectTarget.objects.filter(project = project).delete()
-            s = str(request.POST['targets'])
-            for t in s.translate(None, ";%|\"").split(" "):
-                if ":" in t:
-                    target, task = t.split(":")
-                else:
-                    target = t
-                    task = ""
-                ProjectTarget.objects.create(project = project,
-                                             target = target,
-                                             task = task)
-            project.schedule_build()
-
-        # redirect back to builds page so any new builds in progress etc.
-        # are visible
-        response = HttpResponse()
-        response.status_code = 302
-        response['Location'] = request.build_absolute_uri()
-        return response
 
 class AllBuildsTable(BuildsTable):
     """ Builds page for all builds """
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index 4aa6488..78cc3bd 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -22,6 +22,7 @@ from django.views.generic import RedirectView, TemplateView
 from django.http import HttpResponseBadRequest
 from toastergui import tables
 from toastergui import typeaheads
+from toastergui import api
 
 urlpatterns = patterns('toastergui.views',
         # landing page
@@ -180,6 +181,10 @@ urlpatterns = patterns('toastergui.views',
         url(r'^xhr_customrecipe/', 'xhr_customrecipe',
             name='xhr_customrecipe'),
 
+        url(r'^xhr_buildrequest/project/(?P<pid>\d+)$',
+           api.XhrBuildRequest.as_view(),
+            name='xhr_buildrequest'),
+
           # default redirection
         url(r'^$', RedirectView.as_view(url='landing', permanent=True)),
 )
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 03/11] toaster: xhr Update the implementation of the build cancellation request
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
  2016-02-25 18:21 ` [PATCH 01/11] toaster: bldcontrol Add forceShutDown function to BitbakeController Michael Wood
  2016-02-25 18:21 ` [PATCH 02/11] toaster: Move xhr calls for starting and stopping builds Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 04/11] toaster: libtoaster Update implementation of startABuild and cancelABuild Michael Wood
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

Update the implementation of the backend api for cancelling builds with
the new cancelling BuildRequest state and cancelled Build state.
Also added some docstring about general usage.

Co-Author: Sujith H <sujith.h@gmail.com>

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 bitbake/lib/toaster/toastergui/api.py | 54 +++++++++++++++++++++++++++++------
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/api.py b/bitbake/lib/toaster/toastergui/api.py
index 1b1f598..42901f75 100644
--- a/bitbake/lib/toaster/toastergui/api.py
+++ b/bitbake/lib/toaster/toastergui/api.py
@@ -19,7 +19,7 @@
 
 # Temporary home for the UI's misc API
 
-from orm.models import Project, ProjectTarget
+from orm.models import Project, ProjectTarget, Build
 from bldcontrol.models import BuildRequest
 from bldcontrol import bbcontroller
 from django.http import HttpResponse, JsonResponse
@@ -32,18 +32,54 @@ class XhrBuildRequest(View):
         return HttpResponse()
 
     def post(self, request, *args, **kwargs):
-        """ Process HTTP POSTs which make build requests """
+        """
+          Build control
+
+          Entry point: /xhr_buildrequest/<project_id>
+          Method: POST
+
+          Args:
+              id: id of build to change
+              buildCancel = build_request_id ...
+              buildDelete = id ...
+              targets = recipe_name ...
+
+          Returns:
+              {"error": "ok"}
+            or
+              {"error": <error message>}
+        """
 
         project = Project.objects.get(pk=kwargs['pid'])
 
         if 'buildCancel' in request.POST:
             for i in request.POST['buildCancel'].strip().split(" "):
                 try:
-                    br = BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_QUEUED)
-                    br.state = BuildRequest.REQ_DELETED
+                    br = BuildRequest.objects.get(project=project, pk=i)
+
+                    try:
+                        bbctrl = bbcontroller.BitbakeController(br.environment)
+                        bbctrl.forceShutDown()
+                    except:
+                        # We catch a bunch of exceptions here because
+                        # this is where the server has not had time to start up
+                        # and the build request or build is in transit between
+                        # processes.
+                        # We can safely just set the build as cancelled
+                        # already as it never got started
+                        build = br.build
+                        build.outcome = Build.CANCELLED
+                        build.save()
+
+                    # We now hand over to the buildinfohelper to update the
+                    # build state once we've finished cancelling
+                    br.state = BuildRequest.REQ_CANCELLING
                     br.save()
+
                 except BuildRequest.DoesNotExist:
-                    pass
+                    return JsonResponse({'error':'No such build id %s' % i})
+
+            return JsonResponse({'error': 'ok'})
 
         if 'buildDelete' in request.POST:
             for i in request.POST['buildDelete'].strip().split(" "):
@@ -51,6 +87,7 @@ class XhrBuildRequest(View):
                     BuildRequest.objects.select_for_update().get(project = project, pk = i, state__lte = BuildRequest.REQ_DELETED).delete()
                 except BuildRequest.DoesNotExist:
                     pass
+            return JsonResponse({'error': 'ok' })
 
         if 'targets' in request.POST:
             ProjectTarget.objects.filter(project = project).delete()
@@ -66,9 +103,8 @@ class XhrBuildRequest(View):
                                              task = task)
             project.schedule_build()
 
-        # redirect back to builds page so any new builds in progress etc.
-        # are visible
+            return JsonResponse({'error': 'ok' })
+
         response = HttpResponse()
-        response.status_code = 302
-        response['Location'] = request.build_absolute_uri()
+        response.status_code = 500
         return response
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 04/11] toaster: libtoaster Update implementation of startABuild and cancelABuild
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (2 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 03/11] toaster: xhr Update the implementation of the build cancellation request Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-26 11:55   ` Smith, Elliot
  2016-02-25 18:21 ` [PATCH 05/11] toaster: update BuildEnvironmentController and BitbakeController Michael Wood
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

Update the implementation of startABuild and cancelAbuild to reflect
changes to the backend api. We now have a dedicated endpoint to make
calls into so add this url to libtoaster.ctx and allow passing null in
as a url value to indicate that we want to use the current project

Also:
 - Fix some documentation comments
 - Add the convenience of passing in an array of targets to startABuild

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 .../toaster/toastergui/static/js/customrecipe.js   |  4 +--
 .../lib/toaster/toastergui/static/js/layerBtn.js   |  3 +-
 .../lib/toaster/toastergui/static/js/libtoaster.js | 41 ++++++++++++++--------
 .../toaster/toastergui/static/js/projectpage.js    |  4 +--
 .../toaster/toastergui/static/js/projecttopbar.js  |  6 ++--
 .../toaster/toastergui/static/js/recipedetails.js  |  4 +--
 bitbake/lib/toaster/toastergui/templates/base.html |  1 +
 7 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/static/js/customrecipe.js b/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
index 3c57899..131ac2a 100644
--- a/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
+++ b/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
@@ -207,9 +207,7 @@ function customRecipePageInit(ctx) {
 
   /* Trigger a build of your custom image */
   $(".build-custom-image").click(function(){
-    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
-      libtoaster.ctx.projectId,
-      ctx.recipe.name,
+    libtoaster.startABuild(null, ctx.recipe.name,
       function(){
         window.location.replace(libtoaster.ctx.projectBuildsUrl);
     });
diff --git a/bitbake/lib/toaster/toastergui/static/js/layerBtn.js b/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
index b2666ab..aa43284 100644
--- a/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
+++ b/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
@@ -60,8 +60,7 @@ function layerBtnsInit() {
     e.preventDefault();
     var recipe = $(this).data('recipe-name');
 
-    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
-      libtoaster.ctx.projectId, recipe,
+    libtoaster.startABuild(null, recipe,
       function(){
         /* Success */
         window.location.replace(libtoaster.ctx.projectBuildsUrl);
diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
index b6b49b6..8d1d20f 100644
--- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
+++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
@@ -90,27 +90,35 @@ var libtoaster = (function (){
     jQElement.data('typeahead').render = customRenderFunc;
   }
 
-  /*
-   * url - the url of the xhr build */
-  function _startABuild (url, project_id, targets, onsuccess, onfail) {
+  /* startABuild:
+   * url: xhr_buildrequest or null for current project
+   * targets: an array or space separated list of targets to build
+   * onsuccess: callback for successful execution
+   * onfail: callback for failed execution
+   */
+  function _startABuild (url, targets, onsuccess, onfail) {
 
-    var data = {
-      project_id : project_id,
-      targets : targets,
+    if (!url)
+      url = libtoaster.ctx.xhrBuildRequestUrl;
+
+    /* Flatten the array of targets into a space spearated list */
+    if (targets instanceof Array){
+      targets = targets.reduce(function(prevV, nextV){
+        return prev + ' ' + next;
+      });
     }
 
     $.ajax( {
         type: "POST",
         url: url,
-        data: data,
+        data: { 'targets' : targets },
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
-          /* No proper reponse YOCTO #7995
           if (_data.error !== "ok") {
             console.warn(_data.error);
-          } else { */
+          } else {
             if (onsuccess !== undefined) onsuccess(_data);
-        //  }
+          }
         },
         error: function (_data) {
           console.warn("Call failed");
@@ -120,22 +128,25 @@ var libtoaster = (function (){
   }
 
   /* cancelABuild:
-   * url: projectbuilds
-   * builds_ids: space separated list of build request ids
+   * url: xhr_buildrequest url or null for current project
+   * buildRequestIds: space separated list of build request ids
    * onsuccess: callback for successful execution
    * onfail: callback for failed execution
    */
-  function _cancelABuild(url, build_ids, onsuccess, onfail){
+  function _cancelABuild(url, buildRequestIds, onsuccess, onfail){
+    if (!url)
+      url = libtoaster.ctx.xhrBuildRequestUrl;
+
     $.ajax( {
         type: "POST",
         url: url,
-        data: { 'buildCancel': build_ids },
+        data: { 'buildCancel': buildRequestIds },
         headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
         success: function (_data) {
           if (_data.error !== "ok") {
             console.warn(_data.error);
           } else {
-            if (onsuccess !== undefined) onsuccess(_data);
+            if (onsuccess) onsuccess(_data);
           }
         },
         error: function (_data) {
diff --git a/bitbake/lib/toaster/toastergui/static/js/projectpage.js b/bitbake/lib/toaster/toastergui/static/js/projectpage.js
index 292ceb7..78a9506 100644
--- a/bitbake/lib/toaster/toastergui/static/js/projectpage.js
+++ b/bitbake/lib/toaster/toastergui/static/js/projectpage.js
@@ -232,9 +232,7 @@ function projectPageInit(ctx) {
 
     toBuild = toBuild.trim();
 
-    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
-      libtoaster.ctx.projectId,
-      toBuild,
+    libtoaster.startABuild(null, toBuild,
       function(){
         /* Build request started */
         window.location.replace(libtoaster.ctx.projectBuildsUrl);
diff --git a/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js b/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
index 58a32a0..b09f974 100644
--- a/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
+++ b/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
@@ -82,9 +82,9 @@ function projectTopBarInit(ctx) {
     selectedTarget = { name: newBuildTargetInput.val() };
 
     /* Fire off the build */
-    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
-      null, selectedTarget.name, function(){
-      window.location.replace(libtoaster.ctx.projectBuildsUrl);
+    libtoaster.startABuild(null, selectedTarget.name,
+      function(){
+        window.location.replace(libtoaster.ctx.projectBuildsUrl);
     }, null);
   });
 }
diff --git a/bitbake/lib/toaster/toastergui/static/js/recipedetails.js b/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
index 2bfd0a4..d5f9eac 100644
--- a/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
+++ b/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
@@ -42,9 +42,7 @@ function recipeDetailsPageInit(ctx){
 
   /* Trigger a build of your custom image */
   $(".build-recipe-btn").click(function(){
-    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
-      libtoaster.ctx.projectId,
-      ctx.recipe.name,
+    libtoaster.startABuild(null, ctx.recipe.name,
       function(){
         window.location.replace(libtoaster.ctx.projectBuildsUrl);
     });
diff --git a/bitbake/lib/toaster/toastergui/templates/base.html b/bitbake/lib/toaster/toastergui/templates/base.html
index 6994bcc..ed15c59 100644
--- a/bitbake/lib/toaster/toastergui/templates/base.html
+++ b/bitbake/lib/toaster/toastergui/templates/base.html
@@ -47,6 +47,7 @@
         projectBuildsUrl: {% url 'projectbuilds' project.id as pburl %}{{pburl|json}},
         xhrCustomRecipeUrl : "{% url 'xhr_customrecipe' %}",
         projectId : {{project.id}},
+        xhrBuildRequestUrl: "{% url 'xhr_buildrequest' project.id %}",
         {% else %}
         projectId : undefined,
         projectPageUrl : undefined,
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 05/11] toaster: update BuildEnvironmentController and BitbakeController
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (3 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 04/11] toaster: libtoaster Update implementation of startABuild and cancelABuild Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 06/11] toaster: models Add cancelled state to build outcome Michael Wood
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

From: Sujith H <sujith.h@gmail.com>

Remove getBBController function from BuildEnvironmentController.
The constructor of BitbakeController is updated appropriately so that
call can be made to connect to running server.
The call to startBBServer is removed from bbcontroller and  handledin
localhostbecontroller.

[YOCTO #6787]

Signed-off-by: Sujith H <sujith.h@gmail.com>
---
 bitbake/lib/toaster/bldcontrol/bbcontroller.py     | 26 ++++------------------
 .../toaster/bldcontrol/localhostbecontroller.py    |  6 +++--
 2 files changed, 8 insertions(+), 24 deletions(-)

diff --git a/bitbake/lib/toaster/bldcontrol/bbcontroller.py b/bitbake/lib/toaster/bldcontrol/bbcontroller.py
index 068b835..c382927 100644
--- a/bitbake/lib/toaster/bldcontrol/bbcontroller.py
+++ b/bitbake/lib/toaster/bldcontrol/bbcontroller.py
@@ -37,11 +37,12 @@ class BitbakeController(object):
         It is outside the scope of this class on how the server is started and aquired
     """
 
-    def __init__(self, connection):
-        self.connection = connection
+    def __init__(self, be):
+        self.connection = bb.server.xmlrpc._create_server(be.bbaddress,
+                                                          int(be.bbport))[0]
 
     def _runCommand(self, command):
-        result, error = self.connection.connection.runCommand(command)
+        result, error = self.connection.runCommand(command)
         if error:
             raise Exception(error)
         return result
@@ -155,25 +156,6 @@ class BuildEnvironmentController(object):
         raise Exception("FIXME: Must override setLayers")
 
 
-    def getBBController(self):
-        """ returns a BitbakeController to an already started server; this is the point where the server
-            starts if needed; or reconnects to the server if we can
-        """
-        if not self.connection:
-            self.startBBServer()
-            self.be.lock = BuildEnvironment.LOCK_RUNNING
-            self.be.save()
-
-        server = bb.server.xmlrpc.BitBakeXMLRPCClient()
-        server.initServer()
-        server.saveConnectionDetails("%s:%s" % (self.be.bbaddress, self.be.bbport))
-        self.connection = server.establishConnection([])
-
-        self.be.bbtoken = self.connection.transport.connection_token
-        self.be.save()
-
-        return BitbakeController(self.connection)
-
     def getArtifact(self, path):
         """ This call returns an artifact identified by the 'path'. How 'path' is interpreted as
             up to the implementing BEC. The return MUST be a REST URL where a GET will actually return
diff --git a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
index efd82c3..7de4f63 100644
--- a/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
+++ b/bitbake/lib/toaster/bldcontrol/localhostbecontroller.py
@@ -32,7 +32,7 @@ import subprocess
 
 from toastermain import settings
 
-from bbcontroller import BuildEnvironmentController, ShellCmdException, BuildSetupException
+from bbcontroller import BuildEnvironmentController, ShellCmdException, BuildSetupException, BitbakeController
 
 import logging
 logger = logging.getLogger("toaster")
@@ -100,6 +100,7 @@ class LocalhostBEController(BuildEnvironmentController):
 
         self.be.bbaddress = "localhost"
         self.be.bbstate = BuildEnvironment.SERVER_STARTED
+        self.be.lock = BuildEnvironment.LOCK_RUNNING
         self.be.save()
 
     def getGitCloneDirectory(self, url, branch):
@@ -306,7 +307,8 @@ class LocalhostBEController(BuildEnvironmentController):
             conf.write('INHERIT+="toaster buildhistory"')
 
         # get the bb server running with the build req id and build env id
-        bbctrl = self.getBBController()
+        self.startBBServer()
+        bbctrl = BitbakeController(self.be)
 
         # set variables; TOASTER_BRBE is not set on the server, as this
         # causes events from command-line builds to be attached to the last
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 06/11] toaster: models Add cancelled state to build outcome
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (4 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 05/11] toaster: update BuildEnvironmentController and BitbakeController Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 07/11] toaster: bldcontrol models Add a cancelling state the BuildRequest Michael Wood
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

From: Sujith H <sujith.h@gmail.com>

A new state CANCELLED is introduced to, distinguish
the state of build.

[YOCTO #6787]

Signed-off-by: Sujith H <sujith.h@gmail.com>
---
 .../orm/migrations/0006_add_cancelled_state.py        | 19 +++++++++++++++++++
 bitbake/lib/toaster/orm/models.py                     |  7 ++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py

diff --git a/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py b/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py
new file mode 100644
index 0000000..f8ec65a
--- /dev/null
+++ b/bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('orm', '0004_provides'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='build',
+            name='outcome',
+            field=models.IntegerField(default=2, choices=[(0, b'Succeeded'), (1, b'Failed'), (2, b'In Progress'), (3, b'Cancelled')]),
+        ),
+    ]
diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index 93b5df3..ba0a8a0 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -353,11 +353,13 @@ class Build(models.Model):
     SUCCEEDED = 0
     FAILED = 1
     IN_PROGRESS = 2
+    CANCELLED = 3
 
     BUILD_OUTCOME = (
         (SUCCEEDED, 'Succeeded'),
         (FAILED, 'Failed'),
         (IN_PROGRESS, 'In Progress'),
+        (CANCELLED, 'Cancelled'),
     )
 
     search_allowed_fields = ['machine', 'cooker_log_path', "target__target", "target__target_image_file__file_name"]
@@ -385,7 +387,10 @@ class Build(models.Model):
         if project:
             builds = builds.filter(project=project)
 
-        finished_criteria = Q(outcome=Build.SUCCEEDED) | Q(outcome=Build.FAILED)
+        finished_criteria = \
+                Q(outcome=Build.SUCCEEDED) | \
+                Q(outcome=Build.FAILED) | \
+                Q(outcome=Build.CANCELLED)
 
         recent_builds = list(itertools.chain(
             builds.filter(outcome=Build.IN_PROGRESS).order_by("-started_on"),
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 07/11] toaster: bldcontrol models Add a cancelling state the BuildRequest
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (5 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 06/11] toaster: models Add cancelled state to build outcome Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 08/11] buildinfohelper: Add handler for cancelling a build Michael Wood
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

To accurately reflect the state of a build request we also need a
cancelling state. This is set when we've started a build and then for
whatever reason cancel it, cancelling is not instantaneous so we have
this state to indicate that a cancel is in progress.

Also add a state transition guard. As the state of a BuildRequest can
currently be modified by three processes; Toastergui,
Runbuilds/bldcontrol and the buildinofhelper we cannot say for sure
which process will be running at the time of cancellation so in order to
avoid one of these processes making an incorrect transition only allow
transitions of state to increase.

e.g. CREATED -> QUEUED -> INPROGRESS
And to ignore such requested changes such as
INPROGRESS -> CREATED

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 .../migrations/0002_add_cancelling_state.py        | 19 +++++++++++++++
 bitbake/lib/toaster/bldcontrol/models.py           | 27 +++++++++++++++++++++-
 2 files changed, 45 insertions(+), 1 deletion(-)
 create mode 100644 bitbake/lib/toaster/bldcontrol/migrations/0002_add_cancelling_state.py

diff --git a/bitbake/lib/toaster/bldcontrol/migrations/0002_add_cancelling_state.py b/bitbake/lib/toaster/bldcontrol/migrations/0002_add_cancelling_state.py
new file mode 100644
index 0000000..efcdf49
--- /dev/null
+++ b/bitbake/lib/toaster/bldcontrol/migrations/0002_add_cancelling_state.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bldcontrol', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='buildrequest',
+            name='state',
+            field=models.IntegerField(default=0, choices=[(0, b'created'), (1, b'queued'), (2, b'in progress'), (3, b'completed'), (4, b'failed'), (5, b'deleted'), (6, b'cancelling'), (7, b'archive')]),
+        ),
+    ]
diff --git a/bitbake/lib/toaster/bldcontrol/models.py b/bitbake/lib/toaster/bldcontrol/models.py
index a3a49ce..0343ae9 100644
--- a/bitbake/lib/toaster/bldcontrol/models.py
+++ b/bitbake/lib/toaster/bldcontrol/models.py
@@ -2,6 +2,8 @@ from django.db import models
 from django.core.validators import MaxValueValidator, MinValueValidator
 from orm.models import Project, ProjectLayer, ProjectVariable, ProjectTarget, Build, Layer_Version
 
+import logging
+logger = logging.getLogger("toaster")
 # a BuildEnvironment is the equivalent of the "build/" directory on the localhost
 class BuildEnvironment(models.Model):
     SERVER_STOPPED = 0
@@ -60,7 +62,8 @@ class BuildRequest(models.Model):
     REQ_COMPLETED = 3
     REQ_FAILED = 4
     REQ_DELETED = 5
-    REQ_ARCHIVE = 6
+    REQ_CANCELLING = 6
+    REQ_ARCHIVE = 7
 
     REQUEST_STATE = (
         (REQ_CREATED, "created"),
@@ -69,6 +72,7 @@ class BuildRequest(models.Model):
         (REQ_COMPLETED, "completed"),
         (REQ_FAILED, "failed"),
         (REQ_DELETED, "deleted"),
+        (REQ_CANCELLING, "cancelling"),
         (REQ_ARCHIVE, "archive"),
     )
 
@@ -81,6 +85,27 @@ class BuildRequest(models.Model):
     created     = models.DateTimeField(auto_now_add = True)
     updated     = models.DateTimeField(auto_now = True)
 
+    def __init__(self, *args, **kwargs):
+        super(BuildRequest, self).__init__(*args, **kwargs)
+        # Save the old state incase it's about to be modified
+        self.old_state = self.state
+
+    def save(self, *args, **kwargs):
+        # Check that the state we're trying to set is not going backwards
+        # e.g. from REQ_FAILED to REQ_INPROGRESS
+        if self.old_state != self.state and self.old_state > self.state:
+            logger.warn("Invalid state change requested: "
+                        "Cannot go from %s to %s - ignoring request" %
+                        (BuildRequest.REQUEST_STATE[self.old_state][1],
+                         BuildRequest.REQUEST_STATE[self.state][1])
+                       )
+            # Set property back to the old value
+            self.state = self.old_state
+            return
+
+        super(BuildRequest, self).save(*args, **kwargs)
+
+
     def get_duration(self):
         return (self.updated - self.created).total_seconds()
 
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 08/11] buildinfohelper: Add handler for cancelling a build
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (6 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 07/11] toaster: bldcontrol models Add a cancelling state the BuildRequest Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 09/11] toaster: tables BuildsTable exclude cancelled builds Michael Wood
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

When a build is cancelled the build (action) is complete if it has been
caused the request being cancelled then update the build outcome
accordingly.

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 bitbake/lib/bb/ui/buildinfohelper.py | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/bitbake/lib/bb/ui/buildinfohelper.py b/bitbake/lib/bb/ui/buildinfohelper.py
index 81abede..8e95d89 100644
--- a/bitbake/lib/bb/ui/buildinfohelper.py
+++ b/bitbake/lib/bb/ui/buildinfohelper.py
@@ -211,6 +211,15 @@ class ORMWrapper(object):
         assert isinstance(errors, int)
         assert isinstance(warnings, int)
 
+        if build.outcome == Build.CANCELLED:
+            return
+        try:
+            if build.buildrequest.state == BuildRequest.REQ_CANCELLING:
+                return
+        except AttributeError:
+            # We may not have a buildrequest if this is a command line build
+            pass
+
         outcome = Build.SUCCEEDED
         if errors or taskfailures:
             outcome = Build.FAILED
@@ -1398,9 +1407,17 @@ class BuildInfoHelper(object):
         be.lock = BuildEnvironment.LOCK_LOCK
         be.save()
         br = BuildRequest.objects.get(pk = br_id)
+
+        # if we're 'done' because we got cancelled update the build outcome
+        if br.state == BuildRequest.REQ_CANCELLING:
+            logger.info("Build cancelled")
+            br.build.outcome = Build.CANCELLED
+            br.build.save()
+            errorcode = 0
+
         if errorcode == 0:
             # request archival of the project artifacts
-            br.state = BuildRequest.REQ_ARCHIVE
+            br.state = BuildRequest.REQ_COMPLETED
         else:
             br.state = BuildRequest.REQ_FAILED
         br.save()
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 09/11] toaster: tables BuildsTable exclude cancelled builds
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (7 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 08/11] buildinfohelper: Add handler for cancelling a build Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:21 ` [PATCH 10/11] toaster: mrb_section template Add build cancel button Michael Wood
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

From: Sujith H <sujith.h@gmail.com>

Exclude cancelled builds from showing in the builds table

[YOCTO #6787]

Signed-off-by: Sujith H <sujith.h@gmail.com>
---
 bitbake/lib/toaster/toastergui/tables.py | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/tables.py b/bitbake/lib/toaster/toastergui/tables.py
index 0cda459..e507730 100644
--- a/bitbake/lib/toaster/toastergui/tables.py
+++ b/bitbake/lib/toaster/toastergui/tables.py
@@ -1080,8 +1080,9 @@ class BuildsTable(ToasterTable):
         """
         queryset = self.get_builds()
 
-        # don't include in progress builds
-        queryset = queryset.exclude(outcome=Build.IN_PROGRESS)
+        # Don't include in progress builds pr cancelled builds
+        queryset = queryset.exclude(Q(outcome=Build.IN_PROGRESS) |
+                                    Q(outcome=Build.CANCELLED))
 
         # sort
         queryset = queryset.order_by(self.default_orderby)
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 10/11] toaster: mrb_section template Add build cancel button
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (8 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 09/11] toaster: tables BuildsTable exclude cancelled builds Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-25 18:26   ` Michael Wood
  2016-02-25 18:21 ` [PATCH 11/11] toaster: models Exclude the CANCELLED builds from get_number_of_builds Michael Wood
  2016-02-26 13:26 ` [PATCH 00/11] Build cancellation Smith, Elliot
  11 siblings, 1 reply; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

Add the cancel build button to the mrb section template and add the event
handlers to cancelABuild.
Also clean up the calls to startABuild to use the updated libtoaster methods
and to make the code consistent with it's cancelABuild counterpart.

Co-Author: Sujith H <sujith.h@gmail.com>

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 .../toaster/toastergui/templates/mrb_section.html  | 102 ++++++++++++++-------
 1 file changed, 71 insertions(+), 31 deletions(-)

diff --git a/bitbake/lib/toaster/toastergui/templates/mrb_section.html b/bitbake/lib/toaster/toastergui/templates/mrb_section.html
index 551e341..647f49b 100644
--- a/bitbake/lib/toaster/toastergui/templates/mrb_section.html
+++ b/bitbake/lib/toaster/toastergui/templates/mrb_section.html
@@ -99,7 +99,7 @@
                   " title="Builds in this project cannot be started from Toaster: they are started from the command line">
                   </i>
               {% else %}
-                  <button class="btn
+                  <button class="run-again-btn btn
                       {% if build.outcome == build.SUCCEEDED %}
                           btn-success
                       {% elif build.outcome == build.FAILED %}
@@ -108,10 +108,9 @@
                           btn-info
                       {%endif%}
                       pull-right"
-                      onclick='scheduleBuild({% url 'projectbuilds' build.project.id as bpi %}{{bpi|json}},
-                        {{build.project.name|json}},
-                        {% url 'project' build.project.id as purl %}{{purl|json}},
-                        {{build.target_set.all|get_tasks|json}})'>
+                      data-request-url="{% url 'xhr_buildrequest' build.project.pk %}"
+                      data-target='{{build.target_set.all|get_tasks|json}}'>
+
 
                         Rebuild
                   </button>
@@ -119,46 +118,87 @@
             </div>
     {%endif%}
     {%if build.outcome == build.IN_PROGRESS %}
-            <div class="span4 offset1">
-              <div class="progress" id="build-pc-done-title-{{build.pk}}" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete">
-                  <div id="build-pc-done-bar-{{build.pk}}" style="width: {{build.completeper}}%;" class="bar"></div>
-                </div>
-            </div>
-            <div class="lead pull-right"><span id="build-pc-done-{{build.pk}}">{{build.completeper}}</span>% of tasks complete</div>
-    {%endif%}
-        </div>
+    <div class="span4" style="display:none" id="cancelling-msg-{{build.buildrequest.pk}}">
+      <p class="lead">Cancelling the build ...</p>
+    </div>
+    <div class="span4 offset1 progress-info">
+      <div class="progress" id="build-pc-done-title-{{build.pk}}" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete">
+        <div id="build-pc-done-bar-{{build.pk}}" style="width: {{build.completeper}}%;" class="bar"></div>
+      </div>
     </div>
+    <div class="lead span3 progress-info"><span id="build-pc-done-{{build.pk}}">{{build.completeper}}</span>% of tasks complete</div>
+    {# No build cancel for command line builds project #}
+    {% if build.project.is_default %}
+    <i class="icon-question-sign get-help get-help-blue pull-right" title="" data-original-title="Builds in this project cannot be cancelled from Toaster: they can only be cancalled from the command line"></i>
+    {% else %}
+    <div class="lead pull-right progress-info">
+      <button class="cancel-build-btn btn btn-info pull-right"
+          data-buildrequest-id={{build.buildrequest.pk}}
+          data-request-url="{% url 'xhr_buildrequest' build.project.pk %}" >
+        Cancel
+      </button>
+    </div>
+    {% endif %}
+
+    {%endif%} {# end if in progress #}
+
+    {% if build.outcome == build.CANCELLED %}
+    <div class="span4">
+      <p class="lead">Build cancelled</p>
+    </div>
+    <button class="btn btn-info pull-right run-again-btn"
+        data-request-url="{% url 'xhr_buildrequest' build.project.pk %}"
+        data-target='{{build.target_set.all|get_tasks|json}}'>
+      Run again
+
+    </button>
+    {% endif %}
+  </div>
+</div>
 
   {% endfor %}
   </div>
 
 <script>
 
-function scheduleBuild(url, projectName, projectUrl, buildlist) {
-  console.log("scheduleBuild");
-  libtoaster.startABuild(url, null, buildlist.join(" "), function(){
-    console.log("reloading page");
-    window.location.reload();
-  }, null);
-}
-
 $(document).ready(function(){
+  {%if mrb_type == 'project' %}
+  var projectBuilds = true;
+  {% else %}
+  var projectBuilds = false;
+  {% endif %}
+
+  $(".cancel-build-btn").click(function(e){
+    e.preventDefault();
 
-  $(".cancel-build-btn").click(function (){
     var url = $(this).data('request-url');
-    var buildIds = $(this).data('build-id');
-    var btn = $(this);
+    var buildReqIds = $(this).data('buildrequest-id');
+    var banner = $(this).parents(".alert");
+
+    banner.find(".progress-info").fadeOut(function(){
+      $("#cancelling-msg-" + buildReqIds).show();
+      libtoaster.cancelABuild(url, buildReqIds, function(){
+        if (projectBuilds == false){
+          /* the all builds page is not 'self updating' like thei
+           * project Builds
+           */
+          window.location.reload();
+        }
+      }, null);
+    });
+  });
+
+  $(".run-again-btn").click(function(e){
+    e.preventDefault();
 
-    libtoaster.cancelABuild(url, buildIds, function(){
-      btn.parents(".alert").fadeOut();
+    var url = $(this).data('request-url');
+    var target = $(this).data('target');
+
+    libtoaster.startABuild(url, target, function(){
+      window.location.reload();
     }, null);
   });
 
-  {%if mrb_type == 'project' %}
-  var projectBuilds = true;
-  {% else %}
-  var projectBuilds = false;
-  {% endif %}
 
   var progressTimer;
 
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 11/11] toaster: models Exclude the CANCELLED builds from get_number_of_builds
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (9 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 10/11] toaster: mrb_section template Add build cancel button Michael Wood
@ 2016-02-25 18:21 ` Michael Wood
  2016-02-26 13:26 ` [PATCH 00/11] Build cancellation Smith, Elliot
  11 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:21 UTC (permalink / raw)
  To: toaster

Don't count CANCELLED builds when returning the number of builds.

Signed-off-by: Michael Wood <michael.g.wood@intel.com>
---
 bitbake/lib/toaster/orm/models.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/bitbake/lib/toaster/orm/models.py b/bitbake/lib/toaster/orm/models.py
index ba0a8a0..f943f18 100644
--- a/bitbake/lib/toaster/orm/models.py
+++ b/bitbake/lib/toaster/orm/models.py
@@ -194,7 +194,10 @@ class Project(models.Model):
     def get_number_of_builds(self):
         """Return the number of builds which have ended"""
 
-        return self.build_set.filter(~Q(outcome=Build.IN_PROGRESS)).count()
+        return self.build_set.exclude(
+            Q(outcome=Build.IN_PROGRESS) |
+            Q(outcome=Build.CANCELLED)
+        ).count()
 
     def get_last_build_id(self):
         try:
-- 
2.1.4



^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 10/11] toaster: mrb_section template Add build cancel button
  2016-02-25 18:21 ` [PATCH 10/11] toaster: mrb_section template Add build cancel button Michael Wood
@ 2016-02-25 18:26   ` Michael Wood
  0 siblings, 0 replies; 15+ messages in thread
From: Michael Wood @ 2016-02-25 18:26 UTC (permalink / raw)
  To: toaster@yoctoproject.org

Typo in this patch is fixed in branch michaelw/sujith/build-cancel

http://git.yoctoproject.org/cgit/cgit.cgi/poky-contrib/log/?h=michaelw/sujith/build-cancel


-    <i class="icon-question-sign get-help get-help-blue pull-right" 
title="" data-original-title="Builds in this project cannot be cancelled 
from Toaster: they can only be cancalled from the command line"></i>
+    <i class="icon-question-sign get-help get-help-blue pull-right" 
title="" data-original-title="Builds in this project cannot be cancelled 
from Toaster: they can only be cancelled from the command line"></i>


On 25/02/16 18:21, Michael Wood wrote:
> Add the cancel build button to the mrb section template and add the event
> handlers to cancelABuild.
> Also clean up the calls to startABuild to use the updated libtoaster methods
> and to make the code consistent with it's cancelABuild counterpart.
>
> Co-Author: Sujith H <sujith.h@gmail.com>
>
> Signed-off-by: Michael Wood <michael.g.wood@intel.com>
> ---
>   .../toaster/toastergui/templates/mrb_section.html  | 102 ++++++++++++++-------
>   1 file changed, 71 insertions(+), 31 deletions(-)
>
> diff --git a/bitbake/lib/toaster/toastergui/templates/mrb_section.html b/bitbake/lib/toaster/toastergui/templates/mrb_section.html
> index 551e341..647f49b 100644
> --- a/bitbake/lib/toaster/toastergui/templates/mrb_section.html
> +++ b/bitbake/lib/toaster/toastergui/templates/mrb_section.html
> @@ -99,7 +99,7 @@
>                     " title="Builds in this project cannot be started from Toaster: they are started from the command line">
>                     </i>
>                 {% else %}
> -                  <button class="btn
> +                  <button class="run-again-btn btn
>                         {% if build.outcome == build.SUCCEEDED %}
>                             btn-success
>                         {% elif build.outcome == build.FAILED %}
> @@ -108,10 +108,9 @@
>                             btn-info
>                         {%endif%}
>                         pull-right"
> -                      onclick='scheduleBuild({% url 'projectbuilds' build.project.id as bpi %}{{bpi|json}},
> -                        {{build.project.name|json}},
> -                        {% url 'project' build.project.id as purl %}{{purl|json}},
> -                        {{build.target_set.all|get_tasks|json}})'>
> +                      data-request-url="{% url 'xhr_buildrequest' build.project.pk %}"
> +                      data-target='{{build.target_set.all|get_tasks|json}}'>
> +
>   
>                           Rebuild
>                     </button>
> @@ -119,46 +118,87 @@
>               </div>
>       {%endif%}
>       {%if build.outcome == build.IN_PROGRESS %}
> -            <div class="span4 offset1">
> -              <div class="progress" id="build-pc-done-title-{{build.pk}}" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete">
> -                  <div id="build-pc-done-bar-{{build.pk}}" style="width: {{build.completeper}}%;" class="bar"></div>
> -                </div>
> -            </div>
> -            <div class="lead pull-right"><span id="build-pc-done-{{build.pk}}">{{build.completeper}}</span>% of tasks complete</div>
> -    {%endif%}
> -        </div>
> +    <div class="span4" style="display:none" id="cancelling-msg-{{build.buildrequest.pk}}">
> +      <p class="lead">Cancelling the build ...</p>
> +    </div>
> +    <div class="span4 offset1 progress-info">
> +      <div class="progress" id="build-pc-done-title-{{build.pk}}" style="margin-top:5px;" data-toggle="tooltip" title="{{build.completeper}}% of tasks complete">
> +        <div id="build-pc-done-bar-{{build.pk}}" style="width: {{build.completeper}}%;" class="bar"></div>
> +      </div>
>       </div>
> +    <div class="lead span3 progress-info"><span id="build-pc-done-{{build.pk}}">{{build.completeper}}</span>% of tasks complete</div>
> +    {# No build cancel for command line builds project #}
> +    {% if build.project.is_default %}
> +    <i class="icon-question-sign get-help get-help-blue pull-right" title="" data-original-title="Builds in this project cannot be cancelled from Toaster: they can only be cancalled from the command line"></i>
> +    {% else %}
> +    <div class="lead pull-right progress-info">
> +      <button class="cancel-build-btn btn btn-info pull-right"
> +          data-buildrequest-id={{build.buildrequest.pk}}
> +          data-request-url="{% url 'xhr_buildrequest' build.project.pk %}" >
> +        Cancel
> +      </button>
> +    </div>
> +    {% endif %}
> +
> +    {%endif%} {# end if in progress #}
> +
> +    {% if build.outcome == build.CANCELLED %}
> +    <div class="span4">
> +      <p class="lead">Build cancelled</p>
> +    </div>
> +    <button class="btn btn-info pull-right run-again-btn"
> +        data-request-url="{% url 'xhr_buildrequest' build.project.pk %}"
> +        data-target='{{build.target_set.all|get_tasks|json}}'>
> +      Run again
> +
> +    </button>
> +    {% endif %}
> +  </div>
> +</div>
>   
>     {% endfor %}
>     </div>
>   
>   <script>
>   
> -function scheduleBuild(url, projectName, projectUrl, buildlist) {
> -  console.log("scheduleBuild");
> -  libtoaster.startABuild(url, null, buildlist.join(" "), function(){
> -    console.log("reloading page");
> -    window.location.reload();
> -  }, null);
> -}
> -
>   $(document).ready(function(){
> +  {%if mrb_type == 'project' %}
> +  var projectBuilds = true;
> +  {% else %}
> +  var projectBuilds = false;
> +  {% endif %}
> +
> +  $(".cancel-build-btn").click(function(e){
> +    e.preventDefault();
>   
> -  $(".cancel-build-btn").click(function (){
>       var url = $(this).data('request-url');
> -    var buildIds = $(this).data('build-id');
> -    var btn = $(this);
> +    var buildReqIds = $(this).data('buildrequest-id');
> +    var banner = $(this).parents(".alert");
> +
> +    banner.find(".progress-info").fadeOut(function(){
> +      $("#cancelling-msg-" + buildReqIds).show();
> +      libtoaster.cancelABuild(url, buildReqIds, function(){
> +        if (projectBuilds == false){
> +          /* the all builds page is not 'self updating' like thei
> +           * project Builds
> +           */
> +          window.location.reload();
> +        }
> +      }, null);
> +    });
> +  });
> +
> +  $(".run-again-btn").click(function(e){
> +    e.preventDefault();
>   
> -    libtoaster.cancelABuild(url, buildIds, function(){
> -      btn.parents(".alert").fadeOut();
> +    var url = $(this).data('request-url');
> +    var target = $(this).data('target');
> +
> +    libtoaster.startABuild(url, target, function(){
> +      window.location.reload();
>       }, null);
>     });
>   
> -  {%if mrb_type == 'project' %}
> -  var projectBuilds = true;
> -  {% else %}
> -  var projectBuilds = false;
> -  {% endif %}
>   
>     var progressTimer;
>   



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 04/11] toaster: libtoaster Update implementation of startABuild and cancelABuild
  2016-02-25 18:21 ` [PATCH 04/11] toaster: libtoaster Update implementation of startABuild and cancelABuild Michael Wood
@ 2016-02-26 11:55   ` Smith, Elliot
  0 siblings, 0 replies; 15+ messages in thread
From: Smith, Elliot @ 2016-02-26 11:55 UTC (permalink / raw)
  To: Michael Wood; +Cc: toaster

[-- Attachment #1: Type: text/plain, Size: 9214 bytes --]

I spotted an issue, inline below.

On 25 February 2016 at 18:21, Michael Wood <michael.g.wood@intel.com> wrote:

> Update the implementation of startABuild and cancelAbuild to reflect
> changes to the backend api. We now have a dedicated endpoint to make
> calls into so add this url to libtoaster.ctx and allow passing null in
> as a url value to indicate that we want to use the current project
>
> Also:
>  - Fix some documentation comments
>  - Add the convenience of passing in an array of targets to startABuild
>
> Signed-off-by: Michael Wood <michael.g.wood@intel.com>
> ---
>  .../toaster/toastergui/static/js/customrecipe.js   |  4 +--
>  .../lib/toaster/toastergui/static/js/layerBtn.js   |  3 +-
>  .../lib/toaster/toastergui/static/js/libtoaster.js | 41
> ++++++++++++++--------
>  .../toaster/toastergui/static/js/projectpage.js    |  4 +--
>  .../toaster/toastergui/static/js/projecttopbar.js  |  6 ++--
>  .../toaster/toastergui/static/js/recipedetails.js  |  4 +--
>  bitbake/lib/toaster/toastergui/templates/base.html |  1 +
>  7 files changed, 34 insertions(+), 29 deletions(-)
>
> diff --git a/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
> b/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
> index 3c57899..131ac2a 100644
> --- a/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
> +++ b/bitbake/lib/toaster/toastergui/static/js/customrecipe.js
> @@ -207,9 +207,7 @@ function customRecipePageInit(ctx) {
>
>    /* Trigger a build of your custom image */
>    $(".build-custom-image").click(function(){
> -    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
> -      libtoaster.ctx.projectId,
> -      ctx.recipe.name,
> +    libtoaster.startABuild(null, ctx.recipe.name,
>        function(){
>          window.location.replace(libtoaster.ctx.projectBuildsUrl);
>      });
> diff --git a/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
> b/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
> index b2666ab..aa43284 100644
> --- a/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
> +++ b/bitbake/lib/toaster/toastergui/static/js/layerBtn.js
> @@ -60,8 +60,7 @@ function layerBtnsInit() {
>      e.preventDefault();
>      var recipe = $(this).data('recipe-name');
>
> -    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
> -      libtoaster.ctx.projectId, recipe,
> +    libtoaster.startABuild(null, recipe,
>        function(){
>          /* Success */
>          window.location.replace(libtoaster.ctx.projectBuildsUrl);
> diff --git a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
> b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
> index b6b49b6..8d1d20f 100644
> --- a/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
> +++ b/bitbake/lib/toaster/toastergui/static/js/libtoaster.js
> @@ -90,27 +90,35 @@ var libtoaster = (function (){
>      jQElement.data('typeahead').render = customRenderFunc;
>    }
>
> -  /*
> -   * url - the url of the xhr build */
> -  function _startABuild (url, project_id, targets, onsuccess, onfail) {
> +  /* startABuild:
> +   * url: xhr_buildrequest or null for current project
> +   * targets: an array or space separated list of targets to build
> +   * onsuccess: callback for successful execution
> +   * onfail: callback for failed execution
> +   */
> +  function _startABuild (url, targets, onsuccess, onfail) {
>
> -    var data = {
> -      project_id : project_id,
> -      targets : targets,
> +    if (!url)
> +      url = libtoaster.ctx.xhrBuildRequestUrl;
> +
> +    /* Flatten the array of targets into a space spearated list */
> +    if (targets instanceof Array){
> +      targets = targets.reduce(function(prevV, nextV){
> +        return prev + ' ' + next;
> +      });
>      }
>
>      $.ajax( {
>          type: "POST",
>          url: url,
> -        data: data,
> +        data: { 'targets' : targets },
>          headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
>          success: function (_data) {
> -          /* No proper reponse YOCTO #7995
>            if (_data.error !== "ok") {
>              console.warn(_data.error);
> -          } else { */
> +          } else {
>              if (onsuccess !== undefined) onsuccess(_data);
> -        //  }
> +          }
>          },
>          error: function (_data) {
>

The error function has an argument _data, but in the body of that function
you have:

error: function (_data) {
          console.warn("Call failed");
          console.warn(_data);
          if (onfail) onfail(data); <- reference to data, not _data

When a failure does occur (as it did for me), onfail() doesn't execute
(because of a ReferenceError to data), so the page hangs.


>            console.warn("Call failed");
> @@ -120,22 +128,25 @@ var libtoaster = (function (){
>    }
>
>    /* cancelABuild:
> -   * url: projectbuilds
> -   * builds_ids: space separated list of build request ids
> +   * url: xhr_buildrequest url or null for current project
> +   * buildRequestIds: space separated list of build request ids
>     * onsuccess: callback for successful execution
>     * onfail: callback for failed execution
>     */
> -  function _cancelABuild(url, build_ids, onsuccess, onfail){
> +  function _cancelABuild(url, buildRequestIds, onsuccess, onfail){
> +    if (!url)
> +      url = libtoaster.ctx.xhrBuildRequestUrl;
> +
>      $.ajax( {
>          type: "POST",
>          url: url,
> -        data: { 'buildCancel': build_ids },
> +        data: { 'buildCancel': buildRequestIds },
>          headers: { 'X-CSRFToken' : $.cookie('csrftoken')},
>          success: function (_data) {
>            if (_data.error !== "ok") {
>              console.warn(_data.error);
>            } else {
> -            if (onsuccess !== undefined) onsuccess(_data);
> +            if (onsuccess) onsuccess(_data);
>            }
>          },
>          error: function (_data) {
> diff --git a/bitbake/lib/toaster/toastergui/static/js/projectpage.js
> b/bitbake/lib/toaster/toastergui/static/js/projectpage.js
> index 292ceb7..78a9506 100644
> --- a/bitbake/lib/toaster/toastergui/static/js/projectpage.js
> +++ b/bitbake/lib/toaster/toastergui/static/js/projectpage.js
> @@ -232,9 +232,7 @@ function projectPageInit(ctx) {
>
>      toBuild = toBuild.trim();
>
> -    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
> -      libtoaster.ctx.projectId,
> -      toBuild,
> +    libtoaster.startABuild(null, toBuild,
>        function(){
>          /* Build request started */
>          window.location.replace(libtoaster.ctx.projectBuildsUrl);
> diff --git a/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
> b/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
> index 58a32a0..b09f974 100644
> --- a/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
> +++ b/bitbake/lib/toaster/toastergui/static/js/projecttopbar.js
> @@ -82,9 +82,9 @@ function projectTopBarInit(ctx) {
>      selectedTarget = { name: newBuildTargetInput.val() };
>
>      /* Fire off the build */
> -    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
> -      null, selectedTarget.name, function(){
> -      window.location.replace(libtoaster.ctx.projectBuildsUrl);
> +    libtoaster.startABuild(null, selectedTarget.name,
> +      function(){
> +        window.location.replace(libtoaster.ctx.projectBuildsUrl);
>      }, null);
>    });
>  }
> diff --git a/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
> b/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
> index 2bfd0a4..d5f9eac 100644
> --- a/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
> +++ b/bitbake/lib/toaster/toastergui/static/js/recipedetails.js
> @@ -42,9 +42,7 @@ function recipeDetailsPageInit(ctx){
>
>    /* Trigger a build of your custom image */
>    $(".build-recipe-btn").click(function(){
> -    libtoaster.startABuild(libtoaster.ctx.projectBuildsUrl,
> -      libtoaster.ctx.projectId,
> -      ctx.recipe.name,
> +    libtoaster.startABuild(null, ctx.recipe.name,
>        function(){
>          window.location.replace(libtoaster.ctx.projectBuildsUrl);
>      });
> diff --git a/bitbake/lib/toaster/toastergui/templates/base.html
> b/bitbake/lib/toaster/toastergui/templates/base.html
> index 6994bcc..ed15c59 100644
> --- a/bitbake/lib/toaster/toastergui/templates/base.html
> +++ b/bitbake/lib/toaster/toastergui/templates/base.html
> @@ -47,6 +47,7 @@
>          projectBuildsUrl: {% url 'projectbuilds' project.id as pburl
> %}{{pburl|json}},
>          xhrCustomRecipeUrl : "{% url 'xhr_customrecipe' %}",
>          projectId : {{project.id}},
> +        xhrBuildRequestUrl: "{% url 'xhr_buildrequest' project.id %}",
>          {% else %}
>          projectId : undefined,
>          projectPageUrl : undefined,
> --
> 2.1.4
>
> --
> _______________________________________________
> toaster mailing list
> toaster@yoctoproject.org
> https://lists.yoctoproject.org/listinfo/toaster
>



-- 
Elliot Smith
Software Engineer
Intel Open Source Technology Centre

[-- Attachment #2: Type: text/html, Size: 11718 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 00/11] Build cancellation
  2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
                   ` (10 preceding siblings ...)
  2016-02-25 18:21 ` [PATCH 11/11] toaster: models Exclude the CANCELLED builds from get_number_of_builds Michael Wood
@ 2016-02-26 13:26 ` Smith, Elliot
  11 siblings, 0 replies; 15+ messages in thread
From: Smith, Elliot @ 2016-02-26 13:26 UTC (permalink / raw)
  To: Michael Wood; +Cc: toaster

[-- Attachment #1: Type: text/plain, Size: 3957 bytes --]

Another issue I've noticed: if I cancel a build before it starts properly
(e.g. before the banner showing the bitbake config. scrolls onto the log),
the build cancels fine. But if I then try to start another build, it hangs
indefinitely.

I think this is because runbuilds waits for both a free build environment
and a queued build request before it starts a build. In the case of a
cancelled build, when the build starts, the build environment object is
locked; but when that build is cancelled, the build environment isn't
unlocked. This means that build requests go to the db table but are never
started.

I checked whether this is the likely cause by going through the above steps
and waiting for the requested build to hang; then in the db, I updated the
bldcontrol_buildenvironment table with:

update bldcontrol_buildenvironment set lock = 0;

As soon as I did this, my hanging build request started building.

So I think the solution is to unlock the build environment once a build is
cancelled (see runbuilds.py, which is where the locking is originally
applied). It may be that you can do this by adding the cancelling and
cancelled states to the conditional on line 97.

Elliot

On 25 February 2016 at 18:21, Michael Wood <michael.g.wood@intel.com> wrote:

> This is the combination of Sujith's and my work on build cancel.
>
> Michael Wood (7):
>   toaster: Move xhr calls for starting and stopping builds
>   toaster: xhr Update the implementation of the build cancellation
>     request
>   toaster: libtoaster Update implementation of startABuild and
>     cancelABuild
>   toaster: bldcontrol models Add a cancelling state the BuildRequest
>   buildinfohelper: Add handler for cancelling a build
>   toaster: mrb_section template Add build cancel button
>   toaster: models Exclude the CANCELLED builds from get_number_of_builds
>
> Sujith H (4):
>   toaster: bldcontrol Add forceShutDown function to BitbakeController
>   toaster: update BuildEnvironmentController and BitbakeController
>   toaster: models Add cancelled state to build outcome
>   toaster: tables BuildsTable exclude cancelled builds
>
>  bitbake/lib/bb/ui/buildinfohelper.py               |  19 +++-
>  bitbake/lib/toaster/bldcontrol/bbcontroller.py     |  29 ++----
>  .../toaster/bldcontrol/localhostbecontroller.py    |   6 +-
>  .../migrations/0002_add_cancelling_state.py        |  19 ++++
>  bitbake/lib/toaster/bldcontrol/models.py           |  27 ++++-
>  .../orm/migrations/0006_add_cancelled_state.py     |  19 ++++
>  bitbake/lib/toaster/orm/models.py                  |  12 ++-
>  bitbake/lib/toaster/toastergui/api.py              | 110
> +++++++++++++++++++++
>  .../toaster/toastergui/static/js/customrecipe.js   |   4 +-
>  .../lib/toaster/toastergui/static/js/layerBtn.js   |   3 +-
>  .../lib/toaster/toastergui/static/js/libtoaster.js |  41 +++++---
>  .../toaster/toastergui/static/js/projectpage.js    |   4 +-
>  .../toaster/toastergui/static/js/projecttopbar.js  |   6 +-
>  .../toaster/toastergui/static/js/recipedetails.js  |   4 +-
>  bitbake/lib/toaster/toastergui/tables.py           |  48 +--------
>  bitbake/lib/toaster/toastergui/templates/base.html |   1 +
>  .../toaster/toastergui/templates/mrb_section.html  | 102
> +++++++++++++------
>  bitbake/lib/toaster/toastergui/urls.py             |   5 +
>  18 files changed, 327 insertions(+), 132 deletions(-)
>  create mode 100644
> bitbake/lib/toaster/bldcontrol/migrations/0002_add_cancelling_state.py
>  create mode 100644
> bitbake/lib/toaster/orm/migrations/0006_add_cancelled_state.py
>  create mode 100644 bitbake/lib/toaster/toastergui/api.py
>
> --
> 2.1.4
>
> --
> _______________________________________________
> toaster mailing list
> toaster@yoctoproject.org
> https://lists.yoctoproject.org/listinfo/toaster
>



-- 
Elliot Smith
Software Engineer
Intel Open Source Technology Centre

[-- Attachment #2: Type: text/html, Size: 4894 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-02-26 13:26 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-25 18:21 [PATCH 00/11] Build cancellation Michael Wood
2016-02-25 18:21 ` [PATCH 01/11] toaster: bldcontrol Add forceShutDown function to BitbakeController Michael Wood
2016-02-25 18:21 ` [PATCH 02/11] toaster: Move xhr calls for starting and stopping builds Michael Wood
2016-02-25 18:21 ` [PATCH 03/11] toaster: xhr Update the implementation of the build cancellation request Michael Wood
2016-02-25 18:21 ` [PATCH 04/11] toaster: libtoaster Update implementation of startABuild and cancelABuild Michael Wood
2016-02-26 11:55   ` Smith, Elliot
2016-02-25 18:21 ` [PATCH 05/11] toaster: update BuildEnvironmentController and BitbakeController Michael Wood
2016-02-25 18:21 ` [PATCH 06/11] toaster: models Add cancelled state to build outcome Michael Wood
2016-02-25 18:21 ` [PATCH 07/11] toaster: bldcontrol models Add a cancelling state the BuildRequest Michael Wood
2016-02-25 18:21 ` [PATCH 08/11] buildinfohelper: Add handler for cancelling a build Michael Wood
2016-02-25 18:21 ` [PATCH 09/11] toaster: tables BuildsTable exclude cancelled builds Michael Wood
2016-02-25 18:21 ` [PATCH 10/11] toaster: mrb_section template Add build cancel button Michael Wood
2016-02-25 18:26   ` Michael Wood
2016-02-25 18:21 ` [PATCH 11/11] toaster: models Exclude the CANCELLED builds from get_number_of_builds Michael Wood
2016-02-26 13:26 ` [PATCH 00/11] Build cancellation Smith, Elliot

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.