#!/bin/bash
# cobbler-ubuntu-import

VERBOSITY=0
TEMP_D=""
ISO_DIR="/var/lib/cobbler/isos"
DEFAULT_MIRROR="http://archive.ubuntu.com/ubuntu"

error() { echo "$@" 1>&2; }
errorp() { printf "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; }

Usage() {
	cat <<EOF
Usage: ${0##*/} [ options ] [ release-arch [ release-arch [ ... ] ] ]

   import distro and profile for Ubuntu release-arch

   options:
      -D | --delete-iso   delete the mini iso after downloading.  Normally
                          they are kept in $ISO_DIR
      -m | --mirror M     use mirror rather than default for downloading iso
                          default: ${DEFAULT_MIRROR}
      -c | --update-check check saved ISOs against what is published on the
                          mirror.  exits 0 if an update is needed or iso does
                          not exist in $ISO_DIR
      -r | --remove       remove cobbler profile/distro and cached ISO
   Note, arch can be i386, x86_64, or amd64.  However,
   the registered distro and profile will use 'x86_64' rather than 'amd64'.
   This is to keep consistent with cobbler naming.

   Example:
    - ${0##*/} natty-i386
EOF
}

bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
cleanup() {
   [ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}

loop_mount() {
	# Create more loop nodes, if necessary
	local mounts=$(grep -c /dev/loop /proc/mounts) || mounts=0
	local loops=$(ls /dev/loop* | wc -l) || loops=0
	if [ $mounts -ge $loops ]; then
		mknod -m 660 /dev/loop$loops b 7 $loops
		chown root:disk /dev/loop$loops
	fi
	# Do the loop mount
	mount -o loop "$1" "$2"
}

short_opts="Dhm:o:vcr"
long_opts="delete-iso,help,mirror:,verbose,update-check,remove"
getopt_out=$(getopt --name "${0##*/}" \
	--options "${short_opts}" --long "${long_opts}" -- "$@") &&
	eval set -- "${getopt_out}" ||
	bad_Usage

delete=false
check_update=false
remove=false
mirror=${DEFAULT_MIRROR}

while [ $# -ne 0 ]; do
	cur=${1}; next=${2};
	case "$cur" in
		-h|--help) Usage ; exit 0;;
		-m|--mirror) mirror=${2}; shift;;
		-D|--delete-iso) delete=true;;
		-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
		-c|--update-check) check_update=true;;
		-r|--remove) remove=true;;
		--) shift; break;;
	esac
	shift;
done

## check arguments here
[ $# -ne 0 ] || bad_Usage "must provide arguments"

TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
   fail "failed to make tempdir"
trap cleanup EXIT

# program starts here
if $delete; then
	{ [ -d "$ISO_DIR" ] || mkdir -p "$ISO_DIR"; }  || fail "failed to create $ISO_DIR"
fi
mkdir "$TEMP_D/mnt" || fail "failed to make tempdir/mnt"

for tok in "$@"; do
	rel=${tok%-*}; arch=${tok#*-}
	[ "$arch" = "amd64" ] && 
		{ error "Warning: using x86_64 for arch rather than amd64"; arch="x86_64"; }
	ubuntu_arch=$arch; [ "$arch" = "x86_64" ] && ubuntu_arch=amd64
	iso=$rel-$arch-mini.iso
	u=$mirror/dists/$rel/main/installer-$ubuntu_arch/current/images/netboot/mini.iso
	md5=$mirror/dists/$rel/main/installer-$ubuntu_arch/current/images/MD5SUMS
	if $remove; then
		if [ -f "$ISO_DIR/$iso" ]; then
			rm -rf "$ISO_DIR/$iso" ||
				fail "Could not delete $ISO_DIR/$iso"
		fi
		if cobbler distro list | grep -qs " $rel-$arch"; then
			cobbler distro remove --name=$rel-$arch ||
				fail "Could not remove cobbler profile for $rel-$arch"
		fi
		exit 0
	fi
	if $check_update; then
		# compare md5 of the local iso to whats on the mirror.
		[ ! -f "$ISO_DIR/$iso" ] && exit 0
		md5=$mirror/dists/$rel/main/installer-$ubuntu_arch/current/images/MD5SUMS
		md5sum_local=$(md5sum "$ISO_DIR/$iso") && md5sum_local=${md5sum_local% *} \
			&& [ -n $md5sum_local ] || fail "failed to checksum $ISO_DIR/$iso"
		wget -qO $TEMP_D/MD5SUMS $md5 || fail "failed to download MD5SUMS for $rel-$arch: $u"
		md5sum_remote=$(awk '$2 == "./netboot/mini.iso" { print $1 }' $TEMP_D/MD5SUMS) &&
			[ -n $md5sum_remote ] || fail "failed to parse checksum from $TEMP_D/MD5SUM"
		[ $md5sum_local != $md5sum_remote ] && exit 0
		error "$ISO_DIR/$iso up to date." && exit 3
	fi
	if [ ! -f "$ISO_DIR/$iso" ]; then
		wget -O "$TEMP_D/$iso" "$u" && [ -s "$TEMP_D/$iso" ] ||
			fail "failed download for $rel-$arch: $u"
		{ $delete || mv "$TEMP_D/$iso" "$ISO_DIR/$iso"; } ||
			fail "failed to write to move iso to $ISO_DIR/$iso"
	fi
	{ [ -f $TEMP_D/$iso ] || ln -sf "$ISO_DIR/$iso" "$TEMP_D/$iso"; } ||
		fail "failed to create symlink to existing $ISO_DIR/$iso"
	mounted=0 && loop_mount "$TEMP_D/$iso" "$TEMP_D/mnt" && mounted=1 &&
		cobbler import --name=$rel-$arch --path="$TEMP_D/mnt" \
			--breed=ubuntu --os-version=$rel --arch=$arch &&
		umount "${TEMP_D}/mnt" && mounted=0 || {
				[ $mounted -eq 0 ] || umount "$TEMP_D/mnt";
				fail "failed to import $rel-$arch";
			}
	echo "imported $rel-$arch"
done

# vi: ts=4 noexpandtab
