Thursday, 24 May 2012

Invisible symbols in sssd upstart config causes sssd to not start if /bin/sh is a link to /bin/bash

I've committed a bug for Ubuntu today. Hope they fix that soon, since we have not so much time before migrate all users from 10.04 to 12.04.

https://bugs.launchpad.net/ubuntu/+source/sssd/+bug/1003845

UPD: Quite impressive. It took only 2 hours after bug commit to release a fix! Bravo!

Friday, 18 May 2012

How to setup diskless Ubuntu 12.04 with read-write root partition


Well, this how-to for the diskless Ubuntu setup is not usual. The main point is that all our infrastructure is based on CentOS, but sometimes (like in this case) we must support different Linux distributions for our clients. That is why all server-side configuration will be related to CentOS, and client-side to Ubuntu.

In difference to the official DisklessHowto, this one allows you to prepare a shared installation which can be used by any number of clients simultaneously. All changes to the mounted root will resist in ramfs, so no changes will be written to the NFS, and everything will be gone after restart. This feature in some (many) cases is treated as an advantage.

However, it is recommended to read  DisklessHowto from the Ubuntu site, since all basics related to network boot for Ubuntu described there much better. Also, I took some parts from their documentations to my howto. I believe they wouldn't mind.

Requirements

  • DHCP server
  • TFTP server
  • NFS server
 All my servers uses CentOS, so I will describe server-side the configuration only for this system.
Current server setup is based on CentOS 6.2 x86_64 with IP 192.168.1.10.

Step by step

I. DHCP

I will not describe basics of DHCP configuration, you can easily google it. In order to make PXE work, you need to put just these two option to your DHCP configuration:

filename pxelinux.0;
next-server 192.168.1.10;

Where next-server provides with an address of your TFTP server. It can be put in almost any section of dhcpd.conf: global, class, subnet, pool, group or host.

II. TFTP

1. Install tftp daemon and syslinux package. Syslinux is available from rpmforge.
# yum install tftp-server syslinux
# chkconfig tftp on
# service tftp start 

2. Copy pxelinux files to tftp directory:
# cp /usr/share/syslinux/pxelinux.0 /tftpboot/
# cp /usr/share/syslinux/vesamenu.c32 /tftpboot/

3. Configure pxelinux
# mkdir /tftpboot/pxelinux.cfg
# cat << EOF > /tftpboot/pxelinux.cfg/default
DEFAULT vesamenu.c32
TIMEOUT 600
ONTIMEOUT BootLocal
PROMPT 0
MENU TITLE My PXE Server (by TORNADO)
ALLOWOPTIONS 1
menu width 80
menu rows 15
MENU TABMSGROW 24
MENU MARGIN 10
NOESCAPE 1
LABEL BootLocal
    localboot 0
    TEXT HELP
    Boot to local hard disk
    ENDTEXT
LABEL UBUNTU_1204_DISKLESS
    MENU LABEL Ubuntu 12.04 (64-bit) DISKLESS
    KERNEL Ubuntu/12.04/x86_64/vmlinuz-3.2.0-20-generic
    APPEND root=/dev/nfs nfsroot=192.168.1.10:/srv/nfsroot/Ubuntu/12.04/x86_64,ro initrd=Ubuntu/12.04/x86_64/initrd.img-3.2.0-20-generic ip=dhcp aufs=tmpfs
    TEXT HELP
    Boot the Ubuntu 12.04 64-bit Diskless
    ENDTEXT
EOF 

III. NFS

1. Install nfs
# yum install nfs-utils

# chkconfig nfs on

# service nfs start

2. Add /srv/nfsroot to exports
# cat << EOF > /etc/exports
/srv/nfsroot *(ro,async,no_root_squash,no_subtree_check,no_all_squash)
EOF

3. Apply exports
# exportfs -r

IV. Prepare installation

1. Install Ubuntu
Generally you have two ways.
  1. Use debootstrap.
    I used this option to prepare some tiny installations (like network boot for number of POS terminals).
  2. Install the Ubuntu on the real or virtual system and copy it to NFS server.
    In this article I will follow this way, because I want to prepare a usual Ubuntu installation.
After system was installed and configured as you want, you need to prepare it for network boot.

2. Modify /etc/network/interfaces to set eth0 configuration type to manual:

iface eth0 inet manual

3. Configure /etc/fstab to be looking like this:
# /etc/fstab: static file system information.
#
#                
proc            /proc           proc    defaults        0       0
/dev/nfs       /               nfs    defaults          1       1

4.  Change the following options in /etc/initramfs-tools/initramfs.conf:
MODULES=netboot
BOOT=nfs
DEVICE=eth0
NOTE: If the client source installation you copied the files from should remain bootable and usable from local hard disk, restore the former BOOT=local and MODULES=most options you changed in /etc/initramfs-tools/initramfs.conf. Otherwise, the first time you update the kernel image on the originating installation, the initram will be built for network boot, giving you "can't open /tmp/net-eth0.conf" and "kernel panic". Skip this step if you no longer need the source client installation.

5. Add to /etc/initramfs-tools/modules line:
aufs

6. Copy aufs module to /etc/initramfs-tools/scripts/modules
$ sudo cp /lib/modules/$(uname -r)/kernel/ubuntu/aufs/aufs.ko /etc/initramfs-tools/scripts/modules

7. Copy the following script to /etc/initramfs-tools/scripts/init-bottom as 00_aufs_init (0755):
#!/bin/sh -e

case $1 in
  prereqs)
    exit 0
    ;;
esac

for x in $(cat /proc/cmdline); do
  case $x in
    root=*)
      ROOTNAME=${x#root=}
      ;;
    aufs=*)
      UNION=${x#aufs=}
        case $UNION in
          LABEL=*)
            UNION="/dev/disk/by-label/${UNION#LABEL=}"
            ;;
          UUID=*)
            UNION="/dev/disk/by-uuid/${UNION#UUID=}"
            ;;
        esac    
      ;;
  esac
done

echo "Union=$UNION"

if [ -z "$UNION" ]; then
    exit 0
fi

modprobe -b aufs && echo "OK: modprobe -b aufs" || echo "ERR: modprobe -b aufs"

# make the mount points on the init root file system
mkdir /aufs /ro /rw && echo "OK: mkdir /aufs /ro /rw" || echo "ERR: mkdir /aufs /ro /rw"

# mount read-write file system
if [ "$UNION" = "tmpfs" ]; then
  mount -t tmpfs rw /rw -o noatime,mode=0755 && echo "OK:  mount -t tmpfs rw /rw -o noatime,mode=0755 " || echo "ERR:  mount -t tmpfs rw /rw -o noatime,mode=0755"
else
  mount $UNION /rw -o noatime
fi

# move real root out of the way
mount --move ${rootmnt} /ro && echo "OK: mount --move ${rootmnt} /ro" || echo "ERR: mount --move ${rootmnt} /ro"

mount -t aufs aufs /aufs -o noatime,dirs=/rw:/ro=ro && echo "OK: mount -t aufs aufs /aufs -o noatime,dirs=/rw:/ro=ro" || echo "ERR: mount -t aufs aufs /aufs -o noatime,dirs=/rw:/ro=ro"

# test for mount points on union file system
[ -d /aufs/ro ] || mkdir /aufs/ro
[ -d /aufs/rw ] || mkdir /aufs/rw

mount --move /ro /aufs/ro && echo "OK: mount --move /ro /aufs/ro" || echo "ERR: mount --move /ro /aufs/ro"
mount --move /rw /aufs/rw && echo "OK: mount --move /rw /aufs/rw" || echo "ERR: mount --move /rw /aufs/rw"

# strip fstab off of root partition
grep -v $ROOTNAME /aufs/ro/etc/fstab > /aufs/etc/fstab

mount --move /aufs /root && echo "OK: mount --move /aufs /root" || echo "ERR: mount --move /aufs /root"

exit 0 

To be honest this script isn't mine. I found it some time ago and I don't remember where. If you are the author or you know who he is, please tell me in comments so I put your name here.

8. Build a new initrd image:
$ sudo update-initramfs -k $(uname -r) -c -b /root/

9. Now you can copy this all on server by executing the following command on client:

$ sudo rsync -a --exclude=tmp/* --exclude=proc/* --exclude=sys/* --exclude=dev/* / username@192.168.1.10:/srv/nfsroot/Ubuntu/12.04/x86_64/
Be careful with all slashes! rsync treats source or destination in different way if slash is omitted.
"username" must have write permissions to /srv/nfsroot/Ubuntu/12.04/x86_64.

10. Copy kernel and new initrd image to a proper folder on tftp. Run it ON THE SERVER
# cp /srv/nfsroot/Ubuntu/12.04/x86_64/boot/vmlinuz-$(uname -r) username@192.168.1.10:/tftpboot/Ubuntu/12.04/x86_64/
# cp /srv/nfsroot/Ubuntu/12.04/x86_64/root/initrd.img-$(uname -r) username@192.168.1.10:/tftpboot/Ubuntu/12.04/x86_64/


Notes

Remember, that changes to the root filesystem is limited by you RAM. This means that you will not be able to copy a 4GB video to /tmp if you have only 2GB of RAM.

I have prepared this post without access to my test environment, so some small mistakes are possible. If you find any, please comment.

Sunday, 13 May 2012

Simple export of registry subkeys in HKCU\Software and HKLM\Software

I didn't write .cmd scripts for a very long time. But few weeks ago I faced random failures on my old laptop, so I was forced to migrate. Since the old one was intensively used for a year, a lot off unnecessary stuff was gathered. Smooth migration was rather impossible, so it was decided to reinstall system from scratch and install only the needed software.

I don't like different automatic migration software, so all applications were reinstalled and most of them were configured manually again. But some applications had to keep their old configuration, and this configuration was generally located in registry by the keys like HKLM\Software\<Application> and HKCU\Software\<Application>.

I found it very annoying to parse the list of subkeys (more than 100 applications were installed) looking for the ones I need, so I decided just to dump all "Software" keys to backup and restore just the needed pieces when needed. But if I dump "Software" to a single file, it will be the same issue to extract the needed pieces after.

To solve this problem I used a script that I wrote about 10 years ago, but it is actual even now. It is VERY simple, and I spent much more time to write this post than these two lines:

for /f "tokens=3 delims=\" %%i in ('reg query HKLM\Software') do reg export "HKLM\Software\%%i" "%%i_HKLM.reg" /y
for /f "tokens=3 delims=\" %%i in ('reg query HKCU\Software') do reg export "HKCU\Software\%%i" "%%i_HKCU.reg" /y

Thats it. Put those lines to some .cmd file, execute it, and you will have a bunch of .reg files per Software subkey both HKLM and HKCU.