From 5cb190697c1bce5dcd2ad843922813b0cc74bd24 Mon Sep 17 00:00:00 2001 From: Sean Dague Date: Sat, 1 Nov 2014 01:37:45 +0100 Subject: [PATCH] support installing clients at released versions expand the devstack support for libraries from released versions to support python-* clients and tempest_lib. Depends-On: I81b0d228e7769758c61e5b0323ecfce8c8886d39 Change-Id: I26fac0ccf8fd4818e24618d56bf04b32306f88f6 --- extras.d/70-trove.sh | 1 - functions-common | 1 + lib/ceilometer | 11 ++++++---- lib/cinder | 11 ++++++---- lib/glance | 9 ++++++--- lib/heat | 11 ++++++---- lib/ironic | 14 +++++++++---- lib/keystone | 11 ++++++---- lib/neutron | 12 +++++++---- lib/nova | 12 +++++++---- lib/swift | 10 ++++++--- lib/tempest | 9 ++++++--- lib/trove | 12 +++++------ stack.sh | 12 ++++++++--- stackrc | 48 ++++++++++++++++++++++---------------------- 15 files changed, 113 insertions(+), 71 deletions(-) diff --git a/extras.d/70-trove.sh b/extras.d/70-trove.sh index a4dc7fbc5b..f284354e1f 100644 --- a/extras.d/70-trove.sh +++ b/extras.d/70-trove.sh @@ -11,7 +11,6 @@ if is_service_enabled trove; then cleanup_trove elif [[ "$1" == "stack" && "$2" == "post-config" ]]; then echo_summary "Configuring Trove" - configure_troveclient configure_trove if is_service_enabled key; then diff --git a/functions-common b/functions-common index 48edba8da6..4e6ad14437 100644 --- a/functions-common +++ b/functions-common @@ -1621,6 +1621,7 @@ function use_library_from_git { return $enabled } + # setup a library by name. If we are trying to use the library from # git, we'll do a git based install, otherwise we'll punt and the # library should be installed by a requirements pull from another diff --git a/lib/ceilometer b/lib/ceilometer index 9046b9d3d9..b1ff8b4157 100644 --- a/lib/ceilometer +++ b/lib/ceilometer @@ -35,8 +35,9 @@ set +o xtrace # -------- # Set up default directories +GITDIR["ceilometerclient"]=$DEST/python-ceilometerclient + CEILOMETER_DIR=$DEST/ceilometer -CEILOMETERCLIENT_DIR=$DEST/python-ceilometerclient CEILOMETER_CONF_DIR=/etc/ceilometer CEILOMETER_CONF=$CEILOMETER_CONF_DIR/ceilometer.conf CEILOMETER_API_LOG_DIR=/var/log/ceilometer-api @@ -254,9 +255,11 @@ function install_ceilometer { # install_ceilometerclient() - Collect source and prepare function install_ceilometerclient { - git_clone $CEILOMETERCLIENT_REPO $CEILOMETERCLIENT_DIR $CEILOMETERCLIENT_BRANCH - setup_develop $CEILOMETERCLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$CEILOMETERCLIENT_DIR/tools/,/etc/bash_completion.d/}ceilometer.bash_completion + if use_library_from_git "ceilometerclient"; then + git_clone_by_name "ceilometerclient" + setup_develop "ceilometerclient" + sudo install -D -m 0644 -o $STACK_USER {$CEILOMETERCLIENT_DIR/tools/,/etc/bash_completion.d/}ceilometer.bash_completion + fi } # start_ceilometer() - Start running processes, including screen diff --git a/lib/cinder b/lib/cinder index 29cda42eb2..56878642e3 100644 --- a/lib/cinder +++ b/lib/cinder @@ -36,8 +36,9 @@ if [[ -r $CINDER_PLUGINS/$CINDER_DRIVER ]]; then fi # set up default directories +GITDIR["cinderclient"]=$DEST/python-cinderclient + CINDER_DIR=$DEST/cinder -CINDERCLIENT_DIR=$DEST/python-cinderclient CINDER_STATE_PATH=${CINDER_STATE_PATH:=$DATA_DIR/cinder} CINDER_AUTH_CACHE_DIR=${CINDER_AUTH_CACHE_DIR:-/var/cache/cinder} @@ -402,9 +403,11 @@ function install_cinder { # install_cinderclient() - Collect source and prepare 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 + if use_library_from_git "cinderclient"; then + git_clone_by_name "cinderclient" + setup_develop "cinderclient" + sudo install -D -m 0644 -o $STACK_USER {$CINDERCLIENT_DIR/tools/,/etc/bash_completion.d/}cinder.bash_completion + fi } # apply config.d approach for cinder volumes directory diff --git a/lib/glance b/lib/glance index 4194842407..8cd48b13f9 100644 --- a/lib/glance +++ b/lib/glance @@ -27,9 +27,10 @@ set +o xtrace # -------- # Set up default directories +GITDIR["glanceclient"]=$DEST/python-glanceclient + GLANCE_DIR=$DEST/glance GLANCE_STORE_DIR=$DEST/glance_store -GLANCECLIENT_DIR=$DEST/python-glanceclient GLANCE_CACHE_DIR=${GLANCE_CACHE_DIR:=$DATA_DIR/glance/cache} GLANCE_IMAGE_DIR=${GLANCE_IMAGE_DIR:=$DATA_DIR/glance/images} GLANCE_AUTH_CACHE_DIR=${GLANCE_AUTH_CACHE_DIR:-/var/cache/glance} @@ -286,8 +287,10 @@ function init_glance { # install_glanceclient() - Collect source and prepare function install_glanceclient { - git_clone $GLANCECLIENT_REPO $GLANCECLIENT_DIR $GLANCECLIENT_BRANCH - setup_develop $GLANCECLIENT_DIR + if use_library_from_git "glanceclient"; then + git_clone_by_name "glanceclient" + setup_develop "glanceclient" + fi } # install_glance() - Collect source and prepare diff --git a/lib/heat b/lib/heat index 53eca25450..ed5181b2b8 100644 --- a/lib/heat +++ b/lib/heat @@ -29,8 +29,9 @@ set +o xtrace # -------- # set up default directories +GITDIR["heatclient"]=$DEST/python-heatclient + HEAT_DIR=$DEST/heat -HEATCLIENT_DIR=$DEST/python-heatclient HEAT_CFNTOOLS_DIR=$DEST/heat-cfntools HEAT_TEMPLATES_REPO_DIR=$DEST/heat-templates HEAT_AUTH_CACHE_DIR=${HEAT_AUTH_CACHE_DIR:-/var/cache/heat} @@ -183,9 +184,11 @@ function create_heat_cache_dir { # install_heatclient() - Collect source and prepare function install_heatclient { - git_clone $HEATCLIENT_REPO $HEATCLIENT_DIR $HEATCLIENT_BRANCH - setup_develop $HEATCLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$HEATCLIENT_DIR/tools/,/etc/bash_completion.d/}heat.bash_completion + if use_library_from_git "heatclient"; then + git_clone_by_name "heatclient" + setup_develop "heatclient" + sudo install -D -m 0644 -o $STACK_USER {$HEATCLIENT_DIR/tools/,/etc/bash_completion.d/}heat.bash_completion + fi } # install_heat() - Collect source and prepare diff --git a/lib/ironic b/lib/ironic index 0a84e47ebc..0fadb8d0a1 100644 --- a/lib/ironic +++ b/lib/ironic @@ -28,11 +28,12 @@ set +o pipefail # -------- # Set up default directories +GITDIR["ironicclient"]=$DEST/python-ironicclient + IRONIC_DIR=$DEST/ironic IRONIC_PYTHON_AGENT_DIR=$DEST/ironic-python-agent IRONIC_DATA_DIR=$DATA_DIR/ironic IRONIC_STATE_PATH=/var/lib/ironic -IRONICCLIENT_DIR=$DEST/python-ironicclient IRONIC_AUTH_CACHE_DIR=${IRONIC_AUTH_CACHE_DIR:-/var/cache/ironic} IRONIC_CONF_DIR=${IRONIC_CONF_DIR:-/etc/ironic} IRONIC_CONF_FILE=$IRONIC_CONF_DIR/ironic.conf @@ -150,9 +151,14 @@ function install_ironic { # install_ironicclient() - Collect sources and prepare function install_ironicclient { - git_clone $IRONICCLIENT_REPO $IRONICCLIENT_DIR $IRONICCLIENT_BRANCH - setup_develop $IRONICCLIENT_DIR - sudo install -D -m 0644 -o $STACK_USER {$IRONICCLIENT_DIR/tools/,/etc/bash_completion.d/}ironic.bash_completion + if use_library_from_git "ironicclient"; then + git_clone_by_name "ironicclient" + setup_develop "ironicclient" + sudo install -D -m 0644 -o $STACK_USER {$IRONICCLIENT_DIR/tools/,/etc/bash_completion.d/}ironic.bash_completion + else + # nothing actually "requires" ironicclient, so force instally from pypi + pip_install python-ironicclient + fi } # _cleanup_ironic_apache_wsgi() - Remove wsgi files, disable and remove apache vhost file diff --git a/lib/keystone b/lib/keystone index 276e9718a6..6341ce2eea 100644 --- a/lib/keystone +++ b/lib/keystone @@ -33,6 +33,8 @@ set +o xtrace # -------- # Set up default directories +GITDIR["keystoneclient"]=$DEST/python-keystoneclient + KEYSTONE_DIR=$DEST/keystone KEYSTONE_CONF_DIR=${KEYSTONE_CONF_DIR:-/etc/keystone} KEYSTONE_CONF=$KEYSTONE_CONF_DIR/keystone.conf @@ -45,7 +47,6 @@ else fi KEYSTONEMIDDLEWARE_DIR=$DEST/keystonemiddleware -KEYSTONECLIENT_DIR=$DEST/python-keystoneclient # Set up additional extensions, such as oauth1, federation # Example of KEYSTONE_EXTENSIONS=oauth1,federation @@ -479,9 +480,11 @@ function init_keystone { # install_keystoneclient() - Collect source and prepare 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 + if use_library_from_git "keystoneclient"; then + git_clone_by_name "keystoneclient" + setup_develop "keystoneclient" + sudo install -D -m 0644 -o $STACK_USER {$KEYSTONECLIENT_DIR/tools/,/etc/bash_completion.d/}keystone.bash_completion + fi } # install_keystonemiddleware() - Collect source and prepare diff --git a/lib/neutron b/lib/neutron index d05dcc806f..faca3e0da2 100644 --- a/lib/neutron +++ b/lib/neutron @@ -77,8 +77,10 @@ fi # Set up default directories +GITDIR["neutronclient"]=$DEST/python-neutronclient + + NEUTRON_DIR=$DEST/neutron -NEUTRONCLIENT_DIR=$DEST/python-neutronclient NEUTRON_AUTH_CACHE_DIR=${NEUTRON_AUTH_CACHE_DIR:-/var/cache/neutron} # Support entry points installation of console scripts @@ -601,9 +603,11 @@ function install_neutron { # install_neutronclient() - Collect source and prepare 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 + if use_library_from_git "neutronclient"; then + git_clone_by_name "neutronclient" + setup_develop "neutronclient" + sudo install -D -m 0644 -o $STACK_USER {$NEUTRONCLIENT_DIR/tools/,/etc/bash_completion.d/}neutron.bash_completion + fi } # install_neutron_agent_packages() - Collect source and prepare diff --git a/lib/nova b/lib/nova index 0f838072c1..d5f11928e5 100644 --- a/lib/nova +++ b/lib/nova @@ -29,8 +29,10 @@ set +o xtrace # -------- # Set up default directories +GITDIR["novaclient"]=$DEST/python-novaclient + + NOVA_DIR=$DEST/nova -NOVACLIENT_DIR=$DEST/python-novaclient NOVA_STATE_PATH=${NOVA_STATE_PATH:=$DATA_DIR/nova} # INSTANCES_PATH is the previous name for this NOVA_INSTANCES_PATH=${NOVA_INSTANCES_PATH:=${INSTANCES_PATH:=$NOVA_STATE_PATH/instances}} @@ -637,9 +639,11 @@ function init_nova { # install_novaclient() - Collect source and prepare 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 + if use_library_from_git "novaclient"; then + git_clone_by_name "novaclient" + setup_develop "novaclient" + sudo install -D -m 0644 -o $STACK_USER {$NOVACLIENT_DIR/tools/,/etc/bash_completion.d/}nova.bash_completion + fi } # install_nova() - Collect source and prepare diff --git a/lib/swift b/lib/swift index 7ef44969b6..801628241a 100644 --- a/lib/swift +++ b/lib/swift @@ -34,8 +34,10 @@ if is_ssl_enabled_service "s-proxy" || is_service_enabled tls-proxy; then fi # Set up default directories +GITDIR["swiftclient"]=$DEST/python-swiftclient + + SWIFT_DIR=$DEST/swift -SWIFTCLIENT_DIR=$DEST/python-swiftclient SWIFT_AUTH_CACHE_DIR=${SWIFT_AUTH_CACHE_DIR:-/var/cache/swift} SWIFT_APACHE_WSGI_DIR=${SWIFT_APACHE_WSGI_DIR:-/var/www/swift} SWIFT3_DIR=$DEST/swift3 @@ -675,8 +677,10 @@ function install_swift { } function install_swiftclient { - git_clone $SWIFTCLIENT_REPO $SWIFTCLIENT_DIR $SWIFTCLIENT_BRANCH - setup_develop $SWIFTCLIENT_DIR + if use_library_from_git "swiftclient"; then + git_clone_by_name "swiftclient" + setup_develop "swiftclient" + fi } # start_swift() - Start running processes, including screen diff --git a/lib/tempest b/lib/tempest index 66f1a788f1..25dc171fe2 100644 --- a/lib/tempest +++ b/lib/tempest @@ -45,11 +45,12 @@ set +o xtrace # -------- # Set up default directories +GITDIR["tempest_lib"]=$DEST/tempest-lib + TEMPEST_DIR=$DEST/tempest TEMPEST_CONFIG_DIR=${TEMPEST_CONFIG_DIR:-$TEMPEST_DIR/etc} TEMPEST_CONFIG=$TEMPEST_CONFIG_DIR/tempest.conf TEMPEST_STATE_PATH=${TEMPEST_STATE_PATH:=$DATA_DIR/tempest} -TEMPEST_LIB_DIR=$DEST/tempest-lib NOVA_SOURCE_DIR=$DEST/nova @@ -441,8 +442,10 @@ function create_tempest_accounts { # install_tempest_lib() - Collect source, prepare, and install tempest-lib function install_tempest_lib { - git_clone $TEMPEST_LIB_REPO $TEMPEST_LIB_DIR $TEMPEST_LIB_BRANCH - setup_develop $TEMPEST_LIB_DIR + if use_library_from_git "tempest_lib"; then + git_clone_by_name "tempest_lib" + setup_develop "tempest_lib" + fi } # install_tempest() - Collect source and prepare diff --git a/lib/trove b/lib/trove index 1d1b5f406b..2f8b696924 100644 --- a/lib/trove +++ b/lib/trove @@ -28,8 +28,9 @@ else fi # Set up default configuration +GITDIR["troveclient"]=$DEST/python-troveclient + TROVE_DIR=$DEST/trove -TROVECLIENT_DIR=$DEST/python-troveclient TROVE_CONF_DIR=/etc/trove TROVE_LOCAL_CONF_DIR=$TROVE_DIR/etc/trove TROVE_AUTH_CACHE_DIR=${TROVE_AUTH_CACHE_DIR:-/var/cache/trove} @@ -109,10 +110,6 @@ function cleanup_trove { rm -fr $TROVE_CONF_DIR/* } -# configure_troveclient() - Set config files, create data dirs, etc -function configure_troveclient { - setup_develop $TROVECLIENT_DIR -} # configure_trove() - Set config files, create data dirs, etc function configure_trove { @@ -184,7 +181,10 @@ function configure_trove { # install_troveclient() - Collect source and prepare function install_troveclient { - git_clone $TROVECLIENT_REPO $TROVECLIENT_DIR $TROVECLIENT_BRANCH + if use_library_from_git "troveclient"; then + git_clone_by_name "troveclient" + setup_develop "troveclient" + fi } # install_trove() - Collect source and prepare diff --git a/stack.sh b/stack.sh index ec13338948..5f87a904c3 100755 --- a/stack.sh +++ b/stack.sh @@ -585,7 +585,7 @@ if [[ -d $TOP_DIR/extras.d ]]; then fi # Set the destination directories for other OpenStack projects -OPENSTACKCLIENT_DIR=$DEST/python-openstackclient +GITDIR["openstackclient"]=$DEST/python-openstackclient # Interactive Configuration # ------------------------- @@ -788,8 +788,14 @@ fi # Install middleware install_keystonemiddleware -git_clone $OPENSTACKCLIENT_REPO $OPENSTACKCLIENT_DIR $OPENSTACKCLIENT_BRANCH -setup_develop $OPENSTACKCLIENT_DIR +# install the OpenStack client, needed for most setup commands +if use_library_from_git "openstackclient"; then + git_clone_by_name "openstackclient" + setup_develop "openstackclient" +else + pip_install python-openstackclient +fi + if is_service_enabled key; then if [ "$KEYSTONE_AUTH_HOST" == "$SERVICE_HOST" ]; then diff --git a/stackrc b/stackrc index 15b0951a1a..2f08c730be 100644 --- a/stackrc +++ b/stackrc @@ -199,8 +199,8 @@ TEMPEST_REPO=${TEMPEST_REPO:-${GIT_BASE}/openstack/tempest.git} TEMPEST_BRANCH=${TEMPEST_BRANCH:-master} # TODO(sdague): this should end up as a library component like below -TEMPEST_LIB_REPO=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git} -TEMPEST_LIB_BRANCH=${TEMPEST_LIB_BRANCH:-master} +GITREPO["tempest_lib"]=${TEMPEST_LIB_REPO:-${GIT_BASE}/openstack/tempest-lib.git} +GITBRANCH["tempest_lib"]=${TEMPEST_LIB_BRANCH:-master} ############## @@ -210,48 +210,48 @@ TEMPEST_LIB_BRANCH=${TEMPEST_LIB_BRANCH:-master} ############## # ceilometer client library -CEILOMETERCLIENT_REPO=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git} -CEILOMETERCLIENT_BRANCH=${CEILOMETERCLIENT_BRANCH:-master} +GITREPO["ceilometerclient"]=${CEILOMETERCLIENT_REPO:-${GIT_BASE}/openstack/python-ceilometerclient.git} +GITBRANCH["ceilometerclient"]=${CEILOMETERCLIENT_BRANCH:-master} # volume client -CINDERCLIENT_REPO=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git} -CINDERCLIENT_BRANCH=${CINDERCLIENT_BRANCH:-master} +GITREPO["cinderclient"]=${CINDERCLIENT_REPO:-${GIT_BASE}/openstack/python-cinderclient.git} +GITBRACH["cinderclient"]=${CINDERCLIENT_BRANCH:-master} # python glance client library -GLANCECLIENT_REPO=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git} -GLANCECLIENT_BRANCH=${GLANCECLIENT_BRANCH:-master} +GITREPO["glanceclient"]=${GLANCECLIENT_REPO:-${GIT_BASE}/openstack/python-glanceclient.git} +GITBRANCH["glanceclient"]=${GLANCECLIENT_BRANCH:-master} # python heat client library -HEATCLIENT_REPO=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git} -HEATCLIENT_BRANCH=${HEATCLIENT_BRANCH:-master} +GITREPO["heatclient"]=${HEATCLIENT_REPO:-${GIT_BASE}/openstack/python-heatclient.git} +GITBRANCH["heatclient"]=${HEATCLIENT_BRANCH:-master} # ironic client -IRONICCLIENT_REPO=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git} -IRONICCLIENT_BRANCH=${IRONICCLIENT_BRANCH:-master} +GITREPO["ironicclient"]=${IRONICCLIENT_REPO:-${GIT_BASE}/openstack/python-ironicclient.git} +GITBRANCH["ironicclient"]=${IRONICCLIENT_BRANCH:-master} # python keystone client library to nova that horizon uses -KEYSTONECLIENT_REPO=${KEYSTONECLIENT_REPO:-${GIT_BASE}/openstack/python-keystoneclient.git} -KEYSTONECLIENT_BRANCH=${KEYSTONECLIENT_BRANCH:-master} +GITREPO["keystoneclient"]=${KEYSTONECLIENT_REPO:-${GIT_BASE}/openstack/python-keystoneclient.git} +GITBRANCH["keystoneclient"]=${KEYSTONECLIENT_BRANCH:-master} # neutron client -NEUTRONCLIENT_REPO=${NEUTRONCLIENT_REPO:-${GIT_BASE}/openstack/python-neutronclient.git} -NEUTRONCLIENT_BRANCH=${NEUTRONCLIENT_BRANCH:-master} +GITREPO["neutronclient"]=${NEUTRONCLIENT_REPO:-${GIT_BASE}/openstack/python-neutronclient.git} +GITBRANCH["neutronclient"]=${NEUTRONCLIENT_BRANCH:-master} # python client library to nova that horizon (and others) use -NOVACLIENT_REPO=${NOVACLIENT_REPO:-${GIT_BASE}/openstack/python-novaclient.git} -NOVACLIENT_BRANCH=${NOVACLIENT_BRANCH:-master} +GITREPO["novaclient"]=${NOVACLIENT_REPO:-${GIT_BASE}/openstack/python-novaclient.git} +GITBRANCH["novaclient"]=${NOVACLIENT_BRANCH:-master} # python swift client library -SWIFTCLIENT_REPO=${SWIFTCLIENT_REPO:-${GIT_BASE}/openstack/python-swiftclient.git} -SWIFTCLIENT_BRANCH=${SWIFTCLIENT_BRANCH:-master} +GITREPO["swiftclient"]=${SWIFTCLIENT_REPO:-${GIT_BASE}/openstack/python-swiftclient.git} +GITBRANCH["swiftclient"]=${SWIFTCLIENT_BRANCH:-master} # trove client library test -TROVECLIENT_REPO=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git} -TROVECLIENT_BRANCH=${TROVECLIENT_BRANCH:-master} +GITREPO["troveclient"]=${TROVECLIENT_REPO:-${GIT_BASE}/openstack/python-troveclient.git} +GITBRANCH["troveclient"]=${TROVECLIENT_BRANCH:-master} # consolidated openstack python client -OPENSTACKCLIENT_REPO=${OPENSTACKCLIENT_REPO:-${GIT_BASE}/openstack/python-openstackclient.git} -OPENSTACKCLIENT_BRANCH=${OPENSTACKCLIENT_BRANCH:-master} +GITREPO["openstackclient"]=${OPENSTACKCLIENT_REPO:-${GIT_BASE}/openstack/python-openstackclient.git} +GITBRANCH["openstackclient"]=${OPENSTACKCLIENT_BRANCH:-master} ################### #