Monday, November 19, 2012

Raspberry Pi I2C

I have a Raspberry Pi and lets face it, who doesn't?

I have played with linux on many architectures before including PPC, Hitachi, MIPS, PA-RISC and Sparc so I figure I had better have a go at ARM too.

Apart from playing around, I plan to create a light controller module for my garden lights. This will require some hardware hacking which is always a bit of fun but my main plan is to bring it together with some fancy software.

In previous projects I have interfaced with GPIO and I2C to run door controllers and read swipe cards (Mostly on the WRT54G).

I could not find accurate instructions for getting I2C going on the rpi so here are my instructions for users for raspbian:

Install some tools
# apt-get install i2c-tools

edit  /etc/modprobe.d/raspi-blacklist.conf and comment out the line


i2c-bcm2708

I don't know why it comes as blacklisted.

edit /etc/modules and add the lines
i2c-bcm2708
i2c-dev
This will make sure the drivers are loaded during the boot.

create a file /etc/udev/rules.d/99-i2c.rules and add the line
SUBSYSTEM=="i2c-dev", MODE="0666"
This will give all users access to the i2c devices. You could instead set the owner or group but the rpi is not normally being used as a multi-user device

Now you can test these changes without a reboot:
modprobe i2c-bcm2708
modprobe i2c-dev
udevadm trigger
ls -l /dev/i2c*

And you should see output like this (Your date will be different):
crw-rw-rwT 1 root i2c 89, 0 Nov 18 22:36 /dev/i2c-0
crw-rw-rwT 1 root i2c 89, 1 Nov 18 22:36 /dev/i2c-1

If that works, reboot and run the ls again. The devices should be there and have world read/write permissions.

Now, to connect up some hardware and show that it works. Look for a new blog soon.

Saturday, November 10, 2012

Samba guest access

I was trying to share some photos for my wife to download from my linux desktop machine (CentOS 6). I had ~10Gig of photos but she only wanted a hand full. I though the best option would be to share out the folder using samba and she can use windows explorer to pick the ones she wants

Well it seems simple now but it took a few tries to get it working.

I use security=server which is not the most secure method but it is normally easy & convenient. It also seems to be poorly documented, particularly for more recent samba releases and versions of Windows.

My wife has an account on the password server but not on my new desktop. Guest access I though would be a simple solution here but no so. The problem is that guest access will not work by default when using security=server (despite what the man page says). There is a new setting called map to guest which defaults to Never. I had to change this to Bad User to get it to work.

There are the relevant parts from my working smb.conf:
security = server
password server = myserver
map to guest = Bad User

[photos]
comment = John's photos
path = /home/jnewbigin/photos
guest ok = yes
writable = no
force user = jnewbigin


So now it is working and I am happy and my wife is happy too.

Wednesday, October 31, 2012

Puppet DNS lookup

From time to time NetworkManager breaks my /etc/resolv.conf. I normally turn that off using puppet but when /etc/resolv.conf is broken, puppet won't run so I have to fix it manually :-(

Well, not any more. Now I add a static /etc/hosts entry for the puppet server and puppet will run even when /etc/resolv.conf is broken.

The special part about this is that I look up the IP address using a template so I don't have to hard code the value in my manifest. Google said it could not be done without writing a custom function. As always, I did not believe it...

Assuming you have set $puppetserver to contain the fqdn of your puppet server:

host { 'hostsconf-puppet':
        ensure => present,
        ip => inline_template("<% _erbout.concat(Resolv::DNS.open.getaddress('$puppetserver').to_s) %>"),
        name => $puppetserver,
        target => '/etc/hosts',
}



Tuesday, October 23, 2012

KVM file permissions

Recently I have been testing CentOS 6 with libvirt & KVM. My goal is to set up a cluster of servers and enable migration between them without shared storage.

This seems possible but I hit a roadblock with file permissions. I am using a directory pool but any newly created file is assigned the permissions 0600 and owned by root:cso (cso is the group that all the sysadmins are in). The XML schema for libvirt pools allows me to specify a mode, owner & group but they don't seem to be honoured when the file is created.

My workaround to this problem was to create a hook which runs when a virtual machine is started. This gives me a chance to change the permissions to the correct values. The libvirt hooks are not widely publicised but at least on CentOS 6, you create the file and it just works. See http://libvirt.org/hooks.html

The basic skeleton for my hook is:
/etc/libvirt/hooks/qemu

#!/bin/bash
if [ "$2" = "prepare" -a "$3" = "begin" ] ; then
   # Fix the permissions
fi
exit 0


The next headache is that I don't know which disks are needed for this virtual machine. This info is provided on stdin but it is in XML which is not easy for bash to process.

