Merge "remove generic extras.d support"
diff --git a/extras.d/50-ironic.sh b/extras.d/50-ironic.sh
index 3b8e3d5..0ee6a94 100644
--- a/extras.d/50-ironic.sh
+++ b/extras.d/50-ironic.sh
@@ -1,5 +1,12 @@
 # ironic.sh - Devstack extras script to install ironic
 
+# NOTE(jroll) this is used for the transition to a devstack plugin in
+# the ironic tree.
+IRONIC_USING_PLUGIN=$(trueorfalse False IRONIC_USING_PLUGIN)
+if [[ "$IRONIC_USING_PLUGIN" == "True" ]] ; then
+    return 0
+fi
+
 if is_service_enabled ir-api ir-cond; then
     if [[ "$1" == "source" ]]; then
         # Initial source
diff --git a/functions-common b/functions-common
index 91a1486..1b01eef 100644
--- a/functions-common
+++ b/functions-common
@@ -978,6 +978,34 @@
     echo "$pkg_dir"
 }
 
+# Wrapper for ``apt-get update`` to try multiple times on the update
+# to address bad package mirrors (which happen all the time).
+function apt_get_update {
+    # only do this once per run
+    if [[ "$REPOS_UPDATED" == "True" && "$RETRY_UPDATE" != "True" ]]; then
+        return
+    fi
+
+    # bail if we are offline
+    [[ "$OFFLINE" = "True" ]] && return
+
+    local sudo="sudo"
+    [[ "$(id -u)" = "0" ]] && sudo="env"
+
+    # time all the apt operations
+    time_start "apt-get-update"
+
+    local proxies="http_proxy=${http_proxy:-} https_proxy=${https_proxy:-} no_proxy=${no_proxy:-} "
+    local update_cmd="$sudo $proxies apt-get update"
+    if ! timeout 300 sh -c "while ! $update_cmd; do sleep 30; done"; then
+        die $LINENO "Failed to update apt repos, we're dead now"
+    fi
+
+    REPOS_UPDATED=True
+    # stop the clock
+    time_stop "apt-get-update"
+}
+
 # Wrapper for ``apt-get`` to set cache and proxy environment variables
 # Uses globals ``OFFLINE``, ``*_proxy``
 # apt_get operation package [package ...]
@@ -1158,16 +1186,7 @@
     fi
 
     if is_ubuntu; then
-        local xtrace
-        xtrace=$(set +o | grep xtrace)
-        set +o xtrace
-        if [[ "$REPOS_UPDATED" != "True" || "$RETRY_UPDATE" = "True" ]]; then
-            # if there are transient errors pulling the updates, that's fine.
-            # It may be secondary repositories that we don't really care about.
-            apt_get update  || /bin/true
-            REPOS_UPDATED=True
-        fi
-        $xtrace
+        apt_get_update
     fi
 }
 
diff --git a/inc/python b/inc/python
index 59668a2..c157604 100644
--- a/inc/python
+++ b/inc/python
@@ -28,10 +28,13 @@
 # Get the path to the pip command.
 # get_pip_command
 function get_pip_command {
-    which pip || which pip-python
+    local version="$1"
+    # NOTE(dhellmann): I don't know if we actually get a pip3.4-python
+    # under any circumstances.
+    which pip${version} || which pip${version}-python
 
     if [ $? -ne 0 ]; then
-        die $LINENO "Unable to find pip; cannot continue"
+        die $LINENO "Unable to find pip${version}; cannot continue"
     fi
 }
 
@@ -66,6 +69,13 @@
     pip_install $clean_name
 }
 
+# Determine the python versions supported by a package
+function get_python_versions_for_package {
+    local name=$1
+    cd $name && python setup.py --classifiers \
+        | grep 'Language' | cut -f5 -d: | grep '\.' | tr '\n' ' '
+}
+
 # Wrapper for ``pip install`` to set cache and proxy environment variables
 # Uses globals ``OFFLINE``, ``PIP_VIRTUAL_ENV``,
 # ``PIP_UPGRADE``, ``TRACK_DEPENDS``, ``*_proxy``,
