vmware-vdiskmanager and CentOS 6

This is how you install vmware-vdiskmanager on CentOS 6. I needed to do this so I could read my old vmware-server vmdk.

First go this old KB article and download 1023856-vdiskmanager-linux.7.0.1.zip. It's at the bottom, in the Attachements section. Now you do the following little dance:

unzip 1023856-vdiskmanager-linux.7.0.1.zip
cp 1023856-vmware-vdiskmanager-linux.7.0.1  /usr/local/sbin/vmware-vdiskmanager 
chmod +x  /usr/local/sbin/vmware-vdiskmanager
yum -y install zlib.i686 glibc.i686 openssl098e.i686
md -pv /usr/lib/vmware/lib
cd /usr/lib/vmware/lib/
ln -s /usr/lib/libcrypto.so.0.9.8e 
ln -s libcrypto.so.0.9.8e libcrypto.so.0.9.8 
ln -s libcrypto.so.0.9.8e libcrypto.so.0
ln -s libcrypto.so.0.9.8e libcrypto.so
ln -s /usr/lib/libssl.so.0.9.8e
ln -s libssl.so.0.9.8e libssl.so.0.9.8
ln -s libssl.so.0.9.8e libssl.so.0
ln -s libssl.so.0.9.8e libssl.so

That fucking around in /usr/lib/vmware/lib is because even though VMware claims this is a static binary, it in fact dynamically loads crypto libraries at run time from non-standard places.

You can now convert your split vmdk to a single file and mount it:

vmware-vdiskmanager -r sda.vmdk -t 0 sda-single.vmdk
modprobe nbd max_part=8
qemu-nbd -r --connect=/dev/nbd0 sda-single.vmdk
kpartx -a /dev/nbd0
vgchange -a y YOURVG
mount -o ro /dev/mapper/YOURVG-YOURLV /mnt

Aren't you glad you created a unique VG for each of your VMs?

To unmount:

umount /mnt
vgchange -a n YOURVG
kpartx -d /dev/nbd0
qemu-nbd -d sda-single.vmdk


daemontools, system V init and mysql

This is how you setup a babysitter for a service started with system V init scripts using DJB's deamontools. We can't just put run $service start into a run file, because sys V init scripts start up background daemons. We have to use the daemon's PID file to watch what's going on.

First, I create mysql-babysit. I'm using mysql as an example. For other services, adjust $service and $pidfile.

# mkdir /var/daemontools/supervised/mysql-babysit
# cd /var/daemontools/supervised/mysql-babysit
# cat <<'SH' > mysql-babysit



function sig_finish () {
    echo $(date) $service "$1"
    service $service stop
    [[ $sleepPID ]] && kill $sleepPID
trap 'sig_finish TERM' TERM
trap 'sig_finish KILL' KILL

echo $(date) $service start

service $service start

if [[ -f $pidfile ]] ; then
    pid=$(< $pidfile)
    if [[ $pid ]] ; then
        while grep -q $service /proc/$pid/cmdline 2>/dev/null ; do
            sleep 60 & sleepPID=$!
            wait $sleepPID
        echo $(date) $service exited
        exit 0
echo $(date) $service failed to start
sleep 5
exit 3

Next we create and activate the run script

cd /var/daemontools/supervised/mysql-babysit
# cat <<'SH' >run

exec /var/daemontools/supervised/mysql-babysit/mysql-babysit
# chmod +x run
# chkconfig mysql off
# service mysql stop
# cd ../../service
# ln -s ../supervised/mysql-babysit

We can control mysql with

svc -d /var/daemontools/supervised/mysql-babysit # shutdown mysql
svc -u /var/daemontools/supervised/mysql-babysit # startup mysql
killall mysql # restart mysql


Creating glue records with bind 9

It's not pretty. Basically, you have to create a zone with the exact name of your name servers. Even if one of those name servers are probably controlled by your ISP. Even if you already have an A record for your local NS

In the following examples, ns1.example.com is your primary name server, sdns1.isp.com is the secondary name server your ISP is letting you use.

Add the following to /etc/named.conf:

zone "ns1.example.com" {
        type master;
        file "master/ns1.example.com.zone";

zone "sdns1.isp.com" {
        type master;
        file "master/sdns1.isp.com.zone";

This is master/ns1.example.com.zone:

$TTL 300
@               IN      SOA     ns1.example.com. root.example.com. (
                                2017042702                      ; yymmdd##
                                2h                              ; Refresh
                                1h                              ; Retry
                                2W                              ; Expire
                                1h                              ; Minimum
                IN NS   ns1.example.com.
                IN NS   sdns1.isp.com.

@               IN A  // change this to the real IP

This is master/sdns1.isp.com.zone:

$TTL 300
@               IN      SOA     ns1.example.com. root.awale.qc.ca. (
                                2017042702                      ; yymmdd##
                                2h                              ; Refresh
                                1h                              ; Retry
                                2W                              ; Expire
                                1h                              ; Minimum
                IN NS   ns1.isp.com.
                IN NS   ns2.isp.com.

@               IN A // change this to the real IP of sdns1.isp.com

Get the real IP of sdns1.isp.com with

host sdns1.isp.com
sdns1.isp.com has address

You can find the NS records for sdns1.isp.com with

# dig NS isp.com
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.62.rc1.el6_9.1 <<>> NS isp.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30596
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2

;isp.com.   IN NS

isp.com.  7200 IN NS ns2.isp.com.
isp.com.  7200 IN NS ns1.isp.com.

ns2.isp.com.  172799 IN A
ns1.isp.com.  172799 IN A

;; Query time: 210 msec
;; WHEN: Thu Apr 27 16:10:12 2017
;; MSG SIZE  rcvd: 93


Wacom Intuos Photo and CentOS 6

I've had a Wacom Intuos 5x4 since 1988 or so. But support for the serial protocol it used has disappeared. What's more, my tablet was getting really crusty over nearly 20 years of use. So I went and bought a Wacom Intuos Photo, which has a smaller, wider surface (which is useful given I have 2 screens) but also can use a finger instead of a pen.

Of course, the new tablet didn't work out of the box. Well, it nearly worked.

Back in the day, I patched wacom_drv for XFree86 to get it working. Things have changed greatly since then. On modern Linux, the driver is in the kernel (wacom.ko) which creates an input and event device. X.org then uses HAL to enumerate input devices and HAL also provides hints on how to configure them. The long and short is we no longer need to mess around in xorg.conf when we change hardware. However, it means it gets very hard to debug when one of those layers does something annoying.

The easy way to get an Wacom Intuos Photo, Draw, Art to work on CentOS 6 is to install the backports of linuxwacom drivers. If you are running the stock 2.6.32 kernel, everything will Just Work.

I'm using the elrepo's 4.10 kernel-ml. This gets lm-sensors working for my motherboard and removes an annoying bug with my PS/2 keyboard.

In 4.10 kernel, the wacom driver is recognizing the tablet and doing it's job : creating 3 input event IDs one for the pad, one for the stylus and one for finger touch. However, lshal is rejecting the finger touch. I traced it down to HAL_PROP_BUTTON_TYPE not being set when hald-probe-input is called. This means the stylus automatically works on X.org, but touch doesn't.

To get finger touch to work on X.org, I had to force things. First, I need to create a symlink to the finger event ID using udev, then a partial config file for X.org :

/usr/local/lib/udev/wacom-type.sh will output a short name for each device it is called on. Make sure this script is executable!


name=$(cat /sys/$DEVPATH/device/name)
# echo "$DEVPATH=$name" >>/tmp/wacom-dev.txt

shopt -s nocasematch

if [[ $name =~ Finger ]] ; then
    echo finger
elif [[ $name =~ Pen ]] ; then
    echo pen
elif [[ $name =~ Pad ]] ; then
    echo pad
    echo unknown

exit 0

/etc/udev/rules.d/99-wacom.rules convinces udevd to call the above when the tablet is detected. It also convinces udevd to create a symlink in /dev/input/wacom-finger. Note that I restrict to 056a:033c, which is a Wacom Intuos Draw/Photo/Art small version. You can find the USB ID of your tablet with lsusb.

# Will create /dev/input/wacom-finger, I hope
ACTION!="add|change", GOTO="my_wacom_end"
KERNEL!="event*", GOTO="my_wacom_end"

ENV{ID_VENDOR_ID}!="056a", GOTO="my_wacom_end"
ENV{ID_MODEL_ID}=="033c", PROGRAM=="/usr/local/lib/udev/wacom-type.sh", SYMLINK+="input/wacom-%c"


Test the above by doing udevadm control --reload-rules, unplug tablet, wait, plug in tablet, then ls -l /dev/input and you should see:

lrwxrwxrwx  1 root root      7 Mar 22 15:50 wacom-finger -> event11
lrwxrwxrwx  1 root root      7 Mar 22 15:50 wacom-pad -> event12
lrwxrwxrwx  1 root root      7 Mar 22 15:50 wacom-pen -> event10

The numbers after event will change each time you reboot or replug the tablet.

/etc/X11/xorg.conf.d/wacom.conf will finally convince X.org to use the Wacom finger event id as a touch pad.

Section "InputDevice"
    Identifier "Finger"
    Driver "wacom"
    Option "Vendor" "Wacom"
    Option "AutoServerLayout" "on"
    Option "Type" "touch"
    Option "Device" "/dev/input/wacom-finger"
    Option "Mode" "Absolute"
    Option "Touch" "on"
    Option "Gesture" "off"
#    Option "Tilt" "on"
    Option "Threshold" "20"
    Option "Suppress" "6"
    Option "USB"    "On"

I'd like to very much thank whot and jigpu who spent an impressive amount of time helping me over IRC.

24 hours later, I have found a problem with the approach. If you unplug and replug the tablet, the Finger event ID will change. And while the wacom-finger symlink will be updated, X.org will not know that it's changed and hold onto the old event ID. This means finger will no longer work after replugging the tablet, at least until you restart X.org.


Linux console

So I've finally upgraded Corey. By "upgrade", I mean "replaced every last component except the PSU." So basically it's a replacement.

This means I'm now running CentOS 6 on my desktop ("So soon!?" shut up). It also means I have to fix all the little annoying things about CentOS 6. One of which is that modern kernels us a framebuffer, which switches the console to illegibly small text. The solution is to put video=640x480 or video=800x600 on your kernel command line. Ideally in grub.conf.


Minimal Perl

Setting up Perl on CentOS 6. I'm putting this here so that I can find it easily.

yum install perl perl-CPAN
# make everything automatic
o conf prerequisites_policy follow
o conf build_requires_install_policy yes
o conf commit
cpan local::lib
cpan Bundle::CPAN # keep an eye on this because Realine wants you to hit enter
cpan App::cpanminus

Now we can install Imager (say)

sudo yum install giflib-devel libjpeg-devel libpng-devel libtiff-devel freetype-devel t1lib-devel
cpanm Imager


sqlite3 vs firefox

Firefox keeps lots of useful in sqlite files in the user's profile. Under Linux, you will find these files in ~/.mozilla/firefox/PROFILE_DIR/. To find PROFILE_DIR, you pull look in ~/.mozilla/firefox/profiles.ini. Of interest to me is places.sqlite, which contains info on all sites visited. To pull a list out, simply do

 sqlite3 -csv ~/.mozilla/firefox/ucjmuboi.default/places.sqlite \
    'SELECT url,title,visit_count,visit_date/1000000 FROM moz_historyvisits JOIN moz_places ON place_id = moz_places.id'

The visit_date is bizarely in microseconds, so divide by 1,000,000 to get epoch seconds.

Of course, the above doesn't work on CentOS 5 nor 6. You wil get a Error: file is encrypted or is not a database error. CentOS 5 ships with sqlite 3.3.6, CentOS 6 ships with 3.6.20. Firefox uses 3.7 and creates a file that isn't backward compatible. Here is how to install a compatible version:

cd ~/work
wget http://www.sqlite.org/2016/sqlite-autoconf-3130000.tar.gz
tar zxvf sqlite-autoconf-3130000.tar.gz
cd sqlite-autoconf-3130000
./configure --prefix=/opt/sqlite-3130000
make all
sudo make install
sudo ln -s sqlite-3130000 /opt/sqlite
sudo bash -c "echo /opt/sqlite/lib > /etc/ld.so.conf.d/sqlite.conf"
sudo ldconfig

This will install 3.13.0. Make sure to check the download page for the latest version.

It should be pointed out that by putting /opt/sqlite/lib into ld.so.conf.d, we are overriding the .so default system .so. I don't know if this will break anything. I do know that it means that DBD::SQLite and /usr/bin/sqlite3 now use the new .so and this is what I want.