1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# BitBake Toaster Implementation 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun# Copyright (C) 2014 Intel Corporation 5*4882a593Smuzhiyun# 6*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 7*4882a593Smuzhiyun# 8*4882a593Smuzhiyun 9*4882a593Smuzhiyunimport os 10*4882a593Smuzhiyunimport sys 11*4882a593Smuzhiyunfrom django.db.models import Q 12*4882a593Smuzhiyunfrom bldcontrol.models import BuildEnvironment, BRLayer, BRBitbake 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun# load Bitbake components 15*4882a593Smuzhiyunpath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))) 16*4882a593Smuzhiyunsys.path.insert(0, path) 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunclass BitbakeController(object): 19*4882a593Smuzhiyun """ This is the basic class that controlls a bitbake server. 20*4882a593Smuzhiyun It is outside the scope of this class on how the server is started and aquired 21*4882a593Smuzhiyun """ 22*4882a593Smuzhiyun 23*4882a593Smuzhiyun def __init__(self, be): 24*4882a593Smuzhiyun import bb.server.xmlrpcclient 25*4882a593Smuzhiyun self.connection = bb.server.xmlrpcclient._create_server(be.bbaddress, 26*4882a593Smuzhiyun int(be.bbport))[0] 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun def _runCommand(self, command): 29*4882a593Smuzhiyun result, error = self.connection.runCommand(command) 30*4882a593Smuzhiyun if error: 31*4882a593Smuzhiyun raise Exception(error) 32*4882a593Smuzhiyun return result 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun def disconnect(self): 35*4882a593Smuzhiyun return self.connection.removeClient() 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun def setVariable(self, name, value): 38*4882a593Smuzhiyun return self._runCommand(["setVariable", name, value]) 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun def getVariable(self, name): 41*4882a593Smuzhiyun return self._runCommand(["getVariable", name]) 42*4882a593Smuzhiyun 43*4882a593Smuzhiyun def triggerEvent(self, event): 44*4882a593Smuzhiyun return self._runCommand(["triggerEvent", event]) 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun def build(self, targets, task = None): 47*4882a593Smuzhiyun if task is None: 48*4882a593Smuzhiyun task = "build" 49*4882a593Smuzhiyun return self._runCommand(["buildTargets", targets, task]) 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun def forceShutDown(self): 52*4882a593Smuzhiyun return self._runCommand(["stateForceShutdown"]) 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun 56*4882a593Smuzhiyundef getBuildEnvironmentController(**kwargs): 57*4882a593Smuzhiyun """ Gets you a BuildEnvironmentController that encapsulates a build environment, 58*4882a593Smuzhiyun based on the query dictionary sent in. 59*4882a593Smuzhiyun 60*4882a593Smuzhiyun This is used to retrieve, for example, the currently running BE from inside 61*4882a593Smuzhiyun the toaster UI, or find a new BE to start a new build in it. 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun The return object MUST always be a BuildEnvironmentController. 64*4882a593Smuzhiyun """ 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun from bldcontrol.localhostbecontroller import LocalhostBEController 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun be = BuildEnvironment.objects.filter(Q(**kwargs))[0] 69*4882a593Smuzhiyun if be.betype == BuildEnvironment.TYPE_LOCAL: 70*4882a593Smuzhiyun return LocalhostBEController(be) 71*4882a593Smuzhiyun else: 72*4882a593Smuzhiyun raise Exception("FIXME: Implement BEC for type %s" % str(be.betype)) 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun 75*4882a593Smuzhiyunclass BuildEnvironmentController(object): 76*4882a593Smuzhiyun """ BuildEnvironmentController (BEC) is the abstract class that defines the operations that MUST 77*4882a593Smuzhiyun or SHOULD be supported by a Build Environment. It is used to establish the framework, and must 78*4882a593Smuzhiyun not be instantiated directly by the user. 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun Use the "getBuildEnvironmentController()" function to get a working BEC for your remote. 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun How the BuildEnvironments are discovered is outside the scope of this class. 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun You must derive this class to teach Toaster how to operate in your own infrastructure. 85*4882a593Smuzhiyun We provide some specific BuildEnvironmentController classes that can be used either to 86*4882a593Smuzhiyun directly set-up Toaster infrastructure, or as a model for your own infrastructure set: 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun * Localhost controller will run the Toaster BE on the same account as the web server 89*4882a593Smuzhiyun (current user if you are using the the Django development web server) 90*4882a593Smuzhiyun on the local machine, with the "build/" directory under the "poky/" source checkout directory. 91*4882a593Smuzhiyun Bash is expected to be available. 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun """ 94*4882a593Smuzhiyun def __init__(self, be): 95*4882a593Smuzhiyun """ Takes a BuildEnvironment object as parameter that points to the settings of the BE. 96*4882a593Smuzhiyun """ 97*4882a593Smuzhiyun self.be = be 98*4882a593Smuzhiyun self.connection = None 99*4882a593Smuzhiyun 100*4882a593Smuzhiyun def setLayers(self, bitbake, ls): 101*4882a593Smuzhiyun """ Checks-out bitbake executor and layers from git repositories. 102*4882a593Smuzhiyun Sets the layer variables in the config file, after validating local layer paths. 103*4882a593Smuzhiyun bitbake must be a single BRBitbake instance 104*4882a593Smuzhiyun The layer paths must be in a list of BRLayer object 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun a word of attention: by convention, the first layer for any build will be poky! 107*4882a593Smuzhiyun """ 108*4882a593Smuzhiyun raise NotImplementedError("FIXME: Must override setLayers") 109*4882a593Smuzhiyun 110*4882a593Smuzhiyun def getArtifact(self, path): 111*4882a593Smuzhiyun """ This call returns an artifact identified by the 'path'. How 'path' is interpreted as 112*4882a593Smuzhiyun up to the implementing BEC. The return MUST be a REST URL where a GET will actually return 113*4882a593Smuzhiyun the content of the artifact, e.g. for use as a "download link" in a web UI. 114*4882a593Smuzhiyun """ 115*4882a593Smuzhiyun raise NotImplementedError("Must return the REST URL of the artifact") 116*4882a593Smuzhiyun 117*4882a593Smuzhiyun def triggerBuild(self, bitbake, layers, variables, targets): 118*4882a593Smuzhiyun raise NotImplementedError("Must override BE release") 119*4882a593Smuzhiyun 120*4882a593Smuzhiyunclass ShellCmdException(Exception): 121*4882a593Smuzhiyun pass 122*4882a593Smuzhiyun 123*4882a593Smuzhiyun 124*4882a593Smuzhiyunclass BuildSetupException(Exception): 125*4882a593Smuzhiyun pass 126*4882a593Smuzhiyun 127