Source code walk-through¶
Please see the README file in the root directory of Beaker’s source tree for a detailed description of its layout.
Lab controller¶
The lab controller is the intermediary point of communication between the lab machines, and the beaker server. It provides entry points for the following processes:
- beaker-proxy
- beaker-watchdog
- beaker-transfer
- beaker-provision
These processes authenticate themselves using the credentials found in
/etc/beaker/labcontroller.conf
.
beaker-proxy¶
beaker-proxy is a process that binds to an open unprivileged port on the lab controller. It provides an xmlrpc server that more or less forwards calls made to it (from lab machines) onto the beaker server.
Here is a simple example of a typical controller from
bkr.labcontroller.proxy
:
def task_info(self,
qtask_id):
""" accepts qualified task_id J:213 RS:1234 R:312 T:1234 etc.. Returns dict with status """
logger.debug("task_info %s", qtask_id)
return self.hub.taskactions.task_info(qtask_id)
This is quite straightforward. An xmlrpc call would be made to the the
lab controller onto port 8000 (the default for beaker-proxy), with the
method task_info
and the qtask id
. The task_info()
method
then calls and returns bkr.server.taskactions.task_info
. The hub
variable is a HubProxy
class from bkr.common.hub
. HubProxy
in
turn is merely a thin wrapper over xmlrpclib.ServerProxy
that adds
session based authentication management.
beaker-transfer¶
When provisioning a system in beaker, Beaker transfers various log files to the lab controller as a matter of course. Even more log files are created when running an actual recipe. By default, these logs are uploaded from the test machine to the lab controller.
Using the CACHE
and ARCHIVE_*
variables in
labcontroller.conf
, you can specify a remote server where the log
files can be moved to. Once configured, beaker-transfer is responsible
for moving these files from the lab controller to the remote server.
beaker-watchdog¶
To ensure that recipes do not run on for longer than what they are expected to, Beaker uses a watchdog process. This process keeps track of running recipes on all test systems attached to a particular lab controller. If a recipe is running for longer than what the server has specified it can run for, the watchdog aborts the recipe.
Here is a breakdown of how the process works:
- Recipe progresses up to the Scheduled stage, and a watchdog is created for the recipe.
- Recipe goes into
Waiting
stage and (amongst others things) a reboot command is sent to the lab controller. - System is rebooted and then an RPC is made to the server to start the first task, and create a kill time for the watchdog.
- For each successive task that is run in the recipe, the harness
extends the kill time of the watchdog by the expected run time
specified by the
TestTime
value in testinfo.desc. - If a task runs beyond it’s kill time, the harness will first try and abort the job and continue onto the next test. If the system crashes or panics and the harness isn’t able to recover then beaker-watchdog will abort the recipe (and any remaining tasks). The time between the harness watchdog (also known as local watchdog) and beaker-watchdog (also known as external watchdog) is ten minutes.
beaker-provision¶
It is the responsibility of beaker-provision to handle the provisioning of a system. Its main duties are creating boot loader images and power cycling systems.
Here is a breakdown of how this process works:
- Beaker server generates and serves a kickstart file.
- Beaker server sends a command to beaker-provision with the path to the distro tree, kernel options, and a link to the kickstart file. It also sends a command to power cycle the system.
- From these details, beaker-provision generates the relevant boot loader configuration file, and then power cycles the test system.
- The system boots and starts its install.
Server¶
The main focus of the beaker server is to maintain a distro and system inventory, run tasks against this inventory, and display the results of those tasks. Any interaction with this inventory must be via the server. For further details of the design of Beaker’s services, please see the relevant docs.
Beaker is developed to run in Red Hat Enterprise Linux 7 (RHEL7). Versions previous to 27 were designed for RHEL5 and versions previous to 0.7 were designed for RHEL5. Although it may be technically possible to run Beaker on other distributions, package dependencies and other issues may ensue.
The Beaker server is a web application that is currently a hybrid of TurboGears(TG) 1.x and Flask as we migrate to Flask entirely. Here is a quick breakdown of the major frameworks/libraries and how Beaker server utilizes them.
- TurboGears 1.x
- TurboGears (TG) is a “front-to-back” web meta-framework. TurboGears 1.x is no longer under active development, although the documentation is still available on the TurboGears website. Besides the core modules, TG’s widgets are used for its pre built templates and display functionality. Templates are written in Kid. A number of Beaker’s own custom widgets are also built upon TG widgets.
- Kid
- Provides the templating language for hand written templates, as well as TG
widgets. Kid is no longer under active development. Beaker’s kid templates
rely on some of the TurboGears standard variables and functions as well as custom
variables defined in
bkr.server.stdvars
. - SQLAlchemy
- An ORM database interface. Used exclusively for all access to Beaker’s database. Note that Beaker uses some TG database modules, but these are thin wrappers over SQLAlchemy.
- Flask/CherryPy 2
- Provides resource routing, handling of request and response objects. CherryPy 2 is no longer under active development. Starting with Beaker 0.15, Flask will be used to perform CherryPy’s functions and hence while Beaker still uses CherryPy, any new code should use Flask instead. The existing CherryPy controllers are used as fallback handlers upon recieving a 404 error from Flask.
- Javascript libraries/frameworks
- MochiKit is bundled with TG, however JQuery is heavily used alongside it. Starting with Beaker 0.15, Backbone is used to write client side widgets.
- CSS
- Starting with Beaker 0.15, Bootstrap is used for the Web UI front-end.
- Alembic
- Alembic provides for the creation, management, and invocation of change management scripts for a relational database, using SQLAlchemy as the underlying engine.
As a result of being built on TG, Beaker is an MVC inspired application. Whilst it mostly follows TG conventions, Beaker does sometimes go outside of these when it’s appropriate (and advantageous) to do so.
Model¶
The bkr.server.model
module primarily consists of Object Relational
Mapped (ORM) classes. Fundamentally, these are user defined python
classes associated to database tables, the objects of which are mapped
to rows in the related table.
Controllers¶
A controller is called when a HTTP request is made. The URL is
translated to a particular controller. Starting with Beaker 0.15,
Flask handles the routing of an URL to the appropriate view method.
(Previously, CherryPy was used). For example, a call to
http://beaker.example.com/tasks/executed will call the
bkr.server.tasks.executed
method.
Generally speaking, Beaker controllers are grouped into a single module
for either one of two purposes. Either because the controller provides
various modifies and accessors for a single ORM class (e.g the
bkr.server.system
module contains various accessor and modifier
methods for the System
class), or for the purpose of supporting a
single page view and any associated actions (e.g the
bkr.server.preferences
module contains all of the views and actions
needed for viewing and updating users preferences).
Sometimes a mix of these two can be found, and this is also fine (i.e
bkr.server.tasks
contains controllers for displaying and searching
on task details, as well as methods designed to be called remotely to
provide details of Task
objects).
View¶
Both Kid templates and TG widgets are used to support the ‘View’ of MVC. Beaker uses TG widgets to provide re-usability of commonly rendered page elements. A widget encapsulates the template to be rendered, as well as any javascript and CSS files that are needed by that template. Generally speaking, creating a widget is preferable to using a controller + template due to the re-usability of a widget. However there is no hard and fast rule in regards to this.
As well as standard widgets being provided by TG, Beaker also implements
many of its own widgets in the bkr.server.widgets
module.
Templates are used in one of two ways; by specifying a template in an ‘expose’ decorator; by setting the template variable in a widget, and then calling that widget’s ‘display’ method. Examples of both will be shown in the patch walk-through.
Client¶
The beaker-client package provides shell commands that makes varied
calls to the server. The format of the calls are
bkr <cmd> <options>
, where <cmd>
corresponds to a module in the
bkr/client/commands
directory. The modules of the corresponding code
is a normalized version of the same name as the command, but with the
prefix cmd_. For example, bkr job-list
will call the run()
method of the bkr.client.commands.cmd_job_list
module.
This functionality is provided by the Command
class of the
bkr.client.command
module, of which all Beaker commands inherit
(indirectly or directly). This class also provides the authentication
with the Beaker server via the same bkr classes as the lab controller.