#!/bin/bash
# Author: Steven Shiau <steven _at_ nchc org tw>
# License: GPL
# Description: This script will create a Ubuntu live CD iso which is used as a template for clonezilla image with restoration function.

if [ ! -f "/opt/drbl/sbin/drbl-conf-functions" ]; then
  echo "Unable to find /opt/drbl/sbin/drbl-conf-functions! Program terminated!" 
  exit 1
fi
. /opt/drbl/sbin/drbl-conf-functions

# Load some necessary setting from drbl-ocs.conf
. /opt/drbl/conf/drbl-ocs.conf

mirror_url_def="http://free.nchc.org.tw/ubuntu"
mirror_security_url_def="http://free.nchc.org.tw/ubuntu"
# debian_type can be minimal (about 67 MB for Etch)/minimal-net (about 85 MB for Etch).
# 
debian_type="minimal"
#debian_type="standard"
DEBIAN_DIST_DEF="intrepid"
pkgs="$PKG_FROM_DBN_WHICH_OCS_LIVE_NEED drbl $PKG_FROM_DRBL_FOR_CLONEZILLA_LIVE"
workdir="ubuntu-live"

# Due to a bug, we have to include some essential packages otherwise it will faild in debian_type=minimal. The size difference between minimal and standard for intrepid is about 8 MB. Ref: https://bugs.launchpad.net/ubuntu/+source/cdebootstrap/+bug/189474
if [ "$debian_type" = "minimal" ]; then
  export CDEBOOTSTRAP_OPTIONS="--include=sysv-rc,upstart,system-services,belocs-locales-bin"
fi

# UGLY... but we have to semi hard coded them... since live helper won't work in Ubuntu if we do not assign version number. It's because the kernel package name in Ubuntu is like linux-image-2.6.24-7-generic, and if we do not assign version number, live-helper will try to install linux-image-2.6-generic, which does not exist in ubuntu. In Ubuntu, it's linux-image-generic.
# This is only set as default, later we will use get_latest_kernel_in_repository to find the latest kernel in repository.
gutsy_release_kernel_ver_def="2.6.22-14"
hardy_release_kernel_ver_def="2.6.24-15"
intrepid_release_kernel_ver_def="2.6.26-5"

# DRBL repository
DRBL_REPOSITORY_URL="http://free.nchc.org.tw/drbl-core"
# url to the repository key
DRBL_GPG_KEY_URL="http://drbl.nchc.org.tw/GPG-KEY-DRBL"

# The files in dir $ocs_live_script_dir/ will be copied to the dir /live-hook-dir in dir chroot. The file "ocs-live-hook" is in $ocs_live_script_dir
# We put some files in dir ocs_minimal_hook/ to do some jobs, like clean unnecessary files, set locales...
ocs_live_script_dir="$DRBL_SCRIPT_PATH/setup/files/ocs/live-hook"
# The script inside $ocs_live_script_dir/ will be run when chroot. There are many files in $ocs_live_script_dir/, we will just run one here.
run_hook_script="ocs-live-hook"

#
check_if_root
#
prog="$(basename $0)"

