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