@@ -104,8 +114,22 @@
             local sudo_pip="env"
         else
             local cmd_pip
-            cmd_pip=$(get_pip_command)
+            cmd_pip=$(get_pip_command $PYTHON2_VERSION)
             local sudo_pip="sudo -H"
+            if python3_enabled; then
+                # Look at the package classifiers to find the python
+                # versions supported, and if we find the version of
+                # python3 we've been told to use, use that instead of the
+                # default pip
+                local package_dir=${!#}
+                local python_versions
+                if [[ -d "$package_dir" ]]; then
+                    python_versions=$(get_python_versions_for_package $package_dir)
+                    if [[ $python_versions =~ $PYTHON3_VERSION ]]; then
+                        cmd_pip=$(get_pip_command $PYTHON3_VERSION)
+                    fi
+                fi
+            fi
         fi
     fi
 
@@ -113,6 +137,8 @@
     # Always apply constraints
     cmd_pip="$cmd_pip -c $REQUIREMENTS_DIR/upper-constraints.txt"
 
+    # FIXME(dhellmann): Need to force multiple versions of pip for
+    # packages like setuptools?
     local pip_version
     pip_version=$(python -c "import pip; \
                         print(pip.__version__.strip('.')[0])")
@@ -276,6 +302,21 @@
     fi
 }
 
+# Report whether python 3 should be used
+function python3_enabled {
+    if [[ $USE_PYTHON3 == "True" ]]; then
+        return 0
+    else
+        return 1
+    fi
+}
+
+# Install python3 packages
+function install_python3 {
+    if is_ubuntu; then
+        apt_get install python3.4 python3.4-dev
+    fi
+}
 
 # Restore xtrace
 $INC_PY_TRACE
diff --git a/inc/rootwrap b/inc/rootwrap
index 63ab59a..2a6e4b6 100644
--- a/inc/rootwrap
+++ b/inc/rootwrap
@@ -22,14 +22,14 @@
     local line
 
     # This is pretty simplistic for now - assume only the first line is used
-    if [[ -r SUDO_SECURE_PATH_FILE ]]; then
+    if [[ -r $SUDO_SECURE_PATH_FILE ]]; then
         line=$(head -1 $SUDO_SECURE_PATH_FILE)
     else
         line="Defaults:$STACK_USER secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/sbin:/usr/bin:/bin"
     fi
 
     # Only add ``dir`` if it is not already present
-    if [[ $line =~ $dir ]]; then
+    if [[ ! $line =~ $dir ]]; then
         echo "${line}:$dir" | sudo tee $SUDO_SECURE_PATH_FILE
         sudo chmod 400 $SUDO_SECURE_PATH_FILE
         sudo chown root:root $SUDO_SECURE_PATH_FILE
diff --git a/lib/ironic b/lib/ironic
index 27b0c8d..dd4f8bf 100644
--- a/lib/ironic
+++ b/lib/ironic
@@ -26,6 +26,13 @@
 set +o xtrace
 set +o pipefail
 
+# NOTE(jroll) this is used for the transition to a devstack plugin in
+# the ironic tree.
+IRONIC_USING_PLUGIN=$(trueorfalse False IRONIC_USING_PLUGIN)
+if [[ "$IRONIC_USING_PLUGIN" == "True" ]] ; then
+    return 0
+fi
+
 # Defaults
 # --------
 
@@ -365,6 +372,9 @@
         iniset $IRONIC_CONF_FILE pxe pxe_append_params "$pxe_params"
     fi
 
+    # Set these options for scenarios in which the agent fetches the image
+    # directly from glance, and don't set them where the image is pushed
+    # over iSCSI.
     if is_deployed_by_agent; then
         if [[ "$SWIFT_ENABLE_TEMPURLS" == "True" ]] ; then
             iniset $IRONIC_CONF_FILE glance swift_temp_url_key $SWIFT_TEMPURL_KEY
