Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions etc/kayobe/ansible/maintenance/kvm-disable-nested-virt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
- name: Disable KVM nested virtualisation
hosts: compute
gather_facts: true
vars:
venv: "{{ virtualenv_path }}/openstack"
pre_tasks:
- name: Assert host is capable of virtualisation
ansible.builtin.assert:
that:
- ansible_facts.virtualization_role == 'host'
fail_msg: "Host is not capable of virtualisation"

- name: Set up openstack cli virtualenv
ansible.builtin.pip:
virtualenv: "{{ venv }}"
virtualenv_command: /usr/bin/python3 -m venv
name:
- python-openstackclient
state: latest
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
run_once: true
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Check compute service is disabled for maintenance
ansible.builtin.command: >
{{ venv }}/bin/openstack compute service list
--service nova-compute
--host {{ ansible_facts.nodename }}
--format json
register: compute_service
environment: "{{ openstack_auth_env }}"
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Assert hypervisor is disabled for maintenance
ansible.builtin.assert:
that:
- compute_service.stdout | from_json | length > 0
- (compute_service.stdout | from_json | first).Status == "disabled"
fail_msg: >
Hypervisor {{ ansible_facts.nodename }} is not disabled for maintenance.
Current service state: {{ compute_service.stdout | from_json }}
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Query instances
ansible.builtin.command: >
{{ venv }}/bin/openstack
server list --host {{ ansible_facts.nodename }}
--all-projects
--status ACTIVE
--format json
register: instances
environment: "{{ openstack_auth_env }}"
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Fail if there are instances still on the host
ansible.builtin.fail:
msg: >
Instances still on {{ inventory_hostname }}: {{ instances.stdout | from_json }}
when:
- instances.stdout | from_json | length > 0
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"
tasks:
- name: Set KVM module name
ansible.builtin.set_fact:
kvm_module_name: >-
{{ 'kvm_intel'
if 'GenuineIntel' in (ansible_facts.processor | default([]))
else 'kvm_amd'
if 'AuthenticAMD' in (ansible_facts.processor | default([]))
else 'unknown' }}

- name: Assert supported CPU is present
ansible.builtin.assert:
that:
- kvm_module_name != ''
Comment on lines +85 to +86

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More likely to be unknown than undefined

Suggested change
that:
- kvm_module_name != ''
that:
- kvm_module_name != ''
- kvm_module_name != 'unknown'

fail_msg: "Cannot detect either GenuineIntel or AuthenticAMD processor"

- name: Verify KVM module is loaded
ansible.builtin.stat:
path: "/sys/module/{{ kvm_module_name }}"
register: kvm_module_path
become: true

- name: Check if nested virtualization is supported
ansible.builtin.command: "cat /sys/module/{{ kvm_module_name }}/parameters/nested"
register: nested
changed_when: false
when: kvm_module_path.stat.exists
become: true

- name: Disable nested virtualisation and restart nova_libvirt
when: "not kvm_module_path.stat.exists or ('N' not in nested.stdout_lines | default([]) and '0' not in nested.stdout_lines | default([]))"
become: true
block:
- name: Unload the KVM module
community.general.modprobe:
name: "{{ kvm_module_name}}"

Check warning on line 108 in etc/kayobe/ansible/maintenance/kvm-disable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.18 lint with Python 3.12

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}

Check warning on line 108 in etc/kayobe/ansible/maintenance/kvm-disable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.17 lint with Python 3.10

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing

Suggested change
name: "{{ kvm_module_name}}"
name: "{{ kvm_module_name }}"

state: absent

- name: Ensure KVM module is enabled and nested virtualisation is disabled
community.general.modprobe:
name: "{{ kvm_module_name}}"

Check warning on line 113 in etc/kayobe/ansible/maintenance/kvm-disable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.18 lint with Python 3.12

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}

Check warning on line 113 in etc/kayobe/ansible/maintenance/kvm-disable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.17 lint with Python 3.10

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing

Suggested change
name: "{{ kvm_module_name}}"
name: "{{ kvm_module_name }}"

params: 'nested=0'
persistent: present

- name: Check again if nested virtualization is not supported
ansible.builtin.command: "cat /sys/module/{{ kvm_module_name }}/parameters/nested"
changed_when: false
register: result
failed_when: "'N' not in result.stdout_lines and '0' not in result.stdout_lines"

- name: Restart nova_libvirt container
ansible.builtin.systemd_service:
name: kolla-nova_libvirt-container
state: restarted
126 changes: 126 additions & 0 deletions etc/kayobe/ansible/maintenance/kvm-enable-nested-virt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
- name: Enable KVM nested virtualisation
hosts: compute
gather_facts: true
vars:
venv: "{{ virtualenv_path }}/openstack"
pre_tasks:
- name: Assert host is capable of virtualisation
ansible.builtin.assert:
that:
- ansible_facts.virtualization_role == 'host'
fail_msg: "Host is not capable of virtualisation"

