Skip to content
Merged
68 changes: 50 additions & 18 deletions roles/os_images/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ on the build host.

`os_images_cache`: a path to a directory in which to cache build artefacts.
It defaults to `~/disk_images`
`NOTE`: new images will NOT be built, even if changes are made in config, if an image is already cached.
Use `force_rebuild` flag in order to apply new config changes.
`NOTE`: new images will NOT be built, even if changes are made in config, if an image
is already cached. Use `force_rebuild` flag in order to apply new config changes.

`os_images_auth_type`: OpenStack authentication endpoint and credentials.
Defaults to `password`.
Expand Down Expand Up @@ -57,25 +57,34 @@ mutually exclusive where each contain:
This is a dict of the form of `KEY: VALUE`.
* `packages`: (optional) list of packages to install in the image.
* `size`: (optional) size to make the image filesystem.
* `architecture`: (optional) image CPU architecture to pass to diskimage-builder `-a`.
If unset, default to the diskimage-builder default architecture: `x86_64`, and upload
Glance images with the `cpu_arch: "x86_64"` image property. If architecture is set
to `arm64` or `aarch64`, Glance images with the `cpu_arch: "aarch64"` image property
When setting to other values, consider also setting `properties.cpu_arch` to a
corresponding value.
* `properties`: (optional) dict of properties to set on the glance image.
Common image properties are available
[here](https://docs.openstack.org/glance/latest/user/common-image-properties.html).
* `type`: (optional) image type. Default in DIB is qcow2. Image formats are
available [here](https://docs.openstack.org/glance/latest/user/formats.html).
* `force_rebuild`: (optional) boolean flag indicating whether or not the image should always
be built (even if an existing image that name has been built before). The images on glance
will be replaced if `os_images_upload` is set to `True`. This defaults to
* `force_rebuild`: (optional) boolean flag indicating whether or not the image should
always be built (even if an existing image that name has been built before). The images
in glance will be replaced if `os_images_upload` is set to `True`. This defaults to
`os_images_force_rebuild`if left unset.
* `is_public`: (optional) (deprecated - use `visibility`) whether the image should be set as visible to all
projects or kept private. Note that if both `is_public` and `visibility` are provided, `is_public` will
be preferred.
* `is_public`: (optional) (deprecated - use `visibility`) whether the image should be set
as visible to all projects or kept private. Note that if both `is_public` and `visibility`
are provided, `is_public` will be preferred.
* `visibility`: (optional) Allowed values are 'public', 'private', 'shared'
or 'community'. Default is 'public'
or 'community'. Default is 'public'
* `owner`: (optional) ID of the project that should own the uploaded image.

`os_images_common`: A set of elements to include in every image listed.
Defaults to `cloud-init enable-serial-console stable-interface-names`.

`os_images_common_properties`: A dict of Glance image properties to set on all images.
Defaults to an empty dict, and is overridden by `os_images_list.*.properties`.

`os_images_dib_pkg_name`: Optionally customise the name parameter passed
to the ansible.builtin.pip module when installing diskimage-builder. This can
be used to install diskimage-builder from version control.
Expand All @@ -96,27 +105,50 @@ following parameters:

`os_images_upload`: Whether to upload built images to Glance. Defaults to `True`.

`os_images_force_rebuild`: Whether or not to force a rebuild of the DIB image. The images on Glance
will be replaced with the newly built image if `os_images_upload` is set to `True`. Defaults to
`False`.
`os_images_force_rebuild`: Whether or not to force a rebuild of the DIB image.
The images on Glance will be replaced with the newly built image if `os_images_upload`
is set to `True`. Defaults to `False`.

`os_images_public`: (Deprecated - use `os_images_visibility`) Whether uploaded images are public. Defaults to `True` - note this requires admin permissions.
`os_images_public`: (Deprecated - use `os_images_visibility`) Whether uploaded
images are public. Defaults to `True` - note this requires admin permissions.

`os_images_visibility`: The visibility of images uploaded. One of `community`,`public` or `private`. If unset, defaults to `os_images_public` (requires admin permissions for anything other than `private`)
`os_images_visibility`: The visibility of images uploaded. One of `community`,
`public` or `private`. If unset, defaults to `os_images_public` (requires admin
permissions for anything other than `private`)

`os_images_venv`: Path to virtualenv in which to install python dependencies to upload images.
`os_images_venv`: Path to virtualenv in which to install python dependencies to
upload images.

`os_images_dib_venv`: Path to virtualenv in which to install DIB to build images.

`os_images_promote`: Whether or not to promote new images. Defaults to `False`.

`os_images_retire`: Whether or not to retire old images. Defaults to `os_image_promote`. May be necessary to set separately if you are promoting a new candidate image for which there is no existing one to retire, for example.
`os_images_retire`: Whether or not to retire old images. Defaults to `os_image_promote`.
May be necessary to set separately if you are promoting a new candidate image for which
there is no existing one to retire, for example.

`os_images_build`: Whether or not to build the images.

`os_images_name_suffix`: Image suffix which would be removed during image promotion, for exmple: -rc, -dev, -test etc. Mandatory for promotion functionality. Empty by default.
`os_images_name_suffix`: Image suffix which would be removed during image promotion, for
exmple: -rc, -dev, -test etc. Mandatory for promotion functionality. Empty by default.

`os_images_hide`: Whether or not to hide the images in Glance list. Hiding images is
available as an option in image retirement/promotion process. Defaults to `False`.

Changing platform architecture in os_images
-------------------------------------------

The target CPU architecture for each image defined in `os_images_list` may be set to any
architecture supported by diskimage-builder with the `architecture` parameter.

If it is unset, an image with the default diskimage-builder architecture (`x86_64`) will
be built and optionally uploaded to Glance, with the Glance image property `cpu_arch` set
to `x86_64`. If it is set to `arm64` or `aarch64`, images will be uploaded to Glance with
the Glance image property `cpu_arch` set to `aarch64`.

`os_images_hide`: Whether or not to hide the images in Glance list. Hiding images is available as an option in image retirement/promotion process. Defaults to `False`.
If setting to a different `architecture`, consider also setting `properties.cpu_arch` to an
architecture
[supported by Glance](https://docs.openstack.org/glance/latest/admin/useful-image-properties.html#image-property-keys-and-values).

Dependencies
------------
Expand Down
3 changes: 1 addition & 2 deletions roles/os_images/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ os_images_common: cloud-init enable-serial-console stable-interface-names
# type: qcow2
os_images_list: []
# Common properties to apply to all glance images.
os_images_common_properties:
cpu_arch: x86_64
os_images_common_properties: {}

# OpenStack authentication type: passed to the os_image Ansible module
os_images_auth_type: password
Expand Down
5 changes: 3 additions & 2 deletions roles/os_images/tasks/images.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@
- name: Generate diskimage-builder images
vars:
dib_args: >-
{% if item.size is defined %}--image-size {{ item.size }}{% endif %} {% if item.type is defined %}-t {{ item.type }}{% endif %} {% if item.packages | default
%}-p {{ item.packages | join(',') }}{% endif %} {{ os_images_common }} {{ item.elements | join(' ') }} -o {{ item.name }}
{% if item.size is defined %}--image-size {{ item.size }}{% endif %} {% if item.type is defined %}-t {{ item.type }}{% endif %}
{% if item.packages | default %}-p {{ item.packages | join(',') }}{% endif %} {{ os_images_common }} {{ item.elements | join(' ') }}
-o {{ item.name }} {% if item.architecture is defined %}-a {{ item.architecture }}{% endif %}
ansible.builtin.shell: . {{ os_images_dib_venv }}/bin/activate && disk-image-create {{ dib_args }} > {{ item.name }}.stdout 2> {{ item.name }}.stderr
args:
chdir: "{{ os_images_cache }}/{{ item.name }}"
Expand Down
12 changes: 12 additions & 0 deletions roles/os_images/tasks/prereqs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,15 @@
state: directory
mode: "0755"
become: true

- name: Run multiarch/qemu-user-static image to support cross-arch build
ansible.builtin.command:
# We already have a precheck for presence of docker executable so use it here
cmd: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
# Using --reset means that we always change something
changed_when: true
become: true
when: os_images_list |
selectattr("architecture", "defined") |
rejectattr("architecture", "equalto", ansible_facts.architecture) |
length > 0
14 changes: 13 additions & 1 deletion roles/os_images/tasks/upload.yml
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,22 @@
container_format: bare
disk_format: "{{ item.0.type | default('qcow2') }}"
filename: "{{ os_images_cache }}/{{ item.0.name }}/{{ item.0.name }}.{{ item.0.type | default('qcow2') }}"
properties: "{{ os_images_common_properties | combine(item.0.properties | default({})) or omit }}"
properties: "{{ os_images_common_properties | combine(cpu_arch_properties) | combine(item.0.properties | default({})) or omit }}"
kernel: "{{ item.1.id if is_baremetal else omit }}"
ramdisk: "{{ item.2.id if is_baremetal else omit }}"
vars:
# NOTE(m-anson): When architecture isn't defined for an
# image, assume that we should set cpu_arch: x86_64 as
# this is the diskimage-builder default. If an architecture
# of arm64 or aarch64 is defined, set cpu_arch: aarch64. In
# all other cases, leave it up to the operator to set
# properties.cpu_arch.
cpu_arch_properties: >-
{{
{"cpu_arch": "aarch64"}
if (item.0.architecture is defined and item.0.architecture in ["arm64", "aarch64"])
else ({"cpu_arch": "x86_64"} if item.0.architecture is not defined else {})
}}
is_baremetal: "{{ item.0.elements is defined and 'baremetal' in item.0.elements }}"
visibility: "{{ item.0.visibility | default(item.0.is_public | ternary('public', 'private') if item.0.is_public is defined else os_images_visibility) }}"
with_together:
Expand Down