#!/bin/sh

set -e

export PKGOS_VERBOSE=yes
OSINSTALL_RC=~/osinstallrc
TEMPEST_CONF=/etc/tempest/tempest.conf
# This can be debian or cirros. While it's cool
# to test using the Debian image, it's also a
# quite big image which needs flavor 2 (eg: the
# HDD needs more than 1 GB of space), and it
# takes a while to build it.
TEST_IMAGE_TYPE=cirros
if [ "${TEST_IMAGE_TYPE}" = "debian" ] ; then
	IMAGE_PASS=SupArP4ss
else
	IMAGE_PASS="cubswin:)"
fi

if [ -n "${1}" ] ; then
	DEBIAN_REPO_PARAM=" -u ${1} -s ${1}"
	shift
fi

####################
# INCLUDE OUR LIBS #
####################
if ! [ -r /usr/share/openstack-deploy/preseed-lib ] ; then
	echo "Can't find /usr/share/openstack-deploy/pressed-lib: exiting"
	exit 1
fi
. /usr/share/openstack-deploy/preseed-lib
if ! [ -r /usr/share/openstack-pkg-tools/pkgos_func ] ; then
	echo "Can't find /usr/share/openstack-pkg-tools/pkgos_func: exiting"
	exit 1
fi
. /usr/share/openstack-pkg-tools/pkgos_func

if ! [ -r /etc/default/openstack-proxy-node-network ] ; then
	echo "Can't find /etc/default/openstack-proxy-node-network: exiting"
	exit 1
fi
. /etc/default/openstack-proxy-node-network

if [ -r "${OSINSTALL_RC}" ] ; then
	. ${OSINSTALL_RC}
else
	echo "Cannot find ${OSINSTALL_RC}: exiting..."
	exit 1
fi

if [ -r ~/openrc.sh ] ; then
	. ~/openrc.sh
else
	echo "Cannot find openrc.sh: exiting..."
	exit 1
fi

#################################
# DEFINE SOME UTILITY FUNCTIONS #
#################################
osinstall_check_installed () {
	local PKG_NAME
	PKG_NAME=${1}
	INSTALL_STRING=`dpkg -l ${PKG_NAME} | grep ^ii | awk '{print $2}'`
	if [ "${INSTALL_STRING}" = ${PKG_NAME} ] ; then
		return 0
	else
		return 1
	fi
}

osinstall_install_if_not_installed () {
	local PKG_NAME
	PKG_NAME=${1}
	if ! osinstall_check_installed ${PKG_NAME} ; then
		DEBIAN_FRONTEND=noninteractive ${APTGET} install ${PKG_NAME}
	fi
}

deploy_tempest_install_pkgs () {
	echo "===> Installing tempest and openstack-debian-images"
	osinstall_install_if_not_installed tempest
	cp /usr/share/openstack-deploy/tempest_exclude.conf /etc/tempest/exclude.conf
	osinstall_install_if_not_installed openstack-debian-images
	osinstall_install_if_not_installed openstack-clients
}

build_and_upload_image () {
	# Even if we don't use the Cirros image for tests, we need it
	# because there's some Cinder tests that are expecting the image
	# to be in there.
	# Download the Cirros image
	CIRROS_VERSION=0.3.1
	mkdir -p /opt/stack/new/devstack/files/images/cirros-${CIRROS_VERSION}-x86_64-uec
	wget http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz
	tar -C /opt/stack/new/devstack/files/images/cirros-${CIRROS_VERSION}-x86_64-uec -xvzf cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz
	rm cirros-${CIRROS_VERSION}-x86_64-uec.tar.gz


	AUTH_TOKEN=${RC_KEYSTONE_AUTHTOKEN}

	if [ "${TEST_IMAGE_TYPE}" = debian ] ; then
		echo "===> Creating Debian image"
		build-openstack-debian-image -r jessie -p ${IMAGE_PASS} ${DEBIAN_REPO_PARAM}
		IMAGE_PATH=`ls *.qcow2`
		echo "===> Uploading image to Glance"
		IMAGE_REF=`pkgos_get_id glance image-create --name foo --disk-format=qcow2 --container-format=bare --visibility public --file=${IMAGE_PATH}`
	else
		echo "===> Download the Cirros image"
		IMAGE_PATH=/opt/stack/new/devstack/files/images/cirros-${CIRROS_VERSION}-x86_64-disk.img
		wget http://download.cirros-cloud.net/${CIRROS_VERSION}/cirros-${CIRROS_VERSION}-x86_64-disk.img -O ${IMAGE_PATH}
		IMAGE_REF=`pkgos_get_id glance image-create --name foo --disk-format=qcow2 --container-format=bare --visibility public --file=${IMAGE_PATH}`
	fi
}

