Skip to content

Commit 33a9750

Browse files
m-bullbbezak
authored andcommitted
Prevent accidental Libvirt downgrades
Add a version check for nova_libvirt during deploy and upgrade. Resolve the target image digest once on the first compute host. Compare it with each running container digest before version check. This runs the assertion only on hypervisors that would change image and leaves other hosts untouched. Adds a tiny macro role ``service-image-info`` to resolve container image info (Docker/Podman) once per service. The nova-libvirt version check now uses it to compare running vs target image. Closes-bug: #2120290 Co-Authored-By: Bartosz Bezak <[email protected]> Signed-off-by: Bartosz Bezak <[email protected]> Change-Id: I904a7b959f8fd151ab40bf6ac830dcf13d899239 (cherry picked from commit 7035e11)
1 parent 11010d0 commit 33a9750

File tree

6 files changed

+129
-0
lines changed

6 files changed

+129
-0
lines changed

ansible/roles/nova-cell/tasks/deploy.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
- include_tasks: clone.yml
33
when: nova_dev_mode | bool
44

5+
- import_tasks: version-check.yml
6+
57
- import_tasks: config-host.yml
68

79
- import_tasks: config.yml

ansible/roles/nova-cell/tasks/upgrade.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
---
2+
- import_tasks: version-check.yml
3+
24
- name: Stopping nova cell services
35
become: true
46
kolla_container:
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
---
2+
- block:
3+
- name: Get new Libvirt version
4+
become: true
5+
kolla_container:
6+
action: "start_container"
7+
command: "libvirtd --version"
8+
common_options: "{{ docker_common_options }}"
9+
container_engine: "{{ kolla_container_engine }}"
10+
detach: false
11+
environment:
12+
KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
13+
image: "{{ service.image }}"
14+
name: "libvirt_version_check"
15+
restart_policy: oneshot
16+
remove_on_exit: true
17+
register: libvirt_version_new
18+
failed_when: false
19+
check_mode: false
20+
run_once: true
21+
delegate_to: "{{ groups[service.group] | first }}"
22+
23+
- name: Cache new Libvirt version
24+
set_fact:
25+
libvirt_new_version: "{{ libvirt_version_new.stdout | regex_search('[0-9]+\\.[0-9]+\\.[0-9]+') }}"
26+
run_once: true
27+
delegate_facts: true
28+
delegate_to: "{{ groups[service.group] | first }}"
29+
30+
- name: Get nova_libvirt image info
31+
include_role:
32+
name: service-image-info
33+
run_once: true
34+
35+
- name: Get container facts
36+
become: true
37+
kolla_container_facts:
38+
action: get_containers
39+
container_engine: "{{ kolla_container_engine }}"
40+
name:
41+
- "{{ service.container_name }}"
42+
register: container_facts_per_host
43+
run_once: true
44+
delegate_to: "{{ item }}"
45+
loop: "{{ groups[service.group] }}"
46+
loop_control:
47+
label: "{{ item }}"
48+
49+
- name: Get current Libvirt version
50+
become: true
51+
command: "{{ kolla_container_engine }} exec {{ service.container_name }} libvirtd --version"
52+
register: libvirt_version_current_results
53+
changed_when: false
54+
run_once: true
55+
delegate_to: "{{ item.item }}"
56+
loop: "{{ container_facts_per_host.results }}"
57+
loop_control:
58+
label: "{{ item.item }}"
59+
when:
60+
- item.containers[service.container_name] is defined
61+
- item.containers[service.container_name].State.Running
62+
- (hostvars[groups[service.group] | first].service_image_info.images | default([]) | length) > 0
63+
- item.containers[service.container_name].Image
64+
!= hostvars[groups[service.group] | first].service_image_info.images[0].Id
65+
66+
- name: Check that the new Libvirt version is >= current
67+
vars:
68+
current_version: "{{ item.stdout | regex_search('[0-9]+\\.[0-9]+\\.[0-9]+') }}"
69+
new_version: "{{ hostvars[groups[service.group] | first].libvirt_new_version }}"
70+
assert:
71+
that: "{{ new_version is version(current_version, '>=', strict=true) }}"
72+
fail_msg: >
73+
It looks like you're about to downgrade Libvirt in the nova_libvirt container from
74+
version {{ current_version }} to version {{ new_version }}. If you're absolutely certain
75+
that you want to do this, please skip the tag `nova-libvirt-version-check`.
76+
success_msg: >
77+
Libvirt version check successful: target {{ new_version }} >= current {{ current_version }}.
78+
run_once: true
79+
loop: "{{ libvirt_version_current_results.results }}"
80+
loop_control:
81+
label: "{{ item.item }}"
82+
when: item.stdout is defined
83+
84+
tags: nova-libvirt-version-check
85+
when: enable_nova_libvirt_container | bool and (groups[service.group] | length) > 0
86+
vars:
87+
service_name: "nova-libvirt"
88+
service: "{{ nova_cell_services[service_name] }}"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
# Host to delegate task execution to.
3+
service_image_info_delegate_host: "{{ groups[service.group] | first }}"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
- name: Get target image info (docker)
3+
block:
4+
- community.docker.docker_image_info:
5+
name: "{{ service.image }}"
6+
register: docker_image_info
7+
8+
- set_fact:
9+
service_image_info: "{{ docker_image_info }}"
10+
delegate_facts: true
11+
become: true
12+
delegate_to: "{{ service_image_info_delegate_host }}"
13+
when: kolla_container_engine == 'docker'
14+
15+
- name: Get target image info (podman)
16+
block:
17+
- containers.podman.podman_image_info:
18+
name: "{{ service.image }}"
19+
register: podman_image_info
20+
21+
- set_fact:
22+
service_image_info: "{{ podman_image_info }}"
23+
delegate_facts: true
24+
become: true
25+
delegate_to: "{{ service_image_info_delegate_host }}"
26+
when: kolla_container_engine == 'podman'
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
fixes:
3+
- |
4+
Prevents accidental ``libvirt`` downgrades in ``nova_libvirt`` container
5+
image during deploy and upgrade. Adds a ``nova_libvirt`` version check that
6+
resolves the target image digest once on the first compute host
7+
and runs only on hypervisors where the running container digest differs
8+
from the target.

0 commit comments

Comments
 (0)