Advanced usage of UEC Images

You can customize the way UEC Images boot under a local KVM instance by passing certain kernel command line variables. This approach enables you to pass custom cloud-init data-sources, set the instance's password, hostname, instance-id ...etc

Here is a description of command line parameters used by 'cloud-init' and 'uncloud-init'. By modifying the kernel command line, you can change the behavior of those 2 programs that affect the early boot stage

  • ubuntu-pass=[password|random]
    On first boot, uncloud-init will set the password to be 'password'. If the string provided is literally the string 'random' then a random pass will be created and written to the console. This is not true on images from 12.10 and above (image would have to be booted twice as Ubuntu user won't be present for first uncloud-init run). Recommenedation is to seed the image like so http://ubuntu-smoser.blogspot.fr/2013/02/using-ubuntu-cloud-images-without-cloud.html

  • ds=nocloud;[key=val] or ds=nocloud-net;[key=val]
    ds=nocloud
    Means the instance is booting on a plain hypervisor with no cloud metadata service to be expected
    ds=nocloud-net
    Means the instance is booting on a cloud of some sort, however do not expect the cloud metadata service to be available! This helps cloud-init not wait for the metadata service to appear. You can pass a custom metadata network service by passing the s= parameter

    • s=<seedlocation> | seedfrom=<seedlocation> [default=""]
      This allows you to set the 'seed location'. The value can be a url of 'file:///' format, or of 'http://' format. If you want to use http or another network based seed, then 'nocloud-net' must be used as the data source, rather than 'nocloud'. meta-data and user-data will be read from <seedlocation>meta-data and <seedlocation>user-data respectively.
      For example I set up the tiny urls http://tinyurl.com/sm-user-data and http://tinyurl.com/sm-meta-data . These redirect to pages on my hosted system, the tinyurl is only used to make the urls shorter. Then, I can boot with a command line like:

       "ro init=/usr/lib/cloud-init/uncloud-init root=LABEL=uec-rootfs ds=nocloud-net;s=http://tinyurl.com/sm- ubuntu-pass=random"

      in , and the user-data and meta-data are pulled from the respective URLs. The format of user-data and meta-data is described in cloud-init's documentation doc/examples/seed.

    • h=hostname | local-hostname=hostname [default="ubuntuhost"]
      Set the local hostname for this instance.

    • i=id | instance-id=id [default="nocloud"]
      This sets the the 'instance-id' for the boot. In EC2 or Eucalyptus, this would be something like 'i-abcdefg' and changes for each instance. The cloud-init code uses 'instance-id' to indicate whether this is the first boot. What this means is that, by default, the constant string 'nocloud' as an instance id will on ever initialize once. If youwant to test initialization again, you would have to remove files in /var/lib/cloud/sem or change this string.

  • boot with kvm '-kernel' command line arguments rather than with the boot floppy:

    kvm -drive file=disk.img,if=virtio,boot=on \
       -kernel "${kernel}" \
       -append "root=/dev/vda ro init=/usr/lib/cloud-init/uncloud-init ds=nocloud ubuntu-pass=ubuntu"
  • Import the virtual machine into libvirt (replace PATHTO). Import the following xml with

    virsh "create ./maverick-server-uec-i386.xml"

    <domain type='kvm'>
      <name>maverick-server-uec-i386</name>
      <memory>131072</memory>
      <currentMemory>131072</currentMemory>
      <vcpu>1</vcpu>
      <os>
        <type arch='i686' machine='pc'>hvm</type>
        <boot dev='hd'/>
        <kernel>/PATHTO/maverick-server-uec-i386-vmlinuz-virtual</kernel>
        <cmdline>root=/dev/vda ro init=/usr/lib/cloud-init/uncloud-init ds=nocloud ubuntu-pass=ubuntu</cmdline>
      </os>
      <features>
        <acpi/>
      </features>
      <clock offset='utc'/>
      <on_poweroff>destroy</on_poweroff>
      <on_reboot>restart</on_reboot>
      <on_crash>destroy</on_crash>
      <devices>
        <emulator>/usr/bin/kvm</emulator>
        <disk type='file' device='disk'>
          <source file='/PATHTO/disk.img'/>
          <target dev='vda' bus='virtio'/>
        </disk>
        <interface type='network'>
          <source network='default'/>
        </interface>
        <input type='mouse' bus='ps2'/>
        <graphics type='vnc' port='-1' autoport='yes' listen='127.0.0.1'/>
        <video>
          <model type='cirrus' vram='9216' heads='1'/>
        </video>
      </devices>
    </domain>
  • By providing user-data and meta-data via the seed, you can avoid the need for uncloud-init. Note that in this case, you will not be able to login to the instance over the console:

    kvm -drive file=disk.img,if=virtio,boot=on \
       -kernel "${kernel}" \
       -net nic,model=virtio -net "user,hostfwd=tcp::5555-:22" \
       -append "root=/dev/vda ro ds=nocloud-net;s=http://tinyurl.com/sm-" \
       -curses

    Given the above, which sets up redirections on localhost port 5555 to the guest's port 22, and suitable data in the referenced metadata and user-data, I can then ssh into the system with

    ssh -p 5555 ubuntu@localhost

Read More about running UEC image with cloud-init on a local KVM

  • Use uncloud's "xupdate" mechanism to seed or update the filesystem:

    # create a directory tree for var/lib/cloud/data/cache/nocloud
    $ sdir="var/lib/cloud/data/cache/nocloud"
    $ ud=overlay
    $ mkdir -p "${ud}/updates/${sdir}"
    
    # populate the nocloud's cache dir with some meta-data and user-data
    $ b="http://bazaar.launchpad.net/%7Ecloud-init-dev/cloud-init/trunk/download/head%3A/preseedmetadata.txt-20100811204932-d0e2s9pcebnirj8p-1/"
    $ wget "${b}/meta-data" -O "${ud}/updates/${sdir}/meta-data"
    $ wget "${b}/user-data" -O "${ud}/updates/${sdir}/user-data"
    
    # the 'updates.script' in the top level of this iso will
    # be executed immediately after the contents of the updates/
    # dir are synced to /
    $ cat > "${ud}/updates.script" <<EOF
    #!/bin/sh
    echo ==== HELLO WORLD =====
    sleep 3
    EOF
    $ chmod 755 "${ud}/updates.script"
    
    # create a filesystem to house the data
    $ genisoimage -rock --output updates.iso "${ud}"
    
    # clean the disk image that we're going to boot
    $ qemu-img create -f qcow2 -b ${img} disk.img
    
    # launch kvm with the updates.iso as a virtio device
    # and pass in 'xupdate=vdb:mnt', indicating that updates are
    # on /dev/vdb, and the device contains a filesystem.
    $ kvm -kernel "${kernel}" \
       -drive file=disk.img,if=virtio -drive file=updates.iso,if=virtio \
       -append "root=/dev/vda ro init=/usr/lib/cloud-init/uncloud-init ds=nocloud ubuntu-pass=ubuntu xupdate=vdb:mnt" \
       -curses -net nic,model=virtio -net "user,hostfwd=tcp::5555-:22"

UEC/Images/KVMKernelOptions (last edited 2015-03-10 16:00:55 by bryanquigley)