Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
1 change: 0 additions & 1 deletion ansible/inventory/all-in-one
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ control

[cyborg:children]
control
compute

[tacker:children]
control
Expand Down
1 change: 0 additions & 1 deletion ansible/inventory/multinode
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ control

[cyborg:children]
control
compute

[gnocchi:children]
control
Expand Down
182 changes: 136 additions & 46 deletions ansible/module_utils/kolla_podman_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ def parse_volumes(self, volumes, mounts, filtered_volumes):
)
if src == 'devpts':
mount_item = dict(
source=src,
target=dest,
type='devpts'
)
Expand Down Expand Up @@ -306,6 +307,42 @@ def compare_container(self):
self.changed = True
return self.changed

def compare_cap_add(self, container_info):
new_cap_add = self.params.get('cap_add', list()).copy()

new_cap_add = [
'CAP_' + cap.upper()
if not cap.upper().startswith('CAP_')
else cap.upper()
for cap in new_cap_add
]

try:
current_cap_add = (
container_info['HostConfig'].get('CapAdd', None) or []
)
except (KeyError, TypeError):
current_cap_add = []

current_cap_add = [cap.upper() for cap in current_cap_add]

privileged = container_info['HostConfig'].get('Privileged', False)
if not privileged:
# NOTE(blanson): prepare_container_args() always adds AUDIT_WRITE
# for non-privileged containers. Also works around Podman <4.4 bug
# where AUDIT_WRITE doesn't appear in inspect. Since capabilities
# can't be modified post-creation, this won't mask real drift.
if 'CAP_AUDIT_WRITE' not in new_cap_add:
new_cap_add.append('CAP_AUDIT_WRITE')

if 'CAP_AUDIT_WRITE' not in current_cap_add:
current_cap_add.append('CAP_AUDIT_WRITE')

if set(new_cap_add).symmetric_difference(set(current_cap_add)):
return True

return False

def compare_pid_mode(self, container_info):
new_pid_mode = self.params.get('pid_mode') or self.params.get('pid')
current_pid_mode = container_info['HostConfig'].get('PidMode')
Expand Down Expand Up @@ -349,50 +386,65 @@ def check_slash(string):
else:
return string

raw_volumes, binds = self.generate_volumes()
raw_vols, current_binds = self.generate_volumes(
container_info['HostConfig'].get('Binds'))

current_vols = [check_slash(vol) for vol in raw_vols if vol]
volumes = [check_slash(vol) for vol in raw_volumes if vol]
# NOTE(blanson): Podman automatically appends default flags
# such as rprivate, nosuid, nodev, rbind to all mounts.
# For special paths like /proc, /run, /sys, and /var/run,
# noexec is also added by default. We remove these defaults
# because they do not reflect a meaningful difference
# between the requested and current container configuration.
# Additionally, if neither 'ro' nor 'rw' is specified,
# we implicitly assume 'rw' (Podman's default behavior).
def normalize_mode(path, mode):
default_flags = {'rprivate', 'nosuid', 'nodev', 'rbind'}
special_paths_noexec = {'/proc', '/run', '/sys', '/var/run'}

flags = set(mode.split(',')) if mode else set()
flags -= default_flags

if any(path.startswith(p) for p in special_paths_noexec):
flags.discard('noexec')
if not (flags & {'ro', 'rw'}):
flags.add('rw')
return flags

# NOTE(blanson): Convert a binds dict into a list of
# (src, dst, normalized_flags) tuples. Normalization ignores
# default Podman flags and noexec for special paths to allow
# consistent comparison.
def build_bind_list(binds_dict):
lst = []
for src, info in (binds_dict or {}).items():
src_path = check_slash(src)
dst_path = check_slash(info['bind'])
mode_flags = normalize_mode(
dst_path,
info['mode'],
)
lst.append((src_path, dst_path, mode_flags))
return lst

if not volumes:
volumes = list()
if not current_vols:
current_vols = list()
if not current_binds:
current_binds = list()
binds_input = container_info['HostConfig'].get('Binds')
raw_volumes, binds = self.generate_volumes()
raw_vols, current_binds = (
[], {}
) if not binds_input else self.generate_volumes(binds_input)

volumes.sort()
current_vols.sort()
volumes = [check_slash(v) for v in raw_volumes or [] if v]
current_vols = [check_slash(v) for v in raw_vols or [] if v]

if set(volumes).symmetric_difference(set(current_vols)):
if set(volumes) != set(current_vols):
return True

new_binds = list()
new_current_binds = list()
if binds:
for k, v in binds.items():
k = check_slash(k)
v['bind'] = check_slash(v['bind'])
new_binds.append(
"{}:{}:{}".format(k, v['bind'], v['mode']))

if current_binds:
for k, v in current_binds.items():
k = check_slash(k)
v['bind'] = check_slash(v['bind'])
if 'ro' in v['mode']:
v['mode'] = 'ro'
else:
v['mode'] = 'rw'
new_current_binds.append(
"{}:{}:{}".format(k, v['bind'], v['mode'][0:2]))

