Raspbmc Hyperion On/Off

I’ve just finished making the surround for my TV after testing it all with sticky tape 🙂 it’s looks awesome.

But the first question I was asked “How do I turn it off?”, Apparently the answer of “You don’t” wasn’t the right one. So a little searching brought me to a fellow blog post http://blog.nadnerb.co.uk/?p=11 which takes you through setting up a remote button in xbmc to disable the service.
While I’d be happy with the remote button option, turning the entire service on and off doesn’t sit well with me, what if I want to set mood lighting from my phone 🙂

So I had a little play with hyperion-remote and thought yeah I can script that. So below is my quick and dirty alternative to disabling the service.

First connect to the PI and create a new file (I called it hyperion_toggle_black.sh)
nano -w hyperion_toggle_black.sh

#!/bin/bash
priority=222

hyper_check=`hyperion-remote -l | grep -i ""priority" : $priority"`
echo $hyper_check
if [ -z "$hyper_check" ]
then
   hyperion-remote -p $priority -c black
else
   hyperion-remote -p $priority -x
fi
exit 0

Next make the script executable
chmod +x hyperion_toggle_black.sh
Now you can test it using ./hyperion_toggle_black.sh
Run it a few times and see that the LED’s go on and off.
The important part of this is the priority, XBMC seems to use a priority of 1000, so any number lower should be great. The android app and hyperion-remote seems to default to 50 or 100. Since I want these to still work I need a value higher than these. 222 should be good, but your free to change it if you like. If for example you want a complete off, setting it to 0 or 1 should be above everything else.
This script basically gives hyperion another job at priority 222 to set all the LED’s black, if there is no current priority 222, and clears priority 222 if it already exists. hence the toggle. On the plus side this wont require root privileges to start/stop the service.
Now you can edit the remote keymap file
nano -w /home/pi/.xbmc/userdata/keymaps/remote.xml
Because I’m using an LG TV and the symlink seems fairly basic, I’m limited to what buttons I can assign. I’ve already previously added a ‘Home’ button to my pause, So I’ve decided to change this slightly by using the pause button to trigger the script while it’s already on the Home screen.
Adding the line  lines
<pause>XBMC.System.Exec(“/home/pi/hyperion_toggle_black.sh”)</pause>
Within the Home>Remote section, but keeping the Global>Remote as
<pause>XBMC.ActivateWindow(Home)</pause>
This took a little playing around to work out which buttons I can use, the blog post at http://forum.osmc.tv/showthread.php?tid=6978 gave me the debug and tail commands to use.

Reboot the PI and viola. There’s about a 1 second delay between pressing the button and the LED’s going off/on, but I can live with that for now.

I didn’t need the XBMC notifications like the other blog post, but if this is something you want, you can mash my script to his and get your own thing 🙂

Notes:
I’m not entirely sure if turning the LED’s Black actually turns them off (i.e. no power) so I may in the future expand it with maybe a relay to control the actual power to the LED’s, but this would break the priority thing unless I put in some checks and run the script in the background.
I could also then add a push button to the PI’s GPIO triggering the on/off script at more of a physical level, hey I could even add a few buttons to be able to select an effect. but for now I’m happy to do all of that via my phone, and just have a priority function for XBMC.

Raspberry PI + Maplin WH1080 Weatherstation

Download and write to SD Card the debian image for Raspberry PI.
Boot and connect via SSH (Putty from Windows)
Change to root using sudo su – alternative use sudo in front of commands. Using sudo su – is bad, but I always do it.

Run

apt-get update
apt-get upgrade

