summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Wood <michael.g.wood@intel.com>2016-12-09 16:52:45 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-12-12 20:44:53 +0000
commit7e80e501fb05021d4f4b6793462c488445cb4d89 (patch)
treedf966256a8a94e780e74b82fa9ae369e7c46a551
parent90d995c63717f869ef68976f7d0778e87af989f2 (diff)
downloadpoky-7e80e501fb05021d4f4b6793462c488445cb4d89.tar.gz
bitbake: toaster: api Add layer Add api
Add layer adding REST api and remove old views method. (Bitbake rev: 0c8e41d2217fd568a84e857d1be230fcfd4bb5c7) Signed-off-by: Michael Wood <michael.g.wood@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--bitbake/lib/toaster/toastergui/api.py101
-rw-r--r--bitbake/lib/toaster/toastergui/templates/importlayer.html2
-rw-r--r--bitbake/lib/toaster/toastergui/urls.py6
-rwxr-xr-xbitbake/lib/toaster/toastergui/views.py115
4 files changed, 103 insertions, 121 deletions
diff --git a/bitbake/lib/toaster/toastergui/api.py b/bitbake/lib/toaster/toastergui/api.py
index 4851047bfa..5be633ed11 100644
--- a/bitbake/lib/toaster/toastergui/api.py
+++ b/bitbake/lib/toaster/toastergui/api.py
@@ -20,6 +20,7 @@
20 20
21import re 21import re
22import logging 22import logging
23import json
23from collections import Counter 24from collections import Counter
24 25
25from orm.models import Project, ProjectTarget, Build, Layer_Version 26from orm.models import Project, ProjectTarget, Build, Layer_Version
@@ -136,14 +137,17 @@ class XhrBuildRequest(View):
136 137
137 138
138class XhrLayer(View): 139class XhrLayer(View):
139 """ Get and Update Layer information """ 140 """ Delete, Get, Add and Update Layer information
141
142 Methods: POST DELETE PUT
143 """
140 144
141 def post(self, request, *args, **kwargs): 145 def post(self, request, *args, **kwargs):
142 """ 146 """
143 Update a layer 147 Update a layer
144 148
145 Entry point: /xhr_layer/<layerversion_id>
146 Method: POST 149 Method: POST
150 Entry point: /xhr_layer/<layerversion_id>
147 151
148 Args: 152 Args:
149 vcs_url, dirpath, commit, up_branch, summary, description, 153 vcs_url, dirpath, commit, up_branch, summary, description,
@@ -201,9 +205,100 @@ class XhrLayer(View):
201 return error_response("Could not update layer version entry: %s" 205 return error_response("Could not update layer version entry: %s"
202 % e) 206 % e)
203 207
204 return JsonResponse({"error": "ok"}) 208 return error_response("ok")
209
210 def put(self, request, *args, **kwargs):
211 """ Add a new layer
212
213 Method: PUT
214 Entry point: /xhr_layer/
215 Args:
216 project_id, name,
217 [vcs_url, dir_path, git_ref], [local_source_dir], [layer_deps
218 (csv)]
219
220 """
221 try:
222 project = Project.objects.get(pk=kwargs['pid'])
223
224 layer_data = json.loads(request.body.decode('utf-8'))
225
226 # We require a unique layer name as otherwise the lists of layers
227 # becomes very confusing
228 existing_layers = \
229 project.get_all_compatible_layer_versions().values_list(
230 "layer__name",
231 flat=True)
232
233 add_to_project = False
234 layer_deps_added = []
235 if 'add_to_project' in layer_data:
236 add_to_project = True
237
238 if layer_data['name'] in existing_layers:
239 return JsonResponse({"error": "layer-name-exists"})
240
241 layer = Layer.objects.create(name=layer_data['name'])
242
243 layer_version = Layer_Version.objects.create(
244 layer=layer,
245 project=project,
246 layer_source=LayerSource.TYPE_IMPORTED)
247
248 # Local layer
249 if 'local_source_dir' in layer_data:
250 layer.local_source_dir = layer_data['local_source_dir']
251 # git layer
252 elif 'vcs_url' in layer_data:
253 layer.vcs_url = layer_data['vcs_url']
254 layer_version.dirpath = layer_data['dir_path']
255 layer_version.commit = layer_data['get_ref']
256 layer_version.branch = layer_data['get_ref']
257
258 layer.save()
259 layer_version.save()
260
261 if add_to_project:
262 ProjectLayer.objects.get_or_create(
263 layercommit=layer_version, project=project)
264
265 # Add the layer dependencies
266 if 'layer_deps' in layer_data:
267 for layer_dep_id in layer_data['layer_deps'].split(","):
268 layer_dep = Layer_Version.objects.get(pk=layer_dep_id)
269 LayerVersionDependency.objects.get_or_create(
270 layer_version=layer_version, depends_on=layer_dep)
271
272 # Add layer deps to the project if specified
273 if add_to_project:
274 created, pl = ProjectLayer.objects.get_or_create(
275 layercommit=layer_dep, project=project)
276 layer_deps_added.append(
277 {'name': layer_dep.layer.name,
278 'layerdetailurl':
279 layer_dep.get_detailspage_url(project.pk)})
280
281 except Layer_Version.DoesNotExist:
282 return error_response("layer-dep-not-found")
283 except Project.DoesNotExist:
284 return error_response("project-not-found")
285 except KeyError:
286 return error_response("incorrect-parameters")
287
288 return JsonResponse({'error': "ok",
289 'imported_layer': {
290 'name': layer.name,
291 'layerdetailurl':
292 layer_version.get_detailspage_url()},
293 'deps_added': layer_deps_added})
205 294
206 def delete(self, request, *args, **kwargs): 295 def delete(self, request, *args, **kwargs):
296 """ Delete an imported layer
297
298 Method: DELETE
299 Entry point: /xhr_layer/<layerversion_id>
300
301 """
207 try: 302 try:
208 # We currently only allow Imported layers to be deleted 303 # We currently only allow Imported layers to be deleted
209 layer_version = Layer_Version.objects.get( 304 layer_version = Layer_Version.objects.get(
diff --git a/bitbake/lib/toaster/toastergui/templates/importlayer.html b/bitbake/lib/toaster/toastergui/templates/importlayer.html
index 1f426969af..bd507b5677 100644
--- a/bitbake/lib/toaster/toastergui/templates/importlayer.html
+++ b/bitbake/lib/toaster/toastergui/templates/importlayer.html
@@ -13,7 +13,7 @@
13 <script> 13 <script>
14 $(document).ready(function (){ 14 $(document).ready(function (){
15 var ctx = { 15 var ctx = {
16 xhrImportLayerUrl : "{% url 'xhr_importlayer' %}", 16 xhrLayerUrl : "{% url 'xhr_layer' project.id %}",
17 }; 17 };
18 18
19 try { 19 try {
diff --git a/bitbake/lib/toaster/toastergui/urls.py b/bitbake/lib/toaster/toastergui/urls.py
index ece9ac1696..29f0d96ba7 100644
--- a/bitbake/lib/toaster/toastergui/urls.py
+++ b/bitbake/lib/toaster/toastergui/urls.py
@@ -190,12 +190,14 @@ urlpatterns = patterns('toastergui.views',
190 url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit', 190 url(r'^xhr_configvaredit/(?P<pid>\d+)$', 'xhr_configvaredit',
191 name='xhr_configvaredit'), 191 name='xhr_configvaredit'),
192 192
193 url(r'^xhr_importlayer/$', 'xhr_importlayer', name='xhr_importlayer'),
194
195 url(r'^xhr_layer/(?P<pid>\d+)/(?P<layerversion_id>\d+)$', 193 url(r'^xhr_layer/(?P<pid>\d+)/(?P<layerversion_id>\d+)$',
196 api.XhrLayer.as_view(), 194 api.XhrLayer.as_view(),
197 name='xhr_layer'), 195 name='xhr_layer'),
198 196
197 url(r'^xhr_layer/(?P<pid>\d+)$',
198 api.XhrLayer.as_view(),
199 name='xhr_layer'),
200
199 # JS Unit tests 201 # JS Unit tests
200 url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'), 202 url(r'^js-unit-tests/$', 'jsunittests', name='js-unit-tests'),
201 203
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 2efb0fd56c..94b630a8f7 100755
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -1509,121 +1509,6 @@ if True:
1509 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") 1509 return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json")
1510 1510
1511 1511
1512 def xhr_importlayer(request):
1513 if ('vcs_url' not in request.POST or
1514 'name' not in request.POST or
1515 'git_ref' not in request.POST or
1516 'project_id' not in request.POST):
1517 return HttpResponse(jsonfilter({"error": "Missing parameters; requires vcs_url, name, git_ref and project_id"}), content_type = "application/json")
1518
1519 layers_added = [];
1520
1521 # Rudimentary check for any possible html tags
1522 for val in request.POST.values():
1523 if "<" in val:
1524 return HttpResponse(jsonfilter(
1525 {"error": "Invalid character <"}),
1526 content_type="application/json")
1527
1528 prj = Project.objects.get(pk=request.POST['project_id'])
1529
1530 # Strip trailing/leading whitespace from all values
1531 # put into a new dict because POST one is immutable.
1532 post_data = dict()
1533 for key,val in request.POST.items():
1534 post_data[key] = val.strip()
1535
1536
1537 try:
1538 layer, layer_created = Layer.objects.get_or_create(name=post_data['name'])
1539 except MultipleObjectsReturned:
1540 return HttpResponse(jsonfilter({"error": "hint-layer-exists"}), content_type = "application/json")
1541
1542 if layer:
1543 if layer_created:
1544 layer.vcs_url = post_data.get('vcs_url')
1545 layer.local_source_dir = post_data.get('local_source_dir')
1546 layer.up_date = timezone.now()
1547 layer.save()
1548 else:
1549 # We have an existing layer by this name, let's see if the git
1550 # url is the same, if it is then we can just create a new layer
1551 # version for this layer. Otherwise we need to bail out.
1552 if layer.vcs_url != post_data['vcs_url']:
1553 return HttpResponse(jsonfilter({"error": "hint-layer-exists-with-different-url" , "current_url" : layer.vcs_url, "current_id": layer.id }), content_type = "application/json")
1554
1555 layer_version, version_created = \
1556 Layer_Version.objects.get_or_create(
1557 layer_source=LayerSource.TYPE_IMPORTED,
1558 layer=layer, project=prj,
1559 release=prj.release,
1560 branch=post_data['git_ref'],
1561 commit=post_data['git_ref'],
1562 dirpath=post_data['dir_path'])
1563
1564 if layer_version:
1565 if not version_created:
1566 return HttpResponse(jsonfilter({"error":
1567 "hint-layer-version-exists",
1568 "existing_layer_version":
1569 layer_version.id }),
1570 content_type = "application/json")
1571
1572 layer_version.layer_source = LayerSource.TYPE_IMPORTED
1573
1574 layer_version.up_date = timezone.now()
1575 layer_version.save()
1576
1577 # Add the dependencies specified for this new layer
1578 if ('layer_deps' in post_data and
1579 version_created and
1580 len(post_data["layer_deps"]) > 0):
1581 for layer_dep_id in post_data["layer_deps"].split(","):
1582
1583 layer_dep_obj = Layer_Version.objects.get(pk=layer_dep_id)
1584 LayerVersionDependency.objects.get_or_create(layer_version=layer_version, depends_on=layer_dep_obj)
1585 # Now add them to the project, we could get an execption
1586 # if the project now contains the exact
1587 # dependency already (like modified on another page)
1588 try:
1589 prj_layer, prj_layer_created = ProjectLayer.objects.get_or_create(layercommit=layer_dep_obj, project=prj)
1590 except IntegrityError as e:
1591 logger.warning("Integrity error while saving Project Layers: %s (original %s)" % (e, e.__cause__))
1592 continue
1593
1594 if prj_layer_created:
1595 layerdepdetailurl = reverse('layerdetails', args=(prj.id, layer_dep_obj.pk))
1596 layers_added.append({'id': layer_dep_obj.id, 'name': Layer.objects.get(id=layer_dep_obj.layer_id).name, 'layerdetailurl': layerdepdetailurl })
1597
1598
1599 # If an old layer version exists in our project then remove it
1600 for prj_layers in ProjectLayer.objects.filter(project=prj):
1601 dup_layer_v = Layer_Version.objects.filter(id=prj_layers.layercommit_id, layer_id=layer.id)
1602 if len(dup_layer_v) >0 :
1603 prj_layers.delete()
1604
1605 # finally add the imported layer (version id) to the project
1606 ProjectLayer.objects.create(layercommit=layer_version, project=prj,optional=1)
1607
1608 else:
1609 # We didn't create a layer version so back out now and clean up.
1610 if layer_created:
1611 layer.delete()
1612
1613 return HttpResponse(jsonfilter({"error": "Uncaught error: Could not create layer version"}), content_type = "application/json")
1614
1615 layerdetailurl = reverse('layerdetails', args=(prj.id, layer_version.pk))
1616
1617 json_response = {"error": "ok",
1618 "imported_layer" : {
1619 "name" : layer.name,
1620 "id": layer_version.id,
1621 "layerdetailurl": layerdetailurl,
1622 },
1623 "deps_added": layers_added }
1624
1625 return HttpResponse(jsonfilter(json_response), content_type = "application/json")
1626
1627 def customrecipe_download(request, pid, recipe_id): 1512 def customrecipe_download(request, pid, recipe_id):
1628 recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id) 1513 recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id)
1629 1514