diff --git a/doc/source/contributor/versions.rst b/doc/source/contributor/versions.rst index da02236f84..2d9bdbac6f 100644 --- a/doc/source/contributor/versions.rst +++ b/doc/source/contributor/versions.rst @@ -47,7 +47,7 @@ information about package sources. .. _`Team RabbitMQ 'Cloudsmith' repo (Deb)`: https://www.rabbitmq.com/install-debian.html#apt-cloudsmith .. _`Team RabbitMQ 'Modern Erlang' PPA`: https://launchpad.net/~rabbitmq/+archive/ubuntu/rabbitmq-erlang .. _`Team RabbitMQ 'Cloudsmith' repo (RPM)`: https://www.rabbitmq.com/docs/install-rpm#cloudsmith -.. _`openstack-kolla COPR`: https://copr.fedorainfracloud.org/coprs/g/openstack-kolla/rabbitmq-erlang/ +.. _`openstack-kolla COPR`: https://copr.fedorainfracloud.org/coprs/g/openstack-kolla/rabbitmq-erlang-26/ .. _`Grafana install guide`: https://grafana.com/grafana/download?platform=linux&edition=oss .. _`MariaDB Community downloads`: https://mariadb.com/downloads/community/ diff --git a/docker/base/Dockerfile.j2 b/docker/base/Dockerfile.j2 index 1bb24ceb90..5aec1d230a 100644 --- a/docker/base/Dockerfile.j2 +++ b/docker/base/Dockerfile.j2 @@ -75,7 +75,8 @@ COPY dnf.conf /etc/dnf/dnf.conf {% elif base_arch == 'aarch64' %} {% set base_yum_repo_files = base_yum_repo_files + [ - 'copr-rabbitmq-erlang.repo', + 'copr-rabbitmq-erlang-26.repo', + 'copr-rabbitmq-erlang-27.repo', ] %} {# diff --git a/docker/base/copr-rabbitmq-erlang.repo b/docker/base/copr-rabbitmq-erlang-26.repo similarity index 65% rename from docker/base/copr-rabbitmq-erlang.repo rename to docker/base/copr-rabbitmq-erlang-26.repo index 17df94d9d0..168748bb30 100644 --- a/docker/base/copr-rabbitmq-erlang.repo +++ b/docker/base/copr-rabbitmq-erlang-26.repo @@ -2,10 +2,10 @@ # from https://github.com/rabbitmq/erlang-rpm/ # Thanks to COPR we have aarch64 packages for Rocky Linux -[copr-rabbitmq-erlang] -name=openstack-kolla COPR with Erlang build for RabbitMQ -baseurl=https://download.copr.fedorainfracloud.org/results/@openstack-kolla/rabbitmq-erlang/rhel-$releasever-aarch64/ +[copr-rabbitmq-erlang-26] +name=openstack-kolla COPR with Erlang 26 build for RabbitMQ +baseurl=https://download.copr.fedorainfracloud.org/results/@openstack-kolla/rabbitmq-erlang-26/rhel-$releasever-aarch64/ gpgcheck=1 enabled=0 -gpgkey=https://download.copr.fedorainfracloud.org/results/@openstack-kolla/rabbitmq-erlang/pubkey.gpg +gpgkey=https://download.copr.fedorainfracloud.org/results/@openstack-kolla/rabbitmq-erlang-26/pubkey.gpg repo_gpgcheck=0 diff --git a/docker/base/copr-rabbitmq-erlang-27.repo b/docker/base/copr-rabbitmq-erlang-27.repo new file mode 100644 index 0000000000..a146d604d2 --- /dev/null +++ b/docker/base/copr-rabbitmq-erlang-27.repo @@ -0,0 +1,11 @@ +# NOTE(hrw): this repository contains rebuild of Erlang package from RabbitMQ team +# from https://github.com/rabbitmq/erlang-rpm/ +# Thanks to COPR we have aarch64 packages for Rocky Linux + +[copr-rabbitmq-erlang-27] +name=openstack-kolla COPR with Erlang 27 build for RabbitMQ +baseurl=https://download.copr.fedorainfracloud.org/results/@openstack-kolla/rabbitmq-erlang-27/rhel-$releasever-aarch64/ +gpgcheck=1 +enabled=0 +gpgkey=https://download.copr.fedorainfracloud.org/results/@openstack-kolla/rabbitmq-erlang-27/pubkey.gpg +repo_gpgcheck=0 diff --git a/docker/base/mariadb.repo b/docker/base/mariadb.repo index 4c03f4f404..07d97ef205 100644 --- a/docker/base/mariadb.repo +++ b/docker/base/mariadb.repo @@ -1,6 +1,6 @@ [mariadb] name = MariaDB Server -baseurl = https://dlm.mariadb.com/repo/mariadb-server/10.11.11/yum/rhel/$releasever/$basearch +baseurl = https://dlm.mariadb.com/repo/mariadb-server/10.11/yum/rhel/$releasever/$basearch gpgcheck = 1 enabled = 0 module_hotfixes = 1 diff --git a/docker/base/set_configs.py b/docker/base/set_configs.py index ab5b8c68bd..80c32e5077 100644 --- a/docker/base/set_configs.py +++ b/docker/base/set_configs.py @@ -68,6 +68,10 @@ class ConfigFileCommandDiffers(ExitingException): pass +class StateMismatch(ExitingException): + pass + + class ConfigFile(object): def __init__(self, source, dest, owner=None, perm=None, optional=False, @@ -583,6 +587,56 @@ def execute_command_check(config): def execute_config_check(config): + """Check configuration state consistency and validate config file entries. + + This function compares the current config file destinations from the + provided config dictionary with those stored in the defaults state file. + If any destinations are found in the state file but not in the config, + a StateMismatch exception is raised. These missing files would otherwise + be restored or removed depending on their backup state. + + After validating consistency, the function performs standard checks on + each declared configuration file, including content, permissions, and + ownership validation. + + Args: + config (dict): The configuration dictionary containing 'config_files' + entries as expected by Kolla. + + Raises: + StateMismatch: If there are entries in the defaults state not present + in the provided config. + """ + state = get_defaults_state() + + # Build a set of all current destination paths from config.json + # If the destination is a directory, we append the + # basename of the source + current_dests = { + entry['dest'] if not entry['dest'].endswith('/') else + os.path.join(entry['dest'], os.path.basename(entry['source'])) + for entry in config.get('config_files', []) + if entry.get('dest') + } + + # Detect any paths that are present in the state file but + # missing from config.json. + # These would be either restored (if state[dest] has a backup) + # or removed (if dest is null) + removed_dests = [ + path for path in state.keys() + if path not in current_dests + ] + + if removed_dests: + raise StateMismatch( + f"The following config files are tracked in state but missing " + f"from config.json. " + f"They would be restored or removed: {sorted(removed_dests)}" + ) + + # Perform the regular content, permissions, and ownership + # checks on the declared files for data in config.get('config_files', []): config_file = ConfigFile(**data) config_file.check() diff --git a/kolla/template/repos.yaml b/kolla/template/repos.yaml index f733afca3c..efeedd5e2d 100644 --- a/kolla/template/repos.yaml +++ b/kolla/template/repos.yaml @@ -23,7 +23,8 @@ centos-aarch64: crb: "crb" docker-ce: "docker-ce" epel: "epel" - erlang: "copr-rabbitmq-erlang" + erlang-26: "copr-rabbitmq-erlang-26" + erlang-27: "copr-rabbitmq-erlang-27" extras: "extras" fluentd: "fluent-package-lts" grafana: "grafana" @@ -72,7 +73,7 @@ debian: component: "stable" gpg_key: "influxdb.asc" mariadb: - url: "https://dlm.mariadb.com/repo/mariadb-server/10.11.11/repo/debian" + url: "https://dlm.mariadb.com/repo/mariadb-server/10.11/repo/debian" suite: "bookworm" component: "main" gpg_key: "mariadb.gpg" @@ -129,7 +130,7 @@ debian-aarch64: component: "stable" gpg_key: "influxdb.asc" mariadb: - url: "https://dlm.mariadb.com/repo/mariadb-server/10.11.11/repo/debian" + url: "https://dlm.mariadb.com/repo/mariadb-server/10.11/repo/debian" suite: "bookworm" component: "main" gpg_key: "mariadb.gpg" @@ -181,7 +182,8 @@ rocky-aarch64: crb: "crb" docker-ce: "docker-ce" epel: "epel" - erlang: "copr-rabbitmq-erlang" + erlang-26: "copr-rabbitmq-erlang-26" + erlang-27: "copr-rabbitmq-erlang-27" extras: "extras" fluentd: "fluent-package-lts" grafana: "grafana" @@ -203,12 +205,12 @@ ubuntu: gpg_key: "docker-ce.asc" erlang-26: url: "https://ppa.launchpadcontent.net/rabbitmq/rabbitmq-erlang-26/ubuntu" - suite: "jammy" + suite: "noble" component: "main" gpg_key: "erlang-ppa.gpg" erlang-27: url: "https://ppa.launchpadcontent.net/rabbitmq/rabbitmq-erlang-27/ubuntu" - suite: "jammy" + suite: "noble" component: "main" gpg_key: "erlang-ppa.gpg" fluentd: @@ -228,7 +230,7 @@ ubuntu: component: "stable" gpg_key: "influxdb.asc" mariadb: - url: "https://dlm.mariadb.com/repo/mariadb-server/10.11.11/repo/ubuntu" + url: "https://dlm.mariadb.com/repo/mariadb-server/10.11/repo/ubuntu" suite: "noble" component: "main" gpg_key: "mariadb.gpg" @@ -261,12 +263,12 @@ ubuntu-aarch64: gpg_key: "docker-ce.asc" erlang-26: url: "https://ppa.launchpadcontent.net/rabbitmq/rabbitmq-erlang-26/ubuntu" - suite: "jammy" + suite: "noble" component: "main" gpg_key: "erlang-ppa.gpg" erlang-27: url: "https://ppa.launchpadcontent.net/rabbitmq/rabbitmq-erlang-27/ubuntu" - suite: "jammy" + suite: "noble" component: "main" gpg_key: "erlang-ppa.gpg" fluentd: @@ -286,7 +288,7 @@ ubuntu-aarch64: component: "stable" gpg_key: "influxdb.asc" mariadb: - url: "https://dlm.mariadb.com/repo/mariadb-server/10.11.11/repo/ubuntu" + url: "https://dlm.mariadb.com/repo/mariadb-server/10.11/repo/ubuntu" suite: "noble" component: "main" gpg_key: "mariadb.gpg" diff --git a/releasenotes/notes/bug-2114173-70d0b815a42ae239.yaml b/releasenotes/notes/bug-2114173-70d0b815a42ae239.yaml new file mode 100644 index 0000000000..29349be97f --- /dev/null +++ b/releasenotes/notes/bug-2114173-70d0b815a42ae239.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes set_configs.py not detecting removed config files + during --check, which prevented container restart when + needed. `LP#2114173 `__ diff --git a/releasenotes/notes/erlang-aarch64-versioned-repos-9b1d2c8b8b7a.yaml b/releasenotes/notes/erlang-aarch64-versioned-repos-9b1d2c8b8b7a.yaml new file mode 100644 index 0000000000..e535af4cfd --- /dev/null +++ b/releasenotes/notes/erlang-aarch64-versioned-repos-9b1d2c8b8b7a.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Switches Erlang RPMs on aarch64 to a versioned Erlang 26 or 27 repository, + due to Fedora COPR not supporting multiple package versions in one repo. diff --git a/tests/test_set_config.py b/tests/test_set_config.py index 3b528e4459..6f3f39c746 100644 --- a/tests/test_set_config.py +++ b/tests/test_set_config.py @@ -875,3 +875,47 @@ def test_handle_defaults_state_exist_config_restored( # Verify that the updated state was saved mock_set_defaults_state.assert_called_once_with(expected_state) + + +class ExecuteConfigCheckStateMismatchTest(base.BaseTestCase): + + @mock.patch.object(set_configs, 'get_defaults_state') + def test_execute_config_check_raises_state_mismatch( + self, mock_get_defaults_state + ): + """Test execute_config_check() when state has extra config file. + + This test simulates the scenario where the state file contains + a destination that no longer exists in config.json. It verifies: + - get_defaults_state() returns a state with an extra entry. + - execute_config_check() raises StateMismatch when config.json + omits a tracked destination. + """ + config = { + "command": "/bin/true", + "config_files": [ + { + "source": "/etc/foo/foo.conf", + "dest": "/etc/foo/foo.conf", + "owner": "user1", + "perm": "0644" + } + ] + } + + mock_get_defaults_state.return_value = { + "/etc/foo/foo.conf": { + "source": "/etc/foo/foo.conf", + "preserve_properties": True, + "dest": "/etc/kolla/defaults/etc/foo/foo.conf" + }, + "/etc/old/obsolete.conf": { + "source": "/etc/old/obsolete.conf", + "preserve_properties": True, + "dest": "/etc/kolla/defaults/etc/old/obsolete.conf" + } + } + + self.assertRaises(set_configs.StateMismatch, + set_configs.execute_config_check, + config)