ReferencePlatforms/Buildserver
Contents
Buildserver Ref Image
This document describes how to create a "Build server" ref image. More info is in bug#385911.
Copy Linux Buildbot ref image
- VM->Clone
- Next
- If possible, use a clean snapshot of a machine, otherwise choose "The current state" and click Next.
- 'Create a full clone', Next.
- Choose a name and location and click Next.
- Finish
Add a 10GB drive
- VM->Settings
- Click Add
- Select 'Hard Disk' and click Next
- "Create a new virtual disk" and click Next
- SCSI, click Next
- Disk Size: 10GB, click Next
- Choose location, Finish
Create a single partition on the new hard drive (/dev/sdb) and run the following commands:
mkdir /cvs mkfs -t ext3 -j /dev/sdb1 echo "/dev/sdb1 /cvs ext3 defaults 0 0" >> /etc/fstab mount -a
Install and setup CVSD
CVSD is a wrapper for pserver that allows it to run in a rootjail. Here are the installation instructions:
wget http://ch.tudelft.nl/~arthur/cvsd/cvsd-1.0.13.tar.gz tar -zvxf cvsd-1.0.13.tar.gz cd cvsd-1.0.13 ./configure make make install
Setup CVSD:
mkdir /etc/cvsd cp /usr/local/etc/cvsd/cvsd.conf /etc/cvsd cp /usr/local/etc/init.d/cvsd /etc/init.d chkconfig --add cvsd
Edit /etc/init.d/cvsd and make sure 'CVSD_CFG' is set to '/etc/cvsd/cvsd.conf'. Edit /etc/cvsd/cvsd.conf and change the following parameters:
RootJail /cvs Listen * 2401 Repos /cvsroot CvsArgs -u
Run these commands:
cvsd-buildroot /cvs adduser cvsd
Install CVS
CVS must be patched to work in this setup.
wget http://ftp.gnu.org/non-gnu/cvs/source/stable/1.11.22/cvs-1.11.22.tar.bz2 wget http://people.mozilla.com/~bhearsum/Build/Misc/cvs.noreadlocks.patch tar -jvxf cvs-1.11.22.tar.bz2 cd cvs-1.11.22/src patch -p0 < ../../cvs.noreadlocks.patch cd ../ ./configure --prefix=/cvs make make install
Rsync cvs-mirror.m.o
These instructions taken from How to Create a CVS Mirror:
Create a directory for the repository
mkdir /cvs/cvsroot
Add that directory to your cvsd.conf
echo "/cvsroot" >> /etc/cvsd/cvsd.conf
Create an 'rsync-excludes' file to ignore history, users
echo "CVSROOT/passwd" > /cvs/etc/rsync-excludes echo "CVSROOT/writers" >> /cvs/etc/rsync-excludes echo "CVSROOT/history" >> /cvs/etc/rsync-excludes echo "CVSROOT/history*" >> /cvs/etc/rsync-excludes
Copy this script that will perform an rsync of the Mozilla CVS
/etc/init.d/cvsd stop rsync -q -az --delete --exclude-from=/cvs/etc/rsync-excludes cvs-mirror.mozilla.org::mozilla /cvs/cvsroot /etc/init.d/cvsd start
If you want to continually update your mirror you should create a cron job to do so. Otherwise you can run the above script at any time to do it manually.
Create a buildbot master
mkdir -p /buildbot/default chown -R buildbot /buildbot su - buildbot cd /buildbot/default buildbot create-master . mv Makefile.sample Makefile rm master.cfg.sample
master.cfg:
# -*- python -*- # ex: set syntax=python: # This is a sample buildmaster config file. It must be installed as # 'master.cfg' in your buildmaster's base directory (although the filename # can be changed with the --basedir option to 'mktap buildbot master'). # It has one job: define a dictionary named BuildmasterConfig. This # dictionary has a variety of keys to control different aspects of the # buildmaster. They are documented in docs/config.xhtml . # This is the dictionary that the buildmaster pays attention to. We also use # a shorter alias to save typing. c = BuildmasterConfig = {} ####### PROJECT IDENTITY c['projectName'] = "VMware Team Buildbot" c['slavePortnum'] = 9990 ####### BUILDSLAVES # the 'bots' list defines the set of allowable buildslaves. Each element is a # tuple of bot-name and bot-password. These correspond to values given to the # buildslave's mktap invocation. c['bots'] = [("win32", "w1nbu1ld3r"), ("linux", "l1nuxbu1ld3r")] ####### STATUS PLUGINS from buildbot.status import html c['status'] = [] c['status'].append(html.Waterfall(http_port=8810, allowForce=True)) ####### SOURCES c['sources'] = [] ####### SCHEDULERS c['schedulers'] = [] ####### BUILDERS c['builders'] = [] import mozbuild reload(mozbuild) from mozbuild import * from buildbot.process import factory from buildbot.steps.shell import Configure,Compile s = factory.s ## unix builder trunk_unix_steps = [ s(MozillaCheckoutClientMk, workdir=".", cvsroot=":pserver:anonymous@10.0.0.1:/cvsroot"), s(MozillaClientMkPull, workdir="mozilla"), s(Configure, workdir="mozilla", command=["./configure", "--enable-application=browser"]), s(Compile, workdir="mozilla"), ] trunk_unix_builder = { 'name': "Build Team Default Unix Builder", 'slavenames': ['linux'], 'builddir': "trunk-unix", 'factory': factory.BuildFactory(trunk_unix_steps), 'category': "default", } c['builders'].append(trunk_unix_builder) ## win32 builder trunk_win32_steps = [ s(MozillaCheckoutClientMk, workdir=".", env=MozillaEnvironments['vc8_express']), s(MozillaClientMkPull, workdir="mozilla", env=MozillaEnvironments['vc8_express']), s(Configure, workdir="mozilla", env=MozillaEnvironments['vc8_express'], command=["bash", "-f", "configure", "--enable-application=browser", ]), s(Compile, workdir="mozilla", env=MozillaEnvironments['vc8_express']) ] trunk_win32_builder = { 'name': "Build Team Default Win32 Builder", 'slavenames': ['win32'], 'builddir': "trunk-win32", 'factory': factory.BuildFactory(trunk_win32_steps), 'category': "default" } c['builders'].append(trunk_win32_builder) ## END OF DEFAULT MASTER.CFG
mozbuild.py:
# -*- Python -*- from buildbot.process import step from buildbot.process.step import ShellCommand MozillaEnvironments = { } # standard vc8 express build env; vc8 normal will be very similar, just different # platform SDK location. we can build both from one generic template. MozillaEnvironments['vc8_express'] = { "MOZ_TOOLS": '/cygdrive/d/moztools', "VSINSTALLDIR": 'C:\\Program Files\\Microsoft Visual Studio 8', "VS80COMMTOOLS": 'C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\Tools\\', "VCINSTALLDIR": 'C:\\Program Files\\Microsoft Visual Studio 8\\VC', "FrameworkDir": 'C:\\WINDOWS\\Microsoft.NET\\Framework', "FrameworkVersion": 'v2.0.50727', "FrameworkSDKDir": 'C:\\Program Files\\Microsoft Visual Studio 8\\SDK\\v2.0', "DevEnvDir": "C:\\Program Files\\Microsoft Visual Studio 8\\VC\\Common7\\IDE", "MSVCDir": 'C:\\Program Files\\Microsoft Visual Studio 8\\VC', "PATH": 'C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\IDE;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\bin;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\PlatformSDK\\bin;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\Tools;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\Common7\\Tools\\bin;' + \ 'd:\\moztools\\bin;' + \ 'd:\\cygwin\\bin;' + \ 'd:\\buildtools\\NSIS;' + \ 'd:\\buildtools\\7-zip;' + \ 'd:\\buildtools\\upx;' + \ 'C:\\WINDOWS\system32;', "INCLUDE": 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\ATLMFC\\INCLUDE;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\INCLUDE;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\PlatformSDK\\include', "LIB": 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\ATLMFC\\LIB;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\LIB;' + \ 'C:\\Program Files\\Microsoft Visual Studio 8\\VC\\PlatformSDK\\lib' } class MozillaCheckoutClientMk(ShellCommand): haltOnFailure = True cvsroot = ":pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot" def __init__(self, **kwargs): if 'cvsroot' in kwargs: self.cvsroot = kwargs['cvsroot'] if 'command' not in kwargs: kwargs['command'] = ["cvs", "-d", self.cvsroot, "co", "mozilla/client.mk"] ShellCommand.__init__(self, **kwargs) def describe(self, done=False): return ["client.mk update"] class MozillaClientMkPull(ShellCommand): haltOnFailure = True def __init__(self, **kwargs): if 'project' not in kwargs or kwargs['project'] is None: self.project = "browser" else: self.project = kwargs['project'] del kwargs['project'] if 'workdir' not in kwargs: kwargs['workdir'] = "mozilla" if 'command' not in kwargs: kwargs['command'] = ["make", "-f", "client.mk", "pull_all"] env = {} if 'env' in kwargs: env = kwargs['env'].copy() env['MOZ_CO_PROJECT'] = self.project kwargs['env'] = env ShellCommand.__init__(self, **kwargs) def describe(self, done=False): if not done: return ["pulling (" + self.project + ")"] return ["pull (" + self.project + ")"] class MozillaPackage(ShellCommand): name = "package" warnOnFailure = True description = ["packaging"] descriptionDone = ["package"] command = ["make"]
Set-up Buildbot to start with the system
Create the file '/etc/default/buildbot' with the following contents:
# buildbots to manage # add a new set of variables for each buildbot to start # BB_NUMBER -> index for the buildbot # BB_NAME -> short name that is printed when starting/stopping # BB_USER -> user to run the buildbot as # BB_BASEDIR -> the absolute path to the buildbot master or slave # BB_OPTIONS -> extra options to pass to buildbot # BB_PREFIXCMD -> prefix command, ie. nice, linux32, etc. # # Each of the preceeding are arrays. Each Buildbot you wish to run should # increase the index of each. For example, the first Buildbot should use # [0] on each array. The next one uses [1], etc. BB_NUMBER[0]=0 BB_NAME[0]="Default Buildbot" BB_USER[0]="buildbot" BB_BASEDIR[0]="/buildbot/default/" BB_OPTIONS[0]="" BB_PREFIXCMD[0]=""
Create the file '/etc/init.d/buildbot' with the following contents:
#! /bin/bash # initscript for buildbot ### BEGIN INIT INFO # Provides: cvsd # Required-Start: $local_fs $network # Required-Stop: $local_fs # Should-Start: $remote_fs # Should-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: S 0 1 6 # Short-Description: Buildbot # Description: Buildbot ### END INIT INFO PATH=/sbin:/bin:/usr/sbin:/usr/bin DESC="BuildBot" USER=buildbot DAEMON=/tools/buildbot/bin/buildbot DNAME=buildbot PROCNAME=$NAME [ -r /etc/default/buildbot ] && . /etc/default/buildbot test -x ${DAEMON} || exit 0 . /lib/lsb/init-functions check_config() { errors=0 for i in ${BB_NUMBER[@]}; do [ $i -ge 0 ] || continue if [ -z "${BB_NAME[$i]}" ]; then echo >&2 "buildbot $i: no name" errors=$(($errors+1)) fi if [ -z "${BB_USER[$i]}" ]; then echo >&2 "buildbot $i: no user" errors=$(($errors+1)) elif ! getent passwd ${BB_USER[$i]} >/dev/null; then echo >&2 "buildbot $i: unknown user ${BB_USER[$i]}" errors=$(($errors+1)) fi if [ ! -d "${BB_BASEDIR[$i]}" ]; then echo >&2 "buildbot $i: no base directory ${BB_BASEDIR[$i]}" errors=$(($errors+1)) fi done [ $errors -eq 0 ] || exit 1 } check_config start_buildbot() { NAME="$1" USER="$2" BASEDIR="$3" PREFIXCMD="$4" OPTIONS="$5" #START="--start --quiet --exec ${DAEMON} --name ${NAME} --pidfile ${BASEDIR}/twistd.pid" #[ -n "${USER}" ] && START="${START} --chuid ${USER}" #START="${START} -- start ${BASEDIR} ${OPTIONS}" #${PREFIXCMD} start-stop-daemon ${START} >/dev/null 2>&1 ${PREFIXCMD} su -s /bin/bash -c "${DAEMON} start ${BASEDIR} ${OPTIONS}" - ${USER} return $? } stop_buildbot() { NAME="$1" USER="$2" BASEDIR="$3" PREFIXCMD="$4" ${PREFIXCMD} su -s /bin/bash -c "${DAEMON} stop ${BASEDIR}" - ${USER} return $? } reload_buildbot() { NAME="$1" USER="$2" BASEDIR="$3" PREFIXCMD="$4" ${PREFIXCMD} su -s /bin/bash -c "${DAEMON} sighup ${BASEDIR}" - ${USER} return $? } do_start () { errors=0 for i in ${BB_NUMBER[@]}; do [ $i -ge 0 ] || continue echo "Starting buildbot ${BB_NAME[$i]}" if start_buildbot "${BB_NAME[$i]}" "${BB_USER[$i]}" "${BB_BASEDIR[$i]}" \ "${BB_PREFIXCMD[$i]}" "${BB_OPTIONS[$i]}" then echo "started" else echo "not started" errors=$(($errors+1)) fi done return $errors } do_stop () { errors=0 for i in ${BB_NUMBER[@]}; do [ $i -ge 0 ] || continue echo "Stopping buildbot ${BB_NAME[$i]}" if stop_buildbot "${BB_NAME[$i]}" "${BB_USER[$i]}" "${BB_BASEDIR[$i]}" \ "${BB_PREFIXCMD[$i]}" then echo "stopped" else echo "not stopped" errors=$(($errors+1)) fi done return $errors } do_reload () { errors=0 for i in ${BB_NUMBER[@]}; do [ $i -ge 0 ] || continue echo "Reload buildbot ${BB_NAME[$i]}" if reload_buildbot "${BB_NAME[$i]}" "${BB_USER[$i]}" "${BB_BASEDIR[$i]}" \ "${BB_PREFIXCMD[$i]}" then echo "reloaded" else echo "not reloaded" errors=$(($errors+1)) fi done return $errors } do_restart () { errors=0 for i in ${BB_NUMBER[@]}; do [ $i -ge 0 ] || continue echo "Restarting buildbot ${BB_NAME[$i]}" stop_buildbot "${BB_NAME[$i]}" "${BB_USER[$i]}" "${BB_BASEDIR[$i]}" \ "${BB_PREFIXCMD[$i]}" || true if start_buildbot "${BB_NAME[$i]}" "${BB_USER[$i]}" "${BB_BASEDIR[$i]}" \ "${BB_PREFIXCMD[$i]}" "${BB_OPTIONS[$i]}" then echo "restarted" else echo "not restarted" errors=$(($errors+1)) fi done return $errors } case "$1" in start) do_start exit $? ;; stop) do_stop exit $? ;; reload) do_reload exit $? ;; restart|force-reload) do_restart exit $? ;; *) log_warning_msg "Usage: $0 {start|stop|restart|reload|force-reload}" exit 1 ;; esac exit 0
Run the following command to add buildbot to the init scripts:
chkconfig --add buildbot