# functions
USAGE() {
    echo "Usage:"
    echo "To create a Ubuntu live CD which is used a template for Clonezilla live:"
    echo "$prog [OPTION]"
    echo "OPTION:"
    echo "-b, --branch [stable|testing|unstable]  specifies the DRBL branch to be used in Live CD. Default is stable."
    echo "-d, --debian-dist [gutsy|hardy|intrepid]  Assign Ubuntu dist, the default is $DEBIAN_DIST_DEF if not assigned."
    echo "-i, --assign-version-no NO  Assign the version no as NO instead of date."
    echo "-k, --live-kernel-pkg KERNEL_VER Assign kernel version as KERNEL_VER (KERNEL VER package must exist in repository. Ex. if KERNEL_VER is 2.6.20-1-486, then linux-image-2.6.20-1-486, squashfs-modules-2.6.20-1-486, and unionfs-modules-2.6.20-1-486 will be used."
    echo "-l, --drbl-live-branch [s|stable|t|testing|u|unstable|e|experimental]  specifies the DRBL live branch to be used in Live CD. Default is stable."
    echo "-m|--mirror-url URL Assign the URL for mirror site. Ex. http://free.nchc.org.tw/ubuntu/"
    echo "-s|--mirror-security-url URL Assign the URL of security branch for mirror site. Ex. http://free.nchc.org.tw/ubuntu/"
    echo "-t, --batch     Run in batch mode"
    echo "-v, --verbose   Run make-live/lh_build in verbose mode"
}
#
get_latest_kernel_in_repository() {
  # Since we might run this on gutsy to create hardy live, so we can not use apt-cache to search that. Another approach is to use apt-file to do that. However, it looks like the file http://opensource.nchc.org.tw/ubuntu/dists/hardy/Contents-i386.gz which apt-file fetched is not updated with repository.
  local ktmp kver
  ktmp="$(mktemp -d /tmp/live_kver.XXXXXX || exit 1)"
  for i in $debian_dist-updates $debian_dist; do
    echo "Downloading $mirror_url/dists/$i/main/binary-i386/Packages.gz  to finding latest kernel version..."
    LANG=C wget $wget_opt -P $ktmp/ $mirror_url/dists/$i/main/binary-i386/Packages.gz
    # The info in the Packges.gz is like:
    # Package: linux-image-2.6.24-10-386
    # Package: linux-image-2.6.24-10-generic
    # Package: linux-image-2.6.24-10-server
    # Package: linux-image-2.6.24-10-virtual
    # Package: linux-image-2.6.24-11-386
    # Package: linux-image-2.6.24-11-generic
    # Package: linux-image-2.6.24-11-server
    # Package: linux-image-2.6.24-11-virtual
    kver="$(zgrep -E "^Package: linux-image-2\.6\.[[:digit:]]+.*-generic" $ktmp/Packages.gz  | pkg-ver-latest | sed -e "s|^Package: linux-image-||g" -e "s|-generic$||g")"
    if [ -z "$kver" ]; then
      # Clean Packages.gz to avoid wget using another name like Packages.gz.1 then search the next again
      rm -f $ktmp/Packages.gz
    else
      # Found! Use it. 
      break
    fi
  done
  if [ -n "$kver" ]; then
    release_kernel_ver="$kver"
  else
    [ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
    echo "Warning!"
    echo "Unable to find the latest kernel version in $mirror_url/dists/$i/main/binary-i386/Packages.gz. Use the pre-defined one."
    [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
    echo -n "$msg_press_enter_to_continue"
    read 
    eval release_kernel_ver="\$${i}_release_kernel_ver_def"
  fi
  [ -d "$ktmp" -a -n "$ktmp" ] && rm -rf $ktmp
} # end of get_latest_kernel_in_repository

batch_mode="off"
# Parse command-line options
while [ $# -gt 0 ]; do
  case "$1" in
    -b|--branch)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              drbl_branch="$1"
              shift
            fi
	    [ -z "$drbl_branch" ] && USAGE && exit 1
            ;;
    -d|--debian-dist)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              debian_dist="$1"
              shift
            fi
	    [ -z "$debian_dist" ] && USAGE && exit 1
            ;;
    -i|--assign-version-no)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              version_no="$1"
              shift
            fi
	    [ -z "$version_no" ] && USAGE && exit 1
            ;;
    -k|--live-kernel)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              live_kernel_ver="$1"
              shift
            fi
	    [ -z "$live_kernel_ver" ] && USAGE && exit 1
            ;;
    -l|--drbl-live-branch)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              drbl_live_branch="$1"
              shift
            fi
	    [ -z "$drbl_live_branch" ] && USAGE && exit 1
            ;;
    -m|--mirror-url)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              mirror_url="$1"
              shift
            fi
	    [ -z "$mirror_url" ] && USAGE && exit 1
            ;;
    -s|--mirror-security-url)
            shift
            if [ -z "$(echo $1 |grep ^-.)" ]; then
              # skip the -xx option, in case 
              mirror_security_url="$1"
              shift
            fi
	    [ -z "$mirror_security_url" ] && USAGE && exit 1
            ;;
    -t|--batch)
	    batch_mode="on"
            shift ;;
    -v|--verbose)
	    verbose="on"
            shift ;;
    -*)     echo "${0}: ${1}: invalid option" >&2
            USAGE >& 2
            exit 2 ;;
    *)      break ;;
  esac