@@ -379,9 +389,13 @@
         iniset $IRONIC_CONF_FILE glance swift_container glance
         iniset $IRONIC_CONF_FILE glance swift_temp_url_duration 3600
         iniset $IRONIC_CONF_FILE agent heartbeat_timeout 30
-        iniset $IRONIC_CONF_FILE agent agent_erase_devices_priority 0
     fi
 
+    # FIXME: this really needs to be tested in the gate.
+    # For now, any test using the agent ramdisk should skip cleaning
+    # because it is too slow to run in the gate.
+    iniset $IRONIC_CONF_FILE agent agent_erase_devices_priority 0
+
     if [[ "$IRONIC_IPXE_ENABLED" == "True" ]] ; then
         local pxebin
         pxebin=`basename $IRONIC_PXE_BOOT_IMAGE`
diff --git a/lib/keystone b/lib/keystone
index b19202b..6b4118d 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -218,8 +218,6 @@
 
     iniset_rpc_backend keystone $KEYSTONE_CONF
 
-    iniset $KEYSTONE_CONF eventlet_server admin_bind_host "$KEYSTONE_ADMIN_BIND_HOST"
-
     # Register SSL certificates if provided
     if is_ssl_enabled_service key; then
         ensure_certificates KEYSTONE
@@ -296,13 +294,14 @@
         iniset $KEYSTONE_CONF DEFAULT logging_debug_format_suffix "%(funcName)s %(pathname)s:%(lineno)d"
         iniset $KEYSTONE_CONF DEFAULT logging_exception_prefix "%(process)d TRACE %(name)s %(instance)s"
         _config_keystone_apache_wsgi
+    else
+        iniset $KEYSTONE_CONF eventlet_server admin_bind_host "$KEYSTONE_ADMIN_BIND_HOST"
+        iniset $KEYSTONE_CONF eventlet_server admin_workers "$API_WORKERS"
+        # Public workers will use the server default, typically number of CPU.
     fi
 
     iniset $KEYSTONE_CONF DEFAULT max_token_size 16384
 
-    iniset $KEYSTONE_CONF eventlet_server admin_workers "$API_WORKERS"
-    # Public workers will use the server default, typically number of CPU.
-
     iniset $KEYSTONE_CONF fernet_tokens key_repository "$KEYSTONE_CONF_DIR/fernet-keys/"
 }
 
diff --git a/lib/neutron-legacy b/lib/neutron-legacy
index d00630a..628f646 100644
--- a/lib/neutron-legacy
+++ b/lib/neutron-legacy
@@ -112,6 +112,9 @@
 NEUTRON_CONF=$NEUTRON_CONF_DIR/neutron.conf
 export NEUTRON_TEST_CONFIG_FILE=${NEUTRON_TEST_CONFIG_FILE:-"$NEUTRON_CONF_DIR/debug.ini"}
 
+# Default provider for load balancer service
+DEFAULT_LB_PROVIDER=LOADBALANCER:Haproxy:neutron_lbaas.services.loadbalancer.drivers.haproxy.plugin_driver.HaproxyOnHostPluginDriver:default
+
 # Agent binaries.  Note, binary paths for other agents are set in per-service
 # scripts in lib/neutron_plugins/services/
 AGENT_DHCP_BINARY="$NEUTRON_BIN_DIR/neutron-dhcp-agent"
@@ -550,9 +553,11 @@
             die_if_not_set $LINENO SUBNET_V6_ID "Failure creating SUBNET_V6_ID for $PROVIDER_SUBNET_NAME_V6 $TENANT_ID"
         fi
 