- name: Set up openstack cli virtualenv
ansible.builtin.pip:
virtualenv: "{{ venv }}"
virtualenv_command: /usr/bin/python3 -m venv
name:
- python-openstackclient
state: latest
extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}"
run_once: true
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Check compute service is disabled for maintenance
ansible.builtin.command: >
{{ venv }}/bin/openstack compute service list
--service nova-compute
--host {{ ansible_facts.nodename }}
--format json
register: compute_service
environment: "{{ openstack_auth_env }}"
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Assert hypervisor is disabled for maintenance
ansible.builtin.assert:
that:
- compute_service.stdout | from_json | length > 0
- (compute_service.stdout | from_json | first).Status == "disabled"
fail_msg: >
Hypervisor {{ ansible_facts.nodename }} is not disabled for maintenance.
Current service state: {{ compute_service.stdout | from_json }}
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Query instances
ansible.builtin.command: >
{{ venv }}/bin/openstack
server list --host {{ ansible_facts.nodename }}
--all-projects
--status ACTIVE
--format json
register: instances
environment: "{{ openstack_auth_env }}"
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"

- name: Fail if there are instances still on the host
ansible.builtin.fail:
msg: >
Instances still on {{ inventory_hostname }}: {{ instances.stdout | from_json }}
when:
- instances.stdout | from_json | length > 0
delegate_to: "{{ groups['controllers'][0] }}"
vars:
ansible_host: "{{ hostvars[groups['controllers'][0]].ansible_host }}"
tasks:
- name: Set KVM module name
ansible.builtin.set_fact:
kvm_module_name: >-
{{ 'kvm_intel'
if 'GenuineIntel' in (ansible_facts.processor | default([]))
else 'kvm_amd'
if 'AuthenticAMD' in (ansible_facts.processor | default([]))
else 'unknown' }}

- name: Assert supported CPU is present
ansible.builtin.assert:
that:
- kvm_module_name != ''

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above

fail_msg: "Cannot detect either GenuineIntel or AuthenticAMD processor"

- name: Verify KVM module is loaded
ansible.builtin.stat:
path: "/sys/module/{{ kvm_module_name }}"
register: kvm_module_path
become: true

- name: Check if nested virtualization is supported
ansible.builtin.command: "cat /sys/module/{{ kvm_module_name }}/parameters/nested"
register: nested
changed_when: false
when: kvm_module_path.stat.exists
become: true

- name: Enable nested virtualisation and restart nova_libvirt
when: "not kvm_module_path.stat.exists or ('Y' not in nested.stdout_lines | default([]) and '1' not in nested.stdout_lines | default([]))"
become: true
block:
- name: Unload the KVM module
community.general.modprobe:
name: "{{ kvm_module_name}}"

Check warning on line 108 in etc/kayobe/ansible/maintenance/kvm-enable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.18 lint with Python 3.12

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}

Check warning on line 108 in etc/kayobe/ansible/maintenance/kvm-enable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.17 lint with Python 3.10

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}
state: absent

- name: Ensure KVM module is enabled and nested virtualisation is enabled
community.general.modprobe:
name: "{{ kvm_module_name}}"

Check warning on line 113 in etc/kayobe/ansible/maintenance/kvm-enable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.18 lint with Python 3.12

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}

Check warning on line 113 in etc/kayobe/ansible/maintenance/kvm-enable-nested-virt.yml

View workflow job for this annotation

GitHub Actions / Ansible 2.17 lint with Python 3.10

jinja[spacing]

Jinja2 spacing could be improved: {{ kvm_module_name}} -> {{ kvm_module_name }}
params: 'nested=1'
persistent: present

- name: Check again if nested virtualization is supported
ansible.builtin.command: "cat /sys/module/{{ kvm_module_name }}/parameters/nested"
changed_when: false
register: result
failed_when: "'Y' not in result.stdout_lines and '1' not in result.stdout_lines"

- name: Restart nova_libvirt container
ansible.builtin.systemd_service:
name: kolla-nova_libvirt-container
state: restarted
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
features:
- |
Add two new playbooks to support enabling or disabling of KVM nested virtualisation.
security:
- |
Playbook added to support disabling of KVM nested virtualisation in response to
`CVE-2026-53359 <https://www.openwall.com/lists/oss-security/2026/07/06/7>`__. This
playbook acts as early mitigation to the vulnerability in lieu of kernel patches.
Loading