done

if ! type lh_build &>/dev/null; then
  [ "$BOOTUP" = "color" ] && $SETCOLOR_FAILURE
  echo "This program only works in Ubuntu 7.10 or 8.04!"
  echo "If you are running Ubuntu 7.10 or later, use 'apt-get install live-helper' to install the necessary packages, then run $0 again."
  [ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
  exit 1
fi

[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "///NOTE///"
echo "0. This script works in Ubuntu 7.10, 8.04 and 8.10 with the live-helper from patched one (live-helper_1.0~a47-2) by DRBL (modified from the one in Debian Sid!)"
echo "1. You have to use cdebootstrap instead of debootstrap. Remember to install the one patched by DRBL/Clonezilla team. (cdebootstrap version 0.5.1 or later)"
echo "2. If you want to create Intrepid live on Ubuntu hardy or Debian etch, you should make sure the following exist in /usr/share/cdebootstrap/suites:"
echo "Suite: intrepid"
echo "Config: generic-ubuntu"
echo "Keyring: ubuntu-archive-keyring.gpg"
echo "3. You might also need to use the live-experimental from DRBL (i.e. use run $0 with '-l e') so that:"
echo "  a. Enable aufs instead of unionfs (To avoid this bug: https://bugs.launchpad.net/ubuntu/+source/linux-ubuntu-modules-2.6.22/+bug/150788)."
echo "  b. Avoid a live-initramfs bug, which fails in console login."
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL
if [ "$batch_mode" = "no" ]; then
  echo -n "Press enter to continue... "
  read
fi

rm -rf $workdir/.stage/

# Apply default settings if not assigned
[ -z "$debian_dist" ] && debian_dist="$DEBIAN_DIST_DEF"
[ -z "$mirror_url" ] && mirror_url="$mirror_url_def"
[ -z "$mirror_security_url" ] && mirror_security_url="$mirror_security_url_def"

#
case "$drbl_branch" in
  t|testing)
     echo "Using DRBL testing branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="stable testing"
     ;;
  u|unstable)
     echo "Using DRBL unstable branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="stable testing unstable"
     ;;
  *)
     echo "Using DRBL stable branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="stable"
     ;;
esac
case "$drbl_live_branch" in
  t|testing)
     echo "Using DRBL Live testing branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="$LIVE_REPOSITORY_SECTIONS_drbl live-stable live-testing"
     ;;
  u|unstable)
     echo "Using DRBL Live unstable branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="$LIVE_REPOSITORY_SECTIONS_drbl live-stable live-testing live-unstable"
     ;;
  e|experimental)
     echo "Using DRBL Live experimental branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="$LIVE_REPOSITORY_SECTIONS_drbl live-stable live-testing live-unstable live-experimental"
     ;;
  *)
     echo "Using DRBL live stable branch..."
     LIVE_REPOSITORY_SECTIONS_drbl="$LIVE_REPOSITORY_SECTIONS_drbl live-stable"
     ;;
esac

# If version_no is not assigned, use date (Ex. 20070409)
[ -z "$version_no" ] && version_no="$(date +%Y%m%d)"
target_iso="ubuntu-live-for-ocs-${version_no}.iso"

