Xen, XFS and the barrier error

Probably nobody is going to hit this but since I’ve lost half a morning puzzling my mind about this error, I think it would be useful to blog about it.
We have some old Xen machine running Debian Lenny with Xen 3.2 and while upgrading a VM using a XFS root partition to Debian Wheezy (it was a Squeeze), I’ve got this nice error:

[ 5.024330] blkfront: xvda1: barrier or flush: disabled
[ 5.024338] end_request: I/O error, dev xvda1, sector 4196916
[ 5.024343] end_request: I/O error, dev xvda1, sector 4196916
[ 5.024360] XFS (xvda1): metadata I/O error: block 0x400a34 (“xlog_iodone”) error 5 buf count 3072
[ 5.024369] XFS (xvda1): xfs_do_force_shutdown(0x2) called from line 1007 of file /build/linux-s5x2oE/linux-3.2.46/fs/xfs/xfs_log.c. Return address = 0xffffffffa009fed5
[ 5.024394] XFS (xvda1): Log I/O Error Detected. Shutting down filesystem
[ 5.024401] XFS (xvda1): Please umount the filesystem and rectify the problem(s)
[ 5.024411] XFS (xvda1): xfs_log_force: error 5 returned.
[ 5.024419] XFS (xvda1): xfs_do_force_shutdown(0x1) called from line 1033 of file /build/linux-s5x2oE/linux-3.2.46/fs/xfs/xfs_buf.c. Return address = 0xffffffffa005f8a7

this strange error simply means that the underlying device doesn’t provide barrier support! The simple, quick fix (once you know it) is to specify in the fstab nobarrier option. I think that I found this problem because in Linux 3.2 the barrier option is enabled by default, while it was off in previous kernel versions.

Very slow Hadoop on PowerEdge R815

We have a little internal Hadoop cluster for development and testing, two very powerful Dell PowerEdge R815 with Debian and a bunch of Xen VMs to reproduce a production environment. Problem is that the cluster, even with a relatively small amount of data, was sloooow. And when I say slow I mean almost unusable for Hadoop development (a mapreduce on a small dataset took 5x more than on the big one in production). Even an insignificant

$ hadoop fs -ls

took more than 4s to list the content of HDFS. strace was showing tons of wait() syscalls for no apparent reason, while in the production system the same operation takes 1s and no wait() at all.
After trying almost everything (even without Xen and running Hadoop on the bare metal), I changed by chance a Power Management option in the R815 BIOS. By default it was set to Active Power Controller. Changing it to Maximum Performance did the trick! The ls now takes about a second, just like the production environment. My guess is that probably the default value (which is some kind of automagical load detection) wasn’t able to see that the machine really needed power when running Hadoop, leaving the CPU underclocked to save energy. Maximum power probably is not so green but it solved the problem

HOWTO: install puppet-dashboard on Debian Squeeze

This should apply to Ubuntu Server as well (10.10, 11.04) but it’s tested to work 100% on Debian Squeeze 6.0.
Puppet Dashboard is a neat piece of software really useful if you ara managing a good number of hosts without Puppet.

First of all, install the required deps:

# aptitude install ruby rake dbconfig-common libdbd-mysql-ruby mysql-client rubygems libhttpclient-ruby1.8

you’ll probably have lots of them already installed if you are running Puppet master on the same host (which by the way is not mandatory).
Then, download and install the deb package:

# wget http://downloads.puppetlabs.com/dashboard/puppet-dashboard_1.2.0-1_all.deb
# dpkg -i puppet-dashboard_1.2.0-1_all.deb

Enable the daemon editing the default file /etc/default/puppet-dashboard and then customize your database definition by editing /etc/puppet-dashboard/database.yml which should looks something like this:

production:
database: puppet_dashboard
host: your.database.host
username: puppet_dashboard
password: secret_password
encoding: utf8
adapter: mysql

if you plan to use MySQL as a backend. Remember to create the database and grant the appropriate privileges to the user

GRANT ALL PRIVILEGES ON puppet_dashboard.* TO 'puppet_dashboard'@'%' IDENTIFIED BY 'secret_password';

Now we have to populate the database, Rails way

# cd /usr/share/puppet-dashboard/
# rake RAILS_ENV=production db:migrate

