aboutsummaryrefslogtreecommitdiff
path: root/kolla/docker/nova
diff options
context:
space:
mode:
authorMichal Nasiadka <mnasiadka@gmail.com>2026-07-06 15:26:00 +0200
committerMichal Nasiadka <mnasiadka@gmail.com>2026-07-06 19:59:40 +0000
commitdb35ac8d793506bc43b62e7e39d27a75de1043ed (patch)
treefeec28d13a43490f5fd4260374144a1abfc20331 /kolla/docker/nova
parent1ae1850557e3b99902f73b32c9005618537a1f2d (diff)
downloadkolla-db35ac8d793506bc43b62e7e39d27a75de1043ed.tar.gz
kolla-db35ac8d793506bc43b62e7e39d27a75de1043ed.zip
Migrate to pyproject.toml
[tool.setuptools.data-files] does not support recursive directory installation. The old setup.cfg [files] worked because PBR's FilesConfig.expand_globs() used os.walk() to expand docker/*, but this hook is not triggered by the pbr.build PEP-517 backend. Move docker/ into kolla/ and use [tool.setuptools.package-data] instead. Update kolla_worker._get_images_dir() to check the kolla package directory first so both editable and regular installs work. Change-Id: I4fc452c03740ef22ebbb4e8d0d86c4f4783e2d09 Signed-off-by: Michal Nasiadka <mnasiadka@gmail.com>
Diffstat (limited to 'kolla/docker/nova')
-rw-r--r--kolla/docker/nova/nova-api/Dockerfile.j220
-rw-r--r--kolla/docker/nova/nova-api/extend_start.sh30
-rw-r--r--kolla/docker/nova/nova-base/Dockerfile.j286
-rw-r--r--kolla/docker/nova/nova-base/extend_start.sh10
-rw-r--r--kolla/docker/nova/nova-base/nova_sudoers1
-rw-r--r--kolla/docker/nova/nova-compute-ironic/Dockerfile.j223
-rw-r--r--kolla/docker/nova/nova-compute/Dockerfile.j2112
-rw-r--r--kolla/docker/nova/nova-compute/extend_start.sh5
-rw-r--r--kolla/docker/nova/nova-conductor/Dockerfile.j218
-rw-r--r--kolla/docker/nova/nova-conductor/extend_start.sh17
-rw-r--r--kolla/docker/nova/nova-libvirt-spice/Dockerfile.j2120
-rw-r--r--kolla/docker/nova/nova-libvirt-spice/extend_start.sh11
-rw-r--r--kolla/docker/nova/nova-libvirt-spice/kolla_nova_libvirt_start.sh12
-rw-r--r--kolla/docker/nova/nova-libvirt/Dockerfile.j2100
-rw-r--r--kolla/docker/nova/nova-libvirt/extend_start.sh11
-rw-r--r--kolla/docker/nova/nova-libvirt/kolla_nova_libvirt_start.sh12
-rw-r--r--kolla/docker/nova/nova-novncproxy/Dockerfile.j221
-rw-r--r--kolla/docker/nova/nova-scheduler/Dockerfile.j215
-rw-r--r--kolla/docker/nova/nova-serialproxy/Dockerfile.j215
-rw-r--r--kolla/docker/nova/nova-spicehtml5proxy/Dockerfile.j233
-rw-r--r--kolla/docker/nova/nova-ssh/Dockerfile.j234
-rw-r--r--kolla/docker/nova/nova-ssh/extend_start.sh16
22 files changed, 722 insertions, 0 deletions
diff --git a/kolla/docker/nova/nova-api/Dockerfile.j2 b/kolla/docker/nova/nova-api/Dockerfile.j2
new file mode 100644
index 000000000..57846af79
--- /dev/null
+++ b/kolla/docker/nova/nova-api/Dockerfile.j2
@@ -0,0 +1,20 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_api_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{% set nova_api_packages = [
+] %}
+{{ macros.install_packages(nova_api_packages | customizable("packages")) }}
+
+COPY extend_start.sh /usr/local/bin/kolla_nova_extend_start
+RUN chmod 644 /usr/local/bin/kolla_nova_extend_start
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_api_footer %}{% endblock %}
+{% block footer %}{% endblock %}
diff --git a/kolla/docker/nova/nova-api/extend_start.sh b/kolla/docker/nova/nova-api/extend_start.sh
new file mode 100644
index 000000000..ead6c252b
--- /dev/null
+++ b/kolla/docker/nova/nova-api/extend_start.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# TODO(dszumski): When Nova Conductor in Kolla Ansible supports triggering DB
+# operations, we should review this script and remove any duplicate
+# operations. This is probably anything that isn't to do with the API.
+
+# Bootstrap and exit if KOLLA_BOOTSTRAP variable is set. This catches all cases
+# of the KOLLA_BOOTSTRAP variable being set, including empty.
+if [[ "${!KOLLA_BOOTSTRAP[@]}" ]]; then
+ nova-manage api_db sync
+ nova-manage db sync --local_cell
+ nova-manage db online_data_migrations
+ exit 0
+fi
+
+if [[ "${!KOLLA_UPGRADE[@]}" ]]; then
+ nova-manage api_db sync
+ nova-manage db sync --local_cell
+ exit 0
+fi
+
+if [[ "${!KOLLA_OSM[@]}" ]]; then
+ nova-manage db online_data_migrations
+ exit 0
+fi
+
+if [[ "${!KOLLA_UPGRADE_CHECK[@]}" ]]; then
+ nova-status upgrade check
+ exit $?
+fi
diff --git a/kolla/docker/nova/nova-base/Dockerfile.j2 b/kolla/docker/nova/nova-base/Dockerfile.j2
new file mode 100644
index 000000000..423a9760a
--- /dev/null
+++ b/kolla/docker/nova/nova-base/Dockerfile.j2
@@ -0,0 +1,86 @@
+FROM {{ namespace }}/{{ image_prefix }}openstack-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_base_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.configure_user(name='nova', groups='qemu') }}
+
+{% if base_package_type == 'rpm' %}
+
+{{ macros.enable_extra_repos(['openvswitch']) }}
+
+ {% set nova_base_packages = [
+ 'openvswitch${KOLLA_RPM_OVS_VERSION}',
+ 'python3-openvswitch${KOLLA_RPM_OVS_VERSION}'
+ ] %}
+ {% if base_arch == 'x86_64' %}
+ {% set nova_base_packages = nova_base_packages + [
+ 'edk2-ovmf'
+ ] %}
+ {% elif base_arch == 'aarch64' %}
+ {% set nova_base_packages = nova_base_packages + [
+ 'edk2-aarch64'
+ ] %}
+ {% endif %}
+
+{% elif base_package_type == 'deb' %}
+
+ {% set nova_base_packages = [
+ 'dnsmasq',
+ 'ebtables',
+ 'iproute2',
+ 'iptables',
+ 'openssh-client',
+ 'openvswitch-switch',
+ 'python3-libvirt',
+ 'python3-openvswitch'
+ ] %}
+ {% if base_arch == 'x86_64' %}
+ {% set nova_base_packages = nova_base_packages + [
+ 'ovmf'
+ ] %}
+ {% elif base_arch == 'aarch64' %}
+ {% set nova_base_packages = nova_base_packages + [
+ 'qemu-efi-aarch64',
+ ] %}
+ {% endif %}
+
+{% endif %}
+
+{{ macros.install_packages(nova_base_packages | customizable("packages")) }}
+
+ADD nova-base-archive /nova-base-source
+ADD plugins-archive /
+
+{% set nova_base_pip_packages = [
+ '/nova'
+] %}
+
+{% set nova_base_plugins_pip_packages = [
+ '/plugins/*'
+] %}
+
+COPY nova_sudoers /etc/sudoers.d/kolla_nova_sudoers
+COPY extend_start.sh /usr/local/bin/kolla_extend_start
+
+RUN ln -s nova-base-source/* nova \
+ && {{ macros.install_pip(nova_base_pip_packages | customizable("pip_packages")) }} \
+ && mkdir -p /etc/nova/ \
+ && cp -r /nova/etc/nova/* /etc/nova/ \
+ && cp /var/lib/kolla/venv/etc/pycadf/nova_api_audit_map.conf /etc/nova/ \
+ && sed -i 's|^exec_dirs.*|exec_dirs=/var/lib/kolla/venv/bin,/sbin,/usr/sbin,/bin,/usr/bin,/usr/local/bin,/usr/local/sbin|g' /etc/nova/rootwrap.conf \
+ && if [ "$(ls /plugins)" ]; then \
+ {{ macros.install_pip(nova_base_plugins_pip_packages) }}; \
+ fi \
+ && chmod 750 /etc/sudoers.d \
+ && chmod 440 /etc/sudoers.d/kolla_nova_sudoers \
+ && touch /usr/local/bin/kolla_nova_extend_start \
+ && chmod 644 /usr/local/bin/kolla_extend_start /usr/local/bin/kolla_nova_extend_start
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_base_footer %}{% endblock %}
diff --git a/kolla/docker/nova/nova-base/extend_start.sh b/kolla/docker/nova/nova-base/extend_start.sh
new file mode 100644
index 000000000..eee0f16a1
--- /dev/null
+++ b/kolla/docker/nova/nova-base/extend_start.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+if [[ ! -d "/var/log/kolla/nova" ]]; then
+ mkdir -p /var/log/kolla/nova
+fi
+if [[ $(stat -c %a /var/log/kolla/nova) != "755" ]]; then
+ chmod 755 /var/log/kolla/nova
+fi
+
+. /usr/local/bin/kolla_nova_extend_start
diff --git a/kolla/docker/nova/nova-base/nova_sudoers b/kolla/docker/nova/nova-base/nova_sudoers
new file mode 100644
index 000000000..6d73da6d3
--- /dev/null
+++ b/kolla/docker/nova/nova-base/nova_sudoers
@@ -0,0 +1 @@
+nova ALL = (root) NOPASSWD: /var/lib/kolla/venv/bin/nova-rootwrap /etc/nova/rootwrap.conf *
diff --git a/kolla/docker/nova/nova-compute-ironic/Dockerfile.j2 b/kolla/docker/nova/nova-compute-ironic/Dockerfile.j2
new file mode 100644
index 000000000..3c455e2ec
--- /dev/null
+++ b/kolla/docker/nova/nova-compute-ironic/Dockerfile.j2
@@ -0,0 +1,23 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_compute_ironic_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{% set nova_compute_ironic_packages = [
+ 'genisoimage',
+ 'nvme-cli',
+ 'xorriso'
+] %}
+
+{{ macros.install_packages(nova_compute_ironic_packages | customizable("packages")) }}
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_compute_ironic_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-compute/Dockerfile.j2 b/kolla/docker/nova/nova-compute/Dockerfile.j2
new file mode 100644
index 000000000..8b3c1bcfe
--- /dev/null
+++ b/kolla/docker/nova/nova-compute/Dockerfile.j2
@@ -0,0 +1,112 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_compute_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{% if base_package_type == 'rpm' %}
+
+{{ macros.enable_extra_repos(['ceph', 'epel']) }}
+
+ {% set nova_compute_packages = [
+ 'ceph-common',
+ 'cyrus-sasl-md5',
+ 'cyrus-sasl-scram',
+ 'device-mapper-multipath',
+ 'dosfstools',
+ 'e2fsprogs',
+ 'genisoimage',
+ 'iscsi-initiator-utils',
+ 'libosinfo',
+ 'ndctl',
+ 'nfs-utils',
+ 'nvme-cli',
+ 'parted',
+ 'python3-libguestfs',
+ 'python3-libvirt',
+ 'python3-rtslib',
+ 'qemu-img',
+ 'qemu-kvm-block-rbd',
+ 'rsync',
+ 'sysfsutils',
+ 'targetcli',
+ 'xfsprogs'
+ ] %}
+
+ # NOTE(hrw): daxio is part of pmdk which is x86-64 only in CentOS 8
+ {% if base_arch == 'x86_64' %}
+ {% set nova_compute_packages = nova_compute_packages + [
+ 'daxio'
+ ] %}
+ {% endif %}
+
+{{ macros.install_packages(nova_compute_packages | customizable("packages")) }}
+
+{% elif base_package_type == 'deb' %}
+
+ {% set nova_compute_packages = [
+ 'ceph-common',
+ 'dosfstools',
+ 'e2fsprogs',
+ 'genisoimage',
+ 'libosinfo-bin',
+ 'libsasl2-modules-gssapi-mit',
+ 'multipath-tools',
+ 'ndctl',
+ 'nfs-common',
+ 'nvme-cli',
+ 'open-iscsi',
+ 'parted',
+ 'pmdk-tools',
+ 'python3-cephfs',
+ 'python3-guestfs',
+ 'python3-libvirt',
+ 'python3-rados',
+ 'python3-rbd',
+ 'python3-rtslib-fb',
+ 'qemu-block-extra',
+ 'qemu-utils',
+ 'rsync',
+ 'sasl2-bin',
+ 'swtpm',
+ 'swtpm-tools',
+ 'sysfsutils',
+ 'targetcli-fb',
+ 'tpm2-tools',
+ 'xfsprogs'
+ ] %}
+
+RUN mkdir -p /etc/ceph \
+ && {{ macros.install_packages(nova_compute_packages | customizable("packages"), chain=True) }}
+
+{% endif %}
+
+{% set nova_compute_pip_packages = [
+ 'oslo-vmware'
+ ]
+%}
+
+{% set nova_compute_plugins_pip_packages = [
+ '/plugins/*'
+] %}
+
+ADD plugins-archive /
+
+COPY extend_start.sh /usr/local/bin/kolla_nova_extend_start
+
+RUN {{ macros.install_pip(nova_compute_pip_packages | customizable("pip_packages")) }} \
+ && if [ "$(ls /plugins)" ]; then \
+ {{ macros.install_pip(nova_compute_plugins_pip_packages) }}; \
+ fi \
+ && chmod 644 /usr/local/bin/kolla_nova_extend_start \
+ && rm -f /etc/machine-id
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_compute_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-compute/extend_start.sh b/kolla/docker/nova/nova-compute/extend_start.sh
new file mode 100644
index 000000000..a458625ec
--- /dev/null
+++ b/kolla/docker/nova/nova-compute/extend_start.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+if [[ ! -d /var/lib/nova/instances ]]; then
+ mkdir -p /var/lib/nova/instances
+fi
diff --git a/kolla/docker/nova/nova-conductor/Dockerfile.j2 b/kolla/docker/nova/nova-conductor/Dockerfile.j2
new file mode 100644
index 000000000..b14000400
--- /dev/null
+++ b/kolla/docker/nova/nova-conductor/Dockerfile.j2
@@ -0,0 +1,18 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_conductor_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+COPY extend_start.sh /usr/local/bin/kolla_nova_extend_start
+RUN chmod 644 /usr/local/bin/kolla_nova_extend_start
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_conductor_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-conductor/extend_start.sh b/kolla/docker/nova/nova-conductor/extend_start.sh
new file mode 100644
index 000000000..72c9493f5
--- /dev/null
+++ b/kolla/docker/nova/nova-conductor/extend_start.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+if [[ "${!KOLLA_BOOTSTRAP[@]}" ]]; then
+ nova-manage db sync --local_cell
+ nova-manage db online_data_migrations
+ exit 0
+fi
+
+if [[ "${!KOLLA_UPGRADE[@]}" ]]; then
+ nova-manage db sync --local_cell
+ exit 0
+fi
+
+if [[ "${!KOLLA_OSM[@]}" ]]; then
+ nova-manage db online_data_migrations
+ exit 0
+fi
diff --git a/kolla/docker/nova/nova-libvirt-spice/Dockerfile.j2 b/kolla/docker/nova/nova-libvirt-spice/Dockerfile.j2
new file mode 100644
index 000000000..4c7ded894
--- /dev/null
+++ b/kolla/docker/nova/nova-libvirt-spice/Dockerfile.j2
@@ -0,0 +1,120 @@
+FROM {{ namespace }}/{{ image_prefix }}base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}" build-date="{{ build_date }}"
+{% endblock %}
+
+{% block nova_libvirt_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.configure_user(name='nova', groups='qemu') }}
+
+{% if base_package_type == 'rpm' %}
+
+ {% set nova_libvirt_extra_repos = ['ceph', 'crb', 'epel', 'openvswitch'] %}
+ {% if base_distro == 'rocky' %}
+ {#
+ The stock Rocky qemu-kvm has SPICE compiled out. To enable
+ Kerbside and the nova ``spice-direct`` console we therefore
+ layer the ligenix COPR in so that qemu-kvm and spice-server
+ are available with SPICE re-enabled. The repo definition
+ lives in kolla/template/repos.yaml so deployers can override
+ it like any other extra repo.
+ #}
+ {% set nova_libvirt_extra_repos = nova_libvirt_extra_repos + ['ligenix-qemu-spice'] %}
+ {% endif %}
+
+{{ macros.enable_extra_repos(nova_libvirt_extra_repos) }}
+
+ {% set nova_libvirt_packages = [
+ 'ceph-common',
+ 'cyrus-sasl-md5',
+ 'cyrus-sasl-scram',
+ 'libguestfs',
+ 'libvirt-client',
+ 'libvirt-daemon',
+ 'libvirt-daemon-log',
+ 'libvirt-daemon-config-nwfilter',
+ 'libvirt-daemon-driver-nwfilter',
+ 'libvirt-daemon-driver-nodedev',
+ 'openvswitch${KOLLA_RPM_OVS_VERSION}',
+ 'qemu-img',
+ 'qemu-kvm',
+ 'swtpm',
+ ] %}
+ {% if base_arch == 'x86_64' %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'edk2-ovmf'
+ ] %}
+ {% elif base_arch == 'aarch64' %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'edk2-aarch64'
+ ] %}
+ {% endif %}
+
+ {% if use_ligenix_qemu | default(false) and base_distro == 'rocky' %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'qemu-kvm-ui-spice',
+ 'spice-server',
+ ] %}
+ {% endif %}
+
+{% elif base_package_type == 'deb' %}
+
+ {% set nova_libvirt_packages = [
+ 'ceph-common',
+ 'ebtables',
+ 'libsasl2-modules-gssapi-mit',
+ 'libvirt-clients',
+ 'libvirt-daemon-system',
+ 'mdevctl',
+ 'openvswitch-switch',
+ 'pm-utils',
+ 'python3-cephfs',
+ 'python3-rados',
+ 'python3-rbd',
+ 'qemu-block-extra',
+ 'qemu-system',
+ 'qemu-system-modules-spice',
+ 'qemu-utils',
+ 'sasl2-bin',
+ 'swtpm',
+ 'swtpm-tools',
+ 'tpm2-tools',
+ 'trousers'
+ ] %}
+
+ {% if base_arch == "aarch64" %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'qemu-efi-aarch64'
+ ] %}
+ {% elif base_arch == "x86_64" %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'ovmf',
+ ] %}
+ {% endif %}
+
+ {% if base_distro in ['debian'] %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'libvirt-daemon-log',
+ 'usermode'
+ ] %}
+ {% endif %}
+{% endif %}
+
+{{ macros.install_packages(nova_libvirt_packages | customizable("packages")) }}
+
+{% if base_package_type == 'deb' %}
+
+RUN rm -f /etc/libvirt/qemu/networks/default.xml /etc/libvirt/qemu/networks/autostart/default.xml
+
+{% endif %}
+
+COPY extend_start.sh /usr/local/bin/kolla_extend_start
+COPY kolla_nova_libvirt_start.sh /usr/local/bin/kolla_nova_libvirt_start
+RUN chmod 644 /usr/local/bin/kolla_extend_start && chmod 744 /usr/local/bin/kolla_nova_libvirt_start
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_libvirt_footer %}{% endblock %}
+{% block footer %}{% endblock %}
diff --git a/kolla/docker/nova/nova-libvirt-spice/extend_start.sh b/kolla/docker/nova/nova-libvirt-spice/extend_start.sh
new file mode 100644
index 000000000..cc41b480b
--- /dev/null
+++ b/kolla/docker/nova/nova-libvirt-spice/extend_start.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+if [[ ! -e "/var/log/kolla/libvirt/libvirtd.log" ]]; then
+ mkdir -p /var/log/kolla/libvirt
+ touch /var/log/kolla/libvirt/libvirtd.log
+ chmod 644 /var/log/kolla/libvirt/libvirtd.log
+fi
+if [[ $(stat -c %a /var/log/kolla/libvirt) != "755" ]]; then
+ chmod 755 /var/log/kolla/libvirt
+ chmod 644 /var/log/kolla/libvirt/libvirtd.log
+fi
diff --git a/kolla/docker/nova/nova-libvirt-spice/kolla_nova_libvirt_start.sh b/kolla/docker/nova/nova-libvirt-spice/kolla_nova_libvirt_start.sh
new file mode 100644
index 000000000..f06a63d9e
--- /dev/null
+++ b/kolla/docker/nova/nova-libvirt-spice/kolla_nova_libvirt_start.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -euo pipefail
+
+# NOTE(mikal): Start virtlogd as a sidecar. We need this for
+# nova instance console logs to rotate. Otherwise they will
+# consume unbounded amounts of disk.
+#
+# No exec here: libvirtd will be the "main" process.
+/usr/sbin/virtlogd &
+
+# Now hand over PID 1's direct child role to libvirtd.
+exec /usr/sbin/libvirtd --listen
diff --git a/kolla/docker/nova/nova-libvirt/Dockerfile.j2 b/kolla/docker/nova/nova-libvirt/Dockerfile.j2
new file mode 100644
index 000000000..fb82401b3
--- /dev/null
+++ b/kolla/docker/nova/nova-libvirt/Dockerfile.j2
@@ -0,0 +1,100 @@
+FROM {{ namespace }}/{{ image_prefix }}base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_libvirt_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.configure_user(name='nova', groups='qemu') }}
+
+{% if base_package_type == 'rpm' %}
+
+{{ macros.enable_extra_repos(['ceph', 'crb', 'epel', 'openvswitch']) }}
+
+ {% set nova_libvirt_packages = [
+ 'ceph-common',
+ 'cyrus-sasl-md5',
+ 'cyrus-sasl-scram',
+ 'libguestfs',
+ 'libvirt-client',
+ 'libvirt-daemon',
+ 'libvirt-daemon-log',
+ 'libvirt-daemon-config-nwfilter',
+ 'libvirt-daemon-driver-nwfilter',
+ 'libvirt-daemon-driver-nodedev',
+ 'openvswitch${KOLLA_RPM_OVS_VERSION}',
+ 'qemu-img',
+ 'qemu-kvm',
+ 'swtpm',
+ ] %}
+ {% if base_arch == 'x86_64' %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'edk2-ovmf'
+ ] %}
+ {% elif base_arch == 'aarch64' %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'edk2-aarch64'
+ ] %}
+ {% endif %}
+
+{% elif base_package_type == 'deb' %}
+
+ {% set nova_libvirt_packages = [
+ 'ceph-common',
+ 'ebtables',
+ 'libsasl2-modules-gssapi-mit',
+ 'libvirt-clients',
+ 'libvirt-daemon-system',
+ 'mdevctl',
+ 'openvswitch-switch',
+ 'pm-utils',
+ 'python3-cephfs',
+ 'python3-rados',
+ 'python3-rbd',
+ 'qemu-block-extra',
+ 'qemu-system',
+ 'qemu-system-modules-spice',
+ 'qemu-utils',
+ 'sasl2-bin',
+ 'swtpm',
+ 'swtpm-tools',
+ 'tpm2-tools',
+ 'trousers'
+ ] %}
+
+ {% if base_arch == "aarch64" %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'qemu-efi-aarch64'
+ ] %}
+ {% elif base_arch == "x86_64" %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'ovmf',
+ ] %}
+ {% endif %}
+
+ {% if base_distro in ['debian'] %}
+ {% set nova_libvirt_packages = nova_libvirt_packages + [
+ 'libvirt-daemon-log',
+ 'usermode'
+ ] %}
+ {% endif %}
+{% endif %}
+
+{{ macros.install_packages(nova_libvirt_packages | customizable("packages")) }}
+
+{% if base_package_type == 'deb' %}
+
+RUN rm -f /etc/libvirt/qemu/networks/default.xml /etc/libvirt/qemu/networks/autostart/default.xml
+
+{% endif %}
+
+COPY extend_start.sh /usr/local/bin/kolla_extend_start
+COPY kolla_nova_libvirt_start.sh /usr/local/bin/kolla_nova_libvirt_start
+RUN chmod 644 /usr/local/bin/kolla_extend_start && chmod 744 /usr/local/bin/kolla_nova_libvirt_start
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_libvirt_footer %}{% endblock %}
+{% block footer %}{% endblock %}
diff --git a/kolla/docker/nova/nova-libvirt/extend_start.sh b/kolla/docker/nova/nova-libvirt/extend_start.sh
new file mode 100644
index 000000000..cc41b480b
--- /dev/null
+++ b/kolla/docker/nova/nova-libvirt/extend_start.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+if [[ ! -e "/var/log/kolla/libvirt/libvirtd.log" ]]; then
+ mkdir -p /var/log/kolla/libvirt
+ touch /var/log/kolla/libvirt/libvirtd.log
+ chmod 644 /var/log/kolla/libvirt/libvirtd.log
+fi
+if [[ $(stat -c %a /var/log/kolla/libvirt) != "755" ]]; then
+ chmod 755 /var/log/kolla/libvirt
+ chmod 644 /var/log/kolla/libvirt/libvirtd.log
+fi
diff --git a/kolla/docker/nova/nova-libvirt/kolla_nova_libvirt_start.sh b/kolla/docker/nova/nova-libvirt/kolla_nova_libvirt_start.sh
new file mode 100644
index 000000000..f06a63d9e
--- /dev/null
+++ b/kolla/docker/nova/nova-libvirt/kolla_nova_libvirt_start.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+set -euo pipefail
+
+# NOTE(mikal): Start virtlogd as a sidecar. We need this for
+# nova instance console logs to rotate. Otherwise they will
+# consume unbounded amounts of disk.
+#
+# No exec here: libvirtd will be the "main" process.
+/usr/sbin/virtlogd &
+
+# Now hand over PID 1's direct child role to libvirtd.
+exec /usr/sbin/libvirtd --listen
diff --git a/kolla/docker/nova/nova-novncproxy/Dockerfile.j2 b/kolla/docker/nova/nova-novncproxy/Dockerfile.j2
new file mode 100644
index 000000000..4952ed734
--- /dev/null
+++ b/kolla/docker/nova/nova-novncproxy/Dockerfile.j2
@@ -0,0 +1,21 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_novncproxy_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{% set nova_novncproxy_packages = [
+ 'novnc'
+] %}
+
+{{ macros.install_packages(nova_novncproxy_packages | customizable("packages")) }}
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_novncproxy_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-scheduler/Dockerfile.j2 b/kolla/docker/nova/nova-scheduler/Dockerfile.j2
new file mode 100644
index 000000000..5b0b0b98e
--- /dev/null
+++ b/kolla/docker/nova/nova-scheduler/Dockerfile.j2
@@ -0,0 +1,15 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_scheduler_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_scheduler_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-serialproxy/Dockerfile.j2 b/kolla/docker/nova/nova-serialproxy/Dockerfile.j2
new file mode 100644
index 000000000..c63e925d5
--- /dev/null
+++ b/kolla/docker/nova/nova-serialproxy/Dockerfile.j2
@@ -0,0 +1,15 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_serialproxy_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_serialproxy_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-spicehtml5proxy/Dockerfile.j2 b/kolla/docker/nova/nova-spicehtml5proxy/Dockerfile.j2
new file mode 100644
index 000000000..f3a90b0c5
--- /dev/null
+++ b/kolla/docker/nova/nova-spicehtml5proxy/Dockerfile.j2
@@ -0,0 +1,33 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_spicehtml5proxy_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{% if base_package_type == 'rpm' %}
+
+ {% set nova_spicehtml5proxy_packages = [
+ 'python3-numpy',
+ 'spice-html5'
+ ] %}
+
+{% elif base_package_type == 'deb' %}
+
+ {% set nova_spicehtml5proxy_packages = [
+ 'spice-html5',
+ 'websockify'
+ ] %}
+
+{% endif %}
+
+{{ macros.install_packages(nova_spicehtml5proxy_packages | customizable("packages")) }}
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_spicehtml5proxy_footer %}{% endblock %}
+{% block footer %}{% endblock %}
+
+USER nova
diff --git a/kolla/docker/nova/nova-ssh/Dockerfile.j2 b/kolla/docker/nova/nova-ssh/Dockerfile.j2
new file mode 100644
index 000000000..0d9e36b65
--- /dev/null
+++ b/kolla/docker/nova/nova-ssh/Dockerfile.j2
@@ -0,0 +1,34 @@
+FROM {{ namespace }}/{{ image_prefix }}nova-base:{{ tag }}
+{% block labels %}
+LABEL maintainer="{{ maintainer }}" name="{{ image_name }}"
+{% endblock %}
+
+{% block nova_ssh_header %}{% endblock %}
+
+{% import "macros.j2" as macros with context %}
+
+{{ macros.configure_user(name='nova', shell='/bin/bash') }}
+
+{% set nova_ssh_packages = [
+ 'openssh-server',
+ 'rsync'
+] %}
+
+{% if base_package_type == 'deb' %}
+
+RUN mkdir -p /var/run/sshd \
+ && chmod 0755 /var/run/sshd
+
+{% endif %}
+
+{{ macros.install_packages(nova_ssh_packages | customizable("packages")) }}
+
+COPY extend_start.sh /usr/local/bin/kolla_extend_start
+
+RUN sed -ri 's/session(\s+)required(\s+)pam_loginuid.so/session\1optional\2pam_loginuid.so/' /etc/pam.d/sshd \
+ && chmod 644 /usr/local/bin/kolla_extend_start
+
+{{ macros.kolla_patch_sources() }}
+
+{% block nova_ssh_footer %}{% endblock %}
+{% block footer %}{% endblock %}
diff --git a/kolla/docker/nova/nova-ssh/extend_start.sh b/kolla/docker/nova/nova-ssh/extend_start.sh
new file mode 100644
index 000000000..b80114c0a
--- /dev/null
+++ b/kolla/docker/nova/nova-ssh/extend_start.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+SSH_HOST_KEY_TYPES=( "rsa" "ecdsa" "ed25519" )
+
+for key_type in ${SSH_HOST_KEY_TYPES[@]}; do
+ KEY_PATH=/etc/ssh/ssh_host_${key_type}_key
+ if [[ ! -f "${KEY_PATH}" ]]; then
+ ssh-keygen -q -t ${key_type} -f ${KEY_PATH} -N ""
+ fi
+done
+
+mkdir -p /var/lib/nova/.ssh
+
+if [[ $(stat -c %U:%G /var/lib/nova/.ssh) != "nova:nova" ]]; then
+ chown nova: /var/lib/nova/.ssh
+fi