[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "Creating a Ubuntu live cd iso which is used for clonezilla image with restoration function. The created iso will be in $target_iso" 
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL

if [ "$verbose" = "on" ]; then
  pref="bash -x"
fi

if [ -d "$workdir" ]; then
  echo "Found dir $workdir, clean stale files..."
  chroot $workdir/chroot umount /dev/pts &>/dev/null
  chroot $workdir/chroot umount /proc &>/dev/null
  chroot $workdir/chroot umount /sys &>/dev/null
  ( cd $workdir/; lh_clean )
  [ -n "$workdir" -a -d "$workdir" ] && rm -rf $workdir
fi

# Ubuntu sections:
ubuntu_sections="main restricted universe multiverse"

mkdir $workdir
(
cd $workdir

$pref lh_config --categories "$ubuntu_sections"
$pref lh_config --mirror-binary $mirror_url --mirror-binary-security $mirror_security_url 
$pref lh_config --mirror-bootstrap $mirror_url
$pref lh_config --mirror-chroot $mirror_url --mirror-chroot-security $mirror_security_url

# For Hardy, mkisofs is obsolete. Use genisoimage instead. Since aptitude won't fail if mkisofs (which is listed in drbl.conf) is not found in the repository. We can list mkisofs and genisoimage for pkgs. aptitude, unlike apt, won't exit if mkisofs is not found.
pkgs="$pkgs genisoimage"

# Since casper does not support aufs, and we need aufs to avoid this bug: 
# https://bugs.launchpad.net/ubuntu/+source/linux-ubuntu-modules-2.6.22/+bug/150788. Comment this:
# //NOTE// We must use the live-initramfs patched by DRBL otherwise the created iso won't boot into command line. Some errors like:
# init:/etc/event.d/tty1:15: Unknown stanza
# will occur when booting, so upstart won't run gettty
$pref lh_config --initramfs live-initramfs
#$pref lh_config --linux-flavours generic --linux-packages "linux-restricted-modules"
$pref lh_config --linux-flavours generic

# get the latest kernel ver "release_kernel_ver"
get_latest_kernel_in_repository
[ "$BOOTUP" = "color" ] && $SETCOLOR_WARNING
echo "The kernel version in this live CD will be: $release_kernel_ver"
[ "$BOOTUP" = "color" ] && $SETCOLOR_NORMAL

if [ "$debian_dist" = "gutsy" ]; then
  # Updated! 2007/12/27 with the patch from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448210, now we can use cdebootstrap.
  # ///OLD/// Here actually we can not use "--bootstrap cdebootstrap" due to this bug:
  # ///OLD/// http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448348&trim=no
  # Looks like if we use "--apt apt" instead of "--apt aptitude", there are a lot of warning about failing authenticating deb packages.
  $pref lh_config --bootstrap-flavour $debian_type --packages "$pkgs" --hook /live-hook-dir/$run_hook_script --apt aptitude --apt-recommends disabled --binary-indices disabled --bootstrap cdebootstrap --tasksel none
  # For Ubuntu 7.10, only unionfs comes with kernel, no aufs. However, we need aufs to avoid a bug (see above). An aufs module provided by DRBL works for this.
  # $pref lh_config --distribution $debian_dist --union-filesystem aufs --linux-packages "linux-image${kernel_extra_tag} aufs-modules${kernel_extra_tag} squashfs-modules${kernel_extra_tag}" 
  # For gutsy: linux-image-2.6.22-14-386
  # Live helper auto append "-386" for param from "--linux-packages"
  # TODO: UGLY! 2.6.22-14 should not be hardcoded in this program. We should find a better solution to work with kernel and aufs module.
  $pref lh_config --distribution $debian_dist --union-filesystem aufs 
  $pref lh_config --linux-packages "linux-image-$release_kernel_ver linux-ubuntu-modules-$release_kernel_ver aufs-modules-$release_kernel_ver"
  # Exclude some stuffs from the squashfs root, since in Live system, we will only use vmlinuz and initrd in /{casper,live}, not in the /boot/ in the squashfs.
  export MKSQUASHFS_OPTIONS="-e boot"
elif [ "$debian_dist" = "hardy" ]; then
  # Updated! 2007/12/27 with the patch from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448210, now we can use cdebootstrap.
  # ///OLD/// Here actually we can not use "--bootstrap cdebootstrap" due to this bug:
  # ///OLD/// http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448348&trim=no
  # Looks like if we use "--apt apt" instead of "--apt aptitude", there are a lot of warning about failing authenticating deb packages.
  $pref lh_config --bootstrap-flavour $debian_type --packages "$pkgs" --hook /live-hook-dir/$run_hook_script --apt aptitude --apt-recommends disabled --binary-indices disabled --bootstrap cdebootstrap --tasksel none
  # For hardy, mkisofs was removed. Force to use genisoimage
  # //NOTE// DO NOT put lh_config command option too long, otherwise lh_config will fail and show something like: E: internal error
  # --genisoimage was removed in live-helper 1.0~a37
  # ///NOTE/// From hardy with kernel 2.6.24-7 or later, linux-ubuntu-modules includes aufs module. Therefore aufs-modules-$release_kernel_ver is not requred anymore.
  $pref lh_config --distribution $debian_dist --union-filesystem aufs 
  # $pref lh_config --linux-packages "linux-image-$release_kernel_ver linux-ubuntu-modules-$release_kernel_ver aufs-modules-$release_kernel_ver" 
  $pref lh_config --linux-packages "linux-image-$release_kernel_ver linux-ubuntu-modules-$release_kernel_ver" 
  # $pref lh_config --genisoimage genisoimage 
  # Exclude some stuffs from the squashfs root, since in Live system, we will only use vmlinuz and initrd in /{casper,live}, not in the /boot/ in the squashfs.
  # Do not use lzma (For Hardy or later). /NOTE/ "-e dir_list" must be the last param for mksquashfs.
  export MKSQUASHFS_OPTIONS="-nolzma -e boot"
elif [ "$debian_dist" = "intrepid" ]; then
  # Updated! 2007/12/27 with the patch from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448210, now we can use cdebootstrap.
  # ///OLD/// Here actually we can not use "--bootstrap cdebootstrap" due to this bug:
  # ///OLD/// http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=448348&trim=no
  # In Intrepid, "--apt aptitude" does not work since aptitude is not the default one. Use "--apt apt" (default) instead of "--apt aptitude".
  # Since intrepid uses uvesafb to replace vesafb, we need v86d. Check https://bugs.launchpad.net/ubuntu/+source/v86d/+bug/189621 for more details.
  $pref lh_config --bootstrap-flavour $debian_type --packages "$pkgs v86d" --hook /live-hook-dir/$run_hook_script --apt-recommends disabled --binary-indices disabled --bootstrap cdebootstrap --tasksel none
  # ///NOTE/// From intrepid with kernel 2.6.26-4 or later, linux-ubuntu-modules no more exists, and aufs is builtin in linux-image (not as a module)
  $pref lh_config --distribution $debian_dist --union-filesystem aufs 
  $pref lh_config --linux-packages "linux-image-$release_kernel_ver"
  # Exclude some stuffs from the squashfs root, since in Live system, we will only use vmlinuz and initrd in /{casper,live}, not in the /boot/ in the squashfs.
  # Do not use lzma (For Hardy or later). /NOTE/ "-e dir_list" must be the last param for mksquashfs.
  export MKSQUASHFS_OPTIONS="-nolzma -e boot"
else
  echo "This distribution $debian_dist is not supported."
  echo "Program terminated!"
  exit 1
fi

# We force to use 486 kernel only.
$pref lh_config --linux-flavours generic

# No memtest from debian, we will use the one from drbl since it's newer.
$pref lh_config --memtest disabled

$pref lh_config --hostname "$debian_dist" 
$pref lh_config --username user --bootappend "username=user"
# Disable the security, otherwise live-helper >= 1.0~a37 does not support Ubuntu and will create a wrong sources.list for ubuntu updates and securit. We will create it by ourself.
$pref lh_config --security disabled

# Put hook files
mkdir -p config/chroot_local-includes/live-hook-dir
for i in $ocs_live_script_dir; do
  cp -p $i/* config/chroot_local-includes/live-hook-dir/
done
cp $DRBL_SCRIPT_PATH/conf/drbl.conf config/chroot_local-includes/live-hook-dir/


# prepare ubuntu updates and security source list and drbl source list
cat << AddDRBLRepository > config/chroot_sources/drbl.chroot
deb $mirror_security_url ${debian_dist}-updates $ubuntu_sections
deb $mirror_security_url ${debian_dist}-security $ubuntu_sections
deb $DRBL_REPOSITORY_URL drbl $LIVE_REPOSITORY_SECTIONS_drbl
AddDRBLRepository

# prepare drbl key
LANG=C wget -O config/chroot_sources/drbl.chroot.gpg $DRBL_GPG_KEY_URL

$pref lh_build
)
mv -f $workdir/binary.iso $target_iso