Now you can start /etc/init.d/puppet-dashboard and /etc/init.d/puppet-dashboard-workers and you should be already able to access http://your-host.yourdomain.tld:3000 and see the Puppet Dashboard.
You just have to do two thing more before you can see any actual data in it: enable report sending in the Puppet clients and tell Puppet Master to pull those reports to the Dashboard via HTTP.

So, edit /etc/puppet.pupept.conf on the clients (I suggest you to do it via puppet if you do not already have this setting in it) and add

[agent]
# ... whatever you already have
report=true

and on the Master side

[master]
# ... whatever you already have
reports = store, http
reporturl = http://your-host.yourdomain.tld:3000/reports/upload

That’s it!

Disable directory listing in Apache with Debian

If you find one of your servers with the ugly directory listing enabled, there’s a quick way to disable it in Debian

# echo autoindex | a2dismod
# /etc/init.d/apache2 restart

For other Apache installations in other distro, you can simple find the Autoindex option in your config file and delete it manually, then restart Apache

EDIT: a cleaner and more elegant way to achieve the same is, as the comments section says

# a2dismod autoindex

thanks :)

HOWTO: Poor man VPN in Debian/Ubuntu with OpenSSH

If you are managing a remote Linux network and you are tired of NATting or two ssh hops to enter a remote server, but OpenVPN poses too much overhead, you can use ssh tunneling to easily create a workstation-to-site VPN.
I’ve tested this with Ubuntu 9.10 Karmic Koala as the workstation and Debian 5.0 Lenny as the server, but it should work identically with older Ubuntu and Debian (both server or workstation).

I’ve been inspired by these two tutorials, although both didn’t work 100% for me, but joining pieces did the trick, so here I am :)

Software prerequisites:

  • Standard Debian or Ubuntu
  • openssh-server on the remote side of the VPN
  • openssh-client on the local side of the VPN (your PC)

Network configuration (as an example)

  • Workstation LAN: 192.168.0.0/24
  • Server LAN: 192.168.10.0/24 on eth1
  • VPN: 10.0.0.0/24
  • Remote server public address: 1.2.3.4 on eth0

First of all, on the workstation generate a dedicated key (it should be a dedicated one cause the server will identify you’re going to bring up a tunnel based on the key you’re using to connect) with

# ssh-keygen -f /root/.ssh/VPNkey -b 2048

Now edit /etc/network/interfaces and create a new stanza like this one (remember to change IP addresses – in bold – according to your personal network configuration)

iface tun0 inet static
# from pre-up to true on the same line
pre-up ssh -i /root/.ssh/VPN -S /var/run/ssh-vpn-tunnel-control -M -f -w 0:0 1.2.3.4 true
pre-up sleep 5
address 10.1.0.2
pointopoint 10.1.0.1
netmask 255.255.255.0
up route add -net 192.168.10.0 netmask 255.255.255.0 gw 10.1.0.1 tun0
post-down ssh -i /root/.ssh/VPN -S /var/run/ssh-vpn-tunnel-control -O exit 1.2.3.4

Just a copuple of notes: address is your VPN local endpoint address (say, your workstation) while pointopoint is the remote VPNaddress (your server), which are the two tunnel’s endpoints.

Now let’s go to the server.

Edit /etc/ssh/sshd_server, add the line
PermitTunnel point-to-point

and restart your sshd instance.
Now edit (or create) /root/.ssh/authorized_keys (remember, we are on the server now, not your workstation) and add a line like

tunnel="0",command="/sbin/ifdown tun0; /sbin/ifup tun0" ssh-rsa HERE IT GOES YOUR VPNkey.pub FROM YOUR WORKSTATION

now edit /etc/network/interfaces and add this stanza:

iface tun0 inet static
address 10.1.0.1
netmask 255.255.255.0
pointopoint 10.1.0.2
post-up /sbin/sysctl -w net.ipv4.ip_forward=1
post-up /sbin/iptables -t nat -A POSTROUTING -s 10.1.0.0/24 -o eth1 -j MASQUERADE
post-down /sbin/iptables -t nat -D POSTROUTING -s 10.1.0.0/24 -o eth1 -j MASQUERADE
post-down /sbin/sysctl -w net.ipv4.ip_forward=0