My solution to this was to use XSLT to transform the XML into a bash script.
I have never used XSLT before so there was a fair amount of guessing involved. The output of xsltproc always has an XML header which I strip off with grep. The output is logged to syslog with the logger command. The final hook script looks like this:
/etc/libvirt/hooks/qemu
#!/bin/bash
if [ "$2" = "prepare" -a "$3" = "begin" ] ; then
   /usr/bin/xsltproc /etc/libvirt/hooks/qemu.hook.xsl - | \
      grep -v '?xml' | \
      sh -x | logger
fi
exit 0

As for the XSL, I am no expert but I got it working. I could not work out how to correctly escape the values of the file names so there could be a nasty surprise in there if you don't trust your users.

/etc/libvirt/hooks/qemu.hook.xsl 
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="domain/devices/disk/source">
chown qemu:cso '<xsl:value-of select="@file"/>'
chmod 0660 '<xsl:value-of select="@file"/>'
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>


Monday, October 8, 2012

Mobile Internet

I recently got a new work phone, the Samsung Galaxy Nexus. This is my first 'smart' phone and it seems to be a good fit with my Linux interests.

The problem is that work will not pay for mobile data so I can't make use of it on the train (some may argue that is a good thing). My workaround was to get a portable 3G to WIFI router aka, MIFI, Pocket WIFI etc.

I had already researched phone plans and worked out that the phone 'cap' seems to be one of the best marketing tricks ever schemed up. The only plan of interest to me is the TPG $1 per month pay as you go plan. Being an existing TPG customer I also get 150Mb of free data per month.

So the next question was which router to get? Most comparisons seemed to be caught up on the price of the data but I wanted to know which one works the best. In the end I went for the Vodafone Pocket WIFI. This is a Huawei E585 V2. It comes with a Vodafone SIM which you must activate and install yourself. On special for $40 I though I would give it a go. After several hours trying to activate the SIM and then a few more trying to make the phone get an address via DHCP I was on the internet. (The activation problem was because the Vodafone web site was asking for the wrong ID numbers. The DHCP is still an issue and is presumably a bug in ICS).

So, once it was all working I tried it out on the train and was most unimpressed. Although it would say connected it rarely managed to download as much as a web page. There are people complaining about this on the Vodafone forums and they insist that if there is a problem it will be fixed real soon now. Luckily, Vodafone did not factor in my plan so once my free month was up I unlocked the router and switched to TPG (which uses Optus 3G).

This is much more useful on the train though still does not knock my socks off. I have come to the realisation that the term 'Mobile Broadband' is a misnomer and should really be called 'Portable Broadband'. You can use it in one spot. You can take it and use it somewhere else, but try and use it on the way and it will not work very well at all.

Perhaps other networks work better. I see lots of new towers on the side of the train line. Perhaps other routers work better. The software quality on these things is never very impressive. Perhaps the whole thing is a joke and handing off to the next tower will never work (it does not work for voice, why would it work for data?).

Perhaps one day work will pay for my data and I can compare to the built in functionality of the phone.

Finally, it turns out that using facebook on the train is not as exciting as I was led to believe and my need for data is not that great anyway.

Thursday, September 13, 2012

Adding Drupal nodes with a specific ID

As part of a drupal upgrade/migration I had a requirement to create a few thousand nodes with specific IDs. The internet said it could not be done but I did not believe it.

After diving into the bowels of the drupal code I found the spot which did the creating and it seemed to be doing something quite reasonable with the new node ID.

With just a small amount of convincing I managed to get it to do what I wanted.

diff -ru vanilla/drupal-7.12/modules/node/node.module web/drupal/modules/node/node.module
--- vanilla/drupal-7.12/modules/node/node.module        2012-02-02 09:03:14.000000000 +1100
+++ web/drupal/modules/node/node.module     2012-05-28 16:37:36.827171000 +1000
@@ -1095,6 +1095,12 @@
     if ($node->is_new) {
       // For new nodes, save new records for both the node itself and the node
       // revision.
+if(isset($node->request_nid))
+{
+       echo "Requested save new node with nid {$node->request_nid}\n";
+       $node->nid = $node->request_nid;
+       //print_r($node);
+}
       drupal_write_record('node', $node);
       _node_save_revision($node, $user->uid);
       $op = 'insert';


Creating a node can now be done like this:
$node = new stdClass();
$node->type = ...;
node_object_prepare($node);
// fill in node details here...
$node->request_nid = $my_nid;
node_save($node);


That seems quite trivial now. I don't know why so many people say it can't be done.

Friday, September 7, 2012

/usr/bin/ld: cannot find -lm

I was updating some of my software to run on CentOS6 and I had an unexpected error:
/usr/bin/ld: cannot find -lm
collect2: ld returned 1 exit status

The tool I was building uses -static and it turns out that static libraries are no longer shipped in glibc-devel. They are in a new package called glibc-static.

yum install glibc-static
solved the problem. My program now compiles and thanks to puppet, glibc-static is now installed on all my systems.
package { 'glibc-static': ensure => present }