A solution to Jenkins jobs conflicting over shared resources

I have been looking for a way to manage the execution of Jenkins jobs that require exclusive access to a resource other than the Jenkins slave it is being built on. Let’s consider two scenarios that can cause problems.

Shared Physical Resource

Working with embedded systems I often want to run tests on an embedded device as part of a continuous integration process. I may have multiple Jenkins slaves that are capable of running the jobs, with a single specific embedded device required. If I have multiple jobs how do I ensure that only one runs at a time?

Software License and Tool Versions

For years I have used vxWorks and the Windriver Workbench IDE. Lets suppose that I have three Jenkins Slave Nodes, each with a different version of the tools installed. The tools are licensed by FlexLM on a license server, only one of these slaves can run the tools at the same time. With no restrictions if two jobs are run concurrently that require different versions of the tool then one will fail to build with a license violation. How do I ensure that the jobs are sequenced rather than running concurrently?

The solution

Basic Usage

The Jenkins Lockable Resource Plugin elegantly solves these problems.
The plugin is installed in the normal way from Manage Jenkins->Manage Plugins->Available, tick the box next to the plugin and Install (I restarted as well). Once installed go to Manage Jenkins->Configure System, scroll down to the Lockable Resources Manager and Add Lockable Resource.
In this example I have created a resource to represent a Raspberry Pi running Codesys. I have chosen a unique name (I may have more than one in the future) and a label for the type of node.
Next configure the jobs that require the resource, in the Configuration page for the jobs check the This build requires lockable resources check box.
 
 
 
In this particular build I have selected a specific resource. When the job runs you can see the resource being locked around the job.
If the resource is already locked when the job becomes ready to run then it is held pending in the Build Queue, having NOT blocked the Slave node.
 

Manually Reserving a Resource

One other nice feature of the plugin is that it is possible to manually reserve the resource, so if in my example I wanted to do some maintenance on the raspberry pi I can go to Manage Jenkins->Configure System, and put some text in the Reserved by field to take the lock thus holding off builds until I have finished.
 

Advanced

Suppose that I have two embedded devices that I could run my tests on CODESYS_RPI_1 and CODESYS_RPI_2, both configured identically. However my build job needs to know which has been locked so that it can communicate appropriately. To achieve this I have changed the configuration for my job to depend on the resource Label rather than the resource name, and introduced a variable to hold the name of the resource that was locked, like this

Now looking at the Parameters for the build we can see which resource was locked.
 
This parameter can be used like any other in the build.
 
Some tests may require multiple resources, let’s say that we need two identical devices, setting the Number of resources to request to 2 and building shows the variable now has the names of both resources.
 
 

Conclusion

The lockable Resources Plugin provides a simple, elegant solution to locking/reserving resources for a job. As shown above it is easy to have a lock represent a physical resource, the plugin can equally be used in the licensing scenario, define a single resource to represent the license, each job requires the resource and is locked to running on the appropriate slave. Definitely one to add to my list of favourite Jenkins Plugins.
 
 
 

Using PiFace Control and Display with CODESYS

This post is intended for CODESYS beginners, it aims to give a step by step guide to creating a CODESYS project for the Raspberry Pi with the PiFace Control and Display add on board. (I am actually using PiFace Control and Display 2, but it appears to be compatible).

Start by creating a new standard CODESYS project.

Select the CODESYS Control for Raspberry Pi as the Device and ST as the programming language
The PiFace Control and Display module is interfaced with using SPI, so we need to add two devices to the device tree, first an SPI Master and then the PiFace Control and Display device. To do this right click on SPI in the device tree and select Add Device
Choose the SPI Master
Click Add Device, then without closing the dialog select SPI_master in the device tree, and then in the dialog select PiFace Control&Display
Click Add Device and close the dialog.
IMPORTANT: PiFace Control and Display operates on SPI port 1, and so the SPI_master device needs to be reconfigured to use this port. To set the port open the SPI_master device in the device tree and change the Value of SPI port as shown to ‘/dev/spidev0.1’.
At this point we have a CODESYS project with all of the drivers installed to operate this display and to read the buttons. Adding the IO device has added a function block called PiFace_Control_Display of type PiFaceCaD. Unfortunately it can be very hard to work out how to use this function block with the version of the library containing this block no documentation is installed and commenting of the function block is hidden. We can find some information by switching to the Predefined Professional Feature Set (Tools->Options->Features->Predefined feature sets…->Professional). Now when the Library Manager is opened in the project additional libraries are visible, in particular we are interested in Raspberry SPI PiFace CaD.