the post-up and post-down commands enable the network sharing between the VPN server endpoint and the remote LAN (it’s called masquerading), so you can access the remote LAN from your workstation and not only the remote server. Obviously you need to instruct your workstation with a dedicated static route to reach the remote LAN network, and this is the route add -net in your workstation config.

Now, bring up the tunnel on the workstation with
# ifup tun0
and you should be able to reach a remote server on your remote LAN, with traffic secured by OpenSSH encryption.

HOWTO: Ethernet bonding in Debian Lenny

In an older post I explained how to create a bond interface in Debian Etch… now, this doesn’t work anymore due to some changes in Lenny.

So, long story short, first of all, install ifenslave

# apt-get install ifenslave-2.6

edit /etc/network/interfaces and add the bond0 config:

auto bond0
iface bond0 inet static
address 192.168.1.2
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1
# dns-* options are implemented by the resolvconf package, if installed
dns-nameservers 192.168.1.1
up /sbin/ifenslave bond0 eth0 eth1
down /sbin/ifenslave -d bond0 eth0 eth1

now edit /etc/modprobe.d/arch/x86_64 (change the filename depending on your architecture) and add these lines


alias bond0 bonding
options bonding mode=1 miimon=100 downdelay=200 updelay=200

Brief explanation:

  • miimon N: check if the active interface(s) is alive every N milliseconds
  • downdelay N: wait N milliseconds after a detected link failure to consider the link down
  • updelay N: wait N milliseconds after a detected link restoration to consider the link up
  • mode N: 1 means master/slave configuration, so there’s only one active master. If this link fails, then slave is used.

For a more complete description of all the possible parameters, refer to Linux Documentation/networking/bonding.txt

After this, you can restart networking or reboot if you are working remotely and it should work without a problem. It did for me :)

Column names with trailing spaces in tables and views

Just found out a bizarre feature of MySQL: you simply cannot create a table with a trailing space in a column name. Something like this, doesn’t work:

create table a (`a ` int);
ERROR 1166 (42000): Incorrect column name 'a '

There’s a thread in MySQL’s lists explaining it

Ok, it seems there’s a technical limitation but this solution seems like a lazy workaround to me.
The problem is with CREATE VIEW. In recent MySQL builds you cannot either create a view with a trailing space in a column name. But recent means, at least, greater than 5.0.51a, cause this version DOES let you create a view with a trailing space.

# mysql --version
mysql Ver 14.12 Distrib 5.0.51a, for debian-linux-gnu (x86_64) using readline 5.2

mysql> create view b as select a `a ` from a;
Query OK, 0 rows affected (0.00 sec)

There’s a big problem here: 5.0.51a is the default and supported version in Debian Lenny! So, if you have Lenny as a master of a more recent MySQL installation, be careful cause a CREATE VIEW with a trailing space in a column name will break your replication. Grrrr. MySQL, I hate you, really.

HOWTO: Install Mysql 5.1 for SPARC64 under Debian Lenny

If you happen to own a SPARC64 box, you’ll probably already know that even if the kernel is 64bit the userland comes from the normal SPARC Debian port, so it’s 32bit. Mysql is no exception, with all the 32bit limitations – mainly the 4GB RAM per process limit.

This is really  a PITA because if you have a SPARC64 box probably it has got plenty of RAM and you want to use it at its full potential, without having to messing around with Solaris (yeah, I don’t like it very much, I’m sorry).

This guide covers Mysql 5.1 installation in Debian Lenny, so we have to use SID repositories.


# echo "deb http://ftp.de.debian.org/debian/ sid main" >> /etc/apt/sources.list
# echo "deb-src http://ftp.de.debian.org/debian/ sid main" >> /etc/apt/sources.list

then let’s edit our apt preferences to avoid massive update on next dist-upgrade :)

# vim /etc/apt/preferences
Package: *
Pin: release a=stable
Pin-Priority: 900
Package: *
Pin: release a=sid
Pin-Priority: 100

and then update our repo list

# aptitude update

And here we go:

# apt-get build-dep mysql-server-5.1
# mkdir /tmp/mysql-build; cd /tmp/mysql-build
# apt-get source mysql-server-5.1
# vim mysql-dfsg-5.1*/debian/rules

here we touch a little the rules for compiling cause there are a couple of things that are not going to work by default.

