1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390
|
#!/bin/bash
# This script is run by install_on_xen_host.sh
#
# It modifies the ubuntu image created by install_on_xen_host.sh
# and previously moodified by prepare_guest_template.sh
#
# This script is responsible for:
# - creates a DomU VM
# - creating run.sh, to run the code on DomU boot
#
# by install_on_xen_host.sh
# Exit on errors
set -o errexit
# Echo commands
set -o xtrace
# This directory
THIS_DIR=$(cd $(dirname "$0") && pwd)
TOP_DIR="$THIS_DIR/../"
SCRIPT_DIR="$TOP_DIR/scripts"
COMM_DIR="$TOP_DIR/common"
CONF_DIR="$TOP_DIR/conf"
# Include onexit commands
. $SCRIPT_DIR/on_exit.sh
# xapi functions
. $COMM_DIR/functions
# Source params
source $CONF_DIR/xenrc
# Defaults for optional arguments
DEVSTACK_SRC=${DEVSTACK_SRC:-"https://github.com/openstack-dev/devstack"}
LOGDIR="/opt/stack/devstack_logs"
DISABLE_JOURNALING="false"
# Number of options passed to this script
REMAINING_OPTIONS="$#"
# Get optional parameters
set +e
while getopts ":d:l:r" flag; do
REMAINING_OPTIONS=$(expr "$REMAINING_OPTIONS" - 1)
case "$flag" in
d)
DEVSTACK_SRC="$OPTARG"
REMAINING_OPTIONS=$(expr "$REMAINING_OPTIONS" - 1)
;;
l)
LOGDIR="$OPTARG"
REMAINING_OPTIONS=$(expr "$REMAINING_OPTIONS" - 1)
;;
r)
DISABLE_JOURNALING="true"
;;
\?)
print_usage_and_die "Invalid option -$OPTARG"
;;
esac
done
set -e
# Make sure that all options processed
if [ "0" != "$REMAINING_OPTIONS" ]; then
print_usage_and_die "ERROR: some arguments were not recognised!"
fi
#
# Prepare VM for DevStack
#
#
# Configure Networking
#
host_uuid=$(get_current_host_uuid)
MGT_NETWORK=`xe pif-list management=true host-uuid=$host_uuid params=network-uuid minimal=true`
MGT_BRIDGE_OR_NET_NAME=`xe network-list uuid=$MGT_NETWORK params=bridge minimal=true`
setup_network "$VM_BRIDGE_OR_NET_NAME"
setup_network "$MGT_BRIDGE_OR_NET_NAME"
setup_network "$PUB_BRIDGE_OR_NET_NAME"
if parameter_is_specified "FLAT_NETWORK_BRIDGE"; then
if [ "$(bridge_for "$VM_BRIDGE_OR_NET_NAME")" != "$(bridge_for "$FLAT_NETWORK_BRIDGE")" ]; then
cat >&2 << EOF
ERROR: FLAT_NETWORK_BRIDGE is specified in localrc file, and either no network
found on XenServer by searching for networks by that value as name-label or
bridge name or the network found does not match the network specified by
VM_BRIDGE_OR_NET_NAME. Please check your localrc file.
EOF
exit 1
fi
fi
if ! xenapi_is_listening_on "$MGT_BRIDGE_OR_NET_NAME"; then
cat >&2 << EOF
ERROR: XenAPI does not have an assigned IP address on the management network.
please review your XenServer network configuration / localrc file.
EOF
exit 1
fi
HOST_IP=$(xenapi_ip_on "$MGT_BRIDGE_OR_NET_NAME")
# Also, enable ip forwarding in rc.local, since the above trick isn't working
if ! grep -q "echo 1 >/proc/sys/net/ipv4/ip_forward" /etc/rc.local; then
echo "echo 1 >/proc/sys/net/ipv4/ip_forward" >> /etc/rc.local
fi
# Enable ip forwarding at runtime as well
echo 1 > /proc/sys/net/ipv4/ip_forward
HOST_IP=$(xenapi_ip_on "$MGT_BRIDGE_OR_NET_NAME")
#install the previous ubuntu VM
vm_exist=$(xe vm-list name-label="$DEV_STACK_DOMU_NAME" --minimal)
if [ "$vm_exist" != "" ]
then
echo "Uninstall the previous VM"
xe vm-uninstall vm="$DEV_STACK_DOMU_NAME" force=true
fi
echo "Install a new ubuntu VM according to previous template"
vm_uuid=$(xe vm-install template="$TNAME" new-name-label="$DEV_STACK_DOMU_NAME")
xe vm-param-set other-config:os-vpx=true uuid="$vm_uuid"
# Install XenServer tools, and other such things
$SCRIPT_DIR/prepare_guest_template.sh "$DEV_STACK_DOMU_NAME"
# Set virtual machine parameters
set_vm_memory "$DEV_STACK_DOMU_NAME" "$VM_MEM_MB"
# Max out VCPU count for better performance
max_vcpus "$DEV_STACK_DOMU_NAME"
# Wipe out all network cards
destroy_all_vifs_of "$DEV_STACK_DOMU_NAME"
# Add only one interface to prepare the guest template
add_interface "$DEV_STACK_DOMU_NAME" "$MGT_BRIDGE_OR_NET_NAME" "0"
# start the VM to run the prepare steps
xe vm-start vm="$DEV_STACK_DOMU_NAME" on=$host_uuid
# Wait for prep script to finish and shutdown system
wait_for_VM_to_halt "$DEV_STACK_DOMU_NAME"
## Setup network cards
# Wipe out all
destroy_all_vifs_of "$DEV_STACK_DOMU_NAME"
# Tenant network
add_interface "$DEV_STACK_DOMU_NAME" "$VM_BRIDGE_OR_NET_NAME" "$VM_DEV_NR"
# Management network
add_interface "$DEV_STACK_DOMU_NAME" "$MGT_BRIDGE_OR_NET_NAME" "$MGT_DEV_NR"
# Public network
add_interface "$DEV_STACK_DOMU_NAME" "$PUB_BRIDGE_OR_NET_NAME" "$PUB_DEV_NR"
#
# persistant the VM's interfaces
#
$SCRIPT_DIR/persist_domU_interfaces.sh "$DEV_STACK_DOMU_NAME"
FLAT_NETWORK_BRIDGE="${FLAT_NETWORK_BRIDGE:-$(bridge_for "$VM_BRIDGE_OR_NET_NAME")}"
append_kernel_cmdline "$DEV_STACK_DOMU_NAME" "flat_network_bridge=${FLAT_NETWORK_BRIDGE}"
# Disable FS journaling. It would reduce disk IO, but may lead to file system
# unstable after long time use
if [ "$DISABLE_JOURNALING" = "true" ]; then
vm_vbd=$(xe vbd-list vm-name-label=$DEV_STACK_DOMU_NAME --minimal)
vm_vdi=$(xe vdi-list vbd-uuids=$vm_vbd --minimal)
dom_zero_uuid=$(xe host-param-get param-name=control-domain-uuid uuid=$host_uuid)
tmp_vbd=$(xe vbd-create device=autodetect bootable=false mode=RW type=Disk vdi-uuid=$vm_vdi vm-uuid=$dom_zero_uuid)
xe vbd-plug uuid=$tmp_vbd
sr_id=$(get_local_sr)
kpartx -p p -avs /dev/sm/backend/$sr_id/$vm_vdi
echo "********Before disable FS journaling********"
tune2fs -l /dev/mapper/${vm_vdi}p1 | grep "Filesystem features"
echo "********Disable FS journaling********"
tune2fs -O ^has_journal /dev/mapper/${vm_vdi}p1
echo "********After disable FS journaling********"
tune2fs -l /dev/mapper/${vm_vdi}p1 | grep "Filesystem features"
kpartx -p p -dvs /dev/sm/backend/$sr_id/$vm_vdi
xe vbd-unplug uuid=$tmp_vbd timeout=60
xe vbd-destroy uuid=$tmp_vbd
fi
# Add a separate xvdb, if it was requested
if [[ "0" != "$XEN_XVDB_SIZE_GB" ]]; then
vm=$(xe vm-list name-label="$DEV_STACK_DOMU_NAME" --minimal)
# Add a new disk
localsr=$(get_local_sr)
extra_vdi=$(xe vdi-create \
name-label=xvdb-added-by-devstack \
virtual-size="${XEN_XVDB_SIZE_GB}GiB" \
sr-uuid=$localsr type=user)
xe vbd-create vm-uuid=$vm vdi-uuid=$extra_vdi device=1
fi
#
# Run DevStack VM
#
xe vm-start vm="$DEV_STACK_DOMU_NAME" on=$host_uuid
# Get hold of the Management IP of OpenStack VM
OS_VM_MANAGEMENT_ADDRESS=$MGT_IP
if [ $OS_VM_MANAGEMENT_ADDRESS == "dhcp" ]; then
OS_VM_MANAGEMENT_ADDRESS=$(find_ip_by_name $DEV_STACK_DOMU_NAME $MGT_DEV_NR)
fi
# Create an ssh-keypair, and set it up for dom0 user
rm -f /root/dom0key /root/dom0key.pub
ssh-keygen -f /root/dom0key -P "" -C "dom0"
DOMID=$(get_domid "$DEV_STACK_DOMU_NAME")
xenstore-write /local/domain/$DOMID/authorized_keys/$DOMZERO_USER "$(cat /root/dom0key.pub)"
xenstore-chmod -u /local/domain/$DOMID/authorized_keys/$DOMZERO_USER r$DOMID
function run_on_appliance {
ssh \
-i /root/dom0key \
-o UserKnownHostsFile=/dev/null \
-o StrictHostKeyChecking=no \
-o BatchMode=yes \
"$DOMZERO_USER@$OS_VM_MANAGEMENT_ADDRESS" "$@"
}
# Wait until we can log in to the appliance
while ! run_on_appliance true; do
sleep 1
done
# Remove authenticated_keys updater cronjob
echo "" | run_on_appliance crontab -
# Generate a passwordless ssh key for domzero user
echo "ssh-keygen -f /home/$DOMZERO_USER/.ssh/id_rsa -C $DOMZERO_USER@appliance -N \"\" -q" | run_on_appliance
# Authenticate that user to dom0
run_on_appliance cat /home/$DOMZERO_USER/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
set +x
echo "################################################################################"
echo ""
echo "VM configuration done!"
echo "################################################################################"
xe vm-shutdown vm="$DEV_STACK_DOMU_NAME"
wait_for_VM_to_halt "$DEV_STACK_DOMU_NAME"
#
# Mount the VDI
#
echo "check vdi mapping"
STAGING_DIR=$($SCRIPT_DIR/manage-vdi open $DEV_STACK_DOMU_NAME 0 1 | grep -o "/tmp/tmp.[[:alnum:]]*")
add_on_exit "$SCRIPT_DIR/manage-vdi close $DEV_STACK_DOMU_NAME 0 1"
# Make sure we have a stage
if [ ! -d $STAGING_DIR/etc ]; then
echo "ERROR:ct properly set up!"
exit 1
fi
if [ ! -d "$STAGING_DIR/opt/stack" ]; then
echo "ERROR: scet"
exit -1
fi
rm -f $STAGING_DIR/opt/stack/local.conf
pif=$(xe pif-list management=true host-uuid=$host_uuid --minimal)
XENSERVER_IP=$(xe pif-param-get param-name=IP uuid=$pif)
# Create an systemd task for devstack
cat >$STAGING_DIR/etc/systemd/system/devstack.service << EOF
[Unit]
Description=Install OpenStack by DevStack
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/bin/rm -f /opt/stack/runsh.succeeded
ExecStart=/bin/su -c "/opt/stack/run.sh" stack
StandardOutput=tty
StandardError=tty
[Install]
WantedBy=multi-user.target
EOF
if [ $? -ne 0 ]; then
echo "fatal error, install service failed."
exit 1
fi
# enable this service
rm -f $STAGING_DIR/etc/systemd/system/multi-user.target.wants/devstack.service
ln -s /etc/systemd/system/devstack.service $STAGING_DIR/etc/systemd/system/multi-user.target.wants/devstack.service
# Gracefully cp only if source file/dir exists
function cp_it {
if [ -e $1 ] || [ -d $1 ]; then
cp -pRL $1 $2
fi
}
# Copy over your ssh keys and env if desired
cp_it ~/.ssh $STAGING_DIR/opt/stack/.ssh
cp_it ~/.ssh/id_rsa.pub $STAGING_DIR/opt/stack/.ssh/authorized_keys
cp_it ~/.gitconfig $STAGING_DIR/opt/stack/.gitconfig
cp_it ~/.vimrc $STAGING_DIR/opt/stack/.vimrc
cp_it ~/.bashrc $STAGING_DIR/opt/stack/.bashrc
if [ -d $DEVSTACK_SRC ]; then
# Local repository for devstack exist, copy it to DomU
cp_it $DEVSTACK_SRC $STAGING_DIR/opt/stack/
fi
# Journald default is to not persist logs to disk if /var/log/journal is
# not present. Update the configuration to set storage to persistent which
# will create /var/log/journal if necessary and store logs on disk. This
# avoids the situation where test runs can fill the journald ring buffer
# deleting older logs that may be important to the job.
JOURNALD_CFG=$STAGING_DIR/etc/systemd/journald.conf
if [ -f $JOURNALD_CFG ] ; then
sed -i -e 's/#Storage=auto/Storage=persistent/' $JOURNALD_CFG
fi
# Configure run.sh
DOMU_STACK_DIR=/opt/stack
DOMU_DEV_STACK_DIR=$DOMU_STACK_DIR/devstack
cat <<EOF >$STAGING_DIR/opt/stack/run.sh
#!/bin/bash
set -eux
(
flock -n 9 || exit 1
sudo chown -R stack $DOMU_STACK_DIR
cd $DOMU_STACK_DIR
[ -e /opt/stack/runsh.succeeded ] && rm /opt/stack/runsh.succeeded
echo \$\$ >> /opt/stack/run_sh.pid
if [ ! -d $DOMU_DEV_STACK_DIR ]; then
echo "Can not find the devstack source code, get it from git."
git clone $DEVSTACK_SRC $DOMU_DEV_STACK_DIR
fi
cp $DOMU_STACK_DIR/local.conf $DOMU_DEV_STACK_DIR/
cd $DOMU_DEV_STACK_DIR
./unstack.sh || true
./stack.sh
# Got to the end - success
touch /opt/stack/runsh.succeeded
# Update /etc/issue
(
echo "OpenStack VM - Installed by DevStack"
IPADDR=$(ip -4 address show eth0 | sed -n 's/.*inet \([0-9\.]\+\).*/\1/p')
echo " Management IP: $IPADDR"
echo -n " Devstack run: "
if [ -e /opt/stack/runsh.succeeded ]; then
echo "SUCCEEDED"
else
echo "FAILED"
fi
echo ""
) > /opt/stack/issue
sudo cp /opt/stack/issue /etc/issue
rm /opt/stack/run_sh.pid
) 9> /opt/stack/.runsh_lock
EOF
chmod 755 $STAGING_DIR/opt/stack/run.sh
if [ ! -f $TOP_DIR/local.conf ]; then
echo "ERROR: You should prepare a local.conf and put it under $TOP_DIR"
exit 1
fi
cp_it $TOP_DIR/local.conf $STAGING_DIR/opt/stack/local.conf
cp_it $THIS_DIR/run.sh $STAGING_DIR/opt/stack/run.sh
|