PiFaceCaD

In the Raspberry SPI PiFace CaD library we can see the definition of the PiFaceCaD function block type. The function block has just a single VAR OUTPUT, bySwitches.
The rest of the features of the function block require the use of the Object Oriented features added to IEC61131-3 third edition. The documentation below is extracted directly from the Raspberry SPI PiFace CaD library (With a few corrections)

METHOD Clear

This method is used to clear the display
return value: none 

METHOD DefineCustomBitmap

This method is used to define a custom bitmap, up to 8 custom bitmaps can be used simultaneously return value: none 

Name
Type
Comment
byLocation
BYTE (0..7)
storage positions of the bitmap (0..7)
abyBitmap
ARRAY [0..7] OF BYTE
bitmap definition: each byte (0 (top)..7 (bottom)) represents on line; each bit (0 (right)..4 (left)) of a byte represents one pixel in the line

METHOD Home

This method is used to home the cursor to the upper left corner
return value: none 

METHOD MoveLeft

This method shifts the content of the display about one char to the left
return value: none 

METHOD MoveRight

This method shifts the content of the display about one char to the right
return value: none 

METHOD SetCursor

This method sets the cursor to a specified position
return value: none 
Name
Type
Comment
usiColumn
USINT
column to place the cursor (0..15)
usiRow
USINT
row to place the cursor (0,1)

METHOD SetText

This method sets the content of the display (unspecified characters are left unchanged)
return value: none 
Name
Type
Comment
sLine1
STRING
first line
sLine2
STRING
second line

METHOD Write

This method writes text at the current position
return value: none 
Name
Type
Comment
sText
STRING
string to write

METHOD WriteCustomBitmap

This method writes the specified custom bitmap at the current position
return value: none 
Name
Type
Comment
byLocation
BYTE (0..7)
storage positions of the bitmap (0..7)

PROPERTY Backlight: BOOL (SET)

Sets the backlight on or off 

PROPERTY Blink: BOOL (SET)

Displays or hides the blinking rectangle 

PROPERTY Cursor: BOOL (SET)

Displays or hides the cursor 

PROPERTY Display: BOOL (SET)

Switches the display on or off 

SPI

The PiFaceCad function block Extends the SPI function block, and so we need to understand a little about this function block too. This documentation is lifted from the Raspberry Pi Peripherals library.
This function block is the base class for SPI devices controlled via the SPI device /dev/spidev0.0. It is meant to be extended by other function blocks that overload the body and the following methods/properties and replace it with their specific implementation, always including a call of the base implementation with super^.<MethodName>() :
body (general handling, start-up)
AfterReadInputs (reading input data)
BeforeWriteOutputs (writing output data)
Initialize [optional] (used to read parameters from the configuration)
Operational [optional] (used to signal the status of the device)
The body of this FB is called by the methods AfterReadInputs and BeforeWriteOutputs, where _xAfterReadInputs indicates the caller. Use _iState to control your statemachine. A value of 10 by default indicates that the device is operational. Do not forget to call the base implementation with super^(), where the diagnosis indicators are set according to the Operational property.
 

Hello World

So now we know something about the methods on the PiFaceCaD Function Block we should be able to write a Hello World program.
PROGRAM PLC_PRG
VAR
xUpdate: BOOL := TRUE;
END_VAR
 
IF PiFace_Control_Display.Operational AND xUpdate THEN
PiFace_Control_Display.Clear();
PiFace_Control_Display.SetText(sLine1 := ‘Hello World’, sline2 := ”);
xUpdate := FALSE;
END_IF

Go online and run the application, you should see this

Reading Switches

