diff options
Diffstat (limited to 'bitbake/lib/toaster/toastergui/views.py')
-rw-r--r-- | bitbake/lib/toaster/toastergui/views.py | 220 |
1 files changed, 201 insertions, 19 deletions
diff --git a/bitbake/lib/toaster/toastergui/views.py b/bitbake/lib/toaster/toastergui/views.py index 9a5e48e3bb..061e6436c8 100644 --- a/bitbake/lib/toaster/toastergui/views.py +++ b/bitbake/lib/toaster/toastergui/views.py | |||
@@ -6,24 +6,36 @@ | |||
6 | # SPDX-License-Identifier: GPL-2.0-only | 6 | # SPDX-License-Identifier: GPL-2.0-only |
7 | # | 7 | # |
8 | 8 | ||
9 | import ast | ||
9 | import re | 10 | import re |
11 | import subprocess | ||
12 | import sys | ||
13 | |||
14 | import bb.cooker | ||
15 | from bb.ui import toasterui | ||
16 | from bb.ui import eventreplay | ||
10 | 17 | ||
11 | from django.db.models import F, Q, Sum | 18 | from django.db.models import F, Q, Sum |
12 | from django.db import IntegrityError | 19 | from django.db import IntegrityError |
13 | from django.shortcuts import render, redirect, get_object_or_404 | 20 | from django.shortcuts import render, redirect, get_object_or_404, HttpResponseRedirect |
14 | from django.utils.http import urlencode | 21 | from django.utils.http import urlencode |
15 | from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe | 22 | from orm.models import Build, Target, Task, Layer, Layer_Version, Recipe |
16 | from orm.models import LogMessage, Variable, Package_Dependency, Package | 23 | from orm.models import LogMessage, Variable, Package_Dependency, Package |
17 | from orm.models import Task_Dependency, Package_File | 24 | from orm.models import Task_Dependency, Package_File |
18 | from orm.models import Target_Installed_Package, Target_File | 25 | from orm.models import Target_Installed_Package, Target_File |
19 | from orm.models import TargetKernelFile, TargetSDKFile, Target_Image_File | 26 | from orm.models import TargetKernelFile, TargetSDKFile, Target_Image_File |
20 | from orm.models import BitbakeVersion, CustomImageRecipe | 27 | from orm.models import BitbakeVersion, CustomImageRecipe, EventLogsImports |
21 | 28 | ||
22 | from django.urls import reverse, resolve | 29 | from django.urls import reverse, resolve |
30 | from django.contrib import messages | ||
31 | |||
23 | from django.core.exceptions import ObjectDoesNotExist | 32 | from django.core.exceptions import ObjectDoesNotExist |
33 | from django.core.files.storage import FileSystemStorage | ||
34 | from django.core.files.uploadedfile import InMemoryUploadedFile, TemporaryUploadedFile | ||
24 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger | 35 | from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger |
25 | from django.http import HttpResponseNotFound, JsonResponse | 36 | from django.http import HttpResponseNotFound, JsonResponse |
26 | from django.utils import timezone | 37 | from django.utils import timezone |
38 | from django.views.generic import TemplateView | ||
27 | from datetime import timedelta, datetime | 39 | from datetime import timedelta, datetime |
28 | from toastergui.templatetags.projecttags import json as jsonfilter | 40 | from toastergui.templatetags.projecttags import json as jsonfilter |
29 | from decimal import Decimal | 41 | from decimal import Decimal |
@@ -32,13 +44,20 @@ import os | |||
32 | from os.path import dirname | 44 | from os.path import dirname |
33 | import mimetypes | 45 | import mimetypes |
34 | 46 | ||
47 | from toastergui.forms import LoadFileForm | ||
48 | |||
49 | from collections import namedtuple | ||
50 | |||
35 | import logging | 51 | import logging |
36 | 52 | ||
53 | from toastermain.logs import log_view_mixin | ||
54 | |||
37 | logger = logging.getLogger("toaster") | 55 | logger = logging.getLogger("toaster") |
38 | 56 | ||
39 | # Project creation and managed build enable | 57 | # Project creation and managed build enable |
40 | project_enable = ('1' == os.environ.get('TOASTER_BUILDSERVER')) | 58 | project_enable = ('1' == os.environ.get('TOASTER_BUILDSERVER')) |
41 | is_project_specific = ('1' == os.environ.get('TOASTER_PROJECTSPECIFIC')) | 59 | is_project_specific = ('1' == os.environ.get('TOASTER_PROJECTSPECIFIC')) |
60 | import_page = False | ||
42 | 61 | ||
43 | class MimeTypeFinder(object): | 62 | class MimeTypeFinder(object): |
44 | # setting this to False enables additional non-standard mimetypes | 63 | # setting this to False enables additional non-standard mimetypes |
@@ -56,6 +75,7 @@ class MimeTypeFinder(object): | |||
56 | return guessed_type | 75 | return guessed_type |
57 | 76 | ||
58 | # single point to add global values into the context before rendering | 77 | # single point to add global values into the context before rendering |
78 | @log_view_mixin | ||
59 | def toaster_render(request, page, context): | 79 | def toaster_render(request, page, context): |
60 | context['project_enable'] = project_enable | 80 | context['project_enable'] = project_enable |
61 | context['project_specific'] = is_project_specific | 81 | context['project_specific'] = is_project_specific |
@@ -352,7 +372,6 @@ def _get_parameters_values(request, default_count, default_order): | |||
352 | # set cookies for parameters. this is usefull in case parameters are set | 372 | # set cookies for parameters. this is usefull in case parameters are set |
353 | # manually from the GET values of the link | 373 | # manually from the GET values of the link |
354 | def _set_parameters_values(pagesize, orderby, request): | 374 | def _set_parameters_values(pagesize, orderby, request): |
355 | from django.urls import resolve | ||
356 | current_url = resolve(request.path_info).url_name | 375 | current_url = resolve(request.path_info).url_name |
357 | request.session['%s_count' % current_url] = pagesize | 376 | request.session['%s_count' % current_url] = pagesize |
358 | request.session['%s_orderby' % current_url] =orderby | 377 | request.session['%s_orderby' % current_url] =orderby |
@@ -665,20 +684,20 @@ def recipe_packages(request, build_id, recipe_id): | |||
665 | return response | 684 | return response |
666 | 685 | ||
667 | from django.http import HttpResponse | 686 | from django.http import HttpResponse |
687 | @log_view_mixin | ||
668 | def xhr_dirinfo(request, build_id, target_id): | 688 | def xhr_dirinfo(request, build_id, target_id): |
669 | top = request.GET.get('start', '/') | 689 | top = request.GET.get('start', '/') |
670 | return HttpResponse(_get_dir_entries(build_id, target_id, top), content_type = "application/json") | 690 | return HttpResponse(_get_dir_entries(build_id, target_id, top), content_type = "application/json") |
671 | 691 | ||
672 | from django.utils.functional import Promise | 692 | from django.utils.functional import Promise |
673 | from django.utils.encoding import force_text | 693 | from django.utils.encoding import force_str |
674 | class LazyEncoder(json.JSONEncoder): | 694 | class LazyEncoder(json.JSONEncoder): |
675 | def default(self, obj): | 695 | def default(self, obj): |
676 | if isinstance(obj, Promise): | 696 | if isinstance(obj, Promise): |
677 | return force_text(obj) | 697 | return force_str(obj) |
678 | return super(LazyEncoder, self).default(obj) | 698 | return super(LazyEncoder, self).default(obj) |
679 | 699 | ||
680 | from toastergui.templatetags.projecttags import filtered_filesizeformat | 700 | from toastergui.templatetags.projecttags import filtered_filesizeformat |
681 | import os | ||
682 | def _get_dir_entries(build_id, target_id, start): | 701 | def _get_dir_entries(build_id, target_id, start): |
683 | node_str = { | 702 | node_str = { |
684 | Target_File.ITYPE_REGULAR : '-', | 703 | Target_File.ITYPE_REGULAR : '-', |
@@ -1404,7 +1423,7 @@ if True: | |||
1404 | if not os.path.isdir('%s/conf' % request.POST['importdir']): | 1423 | if not os.path.isdir('%s/conf' % request.POST['importdir']): |
1405 | raise BadParameterException("Bad path or missing 'conf' directory (%s)" % request.POST['importdir']) | 1424 | raise BadParameterException("Bad path or missing 'conf' directory (%s)" % request.POST['importdir']) |
1406 | from django.core import management | 1425 | from django.core import management |
1407 | management.call_command('buildimport', '--command=import', '--name=%s' % request.POST['projectname'], '--path=%s' % request.POST['importdir'], interactive=False) | 1426 | management.call_command('buildimport', '--command=import', '--name=%s' % request.POST['projectname'], '--path=%s' % request.POST['importdir']) |
1408 | prj = Project.objects.get(name = request.POST['projectname']) | 1427 | prj = Project.objects.get(name = request.POST['projectname']) |
1409 | prj.merged_attr = True | 1428 | prj.merged_attr = True |
1410 | prj.save() | 1429 | prj.save() |
@@ -1606,12 +1625,13 @@ if True: | |||
1606 | # make sure we have a machine set for this project | 1625 | # make sure we have a machine set for this project |
1607 | ProjectVariable.objects.get_or_create(project=new_project, | 1626 | ProjectVariable.objects.get_or_create(project=new_project, |
1608 | name="MACHINE", | 1627 | name="MACHINE", |
1609 | value="qemux86") | 1628 | value="qemux86-64") |
1610 | context = {'project': new_project} | 1629 | context = {'project': new_project} |
1611 | return toaster_render(request, "js-unit-tests.html", context) | 1630 | return toaster_render(request, "js-unit-tests.html", context) |
1612 | 1631 | ||
1613 | from django.views.decorators.csrf import csrf_exempt | 1632 | from django.views.decorators.csrf import csrf_exempt |
1614 | @csrf_exempt | 1633 | @csrf_exempt |
1634 | @log_view_mixin | ||
1615 | def xhr_testreleasechange(request, pid): | 1635 | def xhr_testreleasechange(request, pid): |
1616 | def response(data): | 1636 | def response(data): |
1617 | return HttpResponse(jsonfilter(data), | 1637 | return HttpResponse(jsonfilter(data), |
@@ -1648,6 +1668,7 @@ if True: | |||
1648 | except Exception as e: | 1668 | except Exception as e: |
1649 | return response({"error": str(e) }) | 1669 | return response({"error": str(e) }) |
1650 | 1670 | ||
1671 | @log_view_mixin | ||
1651 | def xhr_configvaredit(request, pid): | 1672 | def xhr_configvaredit(request, pid): |
1652 | try: | 1673 | try: |
1653 | prj = Project.objects.get(id = pid) | 1674 | prj = Project.objects.get(id = pid) |
@@ -1683,12 +1704,12 @@ if True: | |||
1683 | t=request.POST['configvarDel'].strip() | 1704 | t=request.POST['configvarDel'].strip() |
1684 | pt = ProjectVariable.objects.get(pk = int(t)).delete() | 1705 | pt = ProjectVariable.objects.get(pk = int(t)).delete() |
1685 | 1706 | ||
1686 | # return all project settings, filter out blacklist and elsewhere-managed variables | 1707 | # return all project settings, filter out disallowed and elsewhere-managed variables |
1687 | vars_managed,vars_fstypes,vars_blacklist = get_project_configvars_context() | 1708 | vars_managed,vars_fstypes,vars_disallowed = get_project_configvars_context() |
1688 | configvars_query = ProjectVariable.objects.filter(project_id = pid).all() | 1709 | configvars_query = ProjectVariable.objects.filter(project_id = pid).all() |
1689 | for var in vars_managed: | 1710 | for var in vars_managed: |
1690 | configvars_query = configvars_query.exclude(name = var) | 1711 | configvars_query = configvars_query.exclude(name = var) |
1691 | for var in vars_blacklist: | 1712 | for var in vars_disallowed: |
1692 | configvars_query = configvars_query.exclude(name = var) | 1713 | configvars_query = configvars_query.exclude(name = var) |
1693 | 1714 | ||
1694 | return_data = { | 1715 | return_data = { |
@@ -1708,7 +1729,7 @@ if True: | |||
1708 | except ProjectVariable.DoesNotExist: | 1729 | except ProjectVariable.DoesNotExist: |
1709 | pass | 1730 | pass |
1710 | try: | 1731 | try: |
1711 | return_data['image_install_append'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_INSTALL_append").value, | 1732 | return_data['image_install:append'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_INSTALL:append").value, |
1712 | except ProjectVariable.DoesNotExist: | 1733 | except ProjectVariable.DoesNotExist: |
1713 | pass | 1734 | pass |
1714 | try: | 1735 | try: |
@@ -1726,6 +1747,7 @@ if True: | |||
1726 | return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") | 1747 | return HttpResponse(json.dumps({"error":str(e) + "\n" + traceback.format_exc()}), content_type = "application/json") |
1727 | 1748 | ||
1728 | 1749 | ||
1750 | @log_view_mixin | ||
1729 | def customrecipe_download(request, pid, recipe_id): | 1751 | def customrecipe_download(request, pid, recipe_id): |
1730 | recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id) | 1752 | recipe = get_object_or_404(CustomImageRecipe, pk=recipe_id) |
1731 | 1753 | ||
@@ -1781,7 +1803,7 @@ if True: | |||
1781 | 'MACHINE', 'BBLAYERS' | 1803 | 'MACHINE', 'BBLAYERS' |
1782 | } | 1804 | } |
1783 | 1805 | ||
1784 | vars_blacklist = { | 1806 | vars_disallowed = { |
1785 | 'PARALLEL_MAKE','BB_NUMBER_THREADS', | 1807 | 'PARALLEL_MAKE','BB_NUMBER_THREADS', |
1786 | 'BB_DISKMON_DIRS','BB_NUMBER_THREADS','CVS_PROXY_HOST','CVS_PROXY_PORT', | 1808 | 'BB_DISKMON_DIRS','BB_NUMBER_THREADS','CVS_PROXY_HOST','CVS_PROXY_PORT', |
1787 | 'PARALLEL_MAKE','TMPDIR', | 1809 | 'PARALLEL_MAKE','TMPDIR', |
@@ -1790,7 +1812,7 @@ if True: | |||
1790 | 1812 | ||
1791 | vars_fstypes = Target_Image_File.SUFFIXES | 1813 | vars_fstypes = Target_Image_File.SUFFIXES |
1792 | 1814 | ||
1793 | return(vars_managed,sorted(vars_fstypes),vars_blacklist) | 1815 | return(vars_managed,sorted(vars_fstypes),vars_disallowed) |
1794 | 1816 | ||
1795 | def projectconf(request, pid): | 1817 | def projectconf(request, pid): |
1796 | 1818 | ||
@@ -1799,12 +1821,12 @@ if True: | |||
1799 | except Project.DoesNotExist: | 1821 | except Project.DoesNotExist: |
1800 | return HttpResponseNotFound("<h1>Project id " + pid + " is unavailable</h1>") | 1822 | return HttpResponseNotFound("<h1>Project id " + pid + " is unavailable</h1>") |
1801 | 1823 | ||
1802 | # remove blacklist and externally managed varaibles from this list | 1824 | # remove disallowed and externally managed varaibles from this list |
1803 | vars_managed,vars_fstypes,vars_blacklist = get_project_configvars_context() | 1825 | vars_managed,vars_fstypes,vars_disallowed = get_project_configvars_context() |
1804 | configvars = ProjectVariable.objects.filter(project_id = pid).all() | 1826 | configvars = ProjectVariable.objects.filter(project_id = pid).all() |
1805 | for var in vars_managed: | 1827 | for var in vars_managed: |
1806 | configvars = configvars.exclude(name = var) | 1828 | configvars = configvars.exclude(name = var) |
1807 | for var in vars_blacklist: | 1829 | for var in vars_disallowed: |
1808 | configvars = configvars.exclude(name = var) | 1830 | configvars = configvars.exclude(name = var) |
1809 | 1831 | ||
1810 | context = { | 1832 | context = { |
@@ -1812,7 +1834,7 @@ if True: | |||
1812 | 'configvars': configvars, | 1834 | 'configvars': configvars, |
1813 | 'vars_managed': vars_managed, | 1835 | 'vars_managed': vars_managed, |
1814 | 'vars_fstypes': vars_fstypes, | 1836 | 'vars_fstypes': vars_fstypes, |
1815 | 'vars_blacklist': vars_blacklist, | 1837 | 'vars_disallowed': vars_disallowed, |
1816 | } | 1838 | } |
1817 | 1839 | ||
1818 | try: | 1840 | try: |
@@ -1839,7 +1861,7 @@ if True: | |||
1839 | except ProjectVariable.DoesNotExist: | 1861 | except ProjectVariable.DoesNotExist: |
1840 | pass | 1862 | pass |
1841 | try: | 1863 | try: |
1842 | context['image_install_append'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_INSTALL_append").value | 1864 | context['image_install:append'] = ProjectVariable.objects.get(project = prj, name = "IMAGE_INSTALL:append").value |
1843 | context['image_install_append_defined'] = "1" | 1865 | context['image_install_append_defined'] = "1" |
1844 | except ProjectVariable.DoesNotExist: | 1866 | except ProjectVariable.DoesNotExist: |
1845 | pass | 1867 | pass |
@@ -1933,3 +1955,163 @@ if True: | |||
1933 | except (ObjectDoesNotExist, IOError): | 1955 | except (ObjectDoesNotExist, IOError): |
1934 | return toaster_render(request, "unavailable_artifact.html") | 1956 | return toaster_render(request, "unavailable_artifact.html") |
1935 | 1957 | ||
1958 | |||
1959 | class CommandLineBuilds(TemplateView): | ||
1960 | model = EventLogsImports | ||
1961 | template_name = 'command_line_builds.html' | ||
1962 | |||
1963 | def get_context_data(self, **kwargs): | ||
1964 | context = super(CommandLineBuilds, self).get_context_data(**kwargs) | ||
1965 | #get value from BB_DEFAULT_EVENTLOG defined in bitbake.conf | ||
1966 | eventlog = subprocess.check_output(['bitbake-getvar', 'BB_DEFAULT_EVENTLOG', '--value']) | ||
1967 | if eventlog: | ||
1968 | logs_dir = os.path.dirname(eventlog.decode().strip('\n')) | ||
1969 | files = os.listdir(logs_dir) | ||
1970 | imported_files = EventLogsImports.objects.all() | ||
1971 | files_list = [] | ||
1972 | |||
1973 | # Filter files that end with ".json" | ||
1974 | event_files = [] | ||
1975 | for file in files: | ||
1976 | if file.endswith(".json"): | ||
1977 | # because BB_DEFAULT_EVENTLOG is a directory, we need to check if the file is a valid eventlog | ||
1978 | with open("{}/{}".format(logs_dir, file)) as efile: | ||
1979 | content = efile.read() | ||
1980 | if 'allvariables' in content: | ||
1981 | event_files.append(file) | ||
1982 | |||
1983 | #build dict for template using db data | ||
1984 | for event_file in event_files: | ||
1985 | if imported_files.filter(name=event_file): | ||
1986 | files_list.append({ | ||
1987 | 'name': event_file, | ||
1988 | 'imported': True, | ||
1989 | 'build_id': imported_files.filter(name=event_file)[0].build_id, | ||
1990 | 'size': os.path.getsize("{}/{}".format(logs_dir, event_file)) | ||
1991 | }) | ||
1992 | else: | ||
1993 | files_list.append({ | ||
1994 | 'name': event_file, | ||
1995 | 'imported': False, | ||
1996 | 'build_id': None, | ||
1997 | 'size': os.path.getsize("{}/{}".format(logs_dir, event_file)) | ||
1998 | }) | ||
1999 | context['import_all'] = True | ||
2000 | |||
2001 | context['files'] = files_list | ||
2002 | context['dir'] = logs_dir | ||
2003 | else: | ||
2004 | context['files'] = [] | ||
2005 | context['dir'] = '' | ||
2006 | |||
2007 | # enable session variable | ||
2008 | if not self.request.session.get('file'): | ||
2009 | self.request.session['file'] = "" | ||
2010 | |||
2011 | context['form'] = LoadFileForm() | ||
2012 | context['project_enable'] = project_enable | ||
2013 | return context | ||
2014 | |||
2015 | def post(self, request, **kwargs): | ||
2016 | logs_dir = request.POST.get('dir') | ||
2017 | all_files = request.POST.get('all') | ||
2018 | |||
2019 | # check if a build is already in progress | ||
2020 | if Build.objects.filter(outcome=Build.IN_PROGRESS): | ||
2021 | messages.add_message( | ||
2022 | self.request, | ||
2023 | messages.ERROR, | ||
2024 | "A build is already in progress. Please wait for it to complete before starting a new build." | ||
2025 | ) | ||
2026 | return JsonResponse({'response': 'building'}) | ||
2027 | imported_files = EventLogsImports.objects.all() | ||
2028 | try: | ||
2029 | if all_files == 'true': | ||
2030 | # use of session variable to deactivate icon for builds in progress | ||
2031 | request.session['all_builds'] = True | ||
2032 | request.session.modified = True | ||
2033 | request.session.save() | ||
2034 | |||
2035 | files = ast.literal_eval(request.POST.get('file')) | ||
2036 | for file in files: | ||
2037 | if imported_files.filter(name=file.get('name')).exists(): | ||
2038 | imported_files.filter(name=file.get('name'))[0].imported = True | ||
2039 | else: | ||
2040 | with open("{}/{}".format(logs_dir, file.get('name'))) as eventfile: | ||
2041 | # load variables from the first line | ||
2042 | variables = None | ||
2043 | while line := eventfile.readline().strip(): | ||
2044 | try: | ||
2045 | variables = json.loads(line)['allvariables'] | ||
2046 | break | ||
2047 | except (KeyError, json.JSONDecodeError): | ||
2048 | continue | ||
2049 | if not variables: | ||
2050 | raise Exception("File content missing build variables") | ||
2051 | eventfile.seek(0) | ||
2052 | params = namedtuple('ConfigParams', ['observe_only'])(True) | ||
2053 | player = eventreplay.EventPlayer(eventfile, variables) | ||
2054 | |||
2055 | toasterui.main(player, player, params) | ||
2056 | event_log_import = EventLogsImports.objects.create(name=file.get('name'), imported=True) | ||
2057 | event_log_import.build_id = Build.objects.last().id | ||
2058 | event_log_import.save() | ||
2059 | else: | ||
2060 | if self.request.FILES.get('eventlog_file'): | ||
2061 | file = self.request.FILES['eventlog_file'] | ||
2062 | else: | ||
2063 | file = request.POST.get('file') | ||
2064 | # use of session variable to deactivate icon for build in progress | ||
2065 | request.session['file'] = file | ||
2066 | request.session['all_builds'] = False | ||
2067 | request.session.modified = True | ||
2068 | request.session.save() | ||
2069 | |||
2070 | if imported_files.filter(name=file).exists(): | ||
2071 | imported_files.filter(name=file)[0].imported = True | ||
2072 | else: | ||
2073 | if isinstance(file, InMemoryUploadedFile) or isinstance(file, TemporaryUploadedFile): | ||
2074 | variables = None | ||
2075 | while line := file.readline().strip(): | ||
2076 | try: | ||
2077 | variables = json.loads(line)['allvariables'] | ||
2078 | break | ||
2079 | except (KeyError, json.JSONDecodeError): | ||
2080 | continue | ||
2081 | if not variables: | ||
2082 | raise Exception("File content missing build variables") | ||
2083 | file.seek(0) | ||
2084 | params = namedtuple('ConfigParams', ['observe_only'])(True) | ||
2085 | player = eventreplay.EventPlayer(file, variables) | ||
2086 | if not os.path.exists('{}/{}'.format(logs_dir, file.name)): | ||
2087 | fs = FileSystemStorage(location=logs_dir) | ||
2088 | fs.save(file.name, file) | ||
2089 | toasterui.main(player, player, params) | ||
2090 | else: | ||
2091 | with open("{}/{}".format(logs_dir, file)) as eventfile: | ||
2092 | # load variables from the first line | ||
2093 | variables = None | ||
2094 | while line := eventfile.readline().strip(): | ||
2095 | try: | ||
2096 | variables = json.loads(line)['allvariables'] | ||
2097 | break | ||
2098 | except (KeyError, json.JSONDecodeError): | ||
2099 | continue | ||
2100 | if not variables: | ||
2101 | raise Exception("File content missing build variables") | ||
2102 | eventfile.seek(0) | ||
2103 | params = namedtuple('ConfigParams', ['observe_only'])(True) | ||
2104 | player = eventreplay.EventPlayer(eventfile, variables) | ||
2105 | toasterui.main(player, player, params) | ||
2106 | event_log_import = EventLogsImports.objects.create(name=file, imported=True) | ||
2107 | event_log_import.build_id = Build.objects.last().id | ||
2108 | event_log_import.save() | ||
2109 | request.session['file'] = "" | ||
2110 | except Exception: | ||
2111 | messages.add_message( | ||
2112 | self.request, | ||
2113 | messages.ERROR, | ||
2114 | "The file content is not in the correct format. Update file content or upload a different file." | ||
2115 | ) | ||
2116 | return HttpResponseRedirect("/toastergui/cmdline/") | ||
2117 | return HttpResponseRedirect('/toastergui/builds/') | ||