blob: 718e1441dc41aaddf8faefac2bb64b68289cea89 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001from django.core.management.base import NoArgsCommand, CommandError
2from django.db import transaction
3from orm.models import Build, ToasterSetting, LogMessage, Target
4from bldcontrol.bbcontroller import getBuildEnvironmentController, ShellCmdException, BuildSetupException
5from bldcontrol.models import BuildRequest, BuildEnvironment, BRError, BRVariable
6import os
7import logging
8
9logger = logging.getLogger("ToasterScheduler")
10
11class Command(NoArgsCommand):
12 args = ""
13 help = "Schedules and executes build requests as possible. Does not return (interrupt with Ctrl-C)"
14
15
16 @transaction.commit_on_success
17 def _selectBuildEnvironment(self):
18 bec = getBuildEnvironmentController(lock = BuildEnvironment.LOCK_FREE)
19 bec.be.lock = BuildEnvironment.LOCK_LOCK
20 bec.be.save()
21 return bec
22
23 @transaction.commit_on_success
24 def _selectBuildRequest(self):
25 br = BuildRequest.objects.filter(state = BuildRequest.REQ_QUEUED).order_by('pk')[0]
26 br.state = BuildRequest.REQ_INPROGRESS
27 br.save()
28 return br
29
30 def schedule(self):
31 import traceback
32 try:
33 br = None
34 try:
35 # select the build environment and the request to build
36 br = self._selectBuildRequest()
37 except IndexError as e:
38 #logger.debug("runbuilds: No build request")
39 return
40 try:
41 bec = self._selectBuildEnvironment()
42 except IndexError as e:
43 # we could not find a BEC; postpone the BR
44 br.state = BuildRequest.REQ_QUEUED
45 br.save()
46 logger.debug("runbuilds: No build env")
47 return
48
49 logger.debug("runbuilds: starting build %s, environment %s" % (br, bec.be))
50
51 # write the build identification variable
52 BRVariable.objects.create(req = br, name="TOASTER_BRBE", value="%d:%d" % (br.pk, bec.be.pk))
53
54 # let the build request know where it is being executed
55 br.environment = bec.be
56 br.save()
57
58 # this triggers an async build
59 bec.triggerBuild(br.brbitbake_set.all(), br.brlayer_set.all(), br.brvariable_set.all(), br.brtarget_set.all())
60
61 except Exception as e:
62 logger.error("runbuilds: Error launching build %s" % e)
63 traceback.print_exc(e)
64 if "[Errno 111] Connection refused" in str(e):
65 # Connection refused, read toaster_server.out
66 errmsg = bec.readServerLogFile()
67 else:
68 errmsg = str(e)
69
70 BRError.objects.create(req = br,
71 errtype = str(type(e)),
72 errmsg = errmsg,
73 traceback = traceback.format_exc(e))
74 br.state = BuildRequest.REQ_FAILED
75 br.save()
76 bec.be.lock = BuildEnvironment.LOCK_FREE
77 bec.be.save()
78
79 def archive(self):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080 for br in BuildRequest.objects.filter(state = BuildRequest.REQ_ARCHIVE):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050081 if br.build == None:
82 br.state = BuildRequest.REQ_FAILED
Patrick Williamsd7e96312015-09-22 08:09:05 -050083 else:
84 br.state = BuildRequest.REQ_COMPLETED
Patrick Williamsc124f4f2015-09-15 14:41:29 -050085 br.save()
86
87 def cleanup(self):
88 from django.utils import timezone
89 from datetime import timedelta
90 # environments locked for more than 30 seconds - they should be unlocked
91 BuildEnvironment.objects.filter(buildrequest__state__in=[BuildRequest.REQ_FAILED, BuildRequest.REQ_COMPLETED]).filter(lock=BuildEnvironment.LOCK_LOCK).filter(updated__lt = timezone.now() - timedelta(seconds = 30)).update(lock = BuildEnvironment.LOCK_FREE)
92
93
94 # update all Builds that failed to start
95
96 for br in BuildRequest.objects.filter(state = BuildRequest.REQ_FAILED, build__outcome = Build.IN_PROGRESS):
97 # transpose the launch errors in ToasterExceptions
98 br.build.outcome = Build.FAILED
99 for brerror in br.brerror_set.all():
100 logger.debug("Saving error %s" % brerror)
101 LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg)
102 br.build.save()
103
104 # we don't have a true build object here; hence, toasterui didn't have a change to release the BE lock
105 br.environment.lock = BuildEnvironment.LOCK_FREE
106 br.environment.save()
107
108
109
110 # update all BuildRequests without a build created
111 for br in BuildRequest.objects.filter(build = None):
112 br.build = Build.objects.create(project = br.project, completed_on = br.updated, started_on = br.created)
113 br.build.outcome = Build.FAILED
114 try:
115 br.build.machine = br.brvariable_set.get(name='MACHINE').value
116 except BRVariable.DoesNotExist:
117 pass
118 br.save()
119 # transpose target information
120 for brtarget in br.brtarget_set.all():
121 Target.objects.create(build = br.build, target= brtarget.target)
122 # transpose the launch errors in ToasterExceptions
123 for brerror in br.brerror_set.all():
124 LogMessage.objects.create(build = br.build, level = LogMessage.EXCEPTION, message = brerror.errmsg)
125
126 br.build.save()
127 pass
128
129
130 def handle_noargs(self, **options):
131 self.cleanup()
132 self.archive()
133 self.schedule()