create_non_admin_keystone_user () {
	openstack project create testme
	openstack user create --password testme --project testme --email root@localhost --enable testme
	openstack project create testme2
	openstack user create --password testme2 --project testme2 --email root@localhost --enable testme2
}

fix_tempest_config () {
	echo "===> Fixing tempest.conf"
	# [DEFAULT]
	pkgos_inifile set ${TEMPEST_CONF} DEFAULT log_file tempest.log
	pkgos_inifile set ${TEMPEST_CONF} DEFAULT log_dir /var/log

	# [identity]
	pkgos_inifile set ${TEMPEST_CONF} identity disable_ssl_certificate_validation true
	pkgos_inifile set ${TEMPEST_CONF} identity uri http://${DEFROUTE_IP}:5000/v2.0
	pkgos_inifile set ${TEMPEST_CONF} identity uri_v3 http://${DEFROUTE_IP}:5000/v3
	pkgos_inifile set ${TEMPEST_CONF} identity auth_version v3
	pkgos_inifile set ${TEMPEST_CONF} identity username testme
	pkgos_inifile set ${TEMPEST_CONF} identity tenant_name testme
	pkgos_inifile set ${TEMPEST_CONF} identity password testme
	pkgos_inifile set ${TEMPEST_CONF} identity alt_username testme2
	pkgos_inifile set ${TEMPEST_CONF} identity alt_tenant_name testme2
	pkgos_inifile set ${TEMPEST_CONF} identity alt_password testme2
	pkgos_inifile set ${TEMPEST_CONF} identity admin_username admin
	pkgos_inifile set ${TEMPEST_CONF} identity admin_tenant_name admin
	pkgos_inifile set ${TEMPEST_CONF} identity admin_password ${RC_KEYSTONE_ADMINPASS}

	# [identity-feature-enabled]
	pkgos_inifile set ${TEMPEST_CONF} identity-feature-enabled api_v2 true
	pkgos_inifile set ${TEMPEST_CONF} identity-feature-enabled api_v3 false

	# [compute]
	pkgos_inifile set ${TEMPEST_CONF} compute image_ref ${IMAGE_REF}
	pkgos_inifile set ${TEMPEST_CONF} compute image_ref_alt ${IMAGE_REF}
	if [ "${TEST_IMAGE_TYPE}" = debian ] ; then
		pkgos_inifile set ${TEMPEST_CONF} compute image_ssh_user debian
	else
		pkgos_inifile set ${TEMPEST_CONF} compute image_ssh_user cirros
	fi
	pkgos_inifile set ${TEMPEST_CONF} compute image_ssh_password ${IMAGE_PASS}
	pkgos_inifile set ${TEMPEST_CONF} compute image_alt_ssh_user root
	pkgos_inifile set ${TEMPEST_CONF} compute image_alt_ssh_password ${IMAGE_PASS}
	sed -i "s/#[\t ]*region[ \t]*=.*/region=regionOne/"  ${TEMPEST_CONF}
	pkgos_inifile set ${TEMPEST_CONF} compute network_for_ssh ext-net
	pkgos_inifile set ${TEMPEST_CONF} compute fixed_network_name demo-net
	# flavor 1 is too small for the 2GB default Jessie image
	if [ "${TEST_IMAGE_TYPE}" = debian ] ; then
		pkgos_inifile set ${TEMPEST_CONF} compute flavor_ref 2
	fi

	pkgos_inifile set ${TEMPEST_CONF} compute ssh_connect_method floating
	if [ "${TEST_IMAGE_TYPE}" = debian ] ; then
		pkgos_inifile set ${TEMPEST_CONF} compute path_to_private_key /root/.ssh/id_rsa
		pkgos_inifile set ${TEMPEST_CONF} compute ssh_auth_method keypair
		pkgos_inifile set ${TEMPEST_CONF} compute ssh_user debian
	fi
	pkgos_inifile set ${TEMPEST_CONF} compute-feature-enabled spice_console true

	# [compute-admin]
	pkgos_inifile set ${TEMPEST_CONF} compute-admin username admin
	pkgos_inifile set ${TEMPEST_CONF} compute-admin tenant_name admin
	pkgos_inifile set ${TEMPEST_CONF} compute-admin password ${RC_KEYSTONE_ADMINPASS}

	# [dashboard]
	pkgos_inifile set ${TEMPEST_CONF} dashboard dashboard_url http://${DEFROUTE_IP}/
	pkgos_inifile set ${TEMPEST_CONF} dashboard login_url http://${DEFROUTE_IP}/auth/login/

	# [network]
	pkgos_inifile set ${TEMPEST_CONF} network tenant_network_cidr ${TENANT_NET_CIDR}
	PUBLIC_NETWORK_ID=`pkgos_get_id neutron net-show ext-net`
	pkgos_inifile set ${TEMPEST_CONF} network public_network_id ${PUBLIC_NETWORK_ID}
# We shouldn't do this. Doing it fails all tests
#	PUBLIC_ROUTER_ID=`pkgos_get_id neutron router-show demo-router`
#	pkgos_inifile set ${TEMPEST_CONF} network public_router_id ${PUBLIC_ROUTER_ID}

	# [service_available]
	pkgos_inifile set ${TEMPEST_CONF} service_available neutron true
	pkgos_inifile set ${TEMPEST_CONF} service_available glance true
	pkgos_inifile set ${TEMPEST_CONF} service_available cinder true
	pkgos_inifile set ${TEMPEST_CONF} service_available swift false
	pkgos_inifile set ${TEMPEST_CONF} service_available nova true
	pkgos_inifile set ${TEMPEST_CONF} service_available heat false
	pkgos_inifile set ${TEMPEST_CONF} service_available ceilometer true
	pkgos_inifile set ${TEMPEST_CONF} service_available horizon true
	#sahara=false
	#ironic=false
	#trove=false
	#marconi=false
}