-        sudo ip link set $OVS_PHYSICAL_BRIDGE up
-        sudo ip link set br-int up
-        sudo ip link set $PUBLIC_INTERFACE up
+        if [[ $Q_AGENT == "openvswitch" ]]; then
+            sudo ip link set $OVS_PHYSICAL_BRIDGE up
+            sudo ip link set br-int up
+            sudo ip link set $PUBLIC_INTERFACE up
+        fi
     else
         NET_ID=$(neutron net-create --tenant-id $TENANT_ID "$PRIVATE_NETWORK_NAME" | grep ' id ' | get_field 2)
         die_if_not_set $LINENO NET_ID "Failure creating NET_ID for $PRIVATE_NETWORK_NAME $TENANT_ID"
@@ -698,7 +703,7 @@
 function start_neutron_l2_agent {
     run_process q-agt "$AGENT_BINARY --config-file $NEUTRON_CONF --config-file /$Q_PLUGIN_CONF_FILE"
 
-    if is_provider_network; then
+    if is_provider_network && [[ $Q_AGENT == "openvswitch" ]]; then
         sudo ovs-vsctl --no-wait -- --may-exist add-port $OVS_PHYSICAL_BRIDGE $PUBLIC_INTERFACE
         sudo ip link set $OVS_PHYSICAL_BRIDGE up
         sudo ip link set br-int up
@@ -870,7 +875,10 @@
 function _configure_neutron_common {
     _create_neutron_conf_dir
 
-    cp $NEUTRON_DIR/etc/neutron.conf $NEUTRON_CONF
+    # Uses oslo config generator to generate core sample configuration files
+    (cd $NEUTRON_DIR && exec ./tools/generate_config_file_samples.sh)
+
+    cp $NEUTRON_DIR/etc/neutron.conf.sample $NEUTRON_CONF
 
     Q_POLICY_FILE=$NEUTRON_CONF_DIR/policy.json
     cp $NEUTRON_DIR/etc/policy.json $Q_POLICY_FILE
@@ -895,7 +903,9 @@
     Q_PLUGIN_CONF_FILE=$Q_PLUGIN_CONF_PATH/$Q_PLUGIN_CONF_FILENAME
     # NOTE(hichihara): Some neutron vendor plugins were already decomposed and
     # there is no config file in Neutron tree. They should prepare the file in each plugin.
-    if [ -f $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE ]; then
+    if [ -f "$NEUTRON_DIR/$Q_PLUGIN_CONF_FILE.sample" ]; then
+        cp "$NEUTRON_DIR/$Q_PLUGIN_CONF_FILE.sample" /$Q_PLUGIN_CONF_FILE
+    elif [ -f $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE ]; then
         cp $NEUTRON_DIR/$Q_PLUGIN_CONF_FILE /$Q_PLUGIN_CONF_FILE
     fi
 
@@ -903,6 +913,8 @@
     iniset $NEUTRON_CONF DEFAULT state_path $DATA_DIR/neutron
     iniset $NEUTRON_CONF DEFAULT use_syslog $SYSLOG
     iniset $NEUTRON_CONF DEFAULT bind_host $Q_LISTEN_ADDRESS
+    iniset $NEUTRON_CONF oslo_concurrency lock_path $DATA_DIR/neutron/lock
+
     # If addition config files are set, make sure their path name is set as well
     if [[ ${#Q_PLUGIN_EXTRA_CONF_FILES[@]} > 0 && $Q_PLUGIN_EXTRA_CONF_PATH == '' ]]; then
         die $LINENO "Neutron additional plugin config not set.. exiting"
@@ -959,7 +971,7 @@
         return
     fi
 
-    cp $NEUTRON_DIR/etc/l3_agent.ini $NEUTRON_TEST_CONFIG_FILE
+    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $NEUTRON_TEST_CONFIG_FILE
 
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT verbose False
     iniset $NEUTRON_TEST_CONFIG_FILE DEFAULT debug False
@@ -975,7 +987,7 @@
 
 function _configure_neutron_dhcp_agent {
 
-    cp $NEUTRON_DIR/etc/dhcp_agent.ini $Q_DHCP_CONF_FILE
+    cp $NEUTRON_DIR/etc/dhcp_agent.ini.sample $Q_DHCP_CONF_FILE
 
     iniset $Q_DHCP_CONF_FILE DEFAULT verbose True
     iniset $Q_DHCP_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -1007,7 +1019,7 @@
         neutron_vpn_configure_agent
     fi
 
-    cp $NEUTRON_DIR/etc/l3_agent.ini $Q_L3_CONF_FILE
+    cp $NEUTRON_DIR/etc/l3_agent.ini.sample $Q_L3_CONF_FILE
 
     iniset $Q_L3_CONF_FILE DEFAULT verbose True
     iniset $Q_L3_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -1028,7 +1040,7 @@
 }
 
 function _configure_neutron_metadata_agent {
-    cp $NEUTRON_DIR/etc/metadata_agent.ini $Q_META_CONF_FILE
+    cp $NEUTRON_DIR/etc/metadata_agent.ini.sample $Q_META_CONF_FILE
 
     iniset $Q_META_CONF_FILE DEFAULT verbose True
     iniset $Q_META_CONF_FILE DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
@@ -1049,8 +1061,12 @@
 }
 
 function _configure_neutron_lbaas {
-    if [ -f $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf ]; then
-        cp $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf $NEUTRON_CONF_DIR
+    # Uses oslo config generator to generate LBaaS sample configuration files
+    (cd $NEUTRON_LBAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+
+    if [ -f $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf.sample ]; then
+        cp $NEUTRON_LBAAS_DIR/etc/neutron_lbaas.conf.sample $NEUTRON_CONF_DIR/neutron_lbaas.conf
+        iniset $NEUTRON_CONF_DIR/neutron_lbaas.conf service_providers service_provider $DEFAULT_LB_PROVIDER
     fi
     neutron_agent_lbaas_configure_common
     neutron_agent_lbaas_configure_agent
diff --git a/lib/neutron_plugins/services/firewall b/lib/neutron_plugins/services/firewall
index 1d81a21..2b7f32d 100644
--- a/lib/neutron_plugins/services/firewall
+++ b/lib/neutron_plugins/services/firewall
@@ -14,8 +14,11 @@
 }
 
 function neutron_fwaas_configure_driver {
+    # Uses oslo config generator to generate FWaaS sample configuration files
+    (cd $NEUTRON_FWAAS_DIR && exec ./tools/generate_config_file_samples.sh)
+
     FWAAS_DRIVER_CONF_FILENAME=/etc/neutron/fwaas_driver.ini
-    cp $NEUTRON_FWAAS_DIR/etc/fwaas_driver.ini $FWAAS_DRIVER_CONF_FILENAME
+    cp $NEUTRON_FWAAS_DIR/etc/fwaas_driver.ini.sample $FWAAS_DRIVER_CONF_FILENAME
 
     iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas enabled True
     iniset_multiline $FWAAS_DRIVER_CONF_FILENAME fwaas driver "neutron_fwaas.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver"
diff --git a/lib/neutron_plugins/services/loadbalancer b/lib/neutron_plugins/services/loadbalancer
index b07d06c..30e9480 100644
--- a/lib/neutron_plugins/services/loadbalancer
+++ b/lib/neutron_plugins/services/loadbalancer
@@ -28,7 +28,7 @@
 
     LBAAS_AGENT_CONF_FILENAME="$LBAAS_AGENT_CONF_PATH/lbaas_agent.ini"
 
-    cp $NEUTRON_LBAAS_DIR/etc/lbaas_agent.ini $LBAAS_AGENT_CONF_FILENAME
+    cp $NEUTRON_LBAAS_DIR/etc/lbaas_agent.ini.sample $LBAAS_AGENT_CONF_FILENAME
 
     # ovs_use_veth needs to be set before the plugin configuration
     # occurs to allow plugins to override the setting.
diff --git a/lib/neutron_plugins/services/metering b/lib/neutron_plugins/services/metering
index 5fd2fdc..5b32468 100644
--- a/lib/neutron_plugins/services/metering
+++ b/lib/neutron_plugins/services/metering
@@ -21,7 +21,7 @@
 
     METERING_AGENT_CONF_FILENAME="$METERING_AGENT_CONF_PATH/metering_agent.ini"
 
-    cp $NEUTRON_DIR/etc/metering_agent.ini $METERING_AGENT_CONF_FILENAME
+    cp $NEUTRON_DIR/etc/metering_agent.ini.sample $METERING_AGENT_CONF_FILENAME
 }
 
 function neutron_metering_stop {
diff --git a/lib/stack b/lib/stack
index 7d98604..f09ddce 100644
--- a/lib/stack
+++ b/lib/stack
@@ -19,6 +19,7 @@
 function stack_install_service {
     local service=$1
     if type install_${service} >/dev/null 2>&1; then
+        # FIXME(dhellmann): Needs to be python3-aware at some point.
         if [[ ${USE_VENV} = True && -n ${PROJECT_VENV[$service]:-} ]]; then
             rm -rf ${PROJECT_VENV[$service]}
             source $TOP_DIR/tools/build_venv.sh ${PROJECT_VENV[$service]} ${ADDITIONAL_VENV_PACKAGES//,/ }
diff --git a/stackrc b/stackrc
index 5dd109c..f949ccb 100644
--- a/stackrc
+++ b/stackrc
@@ -118,6 +118,17 @@
     source $RC_DIR/.localrc.password
 fi
 
+# Control whether Python 3 should be used.
+export USE_PYTHON3=${USE_PYTHON3:-False}
+
+# When Python 3 is supported by an application, adding the specific
+# version of Python 3 to this variable will install the app using that
+# version of the interpreter instead of 2.7.
+export PYTHON3_VERSION=${PYTHON3_VERSION:-3.4}
+
+# Just to be more explicit on the Python 2 version to use.
+export PYTHON2_VERSION=${PYTHON2_VERSION:-2.7}
+
 # allow local overrides of env variables, including repo config
 if [[ -f $RC_DIR/localrc ]]; then
     # Old-style user-supplied config
diff --git a/tools/install_pip.sh b/tools/install_pip.sh
index ab5efb2..f239c7b 100755
--- a/tools/install_pip.sh
+++ b/tools/install_pip.sh
@@ -8,6 +8,7 @@
 
 # Assumptions:
 # - update pip to $INSTALL_PIP_VERSION
+# - if USE_PYTHON3=True, PYTHON3_VERSION refers to a version already installed
 
 set -o errexit
 set -o xtrace
@@ -31,6 +32,8 @@
 echo "Distro: $DISTRO"
 
 function get_versions {
+    # FIXME(dhellmann): Deal with multiple python versions here? This
+    # is just used for reporting, so maybe not?
     PIP=$(which pip 2>/dev/null || which pip-python 2>/dev/null || true)
     if [[ -n $PIP ]]; then
         PIP_VERSION=$($PIP --version | awk '{ print $2}')
@@ -75,6 +78,9 @@
         touch $LOCAL_PIP.downloaded
     fi
     sudo -H -E python $LOCAL_PIP
+    if python3_enabled; then
+        sudo -H -E python${PYTHON3_VERSION} $LOCAL_PIP
+    fi
 }
 
 
@@ -114,6 +120,7 @@
 # python in f23 depends on the python-pip package
 if ! { is_fedora && [[ $DISTRO == "f23" ]]; }; then
     uninstall_package python-pip
+    uninstall_package python3-pip
 fi
 
 install_get_pip
@@ -122,6 +129,7 @@
     configure_pypi_alternative_url
 fi
 
+set -x
 pip_install -U setuptools
 
 get_versions
diff --git a/tools/install_prereqs.sh b/tools/install_prereqs.sh
index 38452cd..031f8a8 100755
--- a/tools/install_prereqs.sh
+++ b/tools/install_prereqs.sh
@@ -81,6 +81,9 @@
     fi
 fi
 
+if python3_enabled; then
+    install_python3
+fi
 
 # Mark end of run
 # ---------------