The ramblings of Steve-0Posts RSS Comments RSS

Archive for the Tag 'linux'

Creating an NFS-root VM template for Xen / Oracle VM

Following up on my previous post about building a Xen / NFS-root kernel, this will take you through creating a VM template capable of using that kernel (or a P2V process for converting existing VM’s / linux servers to nfs-root). I think the intro from the last article still applies, so I’ll include it here:

Over the past year or two, we have transitioned all our servers and hosting to Xen – specifically, we use the Oracle VM management tools on top of xen, and most of our VM’s are Centos 5 x86_64. Since we use NFS NAS’ as storage across our infrastructure, it would be very convenient if we could use a NFS volume as the root drive for VM’s. With the NFS root, we gain things like easy use of filer snapshots, and on-the-fly volume resizing – if we’re ever running short on space in a given VM, its a single command (or a click on a web page) to expand the root drive.

The steps below are the result of a lot of work – the RHEL5 kernel has code in it for an NFS root, but I was never able to get it work correctly, at least under xen. In the end, after lots of experimenting, I was able to build a new kernel from kernel source, that is compatible with Xen and a NFS-Root. Repeat: you cannot build a custom RHEL5 kernel that is capable of booting from NFS under xen.

There are shortcomings/tradeoffs with this approach – you are not able to do any NFS exports from the nfs-root vm, and there is a bit more performance overhead with an NFS-root vm. If you are using a VM to host a high-transaction DB, for instance, I wouldn’t recommend a NFS-root, but for most purposes, it works and performs just fine.

  • Install linux / kickstart / etc to get a good, minimal install of linux, and configure it as you would any linux server. I would suggest a minimal install for your requirements, turn off any unneeded services, lock down permissions, firewall, and any other deployment process you usually go through. Since this is going to be a template, you want this to be ready for any task with minimal configuration changes.
  • On that configured linux system, mount a NFS share that will serve as your future NFS root (or storage for your VM template) to /mnt/tmp
  • Shut down as many running services as possible, so there are no file conflicts/open databases/etc.
  • Copy over the kernel modules from your nfs-root kernel build:rsync -av /path/to/kernel/modules/kernel-ver /mnt/tmp/lib/modules/
  • #copy all files over to nfs mount
    cd /
    cp -ax /{bin,dev,etc,lib,lib64,opt,root,sbin,usr,var,folders} /mnt/tmp
    mkdir /mnt/tmp/{home,proc,sys,tmp}
    chmod 777 /mnt/tmp/tmp
  • Edit /mnt/tmp/etc/fstab to look something like this, main change here is to /:

    /dev/nfs                /                       rootfs  defaults        0 0
    tmpfs                   /dev/shm                tmpfs   defaults        0 0
    devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
    sysfs                   /sys                    sysfs   defaults        0 0
    proc                    /proc                   proc    defaults        0 0
    rpc_pipefs              /var/lib/nfs/rpc_pipefs rpc_pipefs defaults     0 0
  • Edit /mnt/tmp/etc/sysconfig/network-scripts/ifcfg-eth0 as needed to setup the network
  • Create a vm.cfg file for the Xen vm. If using this is an Oracle VM template, make sure to add a zero-byte disk image, and put this under the seed_pool directory. Edit options as needed for your infrastructure.
    dhcp = 'off'
    extra = 'nfsroot=10.0.0.1:/vol/nfsroot,noacl,nfsvers=3,tcp,rsize=32768,wsize=32768 selinux=0 acpi=off noapic'
    gateway = '10.0.0.254'
    hostname = 'nfsroot-vm.mycompany.com'
    ip = '10.0.0.10'
    kernel = '/OVS/P2V_STUFF/nfsboot-custom/vmlinuz-2.6.31.1nfsboot'
    memory = '512'
    name = 'nfsroot-vm'
    netmask = '255.255.255.0'
    on_crash = 'restart'
    on_reboot = 'restart'
    root = '/dev/nfs'
    uuid = '9af0a816-0123-4567-ad50-bc32be92bff7'
    vcpus = 2
    vfb = ['type=vnc,vncunused=1,vnclisten=0.0.0.0,vncpasswd=password']
    vif = ['bridge=vlan100,mac=00:16:3E:31:FF:37,type=netfront']
    vif_other_config = []
  • Start up the vm with Oracle VM manager, or start on the command line with xm create vm.cfg, and cross your fingers!
  • No responses yet

    Build a custom Xen kernel capable of booting from a NFS Root Filesystem

    Over the past year or two, we have transitioned all our servers and hosting to Xen – specifically, we use the Oracle VM management tools on top of xen, and most of our VM’s are Centos 5 x86_64. Since we use NFS NAS’ as storage across our infrastructure, it would be very convenient if we could use a NFS volume as the root drive for VM’s. With the NFS root, we gain things like easy use of filer snapshots, and on-the-fly volume resizing – if we’re ever running short on space in a given VM, its a single command (or a click on a web page) to expand the root drive.

    The steps below are the result of a lot of work – the RHEL5 kernel has code in it for an NFS root, but I was never able to get it work correctly, at least under xen. In the end, after lots of experimenting, I was able to build a new kernel from kernel source, that is compatible with Xen and a NFS-Root. Repeat: you cannot build a custom RHEL5 kernel that is capable of booting from NFS under xen.

    There are shortcomings/tradeoffs with this approach – you are not able to do any NFS exports from the nfs-root vm, and there is a bit more performance overhead with an NFS-root vm. If you are using a VM to host a high-transaction DB, for instance, I wouldn’t recommend a NFS-root, but for most purposes, it works and performs just fine.

    First, you need to build a kernel that supports both xen and an NFS-root – you’ll need a linux machine with a complete build environment, i.e. gcc, make, etc. I have been through this process with 2.6.31, but I would guess that the latest stable kernel version available at http://kernel.org will work just fine.
    - Download the latest kernel source
    - unzip, cd into source directory
    - Copy in attached .config as starting point ( copy as …./linux-(version)/.config )
    - make menuconfig

    Important config options are listed here:

    http://www.virtuatopia.com/index.php/CentOS_5_-_Build_a_Custom_Xen_Kernel_with_NFS_Root_Filesystem_(CONFIG_ROOT_NFS)_Support

    Most importantly, nfs client options and nfs_root need to be built into kernel (not as modules).  Also need to make sure to build Xen modules, and select most of the iptables filters (state is an important one). 

    - make
    - make modules_install

    Once the make and install is complete, you will have a kernel capable of nfs-booting under xen. To collect all the pieces needed:
    - copy over the file vmlinux in the base build directory (this one is ~85MB), this is the kernel (can’t use bzImage with xen nfs boot).
    - Tar up /lib/modules/kernelVer to distribute to nfs client vm.

    See the next article for creating a proper vm.cfg under xen / Oracle VM.

    No responses yet

    Mounting a xen disk image file on dom0

    If you need to get in and edit some files on your xen domU instance, i.e. it isn’t booting up properly, etc, here’s how to mount it on dom0. In this case, we want to mount the second partion on the virtual disk (our root partition):

  • Print out the partition layout:
    fdisk -l /path/to/img/file.img

    Disk System.img: 0 MB, 0 bytes
    255 heads, 63 sectors/track, 0 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes

    Device Boot Start End Blocks Id System
    System.img1 1 4 32098+ 83 Linux
    System.img2 * 5 619 4939987+ 83 Linux
    System.img3 620 750 1052257+ 82 Linux swap / Solaris

  • create directory to mount image under: mkdir /mnt/tmp
  • mount the image using the offset from the fdisk output, the start block (in this case 5)
    mount mount -o loop,offset=$((512*5) /path/to/img/file.img /mnt/tmp
  • Edit files as needed, and unmount when done.
  • No responses yet

    Creating a true read-only user in PostgreSQL

    I develop a product at work that (among many other things) allows users to easily create and manage databases to interact with other packages on their appliance. One feature that was requested and green-lighted is the ability to create a read-only user for existing databases- a user that can connect to a given database and access all tables and views in that DB, and nothing else.

    Since PostgreSQL is our database of choice, I started researching the process, thinking it would be a couple mysql-esqe GRANT statements and that would be it. Turns out that it is a huge PITA in postgres – even my solution I’m documenting here has its shortcomings, but as far as I know is the best / only way to accomplish this task. I ran across quite a few sites that helped with pieces of this, but none that actually tied the process together for production usage. I am by no means a Postgres expert, but do have a good bit of experience mucking around with back-end settings and figuring how to script common tasks.

    There are two main things to watch out for when trying to create a read-only user in PostgreSQL, especially if you come from a DB like MySQL:

  • PostgreSQL only sets permissions on objects, not on databases, so you need to grant read access to all your tables/views/etc, and if you add a table down the line, you need to remember to manully grant read access to it after creating the table.
  • I’m guessing 95% of postgres users just use the default “public” schema, and as such, you need to revoke create privileges from the PUBLIC group. Otherwise, your “read-only” user will still be allowed to create tables that it owns, even if you’ve only given it read only access to all other objects in your database.
  • For this example, we’ll use database name “mydb”, database user/owner “mydbuser”, and we’ll create a read-only user named “mydbuser_ro”. This assumes that you did not define a schema for your database and are using the default “public” schema.

  • Revoke default permissions from public group:
    REVOKE CREATE ON SCHEMA public FROM PUBLIC;
    REVOKE USAGE ON SCHEMA public FROM PUBLIC;
  • Add back permissions for your database owner:
    GRANT CREATE ON SCHEMA public TO mydbuser;
    GRANT USAGE ON SCHEMA public TO mydbuser;
  • Create the new user via the command line, or pgadmin/etc:
    psql -U postgres -t -c "create role mydbuser_ro password 'abc123' NOSUPERUSER NOCREATEDB NOCREATEROLE INHERIT LOGIN;
  • Grant usage permissions for your read-only user:
    GRANT USAGE ON SCHEMA public TO mydbuser_ro;
  • Grant select permissions on all database tables from the command line:
    psql -U postgres -qAt -c "select 'grant select on ' || tablename || ' to \"mydbuser_ro\";' from pg_tables where schemaname = 'public'" mydb | psql -U postgres mydb
  • Setup remote access for the read only user in pg_hba.conf as appropriate
  • Once complete, you can verify the settings with a quick sql query. You should see something like this, with the user=UC (for Usage/Create), and user_ro=U (for Usage):
    mydb=> select * from pg_namespace where nspname='public';
    nspname | nspowner | nspacl
    ---------+----------+------------------------------------------------------------------
    public | 10 |
    {postgres=UC/postgres,mydbuser=UC/postgres,mydbuser_ro=U/postgres}

    One response so far