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