Skip to content

Instantly share code, notes, and snippets.

@smoser
Last active February 13, 2017 16:17
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save smoser/4795358 to your computer and use it in GitHub Desktop.
Save smoser/4795358 to your computer and use it in GitHub Desktop.
user-data for setting up devstack
#!/bin/sh
#
# copied from https://gist.github.com/smoser/5823699
#
set -e
[ -e "/usr/bin/apt-get.distrib" ] ||
sudo dpkg-divert --local --rename --add /usr/bin/apt-get
sudo tee /usr/bin/apt-get >/dev/null <<"EOF"
#!/bin/sh
a=" $* "
emd="eatmydata"
if ! command -v eatmydata >/dev/null 2>&1; then
emd=""
if [ "${a#* install }" != "$a" -a "$(id -u)" = "0" ]; then
# we are root, this is install, so install emd
echo "=== first installing libeatmydata ===" 1>&2
out=$(DEBIAN_FRONTEND=noninteractive "$0.distrib" install \
--quiet --assume-yes libeatmydata 2>&1)
ret=$?
if [ $ret -ne 0 ]; then
echo "FAILED: $out" 1>&2;
echo "failed to install libeatmydata."
exit $ret
fi
emd="eatmydata"
fi
fi 1>&2 </dev/null
exec $emd "$0.distrib" "$@"
EOF
sudo chmod 755 /usr/bin/apt-get
sudo sed -i.dist "s,^deb-src,#deb-src," /etc/apt/sources.list
farchs=$(dpkg --print-foreign-architectures)
case "$farchs" in
*i386*)
{ sudo dpkg --remove-architecture i386 >/dev/null 2>&1 ||
sudo rm /etc/dpkg/dpkg.cfg.d/multiarch; } &&
echo "got rid of i386" ||
echo "failed to remove arch i386"
;;
esac
f="/etc/apt/apt.conf.d/99notranslations"
if [ ! -f "$f" ]; then
echo 'Acquire::Languages "none";' | sudo tee "$f" >/dev/null;
sudo rm -r /var/lib/apt/lists/*Translation*;
fi
# maybe you dont want to disable security
sudo sed -i "/^deb[^-].*security.ubuntu.com/s/^/#/" /etc/apt/sources.list
#!/bin/bash
# flavor-create <name> <id> <ram> <disk> <vcpus>
nova flavor-create --ephemeral=1 --swap=128 --is-public=1 sm1.tiny 77 128 2 1
nova flavor-create --ephemeral=0 --swap=0 --is-public=1 sm1.small 78 512 4 1
nova keypair-add "--pub-key=$HOME/.ssh/id_rsa.pub" default
unlimited=( --instances=-1 --cores=-1 --ram=-1 )
nova quota-class-update "${unlimited[@]}" default
nova quota-update "${unlimited[@]}" admin
nova quota-update "${unlimited[@]}" demo
if neutron quota-show >/dev/null 2>&1; then
neutron quota-update \
--port=-1 --network=-1 --router=-1 --subnet=-1 --floatingip=-1
fi
ROOT_TAR_IMGS=(
http://cloud-images.ubuntu.com/trusty/current/trusty-server-cloudimg-amd64-root.tar.gz
http://download.cirros-cloud.net/0.3.3/cirros-0.3.3-x86_64-lxc.tar.gz
)
case "$VIRT_DRIVER" in
granite|flex)
for url in "${ROOT_TAR_IMGS[@]}"; do
name="${url##*/}"
wget --dot-style=mega "$url" -O "$name" &&
glance image-create --name "$name" --is-public True \
--container-format=bare --disk-format=root-tar < "$name"
if [ $? -eq 0 ]; then
rm -f "$name"
echo "registered $url -> $name"
else
echo "FAIL: did load image '$name' from $url"
fi
done
;;
esac
#!/bin/bash
nova keypair-add "--pub-key=$HOME/.ssh/id_rsa.pub" default
#!/bin/bash
openrc=${OPENRC:-$HOME/devstack/openrc}
tenant=${OS_TENANT:-demo}
error() { echo "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
Usage() {
cat <<EOF
Usage: ${0##*/} [opts] user
--openrc f use openrc 'f'. default: ~${openrc#$HOME}
--tenant|-t t use tenant 't'. default: ${OS_TENANT:-demo}
EOF
}
args=( )
verbose=false
user=""
while [ $# -ne 0 ]; do
case "$1" in
--openrc=*) openrc="${1#*=}"; shift; continue;;
--openrc) openrc="$2"; shift 2; continue;;
--tenant|-t) tenant="$2"; shift; continue;;
--tenant=*) tenant="${1#*=}"; shift 2; continue;;
--help) Usage; exit 0;;
--)
shift
args=( "${args[@]}" "$@" )
break;;
esac
[ -z "$user" ] && { user="$1" ; shift; continue; }
args[${#args[@]}]="$1"
shift
done
[ -f "$openrc" ] || fail "no openrc: $openrc"
[ -n "$user" ] || fail "no user provided"
. "$openrc" "$user" ${tenant:+"$tenant"}
set -- "${args[@]}"
if [ $# -eq 0 ]; then
set -- "${SHELL:-/bin/bash}"
export debian_chroot="${OS_USERNAME}@${OS_TENANT_NAME}"
error "launching shell $1 for user=$OS_USERNAME tenant=$OS_TENANT_NAME"
fi
if $verbose; then
error "tenant: ${OS_TENANT_NAME}"
error "user: ${OS_USERNAME}"
error "cmd: ${args[@]}"
fi
exec "$@"
#!/bin/bash
#
# this is a hacky "create user" script that is used in cooperation
# with devstack. it expects that 'openrc' sourced at the top
# will set up admin credentials for admin when provided the 2 arguments.
#
# then, it creates a user and tenant, and a directory
# with euca2ools and openstack tools config for that user
set -e
name=${1}
[ -n "$name" ] || { echo "must have name";exit 1; }
tenant=${2:-$1}
role=${3:-Member}
password="password"
. openrc admin admin
udir="./users"
mkdir -p "$udir"
mkdir "$udir/$name" || { echo "user $name already created? $udir/$name"; exit 1; }
uhome=$(readlink -f "$udir/$name")
role_id=$(keystone role-list | grep "$role" | get_field 1)
[ -n "$role_id" ] || { echo "did not find role $role"; exit 1; }
echo "role=$role role_id=$role_id"
tenant_id=$(keystone tenant-create --name=$name | grep " id " | get_field 2)
user_id=$(keystone user-create --name=$tenant --pass "$password" \
--email $name@example.com | grep " id " | get_field 2)
keystone user-role-add "--user_id=$user_id" "--role_id=$role_id" "--tenant_id=$tenant_id"
creds=$(keystone ec2-credentials-create "--user_id=$user_id" "--tenant_id=$tenant_id")
ec2_access=$(echo "$creds" | awk '/ access / { print $4 }')
ec2_secret=$(echo "$creds" | awk '/ secret / { print $4 }')
s3_url=$(keystone catalog --service s3 | awk '/ publicURL / { print $4 }')
echo "user: $name"
echo "user_id: $user_id"
echo "tenant: $tenant"
echo "tenant_id: $tenant_id"
echo "role: $role"
echo "role_id: $role_id"
echo "ec2_access: $ec2_access"
echo "ec2_secret: $ec2_secret"
echo "s3_url: $s3_url"
echo "uhome: $uhome"
cat > "$uhome/openrc" <<EOF
#openstack tools
export OS_TENANT_NAME="$tenant"
export OS_USERNAME="$name"
export OS_PASSWORD="$password"
export OS_NO_CACHE=\${OS_NO_CACHE:-1}
export OS_AUTH_URL=http://$SERVICE_HOST:5000/v2.0
export NOVA_VERSION=\${NOVA_VERSION:-1.1}
export COMPUTE_API_VERSION=\${COMPUTE_API_VERSION:-\$NOVA_VERSION}
EOF
cat >> "$uhome/openrc" <<EOF
#euca2ools
export EC2_ACCESS_KEY="$ec2_access"
export EC2_SECRET_KEY="$ec2_secret"
_keydir=\${NOVA_KEY_DIR:-"$(readlink -f "$uhome")"}
export S3_URL="$s3_url"
# Euca2ools Certificate stuff for uploading bundles
export EC2_PRIVATE_KEY=\${_keydir}/pk.pem
export EC2_CERT=\${_keydir}/cert.pem
export EC2_USER_ID=42 # nova does not use user id, but bundling requires it
export EUCALYPTUS_CERT=\${_keydir}/cacert.pem # euca-bundle-image seems to require this set
#alias ec2-bundle-image="ec2-bundle-image --cert \${EC2_CERT} --privatekey \${EC2_PRIVATE_KEY} --user \${EC2_USER_ID} --ec2cert \${NOVA_CERT}"
#alias ec2-upload-bundle="ec2-upload-bundle -a \${EC2_ACCESS_KEY} -s \${EC2_SECRET_KEY} --url \${S3_URL} --ec2cert \${NOVA_CERT}"
EOF
bash -c ". $uhome/openrc; nova x509-get-root-cert $uhome/cacert.pem"
bash -c ". $uhome/openrc; nova x509-create-cert $uhome/pk.pem $uhome/cert.pem"
cat >> "$uhome/openrc" <<EOF
# set log level to DEBUG (helps debug issues)
# export KEYSTONECLIENT_DEBUG=1
# export NOVACLIENT_DEBUG=1
EOF
ln -s "openrc" "$uhome/.eucarc"
cat >> "$uhome/mytool" <<"EOF"
#!/bin/bash
[ -f $HOME/.eucarc ] && HOME="${0%/*}"
. "${0%/*}/openrc"
exec "$@"
EOF
chmod 755 "$uhome/mytool"
# vi: ts=2 expandtab syntax=yaml
[[local|localrc]]
# this is more friendly for proxy than git://
GIT_BASE=http://git.openstack.org
SCREEN_HARDSTATUS="%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%< %= %H"
LOGFILE=stacklog
MYSQL_PASSWORD=golfing
RABBIT_PASSWORD=golfing
SWIFT_HASH=1234123412341234
SERVICE_TOKEN=golfing
SERVICE_PASSWORD=golfing
ADMIN_PASSWORD=golfing
XENAPI_PASSWORD=golfing
VIRT_DRIVER=libvirt
#LIBVIRT_TYPE=kvm
LIBVIRT_TYPE=lxc
GRANITE_REPO=https://github.com/zulcss/nova-compute-flex
GRANITE_BRANCH=master
images=(
http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-disk.img
http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-rootfs.img.gz
http://download.cirros-cloud.net/0.3.2/cirros-0.3.2-x86_64-uec.tar.gz
)
IMAGE_URLS=$(IFS=","; echo "${images[*]}")
# public_network_gateway needs to be on floating_range
PUBLIC_NETWORK_GATEWAY=172.24.4.1
FLOATING_RANGE=172.24.4.0/24
# network_gateway needs to be in fixed_range
FIXED_RANGE=10.11.12.0/24
NETWORK_GATEWAY=10.11.12.1
FIXED_NETWORK_SIZE=256
#FLAT_INTERFACE=
## heat
disable_service heat h-api h-api-cfn h-api-cw h-eng
## nova-vnc
disable_service n-novnc n-xvnc
## horizon
disable_service horizon
## swift
#enable_service s-account s-container s-object s-proxy
## cinder
#disable_service c-api c-sch c-vol
## neutron
#disable_service n-net
#enable_service q-svc q-agt q-dhcp q-l3 q-meta
#cloud-config
# https://gist.github.com/4795358
config:
- &giturl_udstack "http://gist.github.com/4795358.git"
- &vcsrun_opts "--virt=granite --devstack-git=http://git.openstack.org/openstack-dev/devstack"
- &proxy_info "squid.internal:3128 .ubuntu.com 10.5.0.0/16 127.0.0.0/8"
- &import_ids [smoser]
- &user "ubuntu"
apt_update: true
apt_upgrade: true
apt_reboot_if_required: true
packages: [git, tinyproxy]
ssh_import_id: *import_ids
groups:
- kvm
- libvirtd
system_info:
default_user:
name: *user
gecos: "UD Stack User"
groups: [adm, libvirtd, kvm, sudo]
scripts:
- &proxy_setup |
## tiny proxy
set -f
set -- $*
[ $# -eq 0 ] && exit 0
local_cidr="$1"
cp /etc/tinyproxy.conf /etc/tinyproxy.conf.dist
myaddr=$(ifconfig eth0 | awk '$1 == "inet" { sub(/addr:/, "", $2); print $2; }')
{
echo "http_proxy=http://127.0.0.1:8888/"
echo "https_proxy=http://127.0.0.1:8888/"
[ -n "$myaddr" ] && echo "no_proxy=$myaddr,localhost,127.0.0.1"
} >> /etc/environment
{
echo "# local setup"
echo "upstream $1"
shift;
for i in "$@"; do
echo "no upstream \"$i\""
done
echo "no upstream \"169.254.169.254\""
[ -n "$myaddr" ] && echo "no upstream \"$myaddr\""
} >> /etc/tinyproxy.conf
service tinyproxy restart
- &env_run |
set -a
. /etc/environment
exec "$@"
- &log_up |
{
read up sleep < /proc/uptime;
echo "$(date): runcmd up at $up";
echo "proxy: http_proxy=$http_proxy https_proxy=$https_proxy no_proxy=$no_proxy";
} | tee -a ~/runcmd.log
- &write_as_def_user |
p="/usr/local/bin/as-def-user"
{ echo '#!/bin/sh'; echo "defuser=${1:-ubuntu}"; } > "$p"
cat >> "$p" <<"END_DEF_USER"
if [ "${0%usersh}" != "$0" ]; then
set -- sh -c "$@"
fi
exec sudo -Hu "$defuser" -- sh -c \
'set -a; . /etc/environment; cd; exec "$@"' -- "$@"
END_DEF_USER
chmod 755 "$p"
ln -sf "${p##*/}" "${p}sh" # link as-def-usersh
runcmd:
- [sh, -c, *proxy_setup, "--", *proxy_info]
- [sh, -c, *write_as_def_user, "--", *user]
- [as-def-usersh, *log_up]
- [as-def-user, vcs-run, "--target=ud-devstack", *giturl_udstack, --, ./vcs_run, *vcsrun_opts]
# vi: ts=2 expandtab syntax=yaml
#!/usr/bin/python
# ubuntu pastebin getter [https://gist.github.com/smoser/7647304/]
# upget http://paste.ubuntu.com/8508062/ f.txt
# upget http://paste.ubuntu.com/8508062/ > f.txt
# wget http://sn.im/upget -O upget && chmod 755 upget
from __future__ import unicode_literals
str = None
import sys
import urllib3
try:
from html.parser import HTMLParser
except ImportError as e:
from HTMLParser import HTMLParser
class MyParser(HTMLParser):
data = ""
path = []
hit = ['td.code', 'div.paste', 'pre']
def handle_starttag(self, tag, attrs):
r = tag
for k, v in attrs:
if k == "class":
r += "." + v
self.path.append(r)
def handle_endtag(self, tag):
self.path.pop()
def handle_data(self, data):
if self.path[-(len(self.hit)):] == self.hit:
if self.data is None:
self.data = ""
self.data += data
def handle_entityref(self, ref):
self.handle_data(self.unescape("&%s;" % ref))
url = sys.argv[1]
if len(sys.argv) == 2 or sys.argv[2] == "-":
output = sys.stdout
elif len(sys.argv) == 3:
output = open(sys.argv[2], "w")
if url.endswith("/plain/"):
url = url.replace("/plain/", "")
myp = MyParser()
myp.feed(urllib3.PoolManager().request('GET', url).data.decode('utf-8'))
output.write(myp.data)
if myp.data[-1] != "\n":
output.write("\n")
#!/bin/bash
exec > vcs_run.out 2>&1
PATH="$HOME/bin:$PATH"
log() {
echo "$(date -R):" "$@" >> "$mydir/log"
echo "$(date -R):" "$@"
}
update_cfg() {
local file="$1" k="" v=""
shift;
while [ $# -ne 0 ]; do
k=${1%%=*}
v=${1#*=}
[ -n "$v" ] || continue
if grep -q "^$k=" "$file"; then
sed -i "s,^$k=.*,$k=\"$v\"," "$file"
else
echo "$k=\"$v\"" >> "$file"
fi
shift
done
}
do_format_mp() {
# just fix up format_mp input
# format_mp is device:mp:fstype (vdb:/mydata:btrfs)
local input="$1" oifs="$IFS"
IFS=":"; set -- $1; IFS="$oifs"
local dev="$1" mp="$2" fstype="$3"
dev="/dev/${dev#/dev}"
mp="${mp:-/opt/stack/data}" # this is default DATA_DIR
fstype="${fs:-btrfs}"
fmtdev "$dev" "$fstype" "$mp"
}
fmtdev() {
local dev="$1" fs="$2" mp="$3"
[ -e "$dev" ] ||
{ log "$dev did not exist"; return 1; }
if [ "$fs" = "btrfs" ] && ! which mkfs.btrfs >/dev/null 2>&1; then
sudo apt-get install --assume-yes btrfs-tools
fi
sudo umount "$dev" >/dev/null 2>&1
sync
# comment out any lines in /etc/fstab that have our DEV
sudo sed -i "s,^$dev,#$dev," /etc/fstab
local cmd="" flags="defaults,nobootwait"
case "$fs" in
btrfs)
cmd=( "mkfs.$fs" -f "$dev" )
flags="user_subvol_rm_allowed,nobootwait";;
ext*)
cmd=( mkfs.$fs -F "$dev" );;
*) cmd=( "mkfs.$fs" "$dev" );;
esac
sudo "${cmd[@]}" ||
{ log "failed: ${cmd[*]} "; return 1; }
udevadm settle
echo "$dev $mp auto $flags 0 2" | sudo tee -a /etc/fstab
[ -d "$mp" ] || sudo mkdir -p "$mp"
sudo mount "$mp" ||
{ log "Failed to mount $dev to $mp"; return 1; }
log "seem to have mounted $dev as $fs on $mp"
return 0
}
dl() {
local url="$1" target="$2"
local tf="$target.tmp"
case "$url" in
http://paste.ubuntu.com/*) upget "$url" "$tf";;
file://*) cat "$url#file://" > "$tf";;
*)
if [ -f "$url" ]; then
cat "$url" > "$tf"
else
wget "$url" -O "$tf"
fi
esac
[ $? -eq 0 ] || { rm -f "$tf"; return 1; }
mv "$tf" "$target" || { rm -f "$tf"; return 1; }
}
mydir=$(readlink -f "$0") && mydir="${mydir%/*}"
virt="libvirt-lxc"
ds_git="http://git.openstack.org/openstack-dev/devstack"
ds_ref="master"
granite_git=""
granite_branch=""
local_conf=""
format_mp=""
openstack_branch_projects="cinder glance horizon keystone neutron nova
requirements"
openstack_branch="master"
cfgs=( )
set -f; set -- $*; set +f
# explode --a=b into --a b
while [ $# -ne 0 ]; do
case "$1" in
--*=*)
args[${#args[@]}]="${1%%=*}";
args[${#args[@]}]="${1#*=}";;
*) args[${#args[@]}]="$1";;
esac
shift;
done
set -- "${args[@]}"
while [ $# -ne 0 ]; do
cur="$1"; next="$2";
case "$cur" in
# --cfg variables get updated in local.conf.
# ie --cfg GRANITE_REPO=git://.
--cfg) cfgs[${#cfgs[@]}]="$next";;
--virt) virt=${next}; shift;;
--openstack-branch)
for p in ${openstack_branch_projects}; do
n=$(echo "${p}_BRANCH" | tr '[a-z]' '[A-Z]')
cfgs[${#cfgs[@]}]="$n=$next";
done
;;
--devstack-git) ds_git="$next"; shift;;
--devstack-ref) ds_ref="$next"; shift;;
--format-mp) format_mp="$next"; shift;;
--local-conf) local_conf="$next"; shift;;
esac
shift;
done
case "$virt" in
libvirt-lxc|libvirt-kvm)
cfgs[${#cfgs[@]}]="LIBVIRT_TYPE=${virt#libvirt-}"
VIRT_DRIVER=libvirt
cfgs[${#cfgs[@]}]="VIRT_DRIVER=$VIRT_DRIVER";;
granite)
VIRT_DRIVER=granite
cfgs[${#cfgs[@]}]="VIRT_DRIVER=$VIRT_DRIVER";;
*) log "unknown virt=$virt.";;
esac
[ -d "$HOME/bin" ] || mkdir -p "$HOME/bin"
cp dssudo upget "$HOME/bin"
if [ -n "$local_conf" ]; then
dl "$local_conf" "$mydir/local.conf" ||
log "FAIL: failed to download $local_conf"
fi
update_cfg "$mydir/local.conf" "${cfgs[@]}"
dsdir="$HOME/devstack"
hstatus='hardstatus alwayslastline "%-Lw%{= BW}%50>%n%f* %t%{-}%+Lw%< %= %H"'
[ -f ~/.screenrc ] || echo "$hstatus" > ~/.screenrc
[ -f ~/.ssh/id_rsa ] ||
ssh-keygen -f ~/.ssh/id_rsa -N '' </dev/null
#LP: #1092715
sudo chown root:kvm /dev/kvm; sudo chmod 666 /dev/kvm
sudo sh -c '
grep -q nbd /etc/modules || echo "nbd #ud-stack" >> /etc/modules;
modprobe nbd'
sudo ./apt-go-fast
pkgs=""
for t in git:git; do
which ${t%%:*} >/dev/null 2>&1 || continue
pkgs="$pkgs ${t##*:}"
done
if [ -n "${pkgs# }" ]; then
sudo apt-get install --quiet --assume-yes $pkgs
fi
if [ -n "$format_mp" ]; then
do_format_mp "$format_mp"
fi
git clone "$ds_git" "$dsdir"
[ -z "$ds_ref" ] || ( cd "${dsdir}" && git checkout "${ds_ref}" )
cp "$mydir/local.conf" "$dsdir/local.conf"
if [ "$virt_driver" = "granite" ]; then
if [ ! -f "$dsdir/lib/granite" ]; then
log "jerry-rigging granite from '$granite_git' into ${dsdir}"
# need this for prepare_devstack.sh at the moment
sudo apt-get install --assume-yes --quiet realpath
sudo mkdir -p /opt/stack
sudo chown "$(id -u):$(id -g)" /opt/stack
if [ ! -d /opt/stack/granite ]; then
( cd /opt/stack && git clone "$granite_git" granite &&
cd /opt/stack/granite &&
INSTALLDIR=${dsdir%/*} ./contrib/devstack/prepare_devstack.sh;
rm -f "$dsdir/localrc" )
fi
fi
fi
log "starting. $ds_git"
cd "$dsdir"
sstart=${SECONDS}
FORCE=yes ./stack.sh
stack_ret=$?
read up idle < /proc/cpuinfo
msg="took $(($SECONDS-$sstart)) seconds. up $up seconds."
if [ $stack_ret -ne 0 ]; then
log "FAIL: stack.sh failed [$stack_ret]. $msg"
else
log "finished stack.sh. $msg"
fi
# LP: 1335193
bridge="br100"; # FLAT_NETWORK_BRIDGE_DEFAULT
if ! sudo iptables-save | grep -q POSTR.*${bridge}.*CHECKSUM; then
sudo iptables -t mangle -A POSTROUTING -o $bridge \
-p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
fi
range=$(bash -c '
disable_service(){ :;}; enable_service(){ :;};
. .localrc.auto && echo ${FIXED_RANGE:-10.0.0.0/24}')
sudo iptables -t nat -A POSTROUTING -s "$range" '!' -d "$range" -j MASQUERADE
cd "$mydir"
VIRT_DRIVER=$VIRT_DRIVER ./dssudo admin "$mydir/devstack-admin-post"
./dssudo demo "$mydir/devstack-demo-post"
[ "$stack_ret" -eq 0 ] || log "stack.sh failed"
# vi: ts=4 noexpandtab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment