summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/toaster/bldcontrol/bbcontroller.py
diff options
context:
space:
mode:
authorAlexandru DAMIAN <alexandru.damian@intel.com>2014-06-12 12:57:22 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2014-06-13 11:55:34 +0100
commite16352220572835ff2185cf992518fb4f3b2de0e (patch)
tree34ed801e6883d1ebd8e00d4431785dd5e7255039 /bitbake/lib/toaster/bldcontrol/bbcontroller.py
parent87b99274e9c90101ec9d4c49ce0874bcb85f7746 (diff)
downloadpoky-e16352220572835ff2185cf992518fb4f3b2de0e.tar.gz
bitbake: toaster: build control functionality
We add the build control functionality to toaster. * The bldcontrol application gains bbcontroller classes that know how to manage a localhost build environment. * The toaster UI now detects it is running under build environment controller, and update the build controller database and will shut down the bitbake server once the build is complete. * The toaster script can now run in standalone mode, launching the build controller and the web interface instead of just monitoring the build, as in the interactive mode. * A fixture with the default build controller entry for localhost is provided. [YOCTO #5490] [YOCTO #5491] [YOCTO #5492] [YOCTO #5493] [YOCTO #5494] [YOCTO #5537] (Bitbake rev: 10988bd77c8c7cefad3b88744bc5d8a7e3c1f4cf) Signed-off-by: Alexandru DAMIAN <alexandru.damian@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/toaster/bldcontrol/bbcontroller.py')
-rw-r--r--bitbake/lib/toaster/bldcontrol/bbcontroller.py239
1 files changed, 239 insertions, 0 deletions
diff --git a/bitbake/lib/toaster/bldcontrol/bbcontroller.py b/bitbake/lib/toaster/bldcontrol/bbcontroller.py
new file mode 100644
index 0000000000..d2b2a236bd
--- /dev/null
+++ b/bitbake/lib/toaster/bldcontrol/bbcontroller.py
@@ -0,0 +1,239 @@
1#
2# ex:ts=4:sw=4:sts=4:et
3# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
4#
5# BitBake Toaster Implementation
6#
7# Copyright (C) 2014 Intel Corporation
8#
9# This program is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License version 2 as
11# published by the Free Software Foundation.
12#
13# This program is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16# GNU General Public License for more details.
17#
18# You should have received a copy of the GNU General Public License along
19# with this program; if not, write to the Free Software Foundation, Inc.,
20# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
22
23import os
24import sys
25import re
26from django.db import transaction
27from django.db.models import Q
28from bldcontrol.models import BuildEnvironment, BRLayer, BRVariable, BRTarget
29import subprocess
30
31from toastermain import settings
32
33
34# load Bitbake components
35path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
36sys.path.insert(0, path)
37import bb.server.xmlrpc
38
39class BitbakeController(object):
40 """ This is the basic class that controlls a bitbake server.
41 It is outside the scope of this class on how the server is started and aquired
42 """
43
44 def __init__(self, connection):
45 self.connection = connection
46
47 def _runCommand(self, command):
48 result, error = self.connection.connection.runCommand(command)
49 if error:
50 raise Exception(error)
51 return result
52
53 def disconnect(self):
54 return self.connection.removeClient()
55
56 def setVariable(self, name, value):
57 return self._runCommand(["setVariable", name, value])
58
59 def build(self, targets, task = None):
60 if task is None:
61 task = "build"
62 return self._runCommand(["buildTargets", targets, task])
63
64
65
66def getBuildEnvironmentController(**kwargs):
67 """ Gets you a BuildEnvironmentController that encapsulates a build environment,
68 based on the query dictionary sent in.
69
70 This is used to retrieve, for example, the currently running BE from inside
71 the toaster UI, or find a new BE to start a new build in it.
72
73 The return object MUST always be a BuildEnvironmentController.
74 """
75 be = BuildEnvironment.objects.filter(Q(**kwargs))[0]
76 if be.betype == BuildEnvironment.TYPE_LOCAL:
77 return LocalhostBEController(be)
78 elif be.betype == BuildEnvironment.TYPE_SSH:
79 return SSHBEController(be)
80 else:
81 raise Exception("FIXME: Implement BEC for type %s" % str(be.betype))
82
83
84
85class BuildEnvironmentController(object):
86 """ BuildEnvironmentController (BEC) is the abstract class that defines the operations that MUST
87 or SHOULD be supported by a Build Environment. It is used to establish the framework, and must
88 not be instantiated directly by the user.
89
90 Use the "getBuildEnvironmentController()" function to get a working BEC for your remote.
91
92 How the BuildEnvironments are discovered is outside the scope of this class.
93
94 You must derive this class to teach Toaster how to operate in your own infrastructure.
95 We provide some specific BuildEnvironmentController classes that can be used either to
96 directly set-up Toaster infrastructure, or as a model for your own infrastructure set:
97
98 * Localhost controller will run the Toaster BE on the same account as the web server
99 (current user if you are using the the Django development web server)
100 on the local machine, with the "build/" directory under the "poky/" source checkout directory.
101 Bash is expected to be available.
102
103 * SSH controller will run the Toaster BE on a remote machine, where the current user
104 can connect without raise Exception("FIXME: implement")word (set up with either ssh-agent or raise Exception("FIXME: implement")phrase-less key authentication)
105
106 """
107 def __init__(self, be):
108 """ Takes a BuildEnvironment object as parameter that points to the settings of the BE.
109 """
110 self.be = be
111 self.connection = None
112
113 def startBBServer(self):
114 """ Starts a BB server with Toaster toasterui set up to record the builds, an no controlling UI.
115 After this method executes, self.be bbaddress/bbport MUST point to a running and free server,
116 and the bbstate MUST be updated to "started".
117 """
118 raise Exception("Must override in order to actually start the BB server")
119
120 def stopBBServer(self):
121 """ Stops the currently running BB server.
122 The bbstate MUST be updated to "stopped".
123 self.connection must be none.
124 """
125
126 def setLayers(self,ls):
127 """ Sets the layer variables in the config file, after validating local layer paths.
128 The layer paths must be in a list of BRLayer object
129 """
130 raise Exception("Must override setLayers")
131
132
133 def getBBController(self):
134 """ returns a BitbakeController to an already started server; this is the point where the server
135 starts if needed; or reconnects to the server if we can
136 """
137 if not self.connection:
138 self.startBBServer()
139 self.be.lock = BuildEnvironment.LOCK_RUNNING
140 self.be.save()
141
142 server = bb.server.xmlrpc.BitBakeXMLRPCClient()
143 server.initServer()
144 server.saveConnectionDetails("%s:%s" % (self.be.bbaddress, self.be.bbport))
145 self.connection = server.establishConnection([])
146
147 self.be.bbtoken = self.connection.transport.connection_token
148 self.be.save()
149
150 return BitbakeController(self.connection)
151
152 def getArtifact(path):
153 """ This call returns an artifact identified by the 'path'. How 'path' is interpreted as
154 up to the implementing BEC. The return MUST be a REST URL where a GET will actually return
155 the content of the artifact, e.g. for use as a "download link" in a web UI.
156 """
157 raise Exception("Must return the REST URL of the artifact")
158
159 def release(self):
160 """ This stops the server and releases any resources. After this point, all resources
161 are un-available for further reference
162 """
163 raise Exception("Must override BE release")
164
165class ShellCmdException(Exception):
166 pass
167
168class LocalhostBEController(BuildEnvironmentController):
169 """ Implementation of the BuildEnvironmentController for the localhost;
170 this controller manages the default build directory,
171 the server setup and system start and stop for the localhost-type build environment
172
173 The address field is used as working directory; if not set, the build/ directory
174 is created
175 """
176
177 def __init__(self, be):
178 super(LocalhostBEController, self).__init__(be)
179 from os.path import dirname as DN
180 self.cwd = DN(DN(DN(DN(DN(os.path.realpath(__file__))))))
181 if self.be.address is None or len(self.be.address) == 0:
182 self.be.address = "build"
183 self.be.save()
184 self.bwd = self.be.address
185 self.dburl = settings.getDATABASE_URL()
186
187 # transform relative paths to absolute ones
188 if not self.bwd.startswith("/"):
189 self.bwd = os.path.join(self.cwd, self.bwd)
190 self._createBE()
191
192 def _shellcmd(self, command):
193 p = subprocess.Popen(command, cwd=self.cwd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
194 (out,err) = p.communicate()
195 if p.returncode:
196 if len(err) == 0:
197 err = "command: %s" % command
198 else:
199 err = "command: %s \n%s" % (command, err)
200 raise ShellCmdException(err)
201 else:
202 return out
203
204 def _createBE(self):
205 assert self.cwd and os.path.exists(self.cwd)
206 self._shellcmd("bash -c \"source %s/oe-init-build-env %s\"" % (self.cwd, self.bwd))
207
208 def startBBServer(self):
209 assert self.cwd and os.path.exists(self.cwd)
210 print self._shellcmd("bash -c \"source %s/oe-init-build-env %s && DATABASE_URL=%s source toaster start noweb && sleep 1\"" % (self.cwd, self.bwd, self.dburl))
211 # FIXME unfortunate sleep 1 - we need to make sure that bbserver is started and the toaster ui is connected
212 # but since they start async without any return, we just wait a bit
213 print "Started server"
214 assert self.cwd and os.path.exists(self.bwd)
215 self.be.bbaddress = "localhost"
216 self.be.bbport = "8200"
217 self.be.bbstate = BuildEnvironment.SERVER_STARTED
218 self.be.save()
219
220 def stopBBServer(self):
221 assert self.cwd
222 print self._shellcmd("bash -c \"source %s/oe-init-build-env %s && %s source toaster stop\"" %
223 (self.cwd, self.bwd, (lambda: "" if self.be.bbtoken is None else "BBTOKEN=%s" % self.be.bbtoken)()))
224 self.be.bbstate = BuildEnvironment.SERVER_STOPPED
225 self.be.save()
226 print "Stopped server"
227
228 def setLayers(self, layers):
229 assert self.cwd is not None
230 layerconf = os.path.join(self.bwd, "conf/bblayers.conf")
231 if not os.path.exists(layerconf):
232 raise Exception("BE is not consistent: bblayers.conf file missing at ", layerconf)
233 return True
234
235 def release(self):
236 assert self.cwd and os.path.exists(self.bwd)
237 import shutil
238 shutil.rmtree(os.path.join(self.cwd, "build"))
239 assert not os.path.exists(self.bwd)