gen_ssh_root_key () {
	ssh-keygen -t rsa -N "" -f .ssh/id_rsa
	nova keypair-add --pub-key .ssh/id_rsa.pub odtkey
}

setup_loopback_based_lvm_vg () {
	echo "===> Creating a 40 GB loopback file used as LVM"
	## Create a 10GB file on the root
	#dd if=/dev/zero of=/lvm-data.dat count=20971520
	# Create a 40GB file on the root
	#dd if=/dev/zero of=/lvm-data.dat count=83886080 sparse
	qemu-img create /lvm-data.dat 40G
	# Setup the loopback device
	losetup /dev/loop0 /lvm-data.dat
	# Create the PV
	pvcreate /dev/loop0
	# Create the VG
	vgcreate pkgosvg0 /dev/loop0
	# Activate the pkgosvg0
	vgchange -a y pkgosvg0
	echo "Done!"
}

setup_loopback_based_swift () {
	### NOTE: this comes from http://docs.openstack.org/developer/swift/development_saio.html ###

	DEBIAN_FRONTEND=noninteractive ${APTGET} install swift swift-proxy swift-account swift-container swift-object swift-object-expirer xfsprogs

	# Create the loopback device
	mkdir -p /srv
	qemu-img create /srv/swift-disk 20G
	mkfs.xfs /srv/swift-disk

	# Mount it
	mkdir /mnt/sdb1
	echo "/srv/swift-disk /mnt/sdb1 xfs loop,noatime,nodiratime,nobarrier,logbufs=8 0 0" >>/etc/fstab
	mount /mnt/sdb1

	# Setup swift disks
	mkdir /mnt/sdb1/1 /mnt/sdb1/2 /mnt/sdb1/3 /mnt/sdb1/4
	chown swift:swift /mnt/sdb1/*
	for x in `seq 1 4`; do ln -s /mnt/sdb1/$x /srv/$x; done
	mkdir -p /srv/1/node/sdb1 /srv/1/node/sdb5 \
		/srv/2/node/sdb2 /srv/2/node/sdb6 \
		/srv/3/node/sdb3 /srv/3/node/sdb7 \
		/srv/4/node/sdb4 /srv/4/node/sdb8 \
		/var/run/swift
	chown -R swift:swift /var/run/swift
	# **Make sure to include the trailing slash after /srv/$x/**
	for x in `seq 1 4`; do chown -R swift:swift /srv/$x/; done

	# Common Post-Device Setup
	mkdir -p /var/cache/swift /var/cache/swift2 /var/cache/swift3 /var/cache/swift4
	chown swift:swift /var/cache/swift*

	# Enable rsyncd for swift
	cp /usr/share/openstack-deploy/saio/rsyncd.conf /etc
	sed -i s/RSYNC_ENABLE=false/RSYNC_ENABLE=true/ /etc/default/rsync
	service rsync restart

	# Copy the saio config files for swift
	rm -rf /etc/swift/
	mkdir -p /etc/swift/
	cp -rfv /usr/share/openstack-deploy/saio/swift/* /etc/swift/
	chown -R swift:swift /etc/swift

	# Customize the config (ie: keystone authtoken)
	pkgos_inifile set /etc/swift/proxy-server.conf filter:authtoken admin_password ${RC_KEYSTONE_ADMINPASS}
	pkgos_inifile set /etc/swift/proxy-server.conf filter:authtoken identity_uri http://${DEFROUTE_IP}:35357/
	pkgos_inifile set /etc/swift/proxy-server.conf filter:authtoken auth_uri http://${DEFROUTE_IP}:5000/

	# Create the swift ring
	chmod +x /usr/share/openstack-deploy/saio/bin/remakerings
	/usr/share/openstack-deploy/saio/bin/remakerings

	# Restart swift after the config is good
	for i in `ls /etc/init.d/swift-*` ; do $i stop ; done
	for i in `ls /etc/init.d/swift-*` ; do $i start ; done

	# Setup the endpoint
	openstack --os-identity-api-version=3 service create --description "OpenStack Object Storage" --name swift object-store
	openstack --os-identity-api-version=3 endpoint create --region regionOne swift public http://${DEFROUTE_IP}:8080/v1/AUTH_%\(tenant_id\)s
	openstack --os-identity-api-version=3 endpoint create --region regionOne swift admin http://${DEFROUTE_IP}:8080/v1/AUTH_%\(tenant_id\)s
	openstack --os-identity-api-version=3 endpoint create --region regionOne swift internal http://${DEFROUTE_IP}:8080/v1/AUTH_%\(tenant_id\)s
	#openstack --os-domain-name default --os-identity-api-version=3 endpoint create --publicurl http://${DEFROUTE_IP}:8080/v1/AUTH_%\(tenant_id\)s --adminurl http://${DEFROUTE_IP}:8080/ --internalurl http://${DEFROUTE_IP}:8080/v1/AUTH_%\(tenant_id\)s --region regionOne swift
}

install_cinder () {
	# At this point in time, cinder should already be preseeded by openstack-deploy,
	# so just installing it this way should be fine
	DEBIAN_FRONTEND=noninteractive ${APTGET} install cinder-api cinder-volume python-cinderclient cinder-backup cinder-scheduler
	if [ -x /usr/bin/lsb_release ] && [ `lsb_release -a | grep Codename | awk '{print $2}'` = "wheezy" ] ; then
		DEBIAN_FRONTEND=noninteractive ${APTGET} install -t wheezy-backports tgt || true
	else
		DEBIAN_FRONTEND=noninteractive ${APTGET} install tgt || true
	fi
	# Set configuration for swift-backup (normally not needed...)
	#pkgos_inifile set /etc/cinder/cinder.conf backup_swift_tenant admin
	#pkgos_inifile set /etc/cinder/cinder.conf backup_swift_user admin
	#pkgos_inifile set /etc/cinder/cinder.conf backup_swift_key admin
}

deploy_tempest_install_pkgs
create_non_admin_keystone_user
build_and_upload_image
fix_tempest_config
gen_ssh_root_key
setup_loopback_based_lvm_vg
setup_loopback_based_swift
install_cinder
