From 61be9e722dc84c5b4fb8ce6848fd0ee46fd3d7da Mon Sep 17 00:00:00 2001 From: Andrew Bonney Date: Wed, 13 Nov 2024 09:14:38 +0000 Subject: [PATCH] Change ordering of /etc/ operations to improve upgrades This change matches an earlier modification to os_neutron Currently we symlink /etc/ to empty directory at pre-stage, and filling it with config only during post_install. This means, that policies and rootwrap filters are not working properly until playbook execution finish. Additionally, we replace sudoers file with new path in it, which makes current operations impossible for the service, since rootwrap can not gain sudo privileges. With this change we move symlinking and rootwrap steps to handlers, which means that we will do replace configs while service is stopped. During post_install we place all of the configs inside the venv, which is versioned at the moment. This way we minimise downtime of the service while performing upgrades Closes-Bug: #2056180 Change-Id: I9c8212408c21e09895ee5805011aecb40b689a13 --- defaults/main.yml | 6 +++--- handlers/main.yml | 24 ++++++++++++++++++++++++ tasks/nova_db_post_setup.yml | 4 ++-- tasks/nova_db_setup.yml | 16 ++++++++-------- tasks/nova_post_install.yml | 25 +++++++------------------ tasks/nova_pre_install.yml | 29 ++++------------------------- templates/nova.conf.j2 | 4 ++-- vars/main.yml | 9 ++++++--- 8 files changed, 56 insertions(+), 61 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9ca4193c..324878bd 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -330,7 +330,7 @@ nova_console_proxy_types: - "{{ nova_ironic_console_type }}" # Nova console ssl info, presently only used by novnc console type -nova_console_ssl_dir: "/etc/nova/ssl" +nova_console_ssl_dir: "{{ nova_system_home_folder }}/console_ssl" nova_console_ssl_cert: "{{ nova_console_ssl_dir }}/nova-console.pem" nova_console_ssl_key: "{{ nova_console_ssl_dir }}/nova-console.key" @@ -832,8 +832,8 @@ nova_pki_certificates: condition: "{{ nova_pki_certificates_condition | bool }}" # nova destination files for SSL certificates -nova_ssl_cert: /etc/nova/nova.pem -nova_ssl_key: /etc/nova/nova.key +nova_ssl_cert: "{{ nova_system_home_folder }}/nova.pem" +nova_ssl_key: "{{ nova_system_home_folder }}/nova.key" # Installation details for SSL certificates nova_pki_install_certificates: diff --git a/handlers/main.yml b/handlers/main.yml index 3c1337ac..9529b4ed 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -55,6 +55,30 @@ - "'nova_compute' in group_names" - nova_virt_type != 'ironic' +- name: Symlink nova config directory + file: + # NOTE(cloudnull): The "src" path is relative. This ensures all files remain + # within the host/container confines when connecting to + # them using the connection plugin or the root filesystem. + src: "{{ nova_conf_version_dir | regex_replace('^/', '../') }}" + dest: "{{ nova_conf_dir }}" + state: link + force: true + when: nova_install_method == 'source' + listen: + - "venv changed" + +- name: Drop sudoers file + template: + src: "sudoers.j2" + dest: "/etc/sudoers.d/{{ nova_system_user_name }}_sudoers" + mode: "0440" + owner: "root" + group: "root" + listen: + - "Restart nova services" + - "venv changed" + - name: Stop services service: name: "{{ item.service_name }}" diff --git a/tasks/nova_db_post_setup.yml b/tasks/nova_db_post_setup.yml index 910bf8b2..5a6a9a6d 100644 --- a/tasks/nova_db_post_setup.yml +++ b/tasks/nova_db_post_setup.yml @@ -21,7 +21,7 @@ # This needs to be done after Compute hosts are added. - name: Perform a cell_v2 discover command: >- - {{ _db_nova_bin }}/nova-manage cell_v2 discover_hosts{{ (debug | bool) | ternary(' --verbose', '') }}{{ + {{ _db_nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf cell_v2 discover_hosts{{ (debug | bool) | ternary(' --verbose', '') }}{{ (nova_ironic_used | bool) | ternary(' --by-service', '') }} become: yes become_user: "{{ _db_nova_system_user_name }}" @@ -34,7 +34,7 @@ # intervention is required to resolve the issue causing remaining updates to fail. # It should be considered successfully completed only when the exit status is 0. - name: Perform online data migrations - command: "{{ _db_nova_bin }}/nova-manage db online_data_migrations" + command: "{{ _db_nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf db online_data_migrations" become: yes become_user: "{{ _db_nova_system_user_name }}" changed_when: false diff --git a/tasks/nova_db_setup.yml b/tasks/nova_db_setup.yml index 8e3fac16..6060417a 100644 --- a/tasks/nova_db_setup.yml +++ b/tasks/nova_db_setup.yml @@ -14,7 +14,7 @@ # limitations under the License. - name: Synchronize the nova API DB schema - command: "{{ nova_bin }}/nova-manage api_db sync" + command: "{{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf api_db sync" become: yes become_user: "{{ nova_system_user_name }}" changed_when: false @@ -22,7 +22,7 @@ # We need to check for existance of the cell, since nova-manage cell_v2 create_cell # might be not idempotent due to the bug https://bugs.launchpad.net/nova/+bug/1923899 - name: Get UUID of Nova Cells - command: "{{ nova_bin }}/nova-manage cell_v2 list_cells" + command: "{{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf cell_v2 list_cells" become: yes become_user: "{{ nova_system_user_name }}" changed_when: false @@ -39,7 +39,7 @@ # it conditionally. - name: Create the cell0 mapping entry in the nova API DB command: >- - {{ nova_bin }}/nova-manage cell_v2 map_cell0 + {{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf cell_v2 map_cell0 --database_connection mysql+pymysql://{{ nova_api_galera_user }}:{{ nova_api_container_mysql_password }}@{{ nova_api_galera_address }}/{{ nova_cell0_database }}?charset=utf8{% if nova_galera_use_ssl | bool %}&ssl_verify_cert=true{% if nova_galera_ssl_ca_cert | length > 0 %}&ssl_ca={{ nova_galera_ssl_ca_cert }}{% endif %}{% endif %} @@ -51,7 +51,7 @@ - name: Update the cell0 mapping entry in the nova API DB command: >- - {{ nova_bin }}/nova-manage cell_v2 update_cell --cell_uuid 00000000-0000-0000-0000-000000000000 + {{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf cell_v2 update_cell --cell_uuid 00000000-0000-0000-0000-000000000000 --database_connection mysql+pymysql://{{ nova_api_galera_user }}:{{ nova_api_container_mysql_password }}@{{ nova_api_galera_address }}/{{ nova_cell0_database }}?charset=utf8{% if nova_galera_use_ssl | bool %}&ssl_verify_cert=true{% if nova_galera_ssl_ca_cert | length > 0 %}&ssl_ca={{ nova_galera_ssl_ca_cert }}{% endif %}{% endif %} @@ -66,14 +66,14 @@ ('ssl_verify_cert' in _cell0_record[0] and not nova_galera_use_ssl) - name: Synchronize the nova DB schema - command: "{{ nova_bin }}/nova-manage db sync" + command: "{{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf db sync" become: yes become_user: "{{ nova_system_user_name }}" changed_when: false - name: Create the cell1 mapping entry in the nova API DB command: >- - {{ nova_bin }}/nova-manage cell_v2 create_cell + {{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf cell_v2 create_cell --name {{ nova_cell1_name }} --database_connection {scheme}://{username}:{password}@{hostname}:{port}/{path}?{query} --transport-url {scheme}://{username}:{password}@{hostname}:{port}/{{ ( @@ -96,7 +96,7 @@ - name: "Change the template for cell {{ nova_cell1_name }}" command: >- - {{ nova_bin }}/nova-manage cell_v2 update_cell + {{ nova_bin }}/nova-manage --config-file {{ nova_conf_version_dir }}/nova.conf cell_v2 update_cell --cell_uuid {{ _cell1_record[0].split()[3] }} --database_connection {scheme}://{username}:{password}@{hostname}:{port}/{path}?{query} --transport-url {scheme}://{username}:{password}@{hostname}:{port}/{{ ( @@ -115,7 +115,7 @@ # mapping setup and before actual service restart. # https://docs.openstack.org/nova/latest/cli/nova-status.html - name: Run nova-status upgrade check to validate a healthy configuration - command: "{{ nova_bin }}/nova-status upgrade check" + command: "{{ nova_bin }}/nova-status --config-file {{ nova_conf_version_dir }}/nova.conf upgrade check" become: yes become_user: "{{ nova_system_user_name }}" register: nova_status_upgrade_check diff --git a/tasks/nova_post_install.yml b/tasks/nova_post_install.yml index b8b1341c..500e3df2 100644 --- a/tasks/nova_post_install.yml +++ b/tasks/nova_post_install.yml @@ -36,14 +36,14 @@ group: "{{ item.group | default(nova_system_group_name) }}" mode: "{{ item.mode | default(omit) }}" with_items: - - path: "/etc/nova/rootwrap.d" + - path: "{{ nova_conf_version_dir }}/rootwrap.d" owner: "root" group: "root" - name: Copy nova rootwrap filter config copy: src: "{{ item }}" - dest: "/etc/nova/rootwrap.d/" + dest: "{{ nova_conf_version_dir }}/rootwrap.d/" owner: "root" group: "root" mode: "0644" @@ -68,11 +68,11 @@ yml_multilines: "{{ item.yml_multilines | default(omit) }}" with_items: - src: "nova.conf.j2" - dest: "/etc/nova/nova.conf" + dest: "{{ nova_conf_version_dir }}/nova.conf" config_overrides: "{{ nova_nova_conf_overrides }}" config_type: "ini" - src: "vendor_data.json.j2" - dest: "/etc/nova/vendor_data.json" + dest: "{{ nova_conf_version_dir }}/vendor_data.json" config_overrides: "{{ nova_vendor_data_overrides }}" config_type: "json" yml_multilines: True @@ -86,7 +86,7 @@ - name: Implement policy.yaml if there are overrides configured openstack.config_template.config_template: content: "{{ nova_policy_overrides }}" - dest: "/etc/nova/policy.yaml" + dest: "{{ nova_conf_version_dir }}/policy.yaml" owner: "root" group: "{{ nova_system_group_name }}" mode: "0640" @@ -100,7 +100,7 @@ - name: Implement compute host provider.yaml if there are overrides configured openstack.config_template.config_template: content: "{{ item.content }}" - dest: "/etc/nova/provider_config/{{ item.name }}.yaml" + dest: "{{ nova_conf_version_dir }}/provider_config/{{ item.name }}.yaml" owner: "root" group: "{{ nova_system_group_name }}" mode: "0640" @@ -115,7 +115,7 @@ - name: Remove legacy policy.yaml file file: - path: "/etc/nova/policy.yaml" + path: "{{ nova_conf_dir }}/policy.yaml" state: absent when: - nova_policy_overrides | length == 0 @@ -174,14 +174,3 @@ tags: - nova-config - nova-post-install - -- name: Drop sudoers file - template: - src: "sudoers.j2" - dest: "/etc/sudoers.d/{{ nova_system_user_name }}_sudoers" - mode: "0440" - owner: "root" - group: "root" - tags: - - sudoers - - nova-sudoers diff --git a/tasks/nova_pre_install.yml b/tasks/nova_pre_install.yml index c3bdecd5..08c8a4c0 100644 --- a/tasks/nova_pre_install.yml +++ b/tasks/nova_pre_install.yml @@ -53,12 +53,12 @@ block: - name: Stat config directory stat: - path: "/etc/nova" + path: "{{ nova_conf_dir }}" register: nova_conf_dir_stat - name: Remove the config directory file: - path: "/etc/nova" + path: "{{ nova_conf_dir }}" state: absent when: - nova_conf_dir_stat.stat.isdir is defined and @@ -69,12 +69,10 @@ - name: Create nova dir file: path: "{{ item.path }}" - src: "{{ item.src | default(omit) }}" state: "{{ item.state | default('directory') }}" owner: "{{ item.owner | default(nova_system_user_name) }}" group: "{{ item.group | default(nova_system_group_name) }}" mode: "{{ item.mode | default('0755') }}" - force: "{{ item.force | default(omit) }}" when: - (item.condition | default(true)) | bool - item.path not in nova_mount_points @@ -82,17 +80,9 @@ - path: "/openstack" owner: "root" group: "root" - - path: "{{ (nova_install_method == 'distro') | ternary('/etc/nova', (nova_bin | dirname) + '/etc/nova') }}" + - path: "{{ nova_conf_version_dir }}" mode: "0755" - # NOTE(cloudnull): The "src" path is relative. This ensures all files remain - # within the host/container confines when connecting to - # them using the connection plugin or the root filesystem. - - path: "/etc/nova" - src: "{{ nova_bin | dirname | regex_replace('^/', '../') }}/etc/nova" - state: link - force: true - condition: "{{ nova_install_method == 'source' }}" - - path: "/etc/nova/provider_config" + - path: "{{ nova_conf_version_dir }}/provider_config" owner: "root" mode: "0640" - path: "/etc/sudoers.d" @@ -107,17 +97,6 @@ tags: - nova-dirs -- name: Drop sudoers file - template: - src: "sudoers.j2" - dest: "/etc/sudoers.d/{{ nova_system_user_name }}_sudoers" - mode: "0440" - owner: "root" - group: "root" - tags: - - sudoers - - nova-sudoers - - name: Set default nova console for ppc64le set_fact: nova_console_type: "novnc" diff --git a/templates/nova.conf.j2 b/templates/nova.conf.j2 index 0a15e9a9..b291e0a7 100644 --- a/templates/nova.conf.j2 +++ b/templates/nova.conf.j2 @@ -310,11 +310,11 @@ insecure = {{ keystone_service_adminuri_insecure | bool }} {% endif %} [wsgi] -api_paste_config = /etc/nova/api-paste.ini +api_paste_config = {{ nova_conf_dir }}/api-paste.ini [api] -vendordata_jsonfile_path = /etc/nova/vendor_data.json +vendordata_jsonfile_path = {{ nova_conf_dir }}/vendor_data.json dhcp_domain = {{ nova_dhcp_domain }} [scheduler] diff --git a/vars/main.yml b/vars/main.yml index 77e702fc..024018a2 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -13,6 +13,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +nova_conf_dir: /etc/nova +nova_conf_version_dir: "{{ (nova_install_method == 'distro') | ternary(nova_conf_dir, (nova_bin | dirname) + nova_conf_dir) }}" + _nova_is_first_play_host: >- {{ (nova_services['nova-conductor']['group'] in group_names and @@ -119,16 +122,16 @@ nova_mount_points: |- _nova_rootwrap_conf_overrides: DEFAULT: - filters_path: "/etc/nova/rootwrap.d,/usr/share/nova/rootwrap" + filters_path: "{{ nova_conf_dir }}/rootwrap.d,/usr/share/nova/rootwrap" exec_dirs: "{{ nova_bin }},/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin,/usr/local/sbin" nova_core_files: - tmp_f: "/tmp/api-paste.ini" - target_f: "/etc/nova/api-paste.ini" + target_f: "{{ nova_conf_version_dir }}/api-paste.ini" config_overrides: "{{ nova_api_paste_ini_overrides }}" config_type: "ini" - tmp_f: "/tmp/rootwrap.conf" - target_f: "/etc/nova/rootwrap.conf" + target_f: "{{ nova_conf_version_dir }}/rootwrap.conf" config_overrides: "{{ _nova_rootwrap_conf_overrides | combine(nova_rootwrap_conf_overrides, recursive=True) }}" config_type: "ini" owner: "root"