new_binds.sort()
new_current_binds.sort()
req_bind_list = [
(src, dst, frozenset(flags))
for src, dst, flags in build_bind_list(binds)
]
cur_bind_list = [
(src, dst, frozenset(flags))
for src, dst, flags in build_bind_list(current_binds)
]

if set(new_binds).symmetric_difference(set(new_current_binds)):
if set(req_bind_list) != set(cur_bind_list):
return True

def compare_dimensions(self, container_info):
Expand All @@ -416,15 +468,53 @@ def compare_dimensions(self, container_info):
failed=True, msg=repr("Unsupported dimensions"),
unsupported_dimensions=unsupported)
current_dimensions = container_info['HostConfig']

# NOTE(blanson): We normalize ulimits names because the podman api
# returns them as RLIMIT_<UPPER_STRING>
def normalize_ulimit_name(name):
name = name.upper()
if not name.startswith('RLIMIT_'):
return 'RLIMIT_' + name
return name

for key1, key2 in dimension_map.items():
# NOTE(mgoddard): If a resource has been explicitly requested,
# check for a match. Otherwise, ensure it is set to the default.
if key1 in new_dimensions:
if key1 == 'ulimits':
if self.compare_ulimits(new_dimensions[key1],
current_dimensions[key2]):
return True
elif new_dimensions[key1] != current_dimensions[key2]:
if key1 == 'ulimits':
current_ulimits = current_dimensions.get(key2, [])

# NOTE(blanson): We strip podman default ulimits
# because they are not settable by users anyways
# and break idempotency.
filtered_current_ulimits = [
u for u in current_ulimits
if u.get('Name') not in ('RLIMIT_NOFILE', 'RLIMIT_NPROC')
]

desired_ulimits = new_dimensions.get('ulimits', {})

desired_ulimits = {
normalize_ulimit_name(name): limits
for name, limits in desired_ulimits.items()
if normalize_ulimit_name(name) not in (
'RLIMIT_NOFILE', 'RLIMIT_NPROC')
}

normalized_current = [
{
'Name': normalize_ulimit_name(u['Name']),
'Soft': u.get('Soft'),
'Hard': u.get('Hard')
}
for u in filtered_current_ulimits
]

if self.compare_ulimits(
desired_ulimits,
normalized_current
):
return True

elif key1 in new_dimensions:
if new_dimensions[key1] != current_dimensions.get(key2):
return True
elif current_dimensions[key2]:
# The default values of all (except ulimits) currently
Expand Down
27 changes: 8 additions & 19 deletions ansible/roles/nova-cell/tasks/version-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,32 +40,25 @@
name:
- "{{ service.container_name }}"
register: container_facts_per_host
run_once: true
delegate_to: "{{ item }}"
loop: "{{ groups[service.group] }}"
loop_control:
label: "{{ item }}"
when: inventory_hostname in groups[service.group]

- name: Get current Libvirt version
any_errors_fatal: true
become: true
command: "{{ kolla_container_engine }} exec {{ service.container_name }} libvirtd --version"
register: libvirt_version_current_results
changed_when: false
run_once: true
delegate_to: "{{ item.item }}"
loop: "{{ container_facts_per_host.results }}"
loop_control:
label: "{{ item.item }}"
when:
- item.containers[service.container_name] is defined
- item.containers[service.container_name].State.Running
- container_facts_per_host is not skipped
- container_facts_per_host.containers[service.container_name] is defined
- (hostvars[groups[service.group] | first].service_image_info.images | default([]) | length) > 0
- item.containers[service.container_name].Image
- container_facts_per_host.containers[service.container_name].Image
!= hostvars[groups[service.group] | first].service_image_info.images[0].Id

- name: Check that the new Libvirt version is >= current
any_errors_fatal: true
vars:
current_version: "{{ item.stdout | regex_search('[0-9]+\\.[0-9]+\\.[0-9]+') }}"
current_version: "{{ libvirt_version_current_results.stdout | regex_search('[0-9]+\\.[0-9]+\\.[0-9]+') }}"
new_version: "{{ hostvars[groups[service.group] | first].libvirt_new_version }}"
assert:
that: "{{ new_version is version(current_version, '>=', strict=true) }}"
Expand All @@ -75,11 +68,7 @@
that you want to do this, please skip the tag `nova-libvirt-version-check`.
success_msg: >
Libvirt version check successful: target {{ new_version }} >= current {{ current_version }}.
run_once: true
loop: "{{ libvirt_version_current_results.results }}"
loop_control:
label: "{{ item.item }}"
when: item.stdout is defined
when: libvirt_version_current_results is not skipped

