Merge "Display backup dashboard on Horizon when c-bak is enabled"
diff --git a/.zuul.yaml b/.zuul.yaml
index 8bc0823..294dd48 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -644,6 +644,11 @@
description: Rocky Linux 9 Blue Onyx platform test
nodeset: devstack-single-node-rockylinux-9
timeout: 9000
+ # NOTE(danms): This has been failing lately with some repository metadata
+ # errors. We're marking this as non-voting until it appears to have
+ # stabilized:
+ # https://zuul.openstack.org/builds?job_name=devstack-platform-rocky-blue-onyx&skip=0
+ voting: false
vars:
configure_swap_size: 4096
@@ -887,7 +892,9 @@
- devstack-ipv6
- devstack-platform-debian-bookworm
- devstack-platform-debian-bullseye
- - devstack-platform-rocky-blue-onyx
+ # NOTE(danms): Disabled due to instability, see comment in the job
+ # definition above.
+ # - devstack-platform-rocky-blue-onyx
- devstack-enforce-scope
- devstack-multinode
- devstack-unit-tests
diff --git a/doc/source/plugin-registry.rst b/doc/source/plugin-registry.rst
index 2d2a92c..21cf52c 100644
--- a/doc/source/plugin-registry.rst
+++ b/doc/source/plugin-registry.rst
@@ -37,7 +37,6 @@
openstack/devstack-plugin-kafka `https://opendev.org/openstack/devstack-plugin-kafka <https://opendev.org/openstack/devstack-plugin-kafka>`__
openstack/devstack-plugin-nfs `https://opendev.org/openstack/devstack-plugin-nfs <https://opendev.org/openstack/devstack-plugin-nfs>`__
openstack/devstack-plugin-open-cas `https://opendev.org/openstack/devstack-plugin-open-cas <https://opendev.org/openstack/devstack-plugin-open-cas>`__
-openstack/ec2-api `https://opendev.org/openstack/ec2-api <https://opendev.org/openstack/ec2-api>`__
openstack/freezer `https://opendev.org/openstack/freezer <https://opendev.org/openstack/freezer>`__
openstack/freezer-api `https://opendev.org/openstack/freezer-api <https://opendev.org/openstack/freezer-api>`__
openstack/freezer-tempest-plugin `https://opendev.org/openstack/freezer-tempest-plugin <https://opendev.org/openstack/freezer-tempest-plugin>`__
@@ -62,7 +61,6 @@
openstack/monasca-api `https://opendev.org/openstack/monasca-api <https://opendev.org/openstack/monasca-api>`__
openstack/monasca-events-api `https://opendev.org/openstack/monasca-events-api <https://opendev.org/openstack/monasca-events-api>`__
openstack/monasca-tempest-plugin `https://opendev.org/openstack/monasca-tempest-plugin <https://opendev.org/openstack/monasca-tempest-plugin>`__
-openstack/murano `https://opendev.org/openstack/murano <https://opendev.org/openstack/murano>`__
openstack/networking-bagpipe `https://opendev.org/openstack/networking-bagpipe <https://opendev.org/openstack/networking-bagpipe>`__
openstack/networking-baremetal `https://opendev.org/openstack/networking-baremetal <https://opendev.org/openstack/networking-baremetal>`__
openstack/networking-bgpvpn `https://opendev.org/openstack/networking-bgpvpn <https://opendev.org/openstack/networking-bgpvpn>`__
@@ -84,12 +82,8 @@
openstack/ovn-bgp-agent `https://opendev.org/openstack/ovn-bgp-agent <https://opendev.org/openstack/ovn-bgp-agent>`__
openstack/ovn-octavia-provider `https://opendev.org/openstack/ovn-octavia-provider <https://opendev.org/openstack/ovn-octavia-provider>`__
openstack/rally-openstack `https://opendev.org/openstack/rally-openstack <https://opendev.org/openstack/rally-openstack>`__
-openstack/sahara `https://opendev.org/openstack/sahara <https://opendev.org/openstack/sahara>`__
-openstack/sahara-dashboard `https://opendev.org/openstack/sahara-dashboard <https://opendev.org/openstack/sahara-dashboard>`__
-openstack/senlin `https://opendev.org/openstack/senlin <https://opendev.org/openstack/senlin>`__
openstack/shade `https://opendev.org/openstack/shade <https://opendev.org/openstack/shade>`__
openstack/skyline-apiserver `https://opendev.org/openstack/skyline-apiserver <https://opendev.org/openstack/skyline-apiserver>`__
-openstack/solum `https://opendev.org/openstack/solum <https://opendev.org/openstack/solum>`__
openstack/storlets `https://opendev.org/openstack/storlets <https://opendev.org/openstack/storlets>`__
openstack/tacker `https://opendev.org/openstack/tacker <https://opendev.org/openstack/tacker>`__
openstack/tap-as-a-service `https://opendev.org/openstack/tap-as-a-service <https://opendev.org/openstack/tap-as-a-service>`__
diff --git a/files/openstack-cli-server/openstack b/files/openstack-cli-server/openstack
new file mode 100755
index 0000000..ef05f1b
--- /dev/null
+++ b/files/openstack-cli-server/openstack
@@ -0,0 +1,119 @@
+#!/usr/bin/env python3
+# Copyright 2016 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import socket
+import sys
+import os
+import os.path
+import json
+
+server_address = "/tmp/openstack.sock"
+
+sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+
+try:
+ sock.connect(server_address)
+except socket.error as msg:
+ print(msg, file=sys.stderr)
+ sys.exit(1)
+
+
+def send(sock, doc):
+ jdoc = json.dumps(doc)
+ sock.send(b'%d\n' % len(jdoc))
+ sock.sendall(jdoc.encode('utf-8'))
+
+def recv(sock):
+ length_str = b''
+
+ char = sock.recv(1)
+ if len(char) == 0:
+ print("Unexpected end of file", file=sys.stderr)
+ sys.exit(1)
+
+ while char != b'\n':
+ length_str += char
+ char = sock.recv(1)
+ if len(char) == 0:
+ print("Unexpected end of file", file=sys.stderr)
+ sys.exit(1)
+
+ total = int(length_str)
+
+ # use a memoryview to receive the data chunk by chunk efficiently
+ jdoc = memoryview(bytearray(total))
+ next_offset = 0
+ while total - next_offset > 0:
+ recv_size = sock.recv_into(jdoc[next_offset:], total - next_offset)
+ next_offset += recv_size
+ try:
+ doc = json.loads(jdoc.tobytes())
+ except (TypeError, ValueError) as e:
+ raise Exception('Data received was not in JSON format')
+ return doc
+
+try:
+ env = {}
+ passenv = ["CINDER_VERSION",
+ "OS_AUTH_URL",
+ "OS_IDENTITY_API_VERSION",
+ "OS_NO_CACHE",
+ "OS_PASSWORD",
+ "OS_PROJECT_NAME",
+ "OS_REGION_NAME",
+ "OS_TENANT_NAME",
+ "OS_USERNAME",
+ "OS_VOLUME_API_VERSION",
+ "OS_CLOUD"]
+ for name in passenv:
+ if name in os.environ:
+ env[name] = os.environ[name]
+
+ cmd = {
+ "app": os.path.basename(sys.argv[0]),
+ "env": env,
+ "argv": sys.argv[1:]
+ }
+ try:
+ image_idx = sys.argv.index('image')
+ create_idx = sys.argv.index('create')
+ missing_file = image_idx < create_idx and \
+ not any(x.startswith('--file') for x in sys.argv)
+ except ValueError:
+ missing_file = False
+
+ if missing_file:
+ # This means we were called with an image create command, but were
+ # not provided a --file option. That likely means we're being passed
+ # the image data to stdin, which won't work because we do not proxy
+ # stdin to the server. So, we just reject the operation and ask the
+ # caller to provide the file with --file instead.
+ # We've already connected to the server, we need to send it some dummy
+ # data so it doesn't wait forever.
+ send(sock, {})
+ print('Image create without --file is not allowed in server mode',
+ file=sys.stderr)
+ sys.exit(1)
+ else:
+ send(sock, cmd)
+
+ doc = recv(sock)
+ if doc["stdout"] != b'':
+ print(doc["stdout"], end='')
+ if doc["stderr"] != b'':
+ print(doc["stderr"], file=sys.stderr)
+ sys.exit(doc["status"])
+finally:
+ sock.close()
diff --git a/files/openstack-cli-server/openstack-cli-server b/files/openstack-cli-server/openstack-cli-server
new file mode 100755
index 0000000..f3d2747
--- /dev/null
+++ b/files/openstack-cli-server/openstack-cli-server
@@ -0,0 +1,118 @@
+#!/usr/bin/env python3
+# Copyright 2016 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import socket
+import sys
+import os
+import json
+
+from openstackclient import shell as osc_shell
+from io import StringIO
+
+server_address = "/tmp/openstack.sock"
+
+try:
+ os.unlink(server_address)
+except OSError:
+ if os.path.exists(server_address):
+ raise
+
+sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+print('starting up on %s' % server_address, file=sys.stderr)
+sock.bind(server_address)
+
+# Listen for incoming connections
+sock.listen(1)
+
+def send(sock, doc):
+ jdoc = json.dumps(doc)
+ sock.send(b'%d\n' % len(jdoc))
+ sock.sendall(jdoc.encode('utf-8'))
+
+def recv(sock):
+ length_str = b''
+ char = sock.recv(1)
+ while char != b'\n':
+ length_str += char
+ char = sock.recv(1)
+
+ total = int(length_str)
+
+ # use a memoryview to receive the data chunk by chunk efficiently
+ jdoc = memoryview(bytearray(total))
+ next_offset = 0
+ while total - next_offset > 0:
+ recv_size = sock.recv_into(jdoc[next_offset:], total - next_offset)
+ next_offset += recv_size
+ try:
+ doc = json.loads(jdoc.tobytes())
+ except (TypeError, ValueError) as e:
+ raise Exception('Data received was not in JSON format')
+ return doc
+
+while True:
+ csock, client_address = sock.accept()
+ try:
+ doc = recv(csock)
+
+ print("%s %s" % (doc["app"], doc["argv"]), file=sys.stderr)
+ oldenv = {}
+ for name in doc["env"].keys():
+ oldenv[name] = os.environ.get(name, None)
+ os.environ[name] = doc["env"][name]
+
+ try:
+ old_stdout = sys.stdout
+ old_stderr = sys.stderr
+ my_stdout = sys.stdout = StringIO()
+ my_stderr = sys.stderr = StringIO()
+
+ class Exit(BaseException):
+ def __init__(self, status):
+ self.status = status
+
+ def noexit(stat):
+ raise Exit(stat)
+
+ sys.exit = noexit
+
+ if doc["app"] == "openstack":
+ sh = osc_shell.OpenStackShell()
+ ret = sh.run(doc["argv"])
+ else:
+ print("Unknown application %s" % doc["app"], file=sys.stderr)
+ ret = 1
+ except Exit as e:
+ ret = e.status
+ finally:
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+
+ for name in oldenv.keys():
+ if oldenv[name] is None:
+ del os.environ[name]
+ else:
+ os.environ[name] = oldenv[name]
+
+ send(csock, {
+ "stdout": my_stdout.getvalue(),
+ "stderr": my_stderr.getvalue(),
+ "status": ret,
+ })
+
+ except BaseException as e:
+ print(e, file=sys.stderr)
+ finally:
+ csock.close()
diff --git a/functions b/functions
index 01e1d25..f81e8f0 100644
--- a/functions
+++ b/functions
@@ -118,7 +118,7 @@
useimport="--import"
fi
- openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" --public --container-format "$container" --disk-format "$disk" $useimport $properties < "${image}"
+ openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name" --public --container-format "$container" --disk-format "$disk" $useimport $properties --file $(readlink -f "${image}")
}
# Retrieve an image from a URL and upload into Glance.
@@ -425,10 +425,10 @@
# kernel for use when uploading the root filesystem.
local kernel_id="" ramdisk_id="";
if [ -n "$kernel" ]; then
- kernel_id=$(openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name-kernel" $(_image_properties_to_arg $img_property) --public --container-format aki --disk-format aki < "$kernel" -f value -c id)
+ kernel_id=$(openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name-kernel" $(_image_properties_to_arg $img_property) --public --container-format aki --disk-format aki --file $(readlink -f "$kernel") -f value -c id)
fi
if [ -n "$ramdisk" ]; then
- ramdisk_id=$(openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name-ramdisk" $(_image_properties_to_arg $img_property) --public --container-format ari --disk-format ari < "$ramdisk" -f value -c id)
+ ramdisk_id=$(openstack --os-cloud=devstack-admin --os-region-name="$REGION_NAME" image create "$image_name-ramdisk" $(_image_properties_to_arg $img_property) --public --container-format ari --disk-format ari --file $(readlink -f "$ramdisk") -f value -c id)
fi
_upload_image "${image_name%.img}" ami ami "$image" ${kernel_id:+ kernel_id=$kernel_id} ${ramdisk_id:+ ramdisk_id=$ramdisk_id} $img_property
fi
diff --git a/functions-common b/functions-common
index 8ea6df7..84d281b 100644
--- a/functions-common
+++ b/functions-common
@@ -2438,6 +2438,11 @@
_TIME_TOTAL[$name]=$(($total + $elapsed_time))
}
+function install_openstack_cli_server {
+ export PATH=$TOP_DIR/files/openstack-cli-server:$PATH
+ run_process openstack-cli-server "$PYTHON $TOP_DIR/files/openstack-cli-server/openstack-cli-server"
+}
+
function oscwrap {
local xtrace
xtrace=$(set +o | grep xtrace)
diff --git a/lib/apache b/lib/apache
index a314b76..1420f76 100644
--- a/lib/apache
+++ b/lib/apache
@@ -345,15 +345,15 @@
# Set die-on-term & exit-on-reload so that uwsgi shuts down
iniset "$conf" uwsgi die-on-term true
iniset "$conf" uwsgi exit-on-reload false
+ # Set worker-reload-mercy so that worker will not exit till the time
+ # configured after graceful shutdown
+ iniset "$conf" uwsgi worker-reload-mercy $WORKER_TIMEOUT
iniset "$conf" uwsgi enable-threads true
iniset "$conf" uwsgi plugins http,python3
# uwsgi recommends this to prevent thundering herd on accept.
iniset "$conf" uwsgi thunder-lock true
# Set hook to trigger graceful shutdown on SIGTERM
iniset "$conf" uwsgi hook-master-start "unix_signal:15 gracefully_kill_them_all"
- # Set worker-reload-mercy so that worker will not exit till the time
- # configured after graceful shutdown
- iniset "$conf" uwsgi worker-reload-mercy $WORKER_TIMEOUT
# Override the default size for headers from the 4k default.
iniset "$conf" uwsgi buffer-size 65535
# Make sure the client doesn't try to re-use the connection.
@@ -402,8 +402,14 @@
local conf=$1
local wsgi=$2
local name=""
+ # TODO(stephenfin): Remove this call when everyone is using module path
+ # configuration instead of file path configuration
name=$(basename $wsgi)
+ if [[ "$wsgi" = /* ]]; then
+ deprecated "Passing a wsgi script to remove_uwsgi_config is deprecated, pass an application name instead"
+ fi
+
rm -rf $conf
disable_apache_site $name
}
diff --git a/lib/cinder b/lib/cinder
index f7824eb..ae898e9 100644
--- a/lib/cinder
+++ b/lib/cinder
@@ -275,7 +275,7 @@
fi
stop_process "c-api"
- remove_uwsgi_config "$CINDER_UWSGI_CONF" "$CINDER_UWSGI"
+ remove_uwsgi_config "$CINDER_UWSGI_CONF" "cinder-wsgi"
}
# configure_cinder() - Set config files, create data dirs, etc
diff --git a/lib/glance b/lib/glance
index 8ee8426..2746871 100644
--- a/lib/glance
+++ b/lib/glance
@@ -168,7 +168,7 @@
# Cleanup reserved stores directories
sudo rm -rf $GLANCE_STAGING_DIR $GLANCE_TASKS_DIR
fi
- remove_uwsgi_config "$GLANCE_UWSGI_CONF" "$GLANCE_UWSGI"
+ remove_uwsgi_config "$GLANCE_UWSGI_CONF" "glance-wsgi-api"
}
# Set multiple cinder store related config options for each of the cinder store
diff --git a/lib/keystone b/lib/keystone
index 6cb4aac..7d6b05f 100644
--- a/lib/keystone
+++ b/lib/keystone
@@ -150,7 +150,7 @@
sudo rm -f $(apache_site_config_for keystone)
else
stop_process "keystone"
- remove_uwsgi_config "$KEYSTONE_PUBLIC_UWSGI_CONF" "$KEYSTONE_PUBLIC_UWSGI"
+ remove_uwsgi_config "$KEYSTONE_PUBLIC_UWSGI_CONF" "keystone-wsgi-public"
sudo rm -f $(apache_site_config_for keystone-wsgi-public)
fi
}
diff --git a/lib/neutron b/lib/neutron
index bc77f16..ed854fd 100644
--- a/lib/neutron
+++ b/lib/neutron
@@ -823,7 +823,7 @@
if [ "$NEUTRON_DEPLOY_MOD_WSGI" == "True" ]; then
stop_process neutron-api
stop_process neutron-rpc-server
- remove_uwsgi_config "$NEUTRON_UWSGI_CONF" "$NEUTRON_BIN_DIR/neutron-api"
+ remove_uwsgi_config "$NEUTRON_UWSGI_CONF" "neutron-api"
sudo rm -f $(apache_site_config_for neutron-api)
fi
diff --git a/lib/nova b/lib/nova
index a261fac..ee3f29e 100644
--- a/lib/nova
+++ b/lib/nova
@@ -248,8 +248,8 @@
stop_process "n-api"
stop_process "n-api-meta"
- remove_uwsgi_config "$NOVA_UWSGI_CONF" "$NOVA_UWSGI"
- remove_uwsgi_config "$NOVA_METADATA_UWSGI_CONF" "$NOVA_METADATA_UWSGI"
+ remove_uwsgi_config "$NOVA_UWSGI_CONF" "nova-api"
+ remove_uwsgi_config "$NOVA_METADATA_UWSGI_CONF" "nova-metadata"
if [[ "$NOVA_BACKEND" == "LVM" ]]; then
clean_lvm_volume_group $DEFAULT_VOLUME_GROUP_NAME
diff --git a/lib/placement b/lib/placement
index c6bf99f..63fdfb6 100644
--- a/lib/placement
+++ b/lib/placement
@@ -68,7 +68,7 @@
# runs that a clean run would need to clean up
function cleanup_placement {
sudo rm -f $(apache_site_config_for placement-api)
- remove_uwsgi_config "$PLACEMENT_UWSGI_CONF" "$PLACEMENT_UWSGI"
+ remove_uwsgi_config "$PLACEMENT_UWSGI_CONF" "placement-api"
}
# _config_placement_apache_wsgi() - Set WSGI config files
diff --git a/releasenotes/notes/Fix-dbcounter-NotImplementedError-on-SQLAlchemy-2-21bb6dcdf3ce4225.yaml b/releasenotes/notes/Fix-dbcounter-NotImplementedError-on-SQLAlchemy-2-21bb6dcdf3ce4225.yaml
deleted file mode 100644
index f815e14..0000000
--- a/releasenotes/notes/Fix-dbcounter-NotImplementedError-on-SQLAlchemy-2-21bb6dcdf3ce4225.yaml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-fixes:
- - |
- Fixes a NotImplementedError when using the dbcounter SQLAlchemy plugin on
- SQLAlchemy 2.x.
diff --git a/stack.sh b/stack.sh
index c6652e5..0c36e10 100755
--- a/stack.sh
+++ b/stack.sh
@@ -1022,6 +1022,9 @@
setup_dev_lib "python-openstackclient"
else
pip_install_gr python-openstackclient
+ if is_service_enabled openstack-cli-server; then
+ install_openstack_cli_server
+ fi
fi
# Installs alias for osc so that we can collect timing for all
diff --git a/unstack.sh b/unstack.sh
index 33b069b..1b2d8dd 100755
--- a/unstack.sh
+++ b/unstack.sh
@@ -168,6 +168,10 @@
cleanup_etcd3
fi
+if is_service_enabled openstack-cli-server; then
+ stop_service devstack@openstack-cli-server
+fi
+
stop_dstat
# NOTE: Cinder automatically installs the lvm2 package, independently of the