Congress
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

535 lines
20KB

  1. #!/usr/bin/env bash
  2. # Plugin file for congress services
  3. #----------------------------------
  4. # Dependencies:
  5. # ``functions`` file
  6. # ``DEST`` must be defined
  7. # ``STACK_USER`` must be defined
  8. # Functions in this file are classified into the following categories:
  9. #
  10. # - entry points (called from stack.sh or unstack.sh)
  11. # - internal functions
  12. # - congress exercises
  13. # Save trace setting
  14. XTRACE=$(set +o | grep xtrace)
  15. set -o xtrace
  16. # Functions
  17. # ---------
  18. # Test if any Congress services are enabled
  19. # is_congress_enabled
  20. function is_congress_enabled {
  21. [[ ,${ENABLED_SERVICES//congress-agent/} =~ ,"congress" ]] && return 0
  22. return 1
  23. }
  24. # configure_congress()
  25. # Set common config for all congress server and agents.
  26. function configure_congress {
  27. setup_develop $CONGRESS_DIR
  28. # Put config files in ``CONGRESS_CONF_DIR`` for everyone to find
  29. if [[ ! -d $CONGRESS_CONF_DIR ]]; then
  30. sudo mkdir -p $CONGRESS_CONF_DIR
  31. fi
  32. sudo chown $STACK_USER $CONGRESS_CONF_DIR
  33. touch $CONGRESS_CONF
  34. sudo chown $STACK_USER $CONGRESS_CONF
  35. # Format logging
  36. if [ "$LOG_COLOR" == "True" ] && [ "$SYSLOG" == "False" ]; then
  37. setup_colorized_logging $CONGRESS_CONF DEFAULT project_id
  38. fi
  39. CONGRESS_API_PASTE_FILE=$CONGRESS_CONF_DIR/api-paste.ini
  40. cp $CONGRESS_DIR/etc/api-paste.ini $CONGRESS_API_PASTE_FILE
  41. if [[ ! -d $CONGRESS_LIBRARY_DIR ]]; then
  42. mkdir $CONGRESS_LIBRARY_DIR
  43. fi
  44. cp -r $CONGRESS_DIR/library/* $CONGRESS_LIBRARY_DIR
  45. # Update either configuration file
  46. iniset $CONGRESS_CONF DEFAULT bind_host $(ipv6_unquote $SERVICE_LISTEN_ADDRESS)
  47. iniset $CONGRESS_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
  48. iniset $CONGRESS_CONF DEFAULT auth_strategy $CONGRESS_AUTH_STRATEGY
  49. iniset $CONGRESS_CONF DEFAULT datasource_sync_period 30
  50. iniset $CONGRESS_CONF DEFAULT replicated_policy_engine "$CONGRESS_REPLICATED"
  51. iniset $CONGRESS_CONF DEFAULT transport_url rabbit://$RABBIT_USERID:$RABBIT_PASSWORD@$RABBIT_HOST:5672/
  52. iniset $CONGRESS_CONF database connection `database_connection_url $CONGRESS_DB_NAME`
  53. if [ "$ENABLE_CONGRESS_JSON" == "True" ]; then
  54. iniset $CONGRESS_CONF json_ingester enable "True"
  55. # when the main db is not postgres, the devstack function
  56. # database_connection_url_postgresql returns URL with wrong prefix,
  57. # so we do a substitution here
  58. local db_connection_mysql=`database_connection_url_postgresql $CONGRESS_JSON_DB_NAME`
  59. CONGRESS_JSON_DB_CONNECTION_URL=${db_connection_mysql/?*:\/\//postgresql:\/\/}
  60. iniset $CONGRESS_CONF json_ingester db_connection $CONGRESS_JSON_DB_CONNECTION_URL
  61. iniset $CONGRESS_CONF json_ingester config_path "$CONGRESS_JSON_CONF_DIR"
  62. iniset $CONGRESS_CONF json_ingester config_reusables_path "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  63. # setup json ingester config files
  64. if [[ ! -d $CONGRESS_JSON_CONF_DIR ]]; then
  65. mkdir $CONGRESS_JSON_CONF_DIR
  66. fi
  67. echo "keystone_admin_auth_config:" > "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  68. echo " type: keystone" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  69. echo " config:" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  70. echo " project_name: $OS_PROJECT_NAME" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  71. echo " username: $OS_USERNAME" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  72. echo " password: $OS_PASSWORD" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  73. echo " auth_url: `openstack catalog show keystone -f value -c endpoints | sed -n 's/^\s*public: //p' | sed -n '1p'`" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  74. fi
  75. _congress_setup_keystone $CONGRESS_CONF keystone_authtoken
  76. }
  77. function _configure_congress_json_ingester {
  78. local endpoint=`openstack catalog show $1 -f value -c endpoints | sed -n 's/^\s*public:\s*//p' | sed -n '1p'`
  79. if [[ ! -z $endpoint ]]; then
  80. echo "$1_api_endpoint: $endpoint" >> "$CONGRESS_JSON_CONF_REUSABLES_PATH"
  81. _copy_congress_json_ingester_config $1
  82. fi
  83. }
  84. function _copy_congress_json_ingester_config {
  85. cp $CONGRESS_DIR/etc/sample_json_ingesters/$1.yaml $CONGRESS_JSON_CONF_DIR/
  86. }
  87. function configure_congress_datasources {
  88. if [ "$ENABLE_CONGRESS_JSON" == "True" ]; then
  89. _configure_congress_json_ingester cinderv3
  90. _configure_congress_json_ingester glance
  91. _configure_congress_json_ingester heat
  92. _configure_congress_json_ingester keystone
  93. _configure_congress_json_ingester magnum
  94. _configure_congress_json_ingester masakari
  95. _configure_congress_json_ingester mistral
  96. _configure_congress_json_ingester neutron
  97. _configure_congress_json_ingester nova
  98. _configure_congress_json_ingester tacker
  99. _configure_congress_json_ingester zun
  100. _copy_congress_json_ingester_config monasca
  101. _copy_congress_json_ingester_config cve
  102. if [ "$CONGRESS_MULTIPROCESS_DEPLOYMENT" == "False" ]; then
  103. restart_service devstack@congress.service
  104. echo "Waiting for Congress to restart..."
  105. if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$CONGRESS_HOST:$CONGRESS_PORT; do sleep 1; done"; then
  106. die $LINENO "Congress did not restart"
  107. fi
  108. else
  109. restart_service devstack@congress-datasources.service
  110. fi
  111. fi
  112. _configure_service neutron neutronv2
  113. _configure_service neutron-qos neutronv2_qos
  114. _configure_service nova nova
  115. _configure_service key keystonev3
  116. _configure_service cinder cinder
  117. _configure_service swift swift
  118. _configure_service glance glancev2
  119. _configure_service monasca monasca
  120. _configure_service murano murano
  121. _configure_service ironic ironic
  122. _configure_service heat heat
  123. _configure_service aodh aodh
  124. _configure_service mistral mistral
  125. _configure_service tacker tacker
  126. if [[ $ENABLE_CONGRESS_AGENT == "True" ]] ; then
  127. _configure_service congress-agent config
  128. fi
  129. }
  130. function _configure_tempest {
  131. # NOTE(gmann): Every service which are required by congress
  132. # CI/CD has to be explicitly set here on Tempest. Devstack
  133. # only set the Tempest in-tree configured service only which
  134. # are - [nova, keystone, cinder, glance, swift, glance, neutron].
  135. # service_available from Tempest plugin is not guaranteed to be
  136. # set correctly due to different env setup scenario, so it is
  137. # better to set it explicitly here.
  138. local service
  139. local required_services="heat,ironic,aodh,murano,mistral,monasca,neutron-qos,tacker"
  140. for service in ${required_services//,/ }; do
  141. if is_service_enabled $service ; then
  142. iniset $TEMPEST_CONFIG service_available $service "True"
  143. else
  144. iniset $TEMPEST_CONFIG service_available $service "False"
  145. fi
  146. done
  147. iniset $TEMPEST_CONFIG service_available congress "True"
  148. # Notify tempest if z3 is enabled.
  149. if [[ $ENABLE_CONGRESS_Z3 == "True" ]] ; then
  150. iniset $TEMPEST_CONFIG congressz3 enabled "True"
  151. fi
  152. # Set feature flags
  153. # (remove when Queens no longer supported)
  154. iniset $TEMPEST_CONFIG congress-feature-enabled monasca_webhook "True"
  155. iniset $TEMPEST_CONFIG congress-feature-enabled vitrage_webhook "True"
  156. }
  157. function _configure_service {
  158. if is_service_enabled $1; then
  159. if [ "$2" == "config" ] ; then
  160. openstack congress datasource create $2 "$2" \
  161. --config poll_time=10
  162. else
  163. openstack congress datasource create $2 "$2" \
  164. --config poll_time=10 \
  165. --config username=$OS_USERNAME \
  166. --config tenant_name=$OS_PROJECT_NAME \
  167. --config password=$OS_PASSWORD \
  168. --config auth_url=http://$SERVICE_HOST/identity
  169. fi
  170. fi
  171. }
  172. function create_predefined_policy {
  173. if [ -n "$CONGRESS_PREDEFINED_POLICY_FILE" ] ; then
  174. python $CONGRESS_DIR/scripts/preload-policies/output_policy_command.py \
  175. $CONGRESS_PREDEFINED_POLICY_FILE | while read CONGRESS_CMD
  176. do
  177. $CONGRESS_CMD
  178. done
  179. fi
  180. }
  181. function _install_congress_dashboard {
  182. git_clone $CONGRESSDASHBOARD_REPO $CONGRESSDASHBOARD_DIR $CONGRESSDASHBOARD_BRANCH
  183. setup_develop $CONGRESSDASHBOARD_DIR
  184. _congress_setup_horizon
  185. }
  186. function _install_z3 {
  187. if [[ $USE_Z3_RELEASE != None ]]; then
  188. mkdir -p $CONGRESS_Z3_DIR
  189. pushd $CONGRESS_Z3_DIR
  190. z3rel="z3-${USE_Z3_RELEASE}"
  191. z3file="${z3rel}-x64-${os_VENDOR,,}-${os_RELEASE}"
  192. # binary not available for ubuntu-18, so use ubuntu-16 binary instead
  193. if [ ${os_VENDOR,,} == "ubuntu" ] && [ ${os_RELEASE} == "18.04" ]; then
  194. z3file="${z3rel}-x64-ubuntu-16.04"
  195. echo "WARNING: Using ${z3file} binary on ${os_VENDOR,,}-${os_RELEASE} because ${z3rel}-x64-${os_VENDOR,,}-${os_RELEASE} is not available."
  196. fi
  197. url="https://github.com/Z3Prover/z3/releases/download/${z3rel}/${z3file}.zip"
  198. if [ ! -f "${z3file}.zip" ]; then
  199. wget "${url}" || true
  200. fi
  201. if [ ! -f "${z3file}.zip" ]; then
  202. echo "Failed to download z3 release ${USE_Z3_RELEASE} for ${os_VENDOR}-${os_RELEASE}"
  203. exit 1
  204. fi
  205. unzip -o "${z3file}.zip" "${z3file}/bin/python/z3/*" "${z3file}/bin/libz3.so"
  206. dist_dir=$($PYTHON -c "import site; print(site.getsitepackages()[0])")
  207. sudo cp -r "${z3file}/bin/python/z3" "${dist_dir}"
  208. sudo mkdir -p "${dist_dir}/z3/lib"
  209. sudo cp "${z3file}/bin/libz3.so" /usr/lib
  210. sudo ln -s /usr/lib/libz3.so "${dist_dir}/z3/lib/libz3.so"
  211. popd
  212. else
  213. git_clone $CONGRESS_Z3_REPO $CONGRESS_Z3_DIR $CONGRESS_Z3_BRANCH
  214. pushd $CONGRESS_Z3_DIR
  215. ${PYTHON} scripts/mk_make.py --python
  216. cd build
  217. make
  218. sudo make install
  219. popd
  220. fi
  221. }
  222. function _uninstall_z3 {
  223. if [[ $USE_Z3_RELEASE != None ]]; then
  224. sudo rm /usr/lib/libz3.so
  225. dist_dir=$($PYTHON -c "import site; print(site.getsitepackages()[0])")
  226. # Double check we are removing what we must remove.
  227. if [ -f "${dist_dir}/z3/z3core.py" ]; then
  228. sudo rm -rf "${dist_dir}/z3"
  229. fi
  230. else
  231. pushd $CONGRESS_Z3_DIR
  232. cd build
  233. sudo make uninstall
  234. popd
  235. fi
  236. }
  237. # create_congress_cache_dir() - Part of the _congress_setup_keystone() process
  238. function create_congress_cache_dir {
  239. # Create cache dir
  240. sudo mkdir -p $CONGRESS_AUTH_CACHE_DIR
  241. sudo chown $STACK_USER $CONGRESS_AUTH_CACHE_DIR
  242. rm -f $CONGRESS_AUTH_CACHE_DIR/*
  243. }
  244. # create_congress_accounts() - Set up common required congress accounts
  245. # Tenant User Roles
  246. # ---------------------------------------------------------------------
  247. # service congress admin # if enabled
  248. # Migrated from keystone_data.sh
  249. function create_congress_accounts {
  250. if [[ "$ENABLED_SERVICES" =~ "congress" ]]; then
  251. create_service_user "congress"
  252. local congress_service=$(get_or_create_service "congress" \
  253. "policy" "Congress Service")
  254. get_or_create_endpoint $congress_service \
  255. "$REGION_NAME" \
  256. "http://$SERVICE_HOST:$CONGRESS_PORT/" \
  257. "http://$SERVICE_HOST:$CONGRESS_PORT/" \
  258. "http://$SERVICE_HOST:$CONGRESS_PORT/"
  259. fi
  260. }
  261. # init_congress() - Initialize databases, etc.
  262. function init_congress {
  263. recreate_database $CONGRESS_DB_NAME utf8
  264. if [ "$ENABLE_CONGRESS_JSON" == "True" ]; then
  265. if [ ${DATABASE_TYPE,,} != "postgresql" ]; then
  266. # setup separate postgres db if main is not already postgres
  267. install_database_postgresql
  268. install_database_python_postgresql
  269. configure_database_postgresql
  270. fi
  271. recreate_database_postgresql $CONGRESS_JSON_DB_NAME utf8
  272. psql --set=ingester_role="$CONGRESS_JSON_INGESTER_ROLE" \
  273. --set=user_role="$CONGRESS_JSON_USER_ROLE" \
  274. --set=db_name="$CONGRESS_JSON_DB_NAME" \
  275. $CONGRESS_JSON_DB_CONNECTION_URL \
  276. -f $CONGRESS_DIR/scripts/jgress/setup_permissions.sql
  277. fi
  278. # Run Congress db migrations
  279. congress-db-manage --config-file $CONGRESS_CONF upgrade head
  280. }
  281. function install_congress_pythonclient() {
  282. # For using non-released client from git branch, need to add
  283. # LIBS_FROM_GIT=python-congressclient parameter to localrc.
  284. # Otherwise, congress will install python-congressclient from requirements.
  285. if use_library_from_git "python-congressclient"; then
  286. git_clone_by_name "python-congressclient"
  287. setup_dev_lib "python-congressclient"
  288. fi
  289. }
  290. # install_congress() - install dependency, collect client source and prepare
  291. function install_congress {
  292. install_congress_pythonclient
  293. if is_service_enabled horizon; then
  294. _install_congress_dashboard
  295. fi
  296. if [[ $ENABLE_CONGRESS_Z3 == "True" ]] ; then
  297. _install_z3
  298. fi
  299. }
  300. # Start running processes, including screen
  301. function start_congress_service_and_check {
  302. # build config-file options
  303. local cfg_file
  304. local CFG_FILE_OPTIONS="--config-file $CONGRESS_CONF"
  305. # Start the congress services in separate processes
  306. echo_summary "Installing congress services"
  307. if [ "$CONGRESS_MULTIPROCESS_DEPLOYMENT" == "False" ]; then
  308. echo "Installing congress as single process"
  309. run_process congress "$CONGRESS_BIN_DIR/congress-server --node-id=allinonenode $CFG_FILE_OPTIONS"
  310. else
  311. echo "Installing congress as multi process"
  312. run_process congress-api "$CONGRESS_BIN_DIR/congress-server --api --node-id=apinode $CFG_FILE_OPTIONS"
  313. run_process congress-engine "$CONGRESS_BIN_DIR/congress-server --policy-engine --node-id=enginenode $CFG_FILE_OPTIONS"
  314. run_process congress-datasources "$CONGRESS_BIN_DIR/congress-server --datasources --node-id=datanode $CFG_FILE_OPTIONS"
  315. fi
  316. # Start multiple PE's
  317. if [ "$CONGRESS_REPLICATED" == "True" ]; then
  318. run_process congress-engine "$CONGRESS_BIN_DIR/congress-server --policy-engine --node-id=enginenode-2 $CFG_FILE_OPTIONS"
  319. run_process congress-engine "$CONGRESS_BIN_DIR/congress-server --policy-engine --node-id=enginenode-3 $CFG_FILE_OPTIONS"
  320. fi
  321. echo "Waiting for Congress to start..."
  322. if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$CONGRESS_HOST:$CONGRESS_PORT; do sleep 1; done"; then
  323. die $LINENO "Congress did not start"
  324. fi
  325. # Expose encryption key to tempest test launched replica instances
  326. # WARNING: this setting deploys an insecure setup meant for gate-test only
  327. # Explanation: congress_tempest_tests/tests/scenario/congress_ha/test_ha.py
  328. # launches replica congress instances from a different user than the
  329. # original devstack-launched instance. Hence, the encryption keys need
  330. # to be exposed to additional users for the test to work as intended.
  331. # Note: This works correctly only for default encryption key location
  332. # /etc/congress/keys
  333. # If needed in future, this script can read custom key location from
  334. # $CONGRESS_CONF and adjust accordingly
  335. if [ "$CONGRESS_EXPOSE_ENCRYPTION_KEY_FOR_TEST" == "True" ]; then
  336. # Datasource service starts later than api service, so wait until datasource service fully started.
  337. if ! timeout $SERVICE_TIMEOUT sh -c "while [ ! -f /etc/congress/keys/aes_key ]; do sleep 1; done"; then
  338. die $LINENO "Unexpected error in key file creation"
  339. fi
  340. chmod a+rx /etc/congress/keys
  341. chmod a+r /etc/congress/keys/aes_key
  342. fi
  343. }
  344. function _wait_for_congress {
  345. echo "Waiting for Congress to start..."
  346. if ! timeout $SERVICE_TIMEOUT sh -c "while ! wget --no-proxy -q -O- http://$CONGRESS_HOST:$CONGRESS_PORT; do sleep 1; done"; then
  347. die $LINENO "Congress did not start"
  348. fi
  349. }
  350. # stop_congress() - Stop running processes (non-screen)
  351. function stop_congress {
  352. :
  353. }
  354. # cleanup_congress() - Remove residual data files, anything left over from previous
  355. # runs that would need to clean up.
  356. function cleanup_congress {
  357. sudo rm -rf $CONGRESS_AUTH_CACHE_DIR $CONGRESS_CONF_DIR
  358. if [[ $ENABLE_CONGRESS_Z3 == "True" ]] ; then
  359. _uninstall_z3
  360. fi
  361. }
  362. # Configures keystone integration for congress service
  363. function _congress_setup_keystone {
  364. local conf_file=$1
  365. local section=$2
  366. local use_auth_url=$3
  367. if [[ -z $skip_auth_cache ]]; then
  368. iniset $conf_file $section signing_dir $CONGRESS_AUTH_CACHE_DIR
  369. # Create cache dir
  370. create_congress_cache_dir
  371. fi
  372. configure_auth_token_middleware $conf_file $CONGRESS_ADMIN_USERNAME $CONGRESS_AUTH_CACHE_DIR $section
  373. }
  374. # Set up Horizon integration with Congress
  375. function _congress_setup_horizon {
  376. # Dashboard panels
  377. ln -fs $CONGRESSDASHBOARD_DIR/congress_dashboard/enabled/_50_policy.py $HORIZON_DIR/openstack_dashboard/local/enabled/
  378. ln -fs $CONGRESSDASHBOARD_DIR/congress_dashboard/enabled/_60_policies.py $HORIZON_DIR/openstack_dashboard/local/enabled/
  379. ln -fs $CONGRESSDASHBOARD_DIR/congress_dashboard/enabled/_70_datasources.py $HORIZON_DIR/openstack_dashboard/local/enabled/
  380. ln -fs $CONGRESSDASHBOARD_DIR/congress_dashboard/enabled/_75_monitoring.py $HORIZON_DIR/openstack_dashboard/local/enabled/
  381. ln -fs $CONGRESSDASHBOARD_DIR/congress_dashboard/enabled/_80_library.py $HORIZON_DIR/openstack_dashboard/local/enabled/
  382. # Restart Horizon
  383. restart_apache_server
  384. }
  385. function start_cfg_validator_agent {
  386. echo "Launching congress config agent"
  387. run_process congress-agent "$CONGRESS_BIN_DIR/congress-cfg-validator-agt --config-file $CONGRESS_AGT_CONF"
  388. }
  389. function configure_cfg_validator_agent {
  390. if ! is_service_enabled congress; then
  391. setup_develop $CONGRESS_DIR
  392. fi
  393. if [[ ! -d $CONGRESS_CONF_DIR ]]; then
  394. sudo mkdir -p $CONGRESS_CONF_DIR
  395. fi
  396. sudo chown $STACK_USER $CONGRESS_CONF_DIR
  397. touch $CONGRESS_AGT_CONF
  398. sudo chown $STACK_USER $CONGRESS_AGT_CONF
  399. iniset_rpc_backend cfg-validator $CONGRESS_AGT_CONF
  400. iniset $CONGRESS_AGT_CONF DEFAULT debug $ENABLE_DEBUG_LOG_LEVEL
  401. iniset $CONGRESS_AGT_CONF agent host $(hostname)
  402. iniset $CONGRESS_AGT_CONF agent version pike
  403. if is_service_enabled nova; then
  404. VALIDATOR_SERVICES+="nova: { ${NOVA_CONF}:${NOVA_DIR}/etc/nova/nova-config-generator.conf },"
  405. fi
  406. if is_service_enabled neutron; then
  407. VALIDATOR_SERVICES+="neutron: { ${NEUTRON_CONF}:${NEUTRON_DIR}/etc/oslo-config-generator/neutron.conf },"
  408. fi
  409. if is_service_enabled congress; then
  410. VALIDATOR_SERVICES+="congress: { ${CONGRESS_CONF}:${CONGRESS_DIR}/etc/congress-config-generator.conf },"
  411. fi
  412. if [[ ! -z VALIDATOR_SERVICES ]]; then
  413. iniset $CONGRESS_AGT_CONF agent services "${VALIDATOR_SERVICES%?}"
  414. fi
  415. }
  416. # Main dispatcher
  417. #----------------
  418. if is_service_enabled congress || is_service_enabled congress-agent; then
  419. if [[ "$1" == "stack" ]]; then
  420. if [[ "$2" == "install" ]]; then
  421. echo_summary "Installing Congress"
  422. install_congress
  423. elif [[ "$2" == "post-config" ]]; then
  424. if is_service_enabled congress; then
  425. echo_summary "Configuring Congress"
  426. configure_congress
  427. if is_service_enabled key; then
  428. create_congress_accounts
  429. fi
  430. fi
  431. if is_service_enabled congress-agent; then
  432. echo_summary "Configuring Validator agent"
  433. configure_cfg_validator_agent
  434. fi
  435. elif [[ "$2" == "extra" ]]; then
  436. if is_service_enabled congress; then
  437. # Initialize Congress
  438. init_congress
  439. # Start the congress API and Congress taskmgr components
  440. echo_summary "Starting Congress"
  441. start_congress_service_and_check
  442. configure_congress_datasources
  443. create_predefined_policy
  444. fi
  445. if is_service_enabled congress-agent; then
  446. echo_summary "Starting Validator agent"
  447. start_cfg_validator_agent
  448. fi
  449. elif [[ "$2" == "test-config" ]]; then
  450. if is_service_enabled tempest; then
  451. # Configure Tempest for Congress
  452. _configure_tempest
  453. fi
  454. fi
  455. fi
  456. if [[ "$1" == "unstack" ]]; then
  457. stop_congress
  458. fi
  459. if [[ "$1" == "clean" ]]; then
  460. cleanup_congress
  461. fi
  462. fi
  463. # Restore xtrace
  464. $XTRACE