tags: nova-libvirt-version-check
when: enable_nova_libvirt_container | bool and (groups[service.group] | length) > 0
Expand Down
2 changes: 1 addition & 1 deletion ansible/roles/ovn-db/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ ovn_db_services:
group: ovn-sb-db-relay
enabled: "{{ enable_ovn_sb_db_relay | bool }}"
environment:
RELAY_ID: "{{ ovn_sb_db_relay_group_id | default('1') }}"
RELAY_ID: "{{ item | default(ovn_sb_db_relay_group_id | default('1')) | string }}"
image: "{{ ovn_sb_db_relay_image_full }}"
iterate: true
iterate_var: "{{ ovn_sb_db_relay_count | int }}"
Expand Down
2 changes: 1 addition & 1 deletion ansible/roles/ovn-db/templates/ovn-sb-db-relay.json.j2
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"source": "{{ container_config_directory }}/ovsdb-relay.json",
"dest": "/etc/ovn/ovsdb-relay.json",
"owner": "openvswitch",
"owner": "root",
"perm": "0600"
}
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"command": "/opt/cadvisor --port={{ prometheus_cadvisor_port }} --log_dir=/var/log/kolla/prometheus{% if prometheus_cadvisor_cmdline_extras %} {{ prometheus_cadvisor_cmdline_extras }}{% endif %}",
"command": "/opt/cadvisor --port={{ prometheus_cadvisor_port }} --log_dir=/var/log/kolla/prometheus --listen_ip {{ 'api' | kolla_address(inventory_hostname) }}{% if prometheus_cadvisor_cmdline_extras %} {{ prometheus_cadvisor_cmdline_extras }}{% endif %}",
"config_files": [
{% if kolla_copy_ca_into_containers | bool %}
{
Expand Down
7 changes: 3 additions & 4 deletions ansible/roles/service-check-containers/tasks/iterated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
- name: "{{ kolla_role_name | default(project_name) }} | Check containers with iteration"
become: true
vars:
service: "{{ outer_item.value }}"
service: "{{ lookup('vars', (kolla_role_name | default(project_name)) + '_services')[service_name] }}"
kolla_container:
action: "compare_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}"
name: "{{ service.container_name }}_{{ item }}"
image: "{{ service.image | default(omit) }}"
volumes: "{{ service.volumes | default(omit) }}"
dimensions: "{{ service.dimensions | default(omit) }}"
Expand All @@ -22,8 +22,7 @@
labels: "{{ service.labels | default(omit) }}"
command: "{{ service.command | default(omit) }}"
cgroupns_mode: "{{ service.cgroupns_mode | default(omit) }}"
loop:
- "{{ range(1,(service.iterate_var | int) + 1) | list }}"
loop: "{{ range(1, (iterate_count | int) + 1) | list }}"
register: container_check

# NOTE(yoctozepto): Must be a separate task because one cannot see the whole
Expand Down
5 changes: 3 additions & 2 deletions ansible/roles/service-check-containers/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@

- name: Include tasks
vars:
service: "{{ outer_item.value }}"
service_name: "{{ outer_item.key }}"
iterate_count: "{{ outer_item.value.iterate_var | int }}"
include_tasks: iterated.yml
loop: "{{ lookup('vars', (kolla_role_name | default(project_name)) + '_services') | select_services_enabled_and_mapped_to_host | dict2items }}"
loop_control:
loop_var: outer_item
when: (service.iterate | default(False)) | bool
when: (outer_item.value.iterate | default(False)) | bool
14 changes: 14 additions & 0 deletions ansible/roles/service-stop/tasks/iterated.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
- name: "Stopping containers (iterated) for {{ service_name }}"
become: true
vars:
service: "{{ outer_item.value }}"
service_name: "{{ outer_item.key }}"
kolla_container:
action: "stop_container"
common_options: "{{ docker_common_options }}"
name: "{{ service.container_name }}_{{ item }}"
ignore_missing: "{{ kolla_action_stop_ignore_missing | bool }}"
when:
- service.container_name not in skip_stop_containers
loop: "{{ range(1, (service.iterate_var | int) + 1) | list }}"
12 changes: 12 additions & 0 deletions ansible/roles/service-stop/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,16 @@
ignore_missing: "{{ kolla_action_stop_ignore_missing | bool }}"
when:
- service.container_name not in skip_stop_containers
- not (service.iterate | default(False)) | bool
with_dict: "{{ project_services | select_services_enabled_and_mapped_to_host }}"

- name: Include tasks for iterated containers
vars:
service: "{{ outer_item.value }}"
include_tasks: iterated.yml
loop: "{{ project_services | select_services_enabled_and_mapped_to_host | dict2items }}"
loop_control:
loop_var: outer_item
when:
- (service.iterate | default(False)) | bool
- service.iterate_var is defined
6 changes: 6 additions & 0 deletions ansible/roles/skyline/templates/nginx.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ http {
ssl_certificate {{ skyline_ssl_certfile }};
ssl_certificate_key {{ skyline_ssl_keyfile }};
{% endif %}

{% if internal_protocol == 'https' %}
proxy_ssl_protocols TLSv1.2 TLSv1.3;
proxy_ssl_server_name on;
{% endif %}

##
# Logging Settings
##
Expand Down
Loading
Loading