summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/toastergui/views.py
diff options
context:
space:
mode:
authorDavid Reyna <David.Reyna@windriver.com>2018-08-15 18:04:09 -0700
committerRichard Purdie <richard.purdie@linuxfoundation.org>2018-08-20 10:20:51 +0100
commit08fbdc02e32d715ae94e3b9603fb3ec8351c8fd3 (patch)
tree8b1eb6531f782ba531903cc7248fbd5705e5adf3 /bitbake/lib/toaster/toastergui/views.py
parent9af0f1a46bbb6ad9ee8b35957251f4aa826b023f (diff)
downloadpoky-08fbdc02e32d715ae94e3b9603fb3ec8351c8fd3.tar.gz
bitbake: Toaster: Implement the project-specific feature and releated enhancements and defects.
Here is the primary driving enhancement: * Bug 12785 - Support Project Specific configuration for external tools (e.g. ISS, Eclipse) - Isolated project-specific configuration page (full Toaster context hidden) - Support for new project, reconfigure existing project, and import existing command line project - Ability to define variables (e.g. image recipe) and pass them back to external GUI - Ability to execute the cloning phase, so that external GUI receive a buildable project - Ability to call back to the external GUI when updates are completed and ready - Compatibility of above projects with the normal full Toaster interface - Ability to pass to a 'complete' or 'cancel' web page so that the external GUI can immediately stop that Toaster instance, and not leave dangling servers nor edit sessions open Here are the supporting enhancements, where at least the back end is implemented: * Bug 12821 - Make Toaster conf changes compatible with command line usage * Bug 12822 - Support importing user changes to conf files into Toaster * Bug 12823 - Support importing user build directories into Toaster * Bug 12824 - Scan imported layers for content so that they are immediately available * Bug 12825 - show layer clone item in progress bar Here are defects fixed: * Bug 12817 - builddelete.py requires explicit 'add_arguments' * Bug 12818 - Remove orphaned imported layers when project is deleted * Bug 12826 - fix imported layer management * Bug 12819 - build using selected bitbake env, not Toaster's env * Bug 12820 - Toaster randomizes the layer order in toaster_bblayers.conf [YOCTO #12785] (Bitbake rev: 985d6cec290bdd80998a63483561a73c75d82d65) Signed-off-by: David Reyna <David.Reyna@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/toastergui/views.py')
-rw-r--r--[-rwxr-xr-x]bitbake/lib/toaster/toastergui/views.py151
1 files changed, 151 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py
index 34ed2b2e3c..4939b6b1f4 100755..100644
--- a/bitbake/lib/toaster/toastergui/views.py
+++ b/bitbake/lib/toaster/toastergui/views.py
@@ -25,6 +25,7 @@ import re
25from django.db.models import F, Q, Sum 25from django.db.models import F, Q, Sum
26from django.db import IntegrityError 26from django.db import IntegrityError
27from django.shortcuts import render, redirect, get_object_or_404 27from django.shortcuts import render, redirect, get_object_or_404
28from django.utils.http import urlencode
28from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe 29from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe
29from orm.models import LogMessage, Variable, Package_Dependency, Package 30from orm.models import LogMessage, Variable, Package_Dependency, Package
30from orm.models import Task_Dependency, Package_File 31from orm.models import Task_Dependency, Package_File
@@ -51,6 +52,7 @@ logger = logging.getLogger("toaster")
51 52
52# Project creation and managed build enable 53# Project creation and managed build enable
53project_enable = ('1' == os.environ.get('TOASTER_BUILDSERVER')) 54project_enable = ('1' == os.environ.get('TOASTER_BUILDSERVER'))
55is_project_specific = ('1' == os.environ.get('TOASTER_PROJECTSPECIFIC'))
54 56
55class MimeTypeFinder(object): 57class MimeTypeFinder(object):
56 # setting this to False enables additional non-standard mimetypes 58 # setting this to False enables additional non-standard mimetypes
@@ -70,6 +72,7 @@ class MimeTypeFinder(object):
70# single point to add global values into the context before rendering 72# single point to add global values into the context before rendering
71def toaster_render(request, page, context): 73def toaster_render(request, page, context):
72 context['project_enable'] = project_enable 74 context['project_enable'] = project_enable
75 context['project_specific'] = is_project_specific
73 return render(request, page, context) 76 return render(request, page, context)
74 77
75 78
@@ -1434,12 +1437,160 @@ if True:
1434 1437
1435 raise Exception("Invalid HTTP method for this page") 1438 raise Exception("Invalid HTTP method for this page")
1436 1439
1440 # new project
1441 def newproject_specific(request, pid):
1442 if not project_enable:
1443 return redirect( landing )
1444
1445 project = Project.objects.get(pk=pid)
1446 template = "newproject_specific.html"
1447 context = {
1448 'email': request.user.email if request.user.is_authenticated() else '',
1449 'username': request.user.username if request.user.is_authenticated() else '',
1450 'releases': Release.objects.order_by("description"),
1451 'projectname': project.name,
1452 'project_pk': project.pk,
1453 }
1454
1455 # WORKAROUND: if we already know release, redirect 'newproject_specific' to 'project_specific'
1456 if '1' == project.get_variable('INTERNAL_PROJECT_SPECIFIC_SKIPRELEASE'):
1457 return redirect(reverse(project_specific, args=(project.pk,)))
1458
1459 try:
1460 context['defaultbranch'] = ToasterSetting.objects.get(name = "DEFAULT_RELEASE").value
1461 except ToasterSetting.DoesNotExist:
1462 pass
1463
1464 if request.method == "GET":
1465 # render new project page
1466 return toaster_render(request, template, context)
1467 elif request.method == "POST":
1468 mandatory_fields = ['projectname', 'ptype']
1469 try:
1470 ptype = request.POST.get('ptype')
1471 if ptype == "build":
1472 mandatory_fields.append('projectversion')
1473 # make sure we have values for all mandatory_fields
1474 missing = [field for field in mandatory_fields if len(request.POST.get(field, '')) == 0]
1475 if missing:
1476 # set alert for missing fields
1477 raise BadParameterException("Fields missing: %s" % ", ".join(missing))
1478
1479 if not request.user.is_authenticated():
1480 user = authenticate(username = request.POST.get('username', '_anonuser'), password = 'nopass')
1481 if user is None:
1482 user = User.objects.create_user(username = request.POST.get('username', '_anonuser'), email = request.POST.get('email', ''), password = "nopass")
1483
1484 user = authenticate(username = user.username, password = 'nopass')
1485 login(request, user)
1486
1487 # save the project
1488 if ptype == "analysis":
1489 release = None
1490 else:
1491 release = Release.objects.get(pk = request.POST.get('projectversion', None ))
1492
1493 prj = Project.objects.create_project(name = request.POST['projectname'], release = release, existing_project = project)
1494 prj.user_id = request.user.pk
1495 prj.save()
1496 return redirect(reverse(project_specific, args=(prj.pk,)) + "?notify=new-project")
1497
1498 except (IntegrityError, BadParameterException) as e:
1499 # fill in page with previously submitted values
1500 for field in mandatory_fields:
1501 context.__setitem__(field, request.POST.get(field, "-- missing"))
1502 if isinstance(e, IntegrityError) and "username" in str(e):
1503 context['alert'] = "Your chosen username is already used"
1504 else:
1505 context['alert'] = str(e)
1506 return toaster_render(request, template, context)
1507
1508 raise Exception("Invalid HTTP method for this page")
1509
1437 # Shows the edit project page 1510 # Shows the edit project page
1438 def project(request, pid): 1511 def project(request, pid):
1439 project = Project.objects.get(pk=pid) 1512 project = Project.objects.get(pk=pid)
1513
1514 if '1' == os.environ.get('TOASTER_PROJECTSPECIFIC'):
1515 if request.GET:
1516 #Example:request.GET=<QueryDict: {'setMachine': ['qemuarm']}>
1517 params = urlencode(request.GET).replace('%5B%27','').replace('%27%5D','')
1518 return redirect("%s?%s" % (reverse(project_specific, args=(project.pk,)),params))
1519 else:
1520 return redirect(reverse(project_specific, args=(project.pk,)))
1440 context = {"project": project} 1521 context = {"project": project}
1441 return toaster_render(request, "project.html", context) 1522 return toaster_render(request, "project.html", context)
1442 1523
1524 # Shows the edit project-specific page
1525 def project_specific(request, pid):
1526 project = Project.objects.get(pk=pid)
1527
1528 # Are we refreshing from a successful project specific update clone?
1529 if Project.PROJECT_SPECIFIC_CLONING_SUCCESS == project.get_variable(Project.PROJECT_SPECIFIC_STATUS):
1530 return redirect(reverse(landing_specific,args=(project.pk,)))
1531
1532 context = {
1533 "project": project,
1534 "is_new" : project.get_variable(Project.PROJECT_SPECIFIC_ISNEW),
1535 "default_image_recipe" : project.get_variable(Project.PROJECT_SPECIFIC_DEFAULTIMAGE),
1536 "mru" : Build.objects.all().filter(project=project,outcome=Build.IN_PROGRESS),
1537 }
1538 if project.build_set.filter(outcome=Build.IN_PROGRESS).count() > 0:
1539 context['build_in_progress_none_completed'] = True
1540 else:
1541 context['build_in_progress_none_completed'] = False
1542 return toaster_render(request, "project.html", context)
1543
1544 # perform the final actions for the project specific page
1545 def project_specific_finalize(cmnd, pid):
1546 project = Project.objects.get(pk=pid)
1547 callback = project.get_variable(Project.PROJECT_SPECIFIC_CALLBACK)
1548 if "update" == cmnd:
1549 # Delete all '_PROJECT_PREPARE_' builds
1550 for b in Build.objects.all().filter(project=project):
1551 delete_build = False
1552 for t in b.target_set.all():
1553 if '_PROJECT_PREPARE_' == t.target:
1554 delete_build = True
1555 if delete_build:
1556 from django.core import management
1557 management.call_command('builddelete', str(b.id), interactive=False)
1558 # perform callback at this last moment if defined, in case Toaster gets shutdown next
1559 default_target = project.get_variable(Project.PROJECT_SPECIFIC_DEFAULTIMAGE)
1560 if callback:
1561 callback = callback.replace("<IMAGE>",default_target)
1562 if "cancel" == cmnd:
1563 if callback:
1564 callback = callback.replace("<IMAGE>","none")
1565 callback = callback.replace("--update","--cancel")
1566 # perform callback at this last moment if defined, in case this Toaster gets shutdown next
1567 ret = ''
1568 if callback:
1569 ret = os.system('bash -c "%s"' % callback)
1570 project.set_variable(Project.PROJECT_SPECIFIC_CALLBACK,'')
1571 # Delete the temp project specific variables
1572 project.set_variable(Project.PROJECT_SPECIFIC_ISNEW,'')
1573 project.set_variable(Project.PROJECT_SPECIFIC_STATUS,Project.PROJECT_SPECIFIC_NONE)
1574 # WORKAROUND: Release this workaround flag
1575 project.set_variable('INTERNAL_PROJECT_SPECIFIC_SKIPRELEASE','')
1576
1577 # Shows the final landing page for project specific update
1578 def landing_specific(request, pid):
1579 project_specific_finalize("update", pid)
1580 context = {
1581 "install_dir": os.environ['TOASTER_DIR'],
1582 }
1583 return toaster_render(request, "landing_specific.html", context)
1584
1585 # Shows the related landing-specific page
1586 def landing_specific_cancel(request, pid):
1587 project_specific_finalize("cancel", pid)
1588 context = {
1589 "install_dir": os.environ['TOASTER_DIR'],
1590 "status": "cancel",
1591 }
1592 return toaster_render(request, "landing_specific.html", context)
1593
1443 def jsunittests(request): 1594 def jsunittests(request):
1444 """ Provides a page for the js unit tests """ 1595 """ Provides a page for the js unit tests """
1445 bbv = BitbakeVersion.objects.filter(branch="master").first() 1596 bbv = BitbakeVersion.objects.filter(branch="master").first()