The MAKE_J variable doesn’t work very well, so you can modify the grep to look for “CPU” instead of “processor” or you could hardcode it to the number of processor you have. This will make compilation a lot faster.

MAKE_J = -j$(shell if [ -f /proc/cpuinfo ] ; then grep -c CPU* /proc/cpuinfo ; else echo 1 ; fi)

then edit the CFLAGS variable because it’s used to compile some library that will ignore the environment variables we are going to set later in this howto.

CFLAGS=$${MYSQL_BUILD_CFLAGS:-"-O3 -DBIG_JOINS=1 -m64 -mcpu=niagara2 ${FORCE_FPIC_CFLAGS}"} \

it should be about line 73. Please note that -m64 will make it 64bit so it’s mandatory while the mcpu flag it’s to optimize the executable for your CPU. In my case it’s a niagara2 chip but you can use another CPU as well. Check the GCC documentation for more details
Save and quit and then we can start with the compilation process:

# export CFLAGS="-m64 -mcpu=niagara2 -O2 -g"
# export CXXFLAGS="-m64 -mcpu=niagara2 -O2 -g"
# export CPPFLAGS="-m64 -mcpu=niagara2 -O2 -g"
# export LDFLAGS="-m64 -mcpu=niagara2 -O2 -g"
# export DEB_BUILD_OPTIONS="nocheck"
# debuild -us -uc --preserve-env

that’s it. After some minutes (depending on your HW), you should have in /tmp/mysql-build all your new DEBs which you can install with dpkg -i. I advice to install the stock mysql-server-5.1 with aptitude before to get all dependencies installed, then you can use dpkg with your new DEBs.

HOWTO: install Transifex with Mysql on Debian Lenny

Transifex is a not-so-well-known opensource localization platform, written in Python and running on Django (a Python based application server, if you don’t know it). So, being not so well known, there isn’t a lot of documentation about it, and how to install it under Debian 5 Lenny it’s almost undocumented. So, here we go.

First of all, you have to install some packages. Luckily Lenny has got lot of them, although not all the needed

# aptitude install django python-urlgrabber python-setuptools python-pygments python-openid python-markdown python-httplib2
# aptitude install subversion
# aptitude install python-mysqldb
# aptitude install build-essential python-dev

These should be all the packages needed by Transifex which are available as deb packages. Now let’s install the remaining ones through easy_install

# easy_install django-authopenid django-pagination
# easy_install -f http://transifex.org/files/eggs/ contact_form tagging
# easy_install django-notification
# easy_install mercurial

Now the last package, django_evolution which is, AFAIK, only available as an SVN checkout from Google Code

# svn checkout http://django-evolution.googlecode.com/svn/trunk /tmp/django-evol
# mv /tmp/django-evol/django_evolution /usr/lib/python2.5/site-packages/

Now we can download the Transifex tarball

# cd /tmp && wget http://transifex.org/files/transifex-0.6.tar.gz
# tar xzvf transifex-0.6.tar.gz
# cp -a transifex-0.6/transifex /var/www

Now we have to edit some configuration files located in /var/www/transifex/settings with particular attention to the database backend configuration stored in 20-engines.conf. Take this as example

DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'transifex'
DATABASE_USER = 'transifex'
DATABASE_PASSWORD = 'secret_password'
DATABASE_HOST = 'ADDRESS-OF-YOUR-DB'             # Set to empty string for local socket
DATABASE_PORT = '3306'             # Set to empty string for default

obviously you must create a database (called ‘transifex’ in this example) in your database server and give full permissions to a dedicated user (called ‘transifex’ with ‘secret_password’ as password in this example). You can do it with these commands in your mysql console:

CREATE DATABASE transifex;
GRANT ALL ON transifex.* to 'transifex'@'%' IDENTIFIED BY 'secret_password';

Now we can run the configuration scripts, located in the transifex’s base dir

# cd /var/www/transifex
# ./manage.py syncdb
# ./manage.py txcreatedirs
# ./manage.py runserver

Now we can execute a server instance, listening on address $IPADDRESS and port 8088,  and then we can access it fro http://$IPADDRESS:8088 in our web browser. Remember to use nohup if yoiu want to detach it from the console

# ./manage.py $IPADDRESS:8088