diff --git a/clean.sh b/clean.sh index 395941ae21..b5593474cc 100755 --- a/clean.sh +++ b/clean.sh @@ -102,10 +102,12 @@ fi # Clean out /etc -sudo rm -rf /etc/keystone /etc/glance /etc/nova /etc/cinder /etc/swift +sudo rm -rf $INSTALL_PREFIX/etc/keystone $INSTALL_PREFIX/etc/glance \ + $INSTALL_PREFIX/etc/nova $INSTALL_PREFIX/etc/cinder \ + $INSTALL_PREFIX/etc/swift # Clean out tgt -sudo rm /etc/tgt/conf.d/* +sudo rm $INSTALL_PREFIX/etc/tgt/conf.d/* # Clean up the message queue cleanup_rpc_backend diff --git a/files/pkg-freebsd/general b/files/pkg-freebsd/general new file mode 100644 index 0000000000..d97a940518 --- /dev/null +++ b/files/pkg-freebsd/general @@ -0,0 +1,11 @@ +curl +dbus +git +libxml2 +libxslt +psmisc +py27-pip +py27-virtualenv +screen +unzip +wget diff --git a/files/pkg-freebsd/n-cpu b/files/pkg-freebsd/n-cpu new file mode 100644 index 0000000000..b80ce06636 --- /dev/null +++ b/files/pkg-freebsd/n-cpu @@ -0,0 +1 @@ +tmux diff --git a/files/pkg-freebsd/nova b/files/pkg-freebsd/nova new file mode 100644 index 0000000000..a64531c6a6 --- /dev/null +++ b/files/pkg-freebsd/nova @@ -0,0 +1,13 @@ +arping +dnsmasq +gawk +netmask +py27-MySQLdb +py27-libxml2 +py27-eventlet +py27-gflags +py27-kombu +py27-lockfile +py27-mox +py27-sqlite3 +sudo diff --git a/functions b/functions index 0a73b9f0ac..3021947bdf 100644 --- a/functions +++ b/functions @@ -137,6 +137,14 @@ function err() { return $exitcode } +function _dev_exit() { + set +o xtrace + local banner='################################################' + echo $banner 1>&2; + echo "$@" 1>&2; + echo $banner 1>&2; + exit 777 +} # Checks an environment variable is not set or has length 0 OR if the # exit code is non-zero and prints "message" @@ -208,6 +216,30 @@ function get_field() { done } +# Get interface used for the default route +function get_default_iface() { + local iface + + if is_freebsd; then + iface=`netstat -rn | grep default | awk '{print $6}'` + else + iface=`ip route | sed -n '/^default/{ s/.*dev \(\w\+\)\s\+.*/\1/; p; }' | head -1` + fi + echo "$iface" +} + +# Get list of IPs on the interface +function get_host_ips() { + local iface=$1 + local ips + + if is_freebsd; then + ips=`ifconfig ${iface} | grep 'inet ' | cut -d' ' -f2` + else + ips=`LC_ALL=C ip -f inet addr show ${iface} | awk '/inet/ {split($2,parts,"/"); print parts[1]}'` + fi + echo "$ips" +} # Get the default value for HOST_IP # get_default_host_ip fixed_range floating_range host_ip_iface host_ip @@ -218,11 +250,11 @@ function get_default_host_ip() { local host_ip=$4 # Find the interface used for the default route - host_ip_iface=${host_ip_iface:-$(ip route | sed -n '/^default/{ s/.*dev \(\w\+\)\s\+.*/\1/; p; }' | head -1)} + host_ip_iface=${host_ip_iface:-$(get_default_iface)} # Search for an IP unless an explicit is set by ``HOST_IP`` environment variable if [ -z "$host_ip" -o "$host_ip" == "dhcp" ]; then host_ip="" - host_ips=`LC_ALL=C ip -f inet addr show ${host_ip_iface} | awk '/inet/ {split($2,parts,"/"); print parts[1]}'` + host_ips=$(get_host_ips ${host_ip_iface}) for IP in $host_ips; do # Attempt to filter out IP addresses that are part of the fixed and # floating range. Note that this method only works if the ``netaddr`` @@ -246,6 +278,8 @@ function _get_package_dir() { pkg_dir=$FILES/apts elif is_fedora; then pkg_dir=$FILES/rpms + elif is_freebsd; then + pkg_dir=$FILES/pkg-freebsd elif is_suse; then pkg_dir=$FILES/rpms-suse else @@ -402,6 +436,13 @@ GetOSVersion() { else os_CODENAME="" fi + elif [[ `uname -s` == "FreeBSD" ]]; then + os_VENDOR="FreeBSD" + os_RELEASE=$(uname -r) + os_UPDATE=${os_RELEASE##*.} + os_RELEASE=${os_RELEASE%.*} + os_PACKAGE="pkg" + os_CODENAME="" elif [[ -x $(which lsb_release 2>/dev/null) ]]; then os_VENDOR=$(lsb_release -i -s) os_RELEASE=$(lsb_release -r -s) @@ -478,6 +519,9 @@ function GetDistro() { elif [[ "$os_VENDOR" =~ (Fedora) ]]; then # For Fedora, just use 'f' and the release DISTRO="f$os_RELEASE" + elif [[ "$os_VENDOR" =~ (FreeBSD) ]]; then + # For FreeBSD, just use 'freebsd' and the release + DISTRO="freebsd$os_RELEASE" elif [[ "$os_VENDOR" =~ (openSUSE) ]]; then DISTRO="opensuse-$os_RELEASE" elif [[ "$os_VENDOR" =~ (SUSE LINUX) ]]; then @@ -511,6 +555,13 @@ function is_fedora { [ "$os_VENDOR" = "Fedora" ] || [ "$os_VENDOR" = "Red Hat" ] || [ "$os_VENDOR" = "CentOS" ] } +function is_freebsd { + if [[ -z "$os_VENDOR" ]]; then + GetOSVersion + fi + + [ "$os_VENDOR" = "FreeBSD" ] +} # Determine if current distribution is a SUSE-based distribution # (openSUSE, SLE). @@ -671,7 +722,13 @@ function inicomment() { local file=$1 local section=$2 local option=$3 - sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file" + local sed_re="/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" + + if is_freebsd; then + sed -i '' -e "$sed_re" "$file" + else + sed -i -e "$sed_re" "$file" + fi } @@ -681,7 +738,13 @@ function iniuncomment() { local file=$1 local section=$2 local option=$3 - sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file" + local sed_re="/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" + + if is_freebsd; then + sed -i '' -e "$sed_re" "$file" + else + sed -i -e "$sed_re" "$file" + fi } @@ -723,12 +786,23 @@ function iniset() { fi if ! ini_has_option "$file" "$section" "$option"; then # Add it - sed -i -e "/^\[$section\]/ a\\ + if is_freebsd; then + sed -i '' -e "/^\[$section\]/ a\\ +$option = $value +" "$file" + else + sed -i -e "/^\[$section\]/ a\\ $option = $value " "$file" + fi else # Replace it - sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" "$file" + sed_re="/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=[ \t]*\).*$|\1$value|" + if is_freebsd; then + sed -i '' -e "$sed_re" "$file" + else + sed -i -e "$sed_re" "$file" + fi fi } @@ -764,13 +838,24 @@ function iniset_multiline() { echo -e "\n[$section]" >>"$file" else # Remove old values - sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file" + $sed_re="/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" + if is_freebsd; then + sed -i '' -e "$sed_re" "$file" + else + sed -i -e "$sed_re" "$file" + fi fi # Add new ones for v in $values; do - sed -i -e "/^\[$section\]/ a\\ + if is_freebsd; then + sed -i '' -e "/^\[$section\]/ a\\ $option = $v " "$file" + else + sed -i -e "/^\[$section\]/ a\\ +$option = $v +" "$file" + fi done } @@ -930,6 +1015,8 @@ function install_package() { apt_get install "$@" elif is_fedora; then yum_install "$@" + elif is_freebsd; then + sudo pkg install -y "$@" elif is_suse; then zypper_install "$@" else @@ -945,6 +1032,8 @@ function uninstall_package() { apt_get purge "$@" elif is_fedora; then sudo yum remove -y "$@" + elif is_freebsd; then + sudo pkg delete "$@" elif is_suse; then sudo zypper rm "$@" else @@ -968,6 +1057,8 @@ function is_package_installed() { dpkg -s "$@" > /dev/null 2> /dev/null elif [[ "$os_PACKAGE" = "rpm" ]]; then rpm --quiet -q "$@" + elif [[ "$os_PACKAGE" = "pkg" ]]; then + pkg info "$@" > /dev/null 2> /dev/null else exit_distro_not_supported "finding if a package is installed" fi @@ -982,6 +1073,21 @@ function is_set() { } +# Wrapper to account for local host 'install' differences +function host_install { + local inst_src="$1" + local inst_dst="$2" + + if is_freebsd; then + local inst_arg="" + else + local inst_arg="-D" + fi + + sudo install $inst_arg -m 0644 -o $STACK_USER $inst_src $inst_dst +} + + # Wrapper for ``pip install`` to set cache and proxy environment variables # Uses globals ``OFFLINE``, ``PIP_DOWNLOAD_CACHE``, ``PIP_USE_MIRRORS``, # ``TRACK_DEPENDS``, ``*_proxy`` @@ -994,6 +1100,7 @@ function pip_install { if [[ $TRACK_DEPENDS = True ]]; then source $DEST/.venv/bin/activate CMD_PIP=$DEST/.venv/bin/pip + PIP_DOWNLOAD_CACHE=$DEST/.venv/var/cache/pip SUDO_PIP="env" else SUDO_PIP="sudo" @@ -1014,7 +1121,11 @@ function pip_install { # 1.1, the existing extracted build will be used and cause # confusing errors. By creating unique build directories we avoid # this problem. See https://github.com/pypa/pip/issues/709 - local pip_build_tmp=$(mktemp --tmpdir -d pip-build.XXXXX) + if is_freebsd; then + local pip_build_tmp=$(mktemp -d pip-build.XXXXX) + else + local pip_build_tmp=$(mktemp --tmpdir -d pip-build.XXXXX) + fi $SUDO_PIP PIP_DOWNLOAD_CACHE=${PIP_DOWNLOAD_CACHE:-/var/cache/pip} \ HTTP_PROXY=$http_proxy \ @@ -1192,6 +1303,10 @@ function service_check() { # Returns true if the directory is on a filesystem mounted via NFS. function is_nfs_directory() { + if is_freebsd; then + (df -t nfs "$@" > /dev/null 2> /dev/null) + return $? + fi local mount_type=`stat -f -L -c %T $1` test "$mount_type" == "nfs" } @@ -1266,7 +1381,7 @@ function setup_develop() { # where we really really want the overridden version to stick. So provide # a variable that tells us whether or not we should UNDO the requirements # changes (this will be set to False in the OpenStack ci gate) - if [ $UNDO_REQUIREMENTS = "True"]; then + if [ $UNDO_REQUIREMENTS = "True" ]; then if [ $update_requirements -eq 0 ]; then (cd $project_dir && git reset --hard) fi @@ -1636,7 +1751,7 @@ function add_user_to_group() { } -# Get the path to the direcotry where python executables are installed. +# Get the path to the directory where python executables are installed. # get_python_exec_prefix function get_python_exec_prefix() { if is_fedora || is_suse; then @@ -1646,6 +1761,13 @@ function get_python_exec_prefix() { fi } +function get_install_prefix() { + if is_freebsd; then + echo "/usr/local" + else + echo "" + fi +} # Get the location of the $module-rootwrap executables, where module is cinder # or nova. @@ -1681,7 +1803,14 @@ function check_path_perm_sanity() { for i in $(echo ${real_path} | tr "/" " "); do rebuilt_path=$rebuilt_path"/"$i - if [[ $(stat -c '%a' ${rebuilt_path}) = 700 ]]; then + local statperm="" + if is_freebsd; then + statperm="$(stat -f "%p" ${rebuilt_path})" + statperm="${statperm: -3}" + else + statperm="$(stat -c '%a' ${rebuilt_path})" + fi + if [[ $statperm = 700 ]]; then echo "*** DEST path element" echo "*** ${rebuilt_path}" echo "*** appears to have 0700 permissions." diff --git a/lib/cinder b/lib/cinder index 20d6e615f6..15c0adca55 100644 --- a/lib/cinder +++ b/lib/cinder @@ -483,7 +483,12 @@ function install_cinder() { function install_cinderclient() { git_clone $CINDERCLIENT_REPO $CINDERCLIENT_DIR $CINDERCLIENT_BRANCH setup_develop $CINDERCLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$CINDERCLIENT_DIR/tools/,/etc/bash_completion.d/}cinder.bash_completion + + local inst_file='cinder.bash_completion' + local inst_src=$CINDERCLIENT_DIR/tools/$inst_file + local inst_dst=$INSTALL_PREFIX/etc/bash_completion.d/$inst_file + + host_install $inst_src $inst_dst } # apply config.d approach for cinder volumes directory diff --git a/lib/keystone b/lib/keystone index 4353ebab1c..a0df6a2551 100644 --- a/lib/keystone +++ b/lib/keystone @@ -341,7 +341,12 @@ function init_keystone() { function install_keystoneclient() { git_clone $KEYSTONECLIENT_REPO $KEYSTONECLIENT_DIR $KEYSTONECLIENT_BRANCH setup_develop $KEYSTONECLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$KEYSTONECLIENT_DIR/tools/,/etc/bash_completion.d/}keystone.bash_completion + + local inst_file='keystone.bash_completion' + local inst_src=$KEYSTONECLIENT_DIR/tools/$inst_file + local inst_dst=$INSTALL_PREFIX/etc/bash_completion.d/$inst_file + + host_install $inst_src $inst_dst } # install_keystone() - Collect source and prepare diff --git a/lib/neutron b/lib/neutron index 098a589592..3616a04419 100644 --- a/lib/neutron +++ b/lib/neutron @@ -398,7 +398,12 @@ function install_neutron() { function install_neutronclient() { git_clone $NEUTRONCLIENT_REPO $NEUTRONCLIENT_DIR $NEUTRONCLIENT_BRANCH setup_develop $NEUTRONCLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$NEUTRONCLIENT_DIR/tools/,/etc/bash_completion.d/}neutron.bash_completion + + local inst_file='neutron.bash_completion' + local inst_src=$NEUTRONCLIENT_DIR/tools/$inst_file + local inst_dst=$INSTALL_PREFIX/etc/bash_completion.d/$inst_file + + host_install $inst_src $inst_dst } # install_neutron_agent_packages() - Collect source and prepare diff --git a/lib/nova b/lib/nova index 8ef5d9a427..7adfc827b0 100644 --- a/lib/nova +++ b/lib/nova @@ -36,7 +36,7 @@ NOVA_STATE_PATH=${NOVA_STATE_PATH:=$DATA_DIR/nova} NOVA_INSTANCES_PATH=${NOVA_INSTANCES_PATH:=${INSTANCES_PATH:=$NOVA_STATE_PATH/instances}} NOVA_AUTH_CACHE_DIR=${NOVA_AUTH_CACHE_DIR:-/var/cache/nova} -NOVA_CONF_DIR=/etc/nova +NOVA_CONF_DIR=${NOVA_CONF_DIR:-$INSTALL_PREFIX/etc/nova} NOVA_CONF=$NOVA_CONF_DIR/nova.conf NOVA_CELLS_CONF=$NOVA_CONF_DIR/nova-cells.conf NOVA_CELLS_DB=${NOVA_CELLS_DB:-nova_cell} @@ -71,7 +71,7 @@ FORCE_CONFIG_DRIVE=${FORCE_CONFIG_DRIVE:-"always"} # should work in most cases. SCHEDULER=${SCHEDULER:-nova.scheduler.filter_scheduler.FilterScheduler} -QEMU_CONF=/etc/libvirt/qemu.conf +QEMU_CONF=$INSTALL_PREFIX/etc/libvirt/qemu.conf NOVNC_DIR=$DEST/noVNC SPICE_DIR=$DEST/spice-html5 @@ -145,22 +145,25 @@ function clean_iptables() { # runs that a clean run would need to clean up function cleanup_nova() { if is_service_enabled n-cpu; then - # Clean iptables from previous runs - clean_iptables - - # Destroy old instances - instances=`sudo virsh list --all | grep $INSTANCE_NAME_PREFIX | sed "s/.*\($INSTANCE_NAME_PREFIX[0-9a-fA-F]*\).*/\1/g"` - if [ ! "$instances" = "" ]; then - echo $instances | xargs -n1 sudo virsh destroy || true - echo $instances | xargs -n1 sudo virsh undefine --managed-save || true - fi + # TODO this needs to be done in a BSD fashion + if ! is_freebsd; then + # Clean iptables from previous runs + clean_iptables + + # Destroy old instances + instances=`sudo virsh list --all | grep $INSTANCE_NAME_PREFIX | sed "s/.*\($INSTANCE_NAME_PREFIX[0-9a-fA-F]*\).*/\1/g"` + if [ ! "$instances" = "" ]; then + echo $instances | xargs -n1 sudo virsh destroy || true + echo $instances | xargs -n1 sudo virsh undefine --managed-save || true + fi - # Logout and delete iscsi sessions - tgts=$(sudo iscsiadm --mode node | grep $VOLUME_NAME_PREFIX | cut -d ' ' -f2) - for target in $tgts; do - sudo iscsiadm --mode node -T $target --logout || true - done - sudo iscsiadm --mode node --op delete || true + # Logout and delete iscsi sessions + tgts=$(sudo iscsiadm --mode node | grep $VOLUME_NAME_PREFIX | cut -d ' ' -f2) + for target in $tgts; do + sudo iscsiadm --mode node -T $target --logout || true + done + sudo iscsiadm --mode node --op delete || true + fi # Clean out the instances directory. sudo rm -rf $NOVA_INSTANCES_PATH/* @@ -178,6 +181,12 @@ function cleanup_nova() { # configure_nova_rootwrap() - configure Nova's rootwrap function configure_nova_rootwrap() { + local filters_dir="$NOVA_DIR/etc/nova/rootwrap.d" + local root_group="root" + if is_freebsd; then + filters_dir="$filters_dir/freebsd" + root_group="wheel" + fi # Deploy new rootwrap filters files (owned by root). # Wipe any existing rootwrap.d files first if [[ -d $NOVA_CONF_DIR/rootwrap.d ]]; then @@ -185,13 +194,16 @@ function configure_nova_rootwrap() { fi # Deploy filters to /etc/nova/rootwrap.d sudo mkdir -m 755 $NOVA_CONF_DIR/rootwrap.d - sudo cp $NOVA_DIR/etc/nova/rootwrap.d/*.filters $NOVA_CONF_DIR/rootwrap.d - sudo chown -R root:root $NOVA_CONF_DIR/rootwrap.d + sudo cp $filters_dir/*.filters $NOVA_CONF_DIR/rootwrap.d + sudo chown -R root:$root_group $NOVA_CONF_DIR/rootwrap.d sudo chmod 644 $NOVA_CONF_DIR/rootwrap.d/* # Set up rootwrap.conf, pointing to /etc/nova/rootwrap.d sudo cp $NOVA_DIR/etc/nova/rootwrap.conf $NOVA_CONF_DIR/ - sudo sed -e "s:^filters_path=.*$:filters_path=$NOVA_CONF_DIR/rootwrap.d:" -i $NOVA_CONF_DIR/rootwrap.conf - sudo chown root:root $NOVA_CONF_DIR/rootwrap.conf + sudo sed -e "s:^filters_path=.*$:filters_path=$NOVA_CONF_DIR/rootwrap.d:" -i '' $NOVA_CONF_DIR/rootwrap.conf + if is_freebsd; then + sudo sed -e "/^exec_dirs=/ s:$:,/usr/local/bin,/usr/local/sbin:" -i '' $NOVA_CONF_DIR/rootwrap.conf + fi + sudo chown root:$root_group $NOVA_CONF_DIR/rootwrap.conf sudo chmod 0644 $NOVA_CONF_DIR/rootwrap.conf # Specify rootwrap.conf as first parameter to nova-rootwrap ROOTWRAP_SUDOER_CMD="$NOVA_ROOTWRAP $NOVA_CONF_DIR/rootwrap.conf *" @@ -200,8 +212,8 @@ function configure_nova_rootwrap() { TEMPFILE=`mktemp` echo "$USER ALL=(root) NOPASSWD: $ROOTWRAP_SUDOER_CMD" >$TEMPFILE chmod 0440 $TEMPFILE - sudo chown root:root $TEMPFILE - sudo mv $TEMPFILE /etc/sudoers.d/nova-rootwrap + sudo chown root:$root_group $TEMPFILE + sudo mv $TEMPFILE $INSTALL_PREFIX/etc/sudoers.d/nova-rootwrap } # configure_nova() - Set config files, create data dirs, etc @@ -216,13 +228,13 @@ function configure_nova() { configure_nova_rootwrap - if is_service_enabled n-api; then - # Remove legacy paste config if present - rm -f $NOVA_DIR/bin/nova-api-paste.ini + # Remove legacy paste config if present + rm -f $NOVA_DIR/bin/nova-api-paste.ini - # Get the sample configuration file in place - cp $NOVA_DIR/etc/nova/api-paste.ini $NOVA_CONF_DIR + # Get the sample configuration file in place + cp $NOVA_DIR/etc/nova/api-paste.ini $NOVA_CONF_DIR + if is_service_enabled n-api; then # Comment out the keystone configs in Nova's api-paste.ini. # We are using nova.conf to configure this instead. inicomment $NOVA_API_PASTE_INI filter:authtoken auth_host @@ -237,8 +249,12 @@ function configure_nova() { inicomment $NOVA_API_PASTE_INI filter:authtoken signing_dir if is_service_enabled n-cpu; then - # Force IP forwarding on, just on case - sudo sysctl -w net.ipv4.ip_forward=1 + # Force IP forwarding on, just in case + if is_freebsd; then + sudo sysctl net.inet.ip.forwarding=1 + else + sudo sysctl -w net.ipv4.ip_forward=1 + fi if [[ "$VIRT_DRIVER" = 'libvirt' ]]; then # Attempt to load modules: network block device - used to manage qcow images @@ -285,13 +301,15 @@ function configure_nova() { sudo mkdir -p $NOVA_INSTANCES_PATH sudo chown -R $STACK_USER $NOVA_INSTANCES_PATH - # You can specify a different disk to be mounted and used for backing the - # virtual machines. If there is a partition labeled nova-instances we - # mount it (ext filesystems can be labeled via e2label). - if [ -L /dev/disk/by-label/nova-instances ]; then - if ! mount -n | grep -q $NOVA_INSTANCES_PATH; then - sudo mount -L nova-instances $NOVA_INSTANCES_PATH - sudo chown -R $STACK_USER $NOVA_INSTANCES_PATH + if ! is_freebsd; then + # You can specify a different disk to be mounted and used for backing the + # virtual machines. If there is a partition labeled nova-instances we + # mount it (ext filesystems can be labeled via e2label). + if [ -L /dev/disk/by-label/nova-instances ]; then + if ! mount -n | grep -q $NOVA_INSTANCES_PATH; then + sudo mount -L nova-instances $NOVA_INSTANCES_PATH + sudo chown -R $STACK_USER $NOVA_INSTANCES_PATH + fi fi fi fi @@ -392,6 +410,19 @@ function create_nova_conf() { iniset $NOVA_CONF DEFAULT bindir "/usr/bin" fi + if is_freebsd; then + # FreeBSD specific settings + iniset $NOVA_CONF DEFAULT bindir "/usr/local/bin" + iniset $NOVA_CONF DEFAULT network_driver "nova.network.freebsd_net" + iniset $NOVA_CONF DEFAULT l3_lib "nova.network.l3.FreeBSDNetL3" + + # XXX The dhcp_release is currently (2013.12) not available on + # FreeBSD, so we suppress it and also set a shorter timeout for + # reclaiming unused IPs by the system. + iniset $NOVA_CONF DEFAULT force_dhcp_release "False" + iniset $NOVA_CONF DEFAULT fixed_ip_disassocate_timeout "120" + fi + if is_service_enabled n-api; then iniset $NOVA_CONF DEFAULT enabled_apis "$NOVA_ENABLED_APIS" if is_service_enabled tls-proxy; then @@ -532,7 +563,7 @@ function create_nova_cache_dir() { # Create cache dir sudo mkdir -p $NOVA_AUTH_CACHE_DIR sudo chown $STACK_USER $NOVA_AUTH_CACHE_DIR - rm -f $NOVA_AUTH_CACHE_DIR/* + sudo rm -f $NOVA_AUTH_CACHE_DIR/* } function create_nova_conf_nova_network() { @@ -585,7 +616,12 @@ function init_nova() { function install_novaclient() { git_clone $NOVACLIENT_REPO $NOVACLIENT_DIR $NOVACLIENT_BRANCH setup_develop $NOVACLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$NOVACLIENT_DIR/tools/,/etc/bash_completion.d/}nova.bash_completion + + local inst_file='nova.bash_completion' + local inst_src=$NOVACLIENT_DIR/tools/$inst_file + local inst_dst=$INSTALL_PREFIX/etc/bash_completion.d/$inst_file + + host_install $inst_src $inst_dst } # install_nova() - Collect source and prepare @@ -596,7 +632,12 @@ function install_nova() { git_clone $NOVA_REPO $NOVA_DIR $NOVA_BRANCH setup_develop $NOVA_DIR - sudo install -D -m 0644 -o $STACK_USER {$NOVA_DIR/tools/,/etc/bash_completion.d/}nova-manage.bash_completion + + local inst_file='nova-manage.bash_completion' + local inst_src=$NOVA_DIR/tools/$inst_file + local inst_dst=$INSTALL_PREFIX/etc/bash_completion.d/$inst_file + + host_install $inst_src $inst_dst } # start_nova_api() - Start the API process ahead of other things diff --git a/lib/nova_plugins/hypervisor-bhyve b/lib/nova_plugins/hypervisor-bhyve new file mode 100644 index 0000000000..1d4d1d213e --- /dev/null +++ b/lib/nova_plugins/hypervisor-bhyve @@ -0,0 +1,75 @@ +# lib/nova_plugins/hypervisor-bhyve +# Configure the bhyve hypervisor + +# Enable with: +# VIRT_DRIVER=bhyve + +# Dependencies: +# ``functions`` file +# ``nova`` configuration + +# install_nova_hypervisor - install any external requirements +# configure_nova_hypervisor - make configuration changes, including those to other services +# start_nova_hypervisor - start any external services +# stop_nova_hypervisor - stop any external services +# cleanup_nova_hypervisor - remove transient data and cache + +# Save trace setting +MY_XTRACE=$(set +o | grep xtrace) +set +o xtrace + + +# Defaults +# -------- + + +# Entry Points +# ------------ + +# clean_nova_hypervisor - Clean up an installation +function cleanup_nova_hypervisor() { + # This function intentionally left blank + : +} + +# configure_nova_hypervisor - Set config files, create data dirs, etc +function configure_nova_hypervisor() { + iniset $NOVA_CONF DEFAULT compute_driver "nova.virt.bhyve.BhyveDriver" + # Disable arbitrary limits + iniset $NOVA_CONF DEFAULT quota_instances -1 + iniset $NOVA_CONF DEFAULT quota_cores -1 + iniset $NOVA_CONF DEFAULT quota_ram -1 + iniset $NOVA_CONF DEFAULT quota_floating_ips -1 + iniset $NOVA_CONF DEFAULT quota_fixed_ips -1 + iniset $NOVA_CONF DEFAULT quota_metadata_items -1 + iniset $NOVA_CONF DEFAULT quota_injected_files -1 + iniset $NOVA_CONF DEFAULT quota_injected_file_path_bytes -1 + iniset $NOVA_CONF DEFAULT quota_security_groups -1 + iniset $NOVA_CONF DEFAULT quota_security_group_rules -1 + iniset $NOVA_CONF DEFAULT quota_key_pairs -1 + iniset $NOVA_CONF DEFAULT scheduler_default_filters "RetryFilter,AvailabilityZoneFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter" +} + +# install_nova_hypervisor() - Install external components +function install_nova_hypervisor() { + # This function intentionally left blank + : +} + +# start_nova_hypervisor - Start any required external services +function start_nova_hypervisor() { + sudo kldload vmm +} + +# stop_nova_hypervisor - Stop any external services +function stop_nova_hypervisor() { + sudo kldunload vmm +} + + +# Restore xtrace +$MY_XTRACE + +# Local variables: +# mode: shell-script +# End: diff --git a/lib/template b/lib/template index 629e110271..7a59d03e10 100644 --- a/lib/template +++ b/lib/template @@ -29,7 +29,7 @@ set +o xtrace # Set up default directories XXXX_DIR=$DEST/XXXX -XXX_CONF_DIR=/etc/XXXX +XXX_CONF_DIR=$INSTALL_PREFIX/etc/XXXX # Entry Points diff --git a/localrc.controller b/localrc.controller new file mode 100644 index 0000000000..9153f21d00 --- /dev/null +++ b/localrc.controller @@ -0,0 +1,22 @@ +LOGFILE=/home/stack/logs/stack.sh.log +LOG_COLOR=False +SCREEN_LOGDIR=/home/stack/logs/screen + +ADMIN_PASSWORD=c0ntrail123 +DATABASE_PASSWORD=$ADMIN_PASSWORD +RABBIT_PASSWORD=$ADMIN_PASSWORD +SERVICE_TOKEN=$ADMIN_PASSWORD +SERVICE_PASSWORD=$ADMIN_PASSWORD + +OS_USERNAME=admin +OS_TENANT_NAME=admin + +MULTI_HOST=True + +FLOATING_RANGE=192.168.1.128/25 +FIXED_RANGE=172.24.17.0/24 +FIXED_NETWORK_SIZE=256 +FLAT_INTERFACE=igb1 +FLAT_NETWORK_BRIDGE=bridge0 + +disable_service n-cpu n-net diff --git a/localrc.slave b/localrc.slave new file mode 100644 index 0000000000..c52e5775b5 --- /dev/null +++ b/localrc.slave @@ -0,0 +1,63 @@ +# Stack user name +STACK_USER=stack + +# Passwords +ADMIN_PASSWORD=c0ntrail123 +MYSQL_PASSWORD=$ADMIN_PASSWORD +SERVICE_TOKEN=$ADMIN_PASSWORD +SERVICE_PASSWORD=$ADMIN_PASSWORD +RABBIT_PASSWORD=$ADMIN_PASSWORD +STACK_USER_PASSWORD=1qaz + +OS_USERNAME=admin +OS_TENANT_NAME=admin + +DEST=/home/stack + +# Logging +LOGFILE=$DEST/logs/stack.sh.log +LOG_COLOR=False +SCREEN_LOGDIR=$DEST/logs/screen + +#SYSLOG=True +#SYSLOG_HOST=$HOST_IP +#SYSLOG_PORT=516 + +#RECLONE=yes + +SWIFT_HASH="66a3d6b56c1f479c8b4e70ab5c2000f5" +SWIFT_REPLICAS=1 + +# use venv (and exit before init+run => just install all components and exit) +#TRACK_DEPENDS=True + +# force calling tools/install_prereqs.sh +#FORCE_PREREQ=1 + +# Slave host components +MULTI_HOST=True +FIXED_RANGE=172.24.17.0/24 +FIXED_NETWORK_SIZE=254 +FLOATING_RANGE=192.168.1.128/25 + +#ENABLED_SERVICES=n-cpu +ENABLED_SERVICES=n-cpu,n-api-meta,n-net +#ENABLED_SERVICES=n-cpu,n-net + +VIRT_DRIVER=bhyve + +FLAT_INTERFACE=igb1 +FLAT_NETWORK_BRIDGE=bridge0 +PUBLIC_INTERFACE=bridge0 +VLAN_INTERFACE=igb1 + +DATABASE_TYPE=mysql +SERVICE_HOST=10.100.2.31 +MYSQL_HOST=$SERVICE_HOST +RABBIT_HOST=$SERVICE_HOST +KEYSTONE_AUTH_HOST=$SERVICE_HOST +GLANCE_HOSTPORT=$SERVICE_HOST:9292 + +# Nova development repo +NOVA_REPO=https://github.com/Semihalf/openstack-nova.git +NOVA_BRANCH=freebsd diff --git a/stack.sh b/stack.sh index 36312ea619..e205461a3a 100755 --- a/stack.sh +++ b/stack.sh @@ -131,7 +131,7 @@ disable_negated_services # Warn users who aren't on an explicitly supported distro, but allow them to # override check and attempt installation with ``FORCE=yes ./stack`` -if [[ ! ${DISTRO} =~ (oneiric|precise|quantal|raring|saucy|trusty|7.0|wheezy|sid|testing|jessie|f16|f17|f18|f19|opensuse-12.2|rhel6) ]]; then +if [[ ! ${DISTRO} =~ (oneiric|precise|quantal|raring|saucy|trusty|7.0|wheezy|sid|testing|jessie|f16|f17|f18|f19|freebsd11|opensuse-12.2|rhel6) ]]; then echo "WARNING: this script has not been tested on $DISTRO" if [[ "$FORCE" != "yes" ]]; then die $LINENO "If you wish to run this script anyway run with FORCE=yes" @@ -207,27 +207,35 @@ if [[ $EUID -eq 0 ]]; then exit 1 fi -# We're not **root**, make sure ``sudo`` is available -is_package_installed sudo || install_package sudo - -# UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one -sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || - echo "#includedir /etc/sudoers.d" | sudo tee -a /etc/sudoers +if [[ $(whoami) != $STACK_USER ]]; then + err "Current user: $(whoami). Expected: $STACK_USER. Please do 'su - $STACK_USER' and rerun." +fi -# Set up devstack sudoers -TEMPFILE=`mktemp` -echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE -# Some binaries might be under /sbin or /usr/sbin, so make sure sudo will -# see them by forcing PATH -echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE -chmod 0440 $TEMPFILE -sudo chown root:root $TEMPFILE -sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh +# XXX this is inherently broken: if we are not root and not in sudoers already +# modifying /etc/... will fail due to no access. Installing sudo by non +# privileged user will also fail etc. +# We're not **root**, make sure ``sudo`` is available +#is_package_installed sudo || install_package sudo +# +## UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one +#sudo grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || +# echo "#includedir /etc/sudoers.d" | sudo tee -a /etc/sudoers +# +## Set up devstack sudoers +#TEMPFILE=`mktemp` +#echo "$STACK_USER ALL=(root) NOPASSWD:ALL" >$TEMPFILE +## Some binaries might be under /sbin or /usr/sbin, so make sure sudo will +## see them by forcing PATH +#echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $TEMPFILE +#chmod 0440 $TEMPFILE +#sudo chown root:root $TEMPFILE +#sudo mv $TEMPFILE /etc/sudoers.d/50_stack_sh # Create the destination directory and ensure it is writable by the user # and read/executable by everybody for daemons (e.g. apache run for horizon) sudo mkdir -p $DEST +# XXX This fails if TRACK_DEPENDS=True safe_chown -R $STACK_USER $DEST safe_chmod 0755 $DEST @@ -250,6 +258,7 @@ ENABLE_DEBUG_LOG_LEVEL=`trueorfalse True $ENABLE_DEBUG_LOG_LEVEL` # Destination path for service data DATA_DIR=${DATA_DIR:-${DEST}/data} sudo mkdir -p $DATA_DIR +# XXX This fails if TRACK_DEPENDS=True safe_chown -R $STACK_USER $DATA_DIR @@ -575,7 +584,7 @@ failed() { # Print the commands being run so that we can see the command that triggers # an error. It is also useful for following along as the install occurs. -set -o xtrace +#set -o xtrace # Install Packages @@ -588,9 +597,12 @@ set -o xtrace echo_summary "Installing package prerequisites" source $TOP_DIR/tools/install_prereqs.sh -# Configure an appropriate python environment -if [[ "$OFFLINE" != "True" ]]; then - $TOP_DIR/tools/install_pip.sh +# XXX why not install pip from ports/pkg? +if ! is_freebsd; then + # Configure an appropriate python environment + if [[ "$OFFLINE" != "True" ]]; then + $TOP_DIR/tools/install_pip.sh + fi fi # Do the ugly hacks for borken packages and distros @@ -774,16 +786,16 @@ if [[ $SYSLOG != "False" ]]; then \$ModLoad imrelp \$InputRELPServerRun $SYSLOG_PORT EOF - sudo mv /tmp/90-stack-m.conf /etc/rsyslog.d + sudo mv /tmp/90-stack-m.conf $INSTALL_PREFIX/etc/rsyslog.d else # Set rsyslog to send to remote host cat </tmp/90-stack-s.conf *.* :omrelp:$SYSLOG_HOST:$SYSLOG_PORT EOF - sudo mv /tmp/90-stack-s.conf /etc/rsyslog.d + sudo mv /tmp/90-stack-s.conf $INSTALL_PREFIX/etc/rsyslog.d fi - RSYSLOGCONF="/etc/rsyslog.conf" + RSYSLOGCONF="$INSTALL_PREFIX/etc/rsyslog.conf" if [ -f $RSYSLOGCONF ]; then sudo cp -b $RSYSLOGCONF $RSYSLOGCONF.bak if [[ $(grep '$SystemLogRateLimitBurst' $RSYSLOGCONF) ]]; then @@ -845,7 +857,7 @@ init_service_check # Sysstat # ------- - +# XXX Linux only # If enabled, systat has to start early to track OpenStack service startup. if is_service_enabled sysstat;then if [[ -n ${SCREEN_LOGDIR} ]]; then @@ -965,21 +977,31 @@ fi # ---- if is_service_enabled n-net q-dhcp; then - # Delete traces of nova networks from prior runs - # Do not kill any dnsmasq instance spawned by NetworkManager - netman_pid=$(pidof NetworkManager || true) - if [ -z "$netman_pid" ]; then - sudo killall dnsmasq || true - else - sudo ps h -o pid,ppid -C dnsmasq | grep -v $netman_pid | awk '{print $1}' | sudo xargs kill || true + # TODO we have to reinit dhcpd here for FBSD + if ! is_freebsd; then + # Delete traces of nova networks from prior runs + # Do not kill any dnsmasq instance spawned by NetworkManager + netman_pid=$(pidof NetworkManager || true) + if [ -z "$netman_pid" ]; then + sudo killall dnsmasq || true + else + sudo ps h -o pid,ppid -C dnsmasq | grep -v $netman_pid | awk '{print $1}' | sudo xargs kill || true + fi + + clean_iptables fi - clean_iptables rm -rf ${NOVA_STATE_PATH}/networks sudo mkdir -p ${NOVA_STATE_PATH}/networks + # XXX This fails if TRACK_DEPENDS=True safe_chown -R ${USER} ${NOVA_STATE_PATH}/networks + # Force IP forwarding on, just in case - sudo sysctl -w net.ipv4.ip_forward=1 + if is_freebsd; then + sudo sysctl net.inet.ip.forwarding=1 + else + sudo sysctl -w net.ipv4.ip_forward=1 + fi fi diff --git a/stackrc b/stackrc index 6adb676866..3e6c69c701 100644 --- a/stackrc +++ b/stackrc @@ -6,16 +6,16 @@ RC_DIR=$(cd $(dirname "${BASH_SOURCE:-$0}") && pwd) # Destination path for installation DEST=/opt/stack -# Destination for working data -DATA_DIR=${DEST}/data - # Determine stack user if [[ $EUID -eq 0 ]]; then STACK_USER=stack else - STACK_USER=$(whoami) + STACK_USER=${STACK_USER:-$(whoami)} fi +# Set local system prefix i.e. /usr/local or empty +INSTALL_PREFIX=$(get_install_prefix) + # Specify which services to launch. These generally correspond to # screen tabs. To change the default list, use the ``enable_service`` and # ``disable_service`` functions in ``localrc``. @@ -56,6 +56,8 @@ elif [[ -f $RC_DIR/.localrc.auto ]]; then source $RC_DIR/.localrc.auto fi +# Destination for working data +DATA_DIR=${DEST}/data # Repositories # ------------ @@ -212,7 +214,9 @@ PECAN_BRANCH=${PECAN_BRANCH:-master} # also install an **LXC**, **OpenVZ** or **XenAPI** based system. If xenserver-core # is installed, the default will be XenAPI DEFAULT_VIRT_DRIVER=libvirt -is_package_installed xenserver-core && DEFAULT_VIRT_DRIVER=xenserver +if ! is_freebsd ; then + is_package_installed xenserver-core && DEFAULT_VIRT_DRIVER=xenserver +fi VIRT_DRIVER=${VIRT_DRIVER:-$DEFAULT_VIRT_DRIVER} case "$VIRT_DRIVER" in libvirt) diff --git a/tests/functions.sh b/tests/functions.sh index 40376aa63f..5e5662ed50 100755 --- a/tests/functions.sh +++ b/tests/functions.sh @@ -44,7 +44,7 @@ cat >test.ini <test.conf </dev/null; then echo "Creating a group called $STACK_USER" - groupadd $STACK_USER + if is_freebsd; then + pw groupadd $STACK_USER + else + groupadd $STACK_USER + fi fi if ! getent passwd $STACK_USER >/dev/null; then echo "Creating a user called $STACK_USER" - useradd -g $STACK_USER -s /bin/bash -d $DEST -m $STACK_USER + if is_freebsd; then + echo $STACK_USER_PASSWORD | \ + pw useradd -h 0 -n $STACK_USER -c "Devstack" -g $STACK_USER -s /bin/bash -d $DEST -m + else + useradd -g $STACK_USER -s /bin/bash -d $DEST -m $STACK_USER + fi fi echo "Giving stack user passwordless sudo privileges" +SUDOERS_ETC_FILE="$INSTALL_PREFIX/etc/sudoers" +SUDOERS_STACK_FILE="$INSTALL_PREFIX/etc/sudoers.d/50_stack_sh" + # UEC images ``/etc/sudoers`` does not have a ``#includedir``, add one -grep -q "^#includedir.*/etc/sudoers.d" /etc/sudoers || - echo "#includedir /etc/sudoers.d" >> /etc/sudoers +grep -q "^#includedir.*$INSTALL_PREFIX/etc/sudoers.d" $SUDOERS_ETC_FILE || + echo "#includedir $INSTALL_PREFIX/etc/sudoers.d" >> $SUDOERS_ETC_FILE ( umask 226 && echo "$STACK_USER ALL=(ALL) NOPASSWD:ALL" \ - > /etc/sudoers.d/50_stack_sh ) + > $SUDOERS_STACK_FILE ) + +# Some binaries might be under /sbin or /usr/sbin, so make sure sudo will +# see them by forcing PATH +echo "Defaults:$STACK_USER secure_path=/sbin:/usr/sbin:/usr/bin:/bin:/usr/local/sbin:/usr/local/bin" >> $SUDOERS_STACK_FILE diff --git a/tools/fixup_stuff.sh b/tools/fixup_stuff.sh index 325a6d6be1..973b23f099 100755 --- a/tools/fixup_stuff.sh +++ b/tools/fixup_stuff.sh @@ -21,7 +21,7 @@ # - install nose 1.1 from EPEL set -o errexit -set -o xtrace +#set -o xtrace # Keep track of the current directory TOOLS_DIR=$(cd $(dirname "$0") && pwd)