All of the switches on the PiFace Control and Display board are output as bits within a single byte on the PiFaceCaD function block. The bits are numbered as shown
The sample code below demonstrates reading the switches
PROGRAM PLC_PRG
VAR
xUpdate: BOOL := TRUE;
byLastSwitches : BYTE;
bySwitches : BYTE;
END_VAR
 
bySwitches := PiFace_Control_Display.bySwitches;
IF bySwitches <> byLastSwitches THEN
xUpdate := TRUE;
END_IF
IF PiFace_Control_Display.Operational AND xUpdate THEN
PiFace_Control_Display.Clear();
PiFace_Control_Display.Backlight := TRUE;
PiFace_Control_Display.SetText(sLine1 := ‘Hello World’, sline2 := BYTE_TO_STRING(bySwitches));
xUpdate := FALSE;
byLastSwitches := bySwitches;
END_IF

 

Configuring a Jenkins Slave to build VS2013 projects

Introduction

I have previously installed Jenkins, SVN and Trac on a single Raspberry Pi 2, with the intention of having a home Continuous Integration server (CI). I now want to get a visual studio 2013 solution built by Jenkins.

As a first project I have decided to get googletest (gtest) to build. As a precursor I have downloaded version 1.7.0 and added it to my local SVN repository, I then copied the msvc directory to msvc2013, open the solution in VS2013, allowed the onetime upgrade to happen, and then committed the new directory. If I build locally gtest builds with a couple of warnings (which is good because we can then check that jenkins sees the warnings).

I have a clean windows 8.1 PC (virtual machine actually) with Visual Studio 2013 Community Edition installed, and the latest version of Java installed (Version 8 update 51).

As a starting point I am following the Step by Step guide to setup master and slave in the Jenkins documentation.

Configuring the Jenkins Master

In a browser on the intended Jenkins slave, open up the Jenkins server main page (In my case http://xxx.xxx.xxx.xxx:8080, where xxx.xxx.xxx.xxx is the IP address of my RPi). Select Manage Jenkins->Manage Nodes and then select New Node.
Enter a name for Jenkins to reference the slave as and select Dumb Slave, click OK. You are then shown the Configure page for the slave, these are the initial settings I choose, the Label is important, I use it later when setting up the build to identify this as a suitable slave to build on.

Save and then click on the newly added node and then click the Launch button.

I had to edit the Java security settings in the control panel on the PC to make http://192.168.0.34:8080/ a trusted site, the Jenkins slave then launched successfully
For now I want to launch the slave manually, so the configuration of master and slave is done.

Adding the required plugins to Jenkins

I browsed to Jenkins->Manage Jenkins->Manage Plugins. Before adding new plugins I decided to update all installed plugins to their latest version.
I then selected the Available tab and added the following plugins MSBuild, Log Parser, Warnings, Static Analysis Collector.
I browsed to Jenkins->Manage Jenkins->Configure System, scrolled down to MSBuild and added the following configuration.

Note: the location of MSBuild is specific to each version of Visual Studio, This plugin only offers one global path setting for each MSBuild  installation, so every build slave that you create a particular Visual Studio Installation on must have the same install path for MSBuild. I don’t think this is any great restriction.

Configuring the Build

In a browser go to Jenkins and select New Item, enter an item name (The name of your build, I use GoogleTestVS2013). You are then faced with the project configuration page, the exact content of this page depends on which plugins you have installed. The key sections are
Restrict the build to only run on slaves with vs2013 installed.
Link to the source code to checkout
Click Add build Step and select Build a Visual Studio project or solution using MSBuild
Click Add post-build action and select Scan for compiler warnings
For me that was sufficient, Jenkins can now checkout and build my visual studio project, after the build warnings are shown.

 

Integrating trac and Jenkins

In this post I cover how I have integrated Trac and Jenkins using HudsonTracPlugin and Jenkins Trac Plugin. I am running both Trac and Jenkins on a Raspberry Pi 2.

Trac Plugin

The Trac Plugin is a plugin for Jenkins that creates links from Jenkins projects to Trac instances. 
As an example, if you committed a change with the following log message: 

The Trac plugin decorates Jenkins “Changes” HTML to create links to your Trac wiki, tickets, changesets, and source browser.
Reverted changeset:123 to close ticket #456.
your Jenkins job changes page would make changeset:123 and #456 hyperlinks to the appropriate Trac changeset and ticket pages, respectively.
In the Jenkins change details, there would be a link to the Trac pages for the:

 

  • changeset committed,
  • files changed, and
  • diff of the changes for each changed file.

Installation involved browsing to Jenkins->Manage Jenkins->Manage Plugins->Available, selecting Available Plugins and then checking the Edgewall Trac Plugin.
The plugin is then configured as part of a build configuration


As simple as that, references to changesets and ticket numbers are now shown as hyperlinks and there is a link from the build page back to trac.

HudsonTracPlugin

The HudsonTracPlugin is a Trac plugin that includes Jenkins build results into the Trac timeline and (optionally) provides a navbar menu to link to the Jenkins instance.

As a newbie I found the documentation for installing this plugin to be somewhat limited. It was actually remarkably easy.

The first step is to install the plugin which is written in python using easy_install, so in a terminal session to the RPi

sudo easy_install https://trac-hacks.org/svn/hudsontracplugin/0.10/

This gave the following output
Downloading https://trac-hacks.org/svn/hudsontracplugin/0.10/
Doing subversion checkout from https://trac-hacks.org/svn/hudsontracplugin/0.10/ to /tmp/easy_install-xAXEIt/0.10
Processing 0.10
Running setup.py -q bdist_egg –dist-dir /tmp/easy_install-xAXEIt/0.10/egg-dist-tmp-vkGSex
unrecognized .svn/entries format; skipping .
unrecognized .svn/entries format in 
zip_safe flag not set; analyzing archive contents…
Adding HudsonTrac 0.5-r0 to easy-install.pth file

 

Installed /usr/local/lib/python2.7/dist-packages/HudsonTrac-0.5_r0-py2.7.egg
Processing dependencies for HudsonTrac==0.5-r0

Finished processing dependencies for HudsonTrac==0.5-r0

I then chose to reboot my RPi, I suspect I could have just restarted apache.

Using a browser I then went to the Trac Admin->Plugins page, HudsonTrac 0.5-r0 was now listed, I enabled it and Applied Changes as shown.




Finally I logged back in to the RPi and edited trac.ini

sudo vi /var/trac/projects/prod/conf/trac.ini

I added the following to the end of the file

[hudson]
alternate_success_icon = true
api_token =
display_build_descriptions = false
display_building = true
display_culprit = false
display_in_new_tab = false
display_modules = false
job_url = http://192.168.0.34:8080/
list_changesets = true
main_page = http://192.168.0.34:8080/
password =
timeline_opt_label = Builds
username  =

 
I restarted Apache and it worked 🙂 Builds are shown in the timeline, they act as links to the builds on Jenkins. There is also a builds tab added to the trac navbar.

trac performance

There are suggestions for improving performance at http://trac.edgewall.org/wiki/TracPerformance. With my existing configuration I had it typical page loads are taking 4 to 5 seconds, after making the changes below typical page loads are around a second, some faster some slower (loading the first page takes longer).

Related Posts

Switch to using mod_wsgi rather than mod_python

Remove the apache configuration for trac
sudo vi /etc/apache2/sites-enabled/000-default
Remove the lines that are struck through below
<Location /trac>
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /var/trac/projects
PythonOption TracUriRoot /trac
PythonOption PYTHON_EGG_CACHE /tmp
AuthType Digest
AuthName "Subversion Repo"
AuthDigestDomain /trac
AuthDigestProvider file
AuthUserFile /etc/apache2/dav_svn.htdigest
Require valid-user
</Location>
Uninstall mod python and install mod_wsgi
sudo apt-get remove --purge libapache2-mod-python
sudo apt-get install libapache2-mod-wsgi
Now configure WSGI (I found good help for this at https://code.google.com/p/modwsgi/wiki/IntegrationWithTrac.
sudo mkdir /var/trac/cgi-bin
sudo vi /var/trac/cgi-bin/trac.wsgi
I then put this content in to trac.wsgi
#!/usr/bin/python

# -*- coding: utf-8 -*-

#

import sys

sys.stdout = sys.stderr

import os

os.environ[‘TRAC_ENV_PARENT_DIR’] = ‘/var/trac/projects’

os.environ[‘PYTHON_EGG_CACHE’] = ‘/tmp’



import trac.web.main



application = trac.web.main.dispatch_request
Ensure that the script is accessible to apache and executable
sudo chown www-data:www-data -R /var/trac/cgi-bin

sudo chmod +x /var/trac/cgi-bin/trac.wsgi 
Now to configure Apache
sudo vi /etc/apache2/sites-enabled/000-default
Add the following after the last </Directory> element
        WSGIScriptAlias /trac /var/trac/cgi-bin/trac.wsgi


        <Directory /var/trac/cgi-bin>

                WSGIApplicationGroup %{GLOBAL}

                Order deny,allow

                Allow from all

        </Directory>
Restart Apache
sudo /etc/init.d/apache2 restart
I then tested trac and it was still functioning as before 🙂

Mapping Static Resources

By default static resources like style sheets and images are served by trac itself, it is more efficient to have Apache serve these directly rather than get trac to serve them.
First extract the static resources and delete the ones we do not want (I don’t want cgi-bin as I’ve already configured it, and I don’t want htdocs/site because I will directly reference the files in the trac install).
sudo trac-admin /var/trac/projects/play deploy /var/trac/static

sudo rm -rf /var/trac/static/cgi-bin/

sudo rm -rf /var/trac/static/htdocs/site/

sudo chown www-data:www-data -R /var/trac/static
Now configure Apache to directly serve the static resources
sudo vi /etc/apache2/sites-enabled/000-default
Add the following after the last </Directory> element
Alias /trac/play/chrome/common /var/trac/static/htdocs/common

Alias /trac/play/chrome/site /var/trac/projects/play/htdocs/

<Directory “/var/trac/static/htdocs/common“> Order allow,deny
Allow from all</Directory><Directory “/var/trac/projects/play/htdocs/“> Order allow,deny Allow from all</Directory>

 

svn pre-commit hook to ensure a valid trac ticket is referenced

In my previous post I configured the svn post-commit hook so that tickets referenced in the svn commit message had a link to the changes and the commit message added to the ticket comments. This post describes how to configure the svn to prevent commits that do not reference a valid ticket.

The trac community have done all the hard work, so I downloaded trac-pre-commit-hook from http://trac.edgewall.org/browser/trunk/contrib/trac-pre-commit-hook, and placed it in a new directory /var/trac/hooks.

I set the ownership of the script to www-data and made sure it was executable

sudo chown www-data:www-data -R /var/trac/hooks
sudo chmod +x /var/trac/hooks/trac-pre-commit-hook

All that remains to be done is to call this from the svn pre-commit hook. I created a file/var/svn/repos/play/hooks/pre-commit with this content

REPOS=”$1″
TXN=”$2″
TRAC_ENV=”/var/trac/projects/play”
LOG=`/usr/bin/svnlook log -t “$TXN” “$REPOS”`
/usr/bin/python /var/trac/hooks/trac-pre-commit-hook “$TRAC_ENV” “$LOG” || exit 1

If a commit fails to reference an open ticket I now get a message like this

svn commit -m “Some message referencing a closed ticket refs #1” test.txt 
Sending        test.txt
Transmitting file data .svn: E165001: Commit failed (details follow):
svn: E165001: Commit blocked by pre-commit hook (exit code 1) with output:

At least one open ticket must be mentioned in the log message.

Configuring trac

This post covers how I have configured trac, and trac svn integration, it follows on from Installing Trac and SVN on the Raspberry Pi. It is intended just as a personal reminder, but if it is helpful…

Adding SVN repository to trac

Detailed instructions can be found in TracRepositoryAdmin in the trac wiki.
You are then told to do perform the steps below
So first perform a manual sync
sudo -u www-data trac-admin /var/trac/projects/play repository resync "play"
Edit trac.ini to configure the updater.
sudo -u www-data vi /var/trac/projects/play/conf/trac.ini
In the [trac] section set repository_sync_per_request blank

repository_sync_per_request =

In /var/svn/repos/play/hooks create a file called post-commit with this content

#!/bin/sh
export PYTHON_EGG_CACHE="/tmp"
/usr/bin/trac-admin /var/trac/projects/play changeset added "$1" "$2"

In the same place create post-revprop-change with this content

#!/bin/sh
export PYTHON_EGG_CACHE="/tmp"
/usr/bin/trac-admin /var/trac/projects/play changeset modified "$1" "$2"
 
Ensure that both of these scripts are owned by www-data and that both are executable
sudo chown -R www-data:www-data post-commit post-revprop-change

sudo chmod +x post-commit post-revprop-change

 CommitTicketUpdater

Enable the CommitTicketUpdater plugin by going to the admin tab in trac and then selecting Plugins from the Administration Panel, open the Trac 0.12.5 plugin and tick CommitTicketUpdater as shown.

Edit trac.ini to configure the updater.

sudo -u www-data vi /var/trac/projects/play/conf/trac.ini

In the [ticket] section add the following

commit_ticket_update_envelope =
commit_ticket_update_commands.close =
commit_ticket_update_commands.refs = <ALL>
commit_ticket_update_check_perms = true
commit_ticket_update_notify = true

Testing Commit Hook

Having completed all of the above configuration I rebooted my RPi, I don’t know that this is required but it seemed sensible.
I then created a ticket #1 in the play project, To test I checked out the trunk for the play repository and committed a new file with the commit message “Test commit hook See #1”, the commit happened and ticket #1 was updated with the following comment

Logo

I like each trac project to be immediately identifiable so that it is obvious which trac I am working on. I just set the project logo. The logo looks best with an image of a little under 100 pixels high. I saved the files as play.png in /var/trac/projects/play/htdocs.
I then edited trac.ini (as www-data)

sudo -u www-data vi conf/trac.ini

I set the content of [header_logo]

[header_logo]
alt = play repository to test ideas
height = 80
src = site/play.png
width = 300

Related posts

Installing SVN and trac on Raspberry Pi

This post is step by step instructions for installing subversion (SVN) 1.8.10 and trac on the Raspberry Pi. I am writing it as a reminder to myself, but if you find it useful…

Beforehand

It’s a good idea to get up to date


sudo apt-get update
sudo apt-get upgrade

Install Subversion

First of all I checked the version included in the raspbian distribution, and I wanted a later version. I looked at using the WANdisco binaries, but found that they seemed to be missing the binaries required for the raspberry pi. So these instructions use the debian backports.
I followed these instructions. First I added wheezy-backports to me sources.list by creating /etc/apt/sources.list.d/wheezy-backports.list 

deb http://http.debian.net/debian wheezy-backports main

I tried just running sudo apt-get update, however I got the following error

W: GPG error: http://http.debian.net wheezy-backports Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 8B48AD6246925553 NO_PUBKEY 7638D0442B90D010

After a little digging I found that I could add the public keys like this

gpg --keyserver pgpkeys.mit.edu --recv-key 8B48AD6246925553
gpg -a --export 8B48AD6246925553 | sudo apt-key add -
gpg --keyserver pgpkeys.mit.edu --recv-key 7638D0442B90D010
gpg -a --export 7638D0442B90D010 | sudo apt-key add -
sudo apt-get update
sudo apt-get -t wheezy-backports install subversion

Now it is possible to update with no errors

sudo apt-get update

Finally we can install subversion

sudo apt-get -t wheezy-backports install subversion
sudo apt-get -t wheezy-backports install python-subversion

(Note: originally I missed python-subversion, this left a version mismatch and caused errors)
Now check the version installed

svn --version
svn, version 1.8.10 (r1615264)

compiled Apr 24 2015, 04:16:08 on arm-unknown-linux-gnueabihf


Copyright (C) 2014 The Apache Software Foundation.

This software consists of contributions made by many people;

see the NOTICE file for more information.

Subversion is open source software, see http://subversion.apache.org/


The following repository access (RA) modules are available:


* ra_svn : Module for accessing a repository using the svn network protocol.

– with Cyrus SASL authentication

– handles ‘svn’ scheme

* ra_local : Module for accessing a repository on local disk.

– handles ‘file’ scheme

* ra_serf : Module for accessing a repository via WebDAV protocol using serf.

– using serf 1.3.7

– handles ‘http’ scheme

Install Apache

I have decided that I am less likely to get conflicts if the versions of apace and subversion come from the same distribution. So I install from wheezy backports.

sudo apt-get -t wheezy-backports install apache2
sudo apt-get -t wheezy-backports install libapache2-svn

I got a single warning during install

Starting web server: apache2apache2: Could not reliably determine the server’s fully qualified domain name, using 127.0.1.1 for ServerName

I have chosen to ignore this for now. To test the installation of apache I browsed to http://localhost/

Create Repositories

I have decided that the structure I want is to have two repositories, a play repository and a prod repository. This example just shows the creation of the play repository.
sudo mkdir /var/svn
sudo mkdir /var/svn/repos
sudo svnadmin create /var/svn/repos/play

Configure Security

I have decided to use digest access authorisation. NOTE: I am not recommending this method of securing access, but it suits my needs.
Start by editing dav_svn.conf (I use vi you could equally use nano if you prefer)
sudo vi /etc/apache2/mods-available/dav_svn.conf
The default file is all comments, and I choose to leave it intact and just append the following to the end of the file.
<Location /svn>
DAV svn
SVNParentPath /var/svn/repos
AuthType Digest
AuthName "Subversion Repo"
AuthUserFile /etc/apache2/dav_svn.htdigest
Require valid-user
</Location>
Next I need to enable digest authentication and restart apache
sudo a2enmod auth_digest
sudo service apache2 restart
Next I want to create a user in the apache/subversion digest file
sudo htdigest -c /etc/apache2/dav_svn.htdigest "Subversion Repo" david
It is important to note two things here. Firstly, if you add more than one user omit the -c on all subsequent calls as this creates the digest file and so would delete all existing users. Secondly the “Subversion Repo” argument specifies the realm and must match the AuthName in dav_svn.conf.
Now is a good time to test that it is working: browse to http://192.168.0.34/svn/play (the ip address of your RPi), you should be prompted for a username and password, enter the ones you specified when creating the digest and you should be in.
One last step is to tie down the native file access permissions, and to grant the apache user address to write to the repository.
sudo chown -R www-data:www-data /var/svn/repos

Install trac

With trac I have decided to install the version bundled with raspbian (0.12.5). I based the decision on the availability of other trac plugins, also for compatibility with subversion 1.8 I need trac >=0.12.3.
sudo apt-get install trac
sudo apt-get install lib-apache2-mod-python

Configure trac

I want trac to share the same digest authentication as subversion. I also want a separate trac database for my play and prod repositories. The steps below only show the setup for the play repository.
sudo mkdir /var/trac
sudo mkdir /var/trac/projects
sudo chown -R www-data:www-data /var/trac/projects

Edit the apache configuration

sudo vi /etc/apache2/sites-enabled/000-default

Add the following to the end of the file, just before the </VirtualHost> tag. Note that the authentication matches the subversion settings.

<Location /trac>
SetHandler mod_python
PythonInterpreter main_interpreter
PythonHandler trac.web.modpython_frontend
PythonOption TracEnvParentDir /var/trac/projects
PythonOption TracUriRoot /trac
PythonOption PYTHON_EGG_CACHE /tmp
AuthType Digest
AuthName "Subversion Repo"
AuthDigestDomain /trac
AuthDigestProvider file
AuthUserFile /etc/apache2/dav_svn.htdigest
Require valid-user
</Location>

Now it is time to create the play trac project environment

sudo -u www-data trac-admin /var/trac/projects/play initenv

You get asked a few questions, I responded play for the name of the project and accepted all other defaults.
Restart apache

sudo /etc/init.d/apache2 restart

Time to test, browse to http://192.168.0.34/trac/ (use the IP address of your RPi) you should see a list of your trac projects.

Click on the play project name and you should see trac

NOTE: According to TracAuthenticationIntroduction Note that in the current version of Trac, clicking on the logout link above the navigation bar does not logs user out because the browser still remembers the HTTP authentication and keeps sending it.

To be able to administer trac add a user as the trac admin. I use my normal trac login.

sudo -u www-data trac-admin /var/trac/projects/play permission add david TRAC_ADMIN

For further configuration to make the integration tighter and to improve performance see


Using the Camera with CODESYS on the Raspberry Pi

This post is a primer on how to get started with using the Camera in CODESYS on the Raspberry Pi. The content of the post is taken from a mix of the CODESYS documentation and from reverse engineering sample projects.

Configuring the Raspberry Pi

Plug the Camera in to the connector labelled CAMERA on the Raspberry Pi.
Connect using SSH and run sudo raspi-config to enable the camera, then reboot
Now we need to install camera interface, these instructions are taken from the CODESYS documentation, which appears to have got them from http://elinux.org/RPi-Cam-Web-Interface
sudo apt-get update
sudo apt-get dist-upgrade
sudo rpi-update
At this point I rebooted again.
Clone the code from github and run the installer with the following commands:
git clone https://github.com/silvanmelchior/RPi_Cam_Web_Interface.git
cd RPi_Cam_Web_Interface
chmod u+x RPi_Cam_Web_Interface_Installer.sh
./RPi_Cam_Web_Interface_Installer.sh install
When running the installer you get prompted for th name of the install folder – I accepted the default. You also get prompted for the Port to use, I stayed with the default port 80. I chose not to enable web server security. I then rebooted.
Then I browsed to http://192.168.0.38 (the IP address  of my RPi) to verify that everything was working.

Capturing a JPG image

Create a new CODESYS project (standard project) selecting the target device as CODESYS Control for Raspberry Pi. Beneath the Camera device right click over the <Empty> device, select plug device
and then select Raspberry Pi Camera, close the dialog.
You should end up with a Camera in the devices tree like this.
You also have a new variable in IoConfig_Globals called Raspberry_Pi_Camera of type Camera.PiCamera. The methods on this function block can be used to save a picture, or video. For documentation check out the online help in CODESYS.
At a minimum you need to specify the name of an output file, the sample below can be driven using the CODESYS debugger, set xTakeStill TRUE and a picture will be saved.
NOTE: On my system when I originally ran this udiResult was set to 70, and no picture was taken. I had to stop the Camera in the RPi Cam Control Application as warned in the CODESYS documentation, by browsing to the IP address of my Pi and selecting Stop Camera
Once I had stopped the Camera the function returned 0 (Errors.ERR_OK), and the picture was taken. Using the device file browser I was able to locate the Picture at the root of the CODESYS file system on my RPi.
NOTE: The function call Raspberry_Pi_Camera.Still takes a long time to execute, by default around 5 seconds. During this time the Program is hung. If you need to make use of this code I strongly suggest having a dedicated, low priority task to execute a program dedicated to taking the picture. I experimented with a timeout of 0, and the program hung for longer than I was prepared to wait. A timeout of 1 still took a long time to complete.

Installing Jenkins on Raspberry Pi

I want to get a CI system setup at home and decided to try getting Jenkins up and running on a Raspberry Pi 2. My starting point is the latest Rasbian distribution, I have fixed the IP address of this Raspberry PI at 192.168.0.34.

NOTE: I initially tried just installing jenkins from Rasbian, with sudo apt-get update and sudo apt-gt install jenkins, however this installed a very old version of Jenkins and I couldn’t easily update it. This post covers installation of the latest stable version of Jenkins on a clean Rasbian system.

I found instructions to install the latest stable version of Jenkins on Ubuntu and Debian, I chose to install the LTS version.

First I added the key for the LTS version to my repository

wget -q -O - http://pkg.jenkins-ci.org/debian-stable/jenkins-ci.org.key | sudo apt-key add -

Then I updated /etc/apt/sources.list: adding this line to the top of the file

deb http://pkg.jenkins-ci.org/debian-stable binary/

Updated the local package index, then finally install Jenkins:

sudo apt-get update
sudo apt-get install jenkins

the install happened without problems

I then browsed to http://192.168.0.34:8080/, the default port for Jenkins, and voila!