Download the latest Debian Weewx version (http://sourceforge.net/projects/weewx/files/) using wget. Then run

dpkg -i weewx_2.6.4-1_all.deb

This will most likely throw error errors about missing dependencies. Install them using apt-get install

dpkg -i weewx_2.6.4.1_all.deb
(Reading database ... 75409 files and directories currently installed.)
Preparing to replace weewx 2.6.4-1 (using weewx_2.6.4.1_all.deb) ...
Unpacking replacement weewx ...
dpkg: dependency problems prevent configuration of weewx:
 weewx depends on python-configobj (>= 4.5); however:
  Package python-configobj is not installed.
 weewx depends on python-cheetah (>= 2.0); however:
  Package python-cheetah is not installed.
 weewx depends on python-imaging (>= 1.1.6); however:
  Package python-imaging is not installed.
 weewx depends on python-usb (>= 0.4); however:
  Package python-usb is not installed.
dpkg: error processing weewx (--install):
 dependency problems - leaving unconfigured
Errors were encountered while processing:
 weewx

So in my case I run
apt-get install python-configobj python-cheetah python-imaging python-usb
During the install you’ll be asked several configuration questions, fill them in (You can always edit the config file later if you make a mistake).

For the maplin WH1080, Select the FineOffsetUSB.

Once installed weewx should attempt to start (if not you can start it with /etc/init.d/weewx start). Check the syslog for any errors
tail /var/log/syslog -n 50
If all goes well you should see something like

wxengine: Initializing weewx version 2.6.4


wxengine: Using Python 2.7.3 (default, Mar 18 2014, 05:13:23) #012[GCC 4.6.3]


wxengine: pid file is /var/run/weewx.pid


wxengine: Using configuration file /etc/weewx/weewx.conf


wxengine: Loading station type FineOffsetUSB (weewx.drivers.fousb)


fousb: driver version is 1.6


fousb: polling mode is PERIODIC


fousb: polling interval is 60


fousb: altitude is 4.2672 meters


fousb: pressure offset is 0.0


fousb: found station on USB bus=001 device=005


wxengine: StdConvert target unit is 0x1


wxengine: Record generation will be attempted in 'hardware'


wxengine: The archive interval in the configuration file (300) does not match the station hardware interval (60).


wxengine: Using archive interval of 60 seconds


archive: Created and initialized table 'archive' in database 'weewx.sdb'


wxengine: Using archive database: archive_sqlite


stats: Created schema for statistical database


stats: stats database up to date.


wxengine: Using stats database: stats_sqlite


wxengine: Starting up weewx version 2.6.4

If you encounter errors you can edit your weewx configuration using nano -w /etc/weex/weewx.conf
Once you’ve finished editing press ctrl+x (to exit), then y(to save), then enter(same filename). Then restart weewx using /etc/init.d/weewx restart
If all has gone well you may also see entries in your syslog like
weewx[12559]: archive: added record 2014-09-20 18:32:44 UTC (1411237964) to database 'weewx.sdb'; table 'archive'
You should also have /var/www/weewx loaded with files.
As we haven’t yet installed a webserver though you can’t view them.
We’ll install Apache2 Server to handle our webpages.
apt-get install apache2
Once apache is installed open the weewx pages by visiting http://{raspberry pi ip address}/weewx from your browser. e.g. http://192.168.1.52/weewx
This setup does leave weewx running as root, not really something you would do for a system running on the internet. but outside the scope of securing your server for here.
Checkout http://www.weewx.com/docs/usersguide.htm#installing for more info on installing, problems and further guides for configuring your weewx installation.
Also checkout http://davies-barnard.co.uk/2013/12/weewx-rasp/ for a better looking skin template (the link is in one of the comments).

Raspberry PI + GlusterFS (Part 4)

In Part 1 I mentioned encrypting my disks. but didn’t go into it, so here I’m going to run through encrypting, decrypting and using it with GlusterFS.
Part 2 Was an attempted but failed install of the latest GlusterFS (3.5.0) Server
Part 3 Covered installing GlusterFS Server with the new information from Ashley

To recap I’m using the following:-
2 PI’s
2 8Gb SD Cards
2 4GB USB Sticks
2 512Mb USB Sticks.

As yet we haven’t setup any Gluster Volumes and this is all on a pretty fresh system.

First we need to install some tools we’ll be using.

apt-get install cryptsetup pv

I know my 4GB USB Stick is on /dev/sda and 512Mb is on /dev/sdb, I’ll only be concentrating on the 4Gb in this, but make sure if your following along that your using the correct paths. Using the wrong paths can wipe your data.

I dont want any partitions on the stick (I’ll be encrypting the whole drive)

fdisk -l

Shows me I’ve got a few partitions on the stick:-

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   ?   778135908  1919645538   570754815+  5b  Unknown
/dev/sda2   ?   168689522  2104717761   968014120   65  Novell Netware 386
/dev/sda3   ?  1869881465  3805909656   968014096   79  Unknown
/dev/sda4   ?  2885681152  2885736650       27749+   d  Unknown

I can’t remember what this stick was used for (to my knowledge I’ve never used Novell partitions), but we’ll delete them all.

fdisk /dev/sda
d
1
d
2
d
3
d
wq
My partitions were listed 1-4 so it was nice and easy. You can rerun the fdisk -l command to check they’ve all gone.
This step wasn’t strictly necessary but I always like to make sure I’m working with the correct drives.
With the Drive empty of partitions I like to unplug it and plug it back in (keep everything fresh) Note: if you do reconnect the drive make sure your still working with the correct /dev/sd* path. Sometimes this can change.
Now run
cryptsetup -y -v luksFormat /dev/sda
This creates a new encryption key for the Drive (note this is not how you add new keys on a drive, only do this once!!)
Then we need to unlock the drive for use
cryptsetup luksOpen /dev/sda USB1_Crypt
/dev/sda is the drive path
USB1_Crypt is what we’re going to be labelling the decrypted drive.
You’ll be prompted for the Drive passphrase that you just created. If successful it doesn’t actually tell you, just drop you back to a prompt. From here on we wont be doing any drive work on /dev/sda as this will be outside the encrypted bit, we’ll be using /dev/mapper/USB1_Crypt
We can check it’s unlocked with
ls -l /dev/mapper/
You should see something similar to
lrwxrwxrwx 1 root root       8 May 13 18:39 USB1_Crypt -> ../dm-1
You can also check the status using
cryptsetup -v status USB1_Crypt
Now that we have the drive with an encryption key and unlocked we’ll write a bunch of data across the drive
pv -tpreb /dev/zero | dd of=/dev/mapper/USB1_Crypt bs=128M
Writing zero’s to a drive is generally considered bad for data security, but we’re writing them to the encrypted system not the actual stick, so the output to the stick will be encrypted data.
Once the data has finished writing we’ll create a new filesystem on the encrypted disk
mkfs.ext4 /dev/mapper/USB1_Crypt
You don’t have to use ext4, but I generally do.
That’s the USB Stick encrypted
We close the encrypted drive and remove it from /dev/mapper/ with

cryptsetup luksClose USB1_Crypt

If all you wanted was an encrypted Drive that’s it, and you can unlock the drive on systems with cryptsetup installed and then mount away.

So far we’ve encrypted the entire USB Stick, written a bunch of encrypted data across the entire Stick, created a new filesystem, and closed the Stick.
Now we’re ready to mount the Stick ready for Gluster to use.
We’re going to create a folder to mount the Drive into

mkdir /mnt/USB1
We’ll open the encrypted Drive again using

cryptsetup luksOpen /dev/sda USB1_Crypt
Then mount the decrypted drive

mount /dev/mapper/USB1_Crypt /mnt/USB1
If you

ls -l /mnt/USB1
You should see the lost+found directory on the filesystem.
I should mention again I’ve been running through this process on 2 PI’s, and to keep things simple I’m keeping the same names on both systems /mnt/USB1
Now it’s time to get GlusterFS running with these drives.
So while on Gluster-1(PI) issue the command

gluster peer probe Gluster-2
This should find and add the peer Gluster-2 and you can check with

gluster peer list
and

gluster peer status
Now because I always want each Gluster system working by name from Gluster-2 I issue

gluster peer probe Gluster-1
This updates the Gluster-1 peer to it’s name not it’s IP address, There’s nothing wrong with using IP addresses if your using static assigned IP’s on your PI’s, but I wouldn’t recommend doing so if your IP address is DHCP’d
With glusterfs knowing about both Gluster-1 and Gluster-2 we can create a new volume (It’s important that /mnt/USB1 has been mounted on both system before proceeding)
On either PI you can create a new replica volume with 

gluster volume create testvol replica 2 Gluster-1:/mnt/USB1 Gluster-2:/mnt/USB1
This will create a new volume called testvol using /mnt/USB1 on both PI’s. The folder /mnt/USB1 is now referred to as a brick. and volumes consist of bricks.
Now we start the volume

gluster volume start testvol
Finally we need somewhere to mount the gluster filesystem

mkdir /media/testvol
Then we mount it

mount.glusterfs Gluster-1:/testvol /media/testvol
It doesn’t matter which host we use in this command, apparently it’s only used to pull the list of bricks for this volume and will then balance the load.
Now you can write data to /media/testvol. If you’ve mounted the volume on both PI’s you will see the files on both.
You can also

ls -l /mnt/USB1
To see the actual files on the stick (DO NOT do any more than just read the files from /mnt/USB1, playing in this folder can cause issues, you should only be using /media/testvol from now on).
If instead of replica you used a stripe, you’ll be able to see all the files in /media/testvol but only some files in /mnt/USB1 on each PI.
Shutting down 1 of the PI’s in a replca mode volume wont show any difference in /media/testvol (and hopefully on the new 3.5.0 version wont cause you as much of a headache if files get updated while 1 PI is offline, though it is likely to need manual intervention to fix maybe a part 4 🙂 when I get that far) but in striped mode with 1 of the PI’s offline you’ll notice files in /media/testvol have gone missing. For this reason I’m hoping to do both stripe and replica to keep files available across multiple PI’s and allow me to increase the storage space easily.
Replicating across 2 drives will mean I will need to add new storage 2 drives at a time.
Replicating across 3 drives would mean I need to add 3 new drives each time.
Just to make things easy I’ll list the commands to decrypt and mount after the PI has been reboot

cryptsetup luksOpen /dev/sda USB1_Crypt

mount /dev/mapper/USB1_Crypt /mnt/USB1

mount.glusterfs Gluster-1:/testvol /media/testvol

Raspberry PI + GlusterFS (Part 3)

After hitting errors when installing  in Part 2 I decided to split out the solution.
Ashley saw part 2 and had already ran into the same problem (see the comment), thanks to his comment it gave me a huge help on what to do next.
I’ve started with a fresh raspberry pi image so that nothing conflicts. Again get the latest updates

apt-get update
apt-get upgrade

Then download the needed files with the following commands

wget http://download.gluster.org/pub/gluster/glusterfs/3.5/LATEST/Debian/apt/pool/main/g/glusterfs/glusterfs_3.5.0.orig.tar.gz
wget http://download.gluster.org/pub/gluster/glusterfs/3.5/LATEST/Debian/apt/pool/main/g/glusterfs/glusterfs_3.5.0-1.dsc
wget http://download.gluster.org/pub/gluster/glusterfs/3.5/LATEST/Debian/apt/pool/main/g/glusterfs/glusterfs_3.5.0-1.debian.tar.gz

Now extract the archives

tar xzvf glusterfs_3.5.0.orig.tar.gz
tar xzvf glusterfs_3.5.0-1.debian.tar.gz

We need some tools so

apt-get install devscripts

Then we move the debian folder into the glusterfs folder and change into the glusterfs folder

mv debian glusterfs-3.5.0/
cd glusterfs-3.5.0

Next run

debuild -us -uc

This will start but will throw dependency errors.
The important line is

Unmet build dependencies: dh-autoreconf libfuse-dev (>= 2.6.5) libibverbs-dev (>= 1.0.4) libdb-dev attr flex bison libreadline-dev libncurses5-dev libssl-dev libxml2-dev python-all-dev (>= 2.6.6-3~) liblvm2-dev libaio-dev librdmacm-dev chrpath hardening-wrapper

Which I resolved with

apt-get install dh-autoreconf libfuse-dev libibverbs-dev libdb-dev attr flex bison libreadline-dev libncurses5-dev libssl-dev libxml2-dev python-all-dev liblvm2-dev libaio-dev librdmacm-dev chrpath hardening-wrapper

With the dependencies installed I ran

debuild -us -uc

This may output some warnings. On my system I had a few warnings and 2 errors “N: 24 tags overridden (2 errors, 18 warnings, 4 info)”, but it didn’t seem to affect anything.
Now we’ll wrap up with

make
make install

The Make probably isn’t necessary, Once installed we need to start the service

/etc/init.d/glusterd start

You can check everything is working ok with

gluster peer status

This should return

Number of Peers: 0

The only thing left to do is ensure glusterd starts with the system

update-rc.d glusterd defaults

And we’re all set. Now you can take a look at Part 4

Raspberry PI + GlusterFS (Part 2)

IMPORTANT: When running through the steps in Part 2 I encounter errors. Thanks to Ashley commenting I’ve created Part 3. I’ve decided to leave Part 2 intact for anyone searching on errors etc.

Hopefully you’ve read Part 1 and understood what I’m trying to do and why.

Here’s Part 2 attempting the install.
Part 3 Actually does the installation now.
Part 4 will cover the encryption and setup.
First things first, I (being naughty) use root far too much in testing, but do not recommend it all the way through on production servers.
So lets get into root
sudo su -
This should place you in root’s home direcoty.

You can Skip down to get past errors I encountered, but it’s possibly still worth reading the below which ended up not working.

Now we’re going to grab gluster 3.5.0

wget http://download.gluster.org/pub/gluster/glusterfs/3.5/3.5.0/glusterfs-3.5.0.tar.gz
tar xzvf glusterfs-3.5.0.tar.gz
cd glusterfs-3.5.0/
DON’T do this step yet. At this point I jumped straight into a configure attempt
./configure
This threw errors that I’m missing flex or lex
configure: error: Flex or lex required to build glusterfs.
Clearly I’m going to need to install a few dependencies before going further

apt-get update
apt-get install make automake autoconf libtool flex bison pkg-config libssl-dev libxml2-dev python-dev libaio-dev libibverbs-dev librdmacm-dev libreadline-dev liblvm2-dev libglib2.0-dev pkg-config
I’m not sure if all these are needed, but after digging around that’s the list that’s used elsewhere.
Actually reading the INSTALL file says to start with ./autogen.sh so this time we will
./autogen.sh
This took about 5 mins, but didn’t throw errors. Next onto
./configure
This eventually spits out
GlusterFS configure summary
===========================
FUSE client          : yes
Infiniband verbs     : yes
epoll IO multiplex   : yes
argp-standalone      : no
fusermount           : yes
readline             : yes
georeplication       : yes
Linux-AIO            : yes
Enable Debug         : no
systemtap            : no
Block Device xlator  : yes
glupy                : yes
Use syslog           : yes
XML output           : yes
QEMU Block formats   : yes
Encryption xlator    : yes
Now we can get on with the actually compiling

make
This threw a number of warnings for me
warning: function declaration isn’t a prototype [-Wstrict-prototypes]
But didn’t seem to be of great concern.
After about an hour it was ready to continue (I wrote Part 4 from memory while waiting).
We install with


make install

Here’s where I’m getting an error.


../../py-compile: Missing argument to --destdir.

So it’s on stop until I can figure out how to resolve it. one suggestion from version 3.4.x was to add the prefix path to the configure, but this didn’t do anything for me.

Move on to Part 3

Raspberry PI + GlusterFS (Part 1)

Here’s Part 1 which is really background information.
Part 2 will be actually doing stuff, if you dont want to read how/why I ended up here skip to Part 2.

A few days ago I yet again ran out of space on my server. Normally this would just mean deleting a load of junk files, but I’ve been doing that for months I’m now at the point there are no junk files left to delete. So time to increase the storage. Unfortunately problem #2 I currently have 4 sata drives in the server taking up all the connections. Expanding wouldn’t be a problem as I originally setup the drives with lvm to handle large storage requirements. but now there’s nowhere to turn to increase the capacity in this server.

So instead I thought I’d have a look at the alternatives. I’d been hoping to move some of the server services over to PI’s since I first heard about the Raspberry PI project (long before they were released), I knew I could make good use of lots of them.

After a little searching I found Gluster, and this seems to be ideal for what I need. At this point I should say that I clearly expect any USB drive connected to the PI to be slower access than sata on my server. but for my use slower doesn’t matter. I doubt this would suit everyone, but I think Gluster is even a good option on beefy servers/pc’s.

I have an idea that needs testing, so I setup 2 PI’s with 2 USB sticks for storage. A simple apt-get install glusterfs-server gets me moving quickly while reading 2 guides http://www.linuxjournal.com/content/two-pi-r?page=0,0 and http://www.linuxuser.co.uk/tutorials/create-your-own-high-performance-nas-using-glusterfs I quickly have a working system. I’m not going to go into the steps, both the links give details, but here’s my layout:-
2 PI’s
2 8Gb SD Cards
2 4Gb USB Sticks
2 512Mb USB Sticks.
So each PI has an SD card, a 4gb USB Stick and a 512Mb USB Stick.

As I prefer to encrypt all data on my drives I installed cryptsetup and using luksFormat got the USB Sticks ready (more on this later), I unlocked the USB sticks on both PI’s which opens the drive to /dev/mapper/USB1_Crypt and /dev/mapper/USB2_Crypt
I then mount each to /mnt/USB1 and /mnt/USB2 (both were already ext4 filesystems) with USB1 being the 4Gb.
The PI’s are called Gluster-1 and Gluster-2, I know my DHCP and DNS are working so I can use the names when setting up the gluster peers and volumes instead of IP addresses.
Once I’d created the Gluster volume (I tested both stipe and replica) I mounted the testvol (Gluster Volume) into /media/testvol
I made a quick file, and could see it from both servers. It’s also interesting looking in the /mnt/USB1/ folder (but do NOT change anything in here), while using a stripe volume the new file only appears on 1 of the PI’s, creating more files puts some on Gluster-1 and some on Gluster-2. So to see what happens I reboot Gluster-1 and watched the files in /media/testvol yep all the files that are in testvol and actually on Gluster-1 disappear from the file list. As soon as Gluster-1 was back (decrypted and mounted /mnt/USB1) the files were back.

So this is looking pretty good, and adding more storage was easy (I didn’t go into rebalancing the files across new bricks, but I don’t see this being a huge problem). Now I moved onto using Replica instead of Stripe (my ultimate intention will be to use both). Here’s where the fun begins, I actually didn’t delete the test files in /mnt/USB1 from either server, just stopped the gluster volume and deleted it. Creating a new gluster volume in stripe mode was easy, and a few seconds after I started it gluster sync’d up the files already in /mnt/USB1 on both PI’s so now in /media/testvol I can still see all the files and access them fine. Now I reboot Gluster-2 and checked the files in /media/testvol on Gluster-1 yep all the files are there (there’s was a 2-3 second delay on ls I assume I was previously connected to Gluster-2 and it had to work out it wasn’t there anymore but from there on was fine).

I have a working replica system 🙂 and it’s taken me no-time at all to get running. I brought Gluster-2 back online, then thought what if I change files when one of them is offline. Reboot Gluster-1, and change some of the test in a few of the test files in /media/testvol and create a new testfile. Then I bring Gluster-1 back online, and here’s where things fall apart!!!
The new testfile is on both and fine, the existing files I hadn’t changed are all fine too. But the files I changed I can’t access anymore, I’m getting cat: testy1: Input/output error. This isn’t good so I check the file testy1 file in /mnt/USB1 on both PI’s, Gluster-2 has the changes (as expected it was online when I made the changes) Gluster-1 has the original.

So head over to google to find out how I’d fix such a scenario (a friend told me years ago “your never the first person to have a problem” google every error message) yep there’s information on it, it’s called split-brain. The first solution I find is to delete the file that’s wrong from /mnt/USB1 that is incorrect. This didn’t solve my problem, testy1 was recreated but was still giving I/O error a little more reading says that gluster creates hard links and you need to go and delete these too, apparently in a .glusterfs folder but I couldn’t find it, there was also a heal function that would show me what files are affected. But not on my system. gluster doesn’t know heal. WHY????
gluster -V tells me I’m running an old version from 2013 (I think 3.2.8 but that’s from memory) the latest version is 3.5.0

I also came across some information saying that Stripes using 3 or more can quorum changes to resolve issues with file differences (I think this has to be setup though, I can see situations that automatically doing so could cause data loss, such as log files being written and having different data not just that one may have stopped being written to).
Anyway it looks like having 3.5.0 with a heal function would be beneficial, and I always prefer for things to be upto date where possible anyway.
Looking at the Gluster download page there’s a simple way to add gluster to the debian apt system. So I followed the steps to add it, and run apt-get update. Now another problem it’s not able to download the gluster info, but the link it’s using I can access fine. Then something jumps out at me, “Architectures: amd64″, Raspberry uses arm so this isn’t built for it. Now I have no idea if this is right or wrong but it makes sense to me.

Like many other things, it’s time to manually compile and install.
So there’s the background (sorry it took so long), Part 2 is going to run through manually installing gluster on the PI

Error ‘glibc detected *** /usr/bin/python: double free or corruption (fasttop)’ on Raspberry Pi using Python

Just a very quick post.
I’m working on a small project I’ve had in mind for a few months, basically pull and image and display it on the tv (there’s more to it, or I’d just settle for RasBMC).

So I’ve been coding it all up using python with pygame to display the image, all fine.

Then I introduced loops to refresh the images, and update the display. I had issues around other code and couldn’t keep looking at the tv while the code was running so I introduced a few mp3’s to play as the images were being refreshed and as the display was updating. All worked well, it sounded like I was on the Enterprise.

Further into coding up different functions, and some more headaches I’d cleared up alot of the minor error’s I had been getting, and was now ready to push the system to speed up the refreshes.

I’d managed to put a few images to refresh every second, and it appeared to be going well.
Then it stopped making a sound, checked and python had crashed with error:
glibc detected *** /usr/bin/python: double free or corruption (fasttop)

So I changed the code I’d been working on (clearly that’s the problem, didn’t have this earlier), but nope didn’t solve it.
Onto google, but this brought up alot of big reports about other things. checked a few, made a few changes. but I’m still getting the problem. Troubling though, if this is going to come down to the fact I’m refreshing alot and it’s getting intensive, it’s going to be a show stopper for this project.

Thankfully I did a little more searching and came across
http://www.raspberrypi.org/forums/viewtopic.php?t=36878&p=308220

Now I dont have the same problem (playing wav’s) but this drew me to the fact I’m playing mp3’s and these have increased in how much I’m playing them and they now overlap alot more than earlier.

So I decided to drop them out. Eureka it’s been running about 15 minutes and not died (previously a few minutes), sad thing is I’m now kinda missing my beeps.
I had hoped to be able to play an alert sound, if certain events happened so I may have to rethink how I can do so without causing crashes.

Anyways there it is in case it’s of help to someone else. I’ll be posting about the project at a later date, once I’ve done a little more with the code and tested it a bit more. It’s my first serious attempt in python, I can make programmers cry at the best of times so I’m expecting people to be able to rip this apart (but I’m actually very interested in getting it stable, so will welcome the criticism/ideas.

Nagios Twitter Alerts

I’ve had nagios running for years, so decided to play around with the alerts.
Twitter seemed the obvious choice, it’s easy for a people to follow the twitter account that’s publishing the alerts, and great if you actively use twitter (I don’t, this was more of a ‘how would you’ rather than a need).
First thing is to register a twitter account that nagios will publish as. I setup https://twitter.com/NagiosStarB
Once you’ve registered you need to edit your profile and add a mobile phone number (This is needed before you can change the app permissions later. Once you’ve done that you can delete the mobile number).
Now head over to https://apps.twitter.com/ and create a new app
Fill in Name, Description and Website (This isn’t particularly important, as we’re not pushing this app out to users).
You’ll be taken straight into the new app (if not simply click on it).

We need to change the Access Level, Click on ‘modify app permissions’

I chose ‘Read, Write and Access direct messages’, although ‘Read and Write’ would be fine. Click ‘Update settings’ (If you didn’t add your mobile number to your account earlier, you;ll get an error).
Now click ‘API Keys’

You need to copy the API key and API secret (Please dont try to use mine).
Now click ‘create my access token’ close to the bottom of the page.

You also need to copy your ‘Access token’ and ‘Access tocken secret’

Now we move onto the notification script.
Login to your Nagios server via SSH.
You need to ensure you have python-dev & python-pip installed.

apt-get install python-dev python-pip
pip install tweepy

Then cd into your nagios libexec folder (mines at /usr/local/nagios/libexec)

cd /usr/local/nagios/libexec/

We now add a new file called twitternagiosstatus.py

nano -w twitternagiosstatus.py

Copy and paste the following code into the file

#!/usr/bin/env python2.7
# tweet.py by Alex Eames http://raspi.tv/?p=5908
import tweepy
import sys
import logging

# Setup Debug Logging
logging.basicConfig(filename='/tmp/twitternagios.log',level=logging.DEBUG)
logging.debug('Starting Debug Log')

# Consumer keys and access tokens, used for OAuth
consumer_key = 'jNgRhCGx7NzZn1Cr01mucA'
consumer_secret = 'nTUDfUo0jH2oYyG8i6qdyrQXfwQ6QXT7dwjVykrWho'
access_token = '2360118330-HP5bbGQgTw5F1UIN3qOjdtvqp1ZkhxlHroiETIQ'
access_token_secret = 'rXjXwfoGGNKibKfXHw9YYL927kCBQiQL58Br0qMdaI5tB'

# OAuth process, using the keys and tokens
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

# Creation of the actual interface, using authentication
api = tweepy.API(auth)

if len(sys.argv) >= 2:
    tweet_text = sys.argv[1]
    logging.debug('Argument #1 ' + tweet_text)

    if len(tweet_text) <= 140:
        logging.debug('Tweeting: ' + tweet_text)
        api.update_status(tweet_text)
    else:
        print "tweet sent truncated. Too long. 140 chars Max."
        logging.debug('Too Long. Tweet sent truncated.')
        api.update_status(tweet_text[0:140])

Replace consumer_key with your API key, consumer_secret with your API secret, access_token with your access token and access_token_secret with your Access token secret.
Now save and exit the editor.

CTRL+x then Y then Enter.

With the file saved, we need to make it executable.

chmod +x twitternagiosstatus.py

You can now test that the script works by typing

./twitternagiosstatus.py "testy testy"

You should now be able to see the Tweet on your new account (you may need to refresh the page).
If all has gone well so far, you can now add your Nagios Configuration.
Change Directory into your nagios etc

cd /usr/local/nagios/etc/

Edit your commands.cfg (mine is inside objects)

nano -w objects/commands.cfg

Where you choose to place the new configurations doesn’t really matter, but to keep things in order I choose just below the email commands.
Copy and paste the following

# 'notify-host-by-twitter' command definition
define command{
        command_name    notify-host-by-twitter
        command_line    /usr/local/nagios/libexec/twitternagiosstatus.py "$NOTIFICATIONTYPE$: $HOSTALIAS$ is $HOSTSTATE$"
}

# 'notify-service-by-twitter' command definition
define command{
        command_name    notify-service-by-twitter
        command_line    /usr/local/nagios/libexec/twitternagiosstatus.py "$NOTIFICATIONTYPE$: $SERVICEDESC$ ON $HOSTALIAS$ is $SERVICESTATE$"
}

You can adjust the specifics, but adding other $$ arguments (Use the email notification commands as an example). Save and exit

CTRL+x, then Y, then ENTER

Now we add a new contact. Edit contacts.cfg

nano -w objects/contacts.cfg

Copy and Paste the following

define contact{
        contact_name                    nagios-twitter
        alias                           Nagios Twitter

        service_notification_period     24x7
        host_notification_period        24x7
        service_notification_options    w,u,c,r,f
        host_notification_options       d,u,r,f,s
        service_notification_commands   notify-service-by-twitter
        host_notification_commands      notify-host-by-twitter
        }

define contactgroup{
        contactgroup_name       nagiostwitter
        alias                   Nagios Twitter Notifications
        members                 nagios-twitter
        }

I decided to create a specific contact and contact-group for this, but you can adjust as you wish, add the contact to other contact-groups if you wish.
Now the last bit,
Add the new contact group to the hosts & services, templates or host-groups and service-groups.
How you decide to do this will depend on how you’ve set out your hosts, services, templates and contacts. For me I edit the each of the host files and add contact_groups  nagiostwitter to each host and service.
(IMPORTANT: this will override settings that are inherited from templates, so if you already have email notifications active you’ll either have to just add nagiostwitter to the template or add users to this). Dont forgot to , delimited
An example host of mine

define host{
        use                     linux-server            ; Name of host template$
                                                        ; This host definition $
                                                        ; in (or inherited by) $
        host_name               excalibur
        alias                   Excalibur
        address                 192.168.1.27
        parents                 switch-netgear8
        hostgroups              linux-servers
        statusmap_image         linux40.gd2
        contact_groups          nagiostwitter,sysadm
        }

An example service on this host

define service{
        use                             generic-service         ; Name of servi$
        host_name                       excalibur
        service_description             PING
        check_command                   check_ping!100.0,20%!500.0,60%
        contact_groups                  nagiostwitter,sysadm
        }

That’s it, hopefully if all’s done right you can restart the nagios service.

/etc/init.d/nagios restart

Now your twitter feed will start to be populated with each alert. I can’t emphasis enough that if the nagios configuration is done wrong you may break other alerts that are already setup.
I really need to thank http://raspi.tv/2013/how-to-create-a-twitter-app-on-the-raspberry-pi-with-python-tweepy-part-1#install here as I used this as a starting point.

UPDATE:
A few weeks ago I received an email from twitter telling me my application had been blocked for write operations. It also said to check the Twitter API Terms of Service. I didn’t think this would cause a problem, I’m not spamming anyone other than myself or users I’ve asked to follow the alerts. So I read the Terms of Service, and it’s all fine. I raised a support request with Twitter and had a very quick response saying “Twitter has automated systems that find and disable abusive API keys in bulk. Unfortunately, it looks like your application got caught up in one of these spam groups by mistake. We have reactivated the API key and we apologize for the inconvenience.”
This did stop my alerts for a few days though.So just be aware of this.

UPDATE 2:
Thanks to a comment from Claudio to truncate messages over 140 characters. I’ve incorporated this recommendation into the code above.

Raspberry PI + RTorrent +Apache2 + RUTorrent

I’ve been using one of my PI’s as a torrent server for some time. Recently I decided to refresh the entire system. This will NOT go into the legalities of downloading anything, I expect everyone to only be using this for downloading raspberry images 🙂

Version Info:
2014-01-07-wheezy-raspbian.img
libtorrent 0.13.2
rtorrent 0.9.2
rutorrent 3.6

I’m going to assume you can SSH to your PI, and recommend you get all the latest updates before you start. I’m also going to be naughty and be running all the commands as root.
sudo su –

Then we’ll get the stuff needed to compile rtorrent and a few things needed for the plugins

apt-get install subversion build-essential automake libtool libcppunit-dev libcurl3-dev libsigc++-2.0-dev libxmlrpc-c-dev unzip unrar-free curl libncurses-dev apache2 php5 php5-cli php5-curl libapache2-mod-scgi mediainfo ffmpeg screen

While your waiting may as well get a coffee. With that all finished we’re going to grab the rtorrent packages.

mkdir /root/rtorrent
cd /root/rtorrent

wget http://libtorrent.rakshasa.no/downloads/libtorrent-0.13.2.tar.gz
wget http://libtorrent.rakshasa.no/downloads/rtorrent-0.9.2.tar.gz
wget http://dl.bintray.com/novik65/generic/rutorrent-3.6.tar.gz
wget http://dl.bintray.com/novik65/generic/plugins-3.6.tar.gz

tar xvf libtorrent-0.13.2.tar.gz
tar xvf rtorrent-0.9.2.tar.gz
tar xvf rutorrent-3.6.tar.gz
tar xvf plugins-3.6.tar.gz

Now that you’ve got everything extracted it’s time to compile and install libtorrent

cd /root/rtorrent/libtorrent-0.13.2
./autogen.sh
./configure
make
make install

With libtorrent installed it’s time to compile and install rtorrent

cd /root/rtorrent/rtorrent-0.9.2
./autogen.sh
./configure --with-xmlrpc-c
make
make install
ldconfig

Once you’ve reached this bit, we’re finished with the hanging around. We’ll now install rutorrent and it’s plugins

cd /root/rtorrent
rm /var/www/index.html
cp -r rutorrent/* /var/www/
cp -r plugins/* /var/www/plugins
chown -R www-data:www-data /var/www
a2enmod scgi
service apache2 restart

We’ll next create a new user account for rtorrent to run as

adduser -m -r rtorrent

Now we switch to the new user account to add the required rtorrent directories and config

su rtorrent
mkdir .sessions
mkdir complete
mkdir torrents
mkdir watch
nano -w .rtorrent.rc

Copy and Paste the following:-

# This is an example resource file for rTorrent. Copy to
# ~/.rtorrent.rc and enable/modify the options as needed. Remember to
# uncomment the options you wish to enable.

# Maximum and minimum number of peers to connect to per torrent.
#min_peers = 40
#max_peers = 100

# Same as above but for seeding completed torrents (-1 = same as downloading)
#min_peers_seed = 10
#max_peers_seed = 50

# Maximum number of simultanious uploads per torrent.
#max_uploads = 15

# Global upload and download rate in KiB. "0" for unlimited.
download_rate = 0
upload_rate = 100

# Default directory to save the downloaded torrents.
directory = ~/torrents

# Default session directory. Make sure you don't run multiple instance
# of rtorrent using the same session directory. Perhaps using a
# relative path?
session = ~/.sessions

# Watch a directory for new torrents, and stop those that have been
# deleted.
schedule = watch_directory,5,5,load_start=~/watch/*.torrent
schedule = untied_directory,5,5,stop_untied=~/watch/*.torrent

# Close torrents when diskspace is low.
schedule = low_diskspace,5,10,close_low_diskspace=200M

# Stop torrents when reaching upload ratio in percent,
# when also reaching total upload in bytes, or when
# reaching final upload ratio in percent.
# example: stop at ratio 2.0 with at least 200 MB uploaded, or else ratio 20.0
#schedule = ratio,60,60,"stop_on_ratio=200,200M,2000"
#schedule = ratio,5,5,"stop_on_ratio=1,1M,10"
ratio.enable=
ratio.min.set=1
ratio.max.set=2
ratio.upload.set=1K
system.method.set = group.seeding.ratio.command, d.close=, d.stop=

# Set Schedules
#schedule = throttle_1,00:10:00,24:00:00,download_rate=0
#schedule = throttle_2,07:50:00,24:00:00,download_rate=200

# Stop Seeding When complete
#system.method.set_key = event.download.finished,1close_seeding,d.close=
#system.method.set_key = event.download.finished,2stop_seeding,d.stop=

# The ip address reported to the tracker.
#ip = 127.0.0.1
#ip = rakshasa.no

# The ip address the listening socket and outgoing connections is
# bound to.
##bind = 127.0.0.1
#bind = rakshasa.no

# Port range to use for listening.
port_range = 51515-51520

# Start opening ports at a random position within the port range.
#port_random = no

# Check hash for finished torrents. Might be usefull until the bug is
# fixed that causes lack of diskspace not to be properly reported.
#check_hash = no

# Set whetever the client should try to connect to UDP trackers.
use_udp_trackers = yes

# Alternative calls to bind and ip that should handle dynamic ip's.
#schedule = ip_tick,0,1800,ip=rakshasa
#schedule = bind_tick,0,1800,bind=rakshasa

# Encryption options, set to none (default) or any combination of the following:
# allow_incoming, try_outgoing, require, require_RC4, enable_retry, prefer_plaintext
#
# The example value allows incoming encrypted connections, starts unencrypted
# outgoing connections but retries with encryption if they fail, preferring
# plaintext to RC4 encryption after the encrypted handshake
#
# encryption = allow_incoming,enable_retry,prefer_plaintext
#encryption = allow_incomming,try_outgoing

# Enable DHT support for trackerless torrents or when all trackers are down.
# May be set to "disable" (completely disable DHT), "off" (do not start DHT),
# "auto" (start and stop DHT as needed), or "on" (start DHT immediately).
# The default is "off". For DHT to work, a session directory must be defined.
#
# dht = auto
dht = off

# UDP port to use for DHT.
#
# dht_port = 6881

# Enable peer exchange (for torrents not marked private)
#
# peer_exchange = yes
peer_exchange = no

#
# Do not modify the following parameters unless you know what you're doing.
#

# Hash read-ahead controls how many MB to request the kernel to read
# ahead. If the value is too low the disk may not be fully utilized,
# while if too high the kernel might not be able to keep the read
# pages in memory thus end up trashing.
#hash_read_ahead = 10

# Interval between attempts to check the hash, in milliseconds.
#hash_interval = 100

# Number of attempts to check the hash while using the mincore status,
# before forcing. Overworked systems might need lower values to get a
# decent hash checking rate.
#hash_max_tries = 10

#Added for rutorrent stuff
encoding_list = UTF-8
#scgi_local = /tmp/rpc.socket
#schedule = chmod,0,0,"execute=chmod,777,/tmp/rpc.socket"
scgi_port = localhost:5000

# Start The Plugins when Rtorrent Starts not when the page is first opened. If apache service is restart separately the plugins are likely to be stopped. Only really needed for RSS feeds.
execute = {sh,-c,/usr/bin/php /var/www/php/initplugins.php &}

Save and Exit (ctrl+x then y then enter)
We now need to perform a test run of rtorrent.

rtorrent

It should start without any problems. You may get a few warnings inside rtorrent, but it should still be running. To Exit press ctrl+q.
You should now exit the rtorrent user.

exit

Finally we’re going to setup rtorrent to automatically start when the PI is powered up.

nano -w /etc/init.d/rtorrent

Copy and Paste the Following:-

#!/bin/bash

# To start the script automatically at bootup type the following command
# update-rc.d torrent defaults 99

RTUSER=rtorrent
TORRENT=/usr/local/bin/rtorrent

case $1 in
start)
#display to user that what is being started
echo "Starting rtorrent..."
sleep 4
#start the process and record record it's pid
rm /home/rtorrent/.sessions/rtorrent.lock
start-stop-daemon --start --background --pidfile /var/run/rtorrent.pid --make-pidfile --exec /bin/su -- -c "/usr/bin/screen -dmUS torrent $TORRENT" $RTUSER
## start-stop-daemon --start --background --exec /usr/bin/screen -- -dmUS torrent $TORRENT
#output failure or success
#info on how to interact with the torrent
echo "To interact with the torrent client, you will need to reattach the screen session with following command"
echo "screen -r torrent"
if [[ $? -eq 0 ]]; then
echo "The process started successfully"
else
echo "The process failed to start"
fi
;;

stop)
#display that we are stopping the process
echo "Stopping rtorrent"
#stop the process using pid from start()
start-stop-daemon --stop --name rtorrent
#output success or failure
if [[ $? -eq 0 ]]; then
echo "The process stopped successfully"
else
echo "The process failed to stop"
fi
;;

*)
# show the options
echo "Usage: {start|stop}"
;;
esac

Save and Exit (ctrl+x then y then enter)
Then run


chmod +x /etc/init.d/rtorrent

update-rc.d rtorrent defaults

And that’s it. You could now start rtorrent using “/etc/init.d/rtorrent start”, but it’s just as easy to reboot and test that the startup scripts runs. Once you’ve reboot or started rtorrent you can access the webpage at http://{ip-address or name} Notes:-

This setup is meant to run internally, as such there is no security on the apache setup.

Personally I forward ports 51515-51520 on the router onto the PI, this makes a difference in download speed (much quicker) but as it's opening ports it's a security risk so you'll have to decided whether or not to.

I run this setup behind a vpn using ipredator.se, if there's any demand I'll write up another guide on how to configure that and ensure your traffic is locked to only go over the vpn.

Raspberry PI – LDAP Auth

Using Rasbian 20-12-2013 with updates

Install libnss-ldap

apt-get install libnss-ldap

Once complete you’ll be prompted for ldap details

ldap server e.g ldap://192.168.1.3/ ldap://192.168.1.2/
base dn e.g dc=system,dc=local
ldap version e.g 3
Does LDAP require login e.g No
Special LDAP privileges for Root e.g No

Once you’ve given the ldap details you need to update nsswitch.conf

nano -w /etc/nsswitch.conf

Previous config:

passwd:         compat
group:          compat
shadow:         compat

hosts:          files dns

networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

New config:

#passwd:         compat
passwd:         files ldap
#group:          compat
group:          files ldap
#shadow:         compat
shadow:         files ldap

hosts:          files dns

networks:       files

protocols:      db files
services:       db files
ethers:         db files
rpc:            db files

netgroup:       nis

Then we add the following so that home directories are automatically created

nano -w /usr/share/pam-configs/my_mkhomedir
Name: activate mkhomedir

Default: yes
Priority: 900
Session-Type: Additional
Session:
required                        pam_mkhomedir.so umask=0022 skel=/etc/skel

Apply the above using

pam-auth-update

To make sure everything is applied and the cache daemon doesn’t screw about I reboot. Once reboot login worked fine. A few commands that can help see what’s happening

getent passwd
getent group
tail /var/log/auth.log