diff --git a/.github/workflows/overcloud-host-image-build.yml b/.github/workflows/overcloud-host-image-build.yml new file mode 100644 index 000000000..cf9b62806 --- /dev/null +++ b/.github/workflows/overcloud-host-image-build.yml @@ -0,0 +1,177 @@ +--- +name: Build overcloud host images +on: + workflow_dispatch: + inputs: + centos: + description: Build CentOS Stream + type: boolean + default: true + rocky: + description: Build Rocky Linux + type: boolean + default: true + ubuntu: + description: Build Ubuntu + type: boolean + default: true + +env: + ANSIBLE_FORCE_COLOR: True +jobs: + overcloud-host-image-build: + name: Build overcloud host images + if: github.repository == 'stackhpc/stackhpc-kayobe-config' + runs-on: [self-hosted, stackhpc-kayobe-config-kolla-builder] + steps: + - uses: actions/checkout@v3 + with: + path: src/kayobe-config + + - name: Clone StackHPC Kayobe repository + uses: actions/checkout@v3 + with: + repository: stackhpc/kayobe + ref: refs/heads/stackhpc/xena + path: src/kayobe + + # FIXME: Failed in kolla-ansible : Ensure the latest version of pip is installed + - name: Install dependencies + run: | + sudo dnf -y install python3-virtualenv + + - name: Setup networking + run: | + if ! ip l show breth1 >/dev/null 2>&1; then + sudo ip l add breth1 type bridge + fi + sudo ip l set breth1 up + if ! ip a show breth1 | grep 192.168.33.3/24; then + sudo ip a add 192.168.33.3/24 dev breth1 + fi + if ! ip l show dummy1 >/dev/null 2>&1; then + sudo ip l add dummy1 type dummy + fi + sudo ip l set dummy1 up + sudo ip l set dummy1 master breth1 + + - name: Install Kayobe + run: | + mkdir -p venvs && + pushd venvs && + python3 -m venv kayobe && + source kayobe/bin/activate && + pip install -U pip && + pip install ../src/kayobe + + - name: Bootstrap the control host + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe control host bootstrap + + - name: Configure the seed host + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe seed host configure + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + + - name: Create bifrost_httpboot Docker volume + run: | + if [[ $(sudo docker volume ls -f Name=bifrost_httpboot -q | wc -l) = 0 ]]; then + sudo docker volume create bifrost_httpboot + fi + + - name: Clean any previous build artifact + run: | + rm -f /tmp/updated_images.txt + + - name: Build a CentOS Stream 8 overcloud host image + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe overcloud host image build --force-rebuild \ + -e os_distribution=centos \ + -e stackhpc_overcloud_dib_name=overcloud-centos-stream-8 + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: inputs.centos + + - name: Upload CentOS Stream 8 overcloud host image artifact + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe playbook run \ + src/kayobe-config/etc/kayobe/ansible/pulp-host-image-upload.yml \ + -e image_path='/opt/kayobe/images/overcloud-centos-stream-8' \ + -e os_distribution='centos' + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: inputs.centos + + - name: Build a Rocky Linux 8 overcloud host image + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe overcloud host image build --force-rebuild \ + -e os_distribution=rocky \ + -e stackhpc_overcloud_dib_name=overcloud-rocky-linux-8 + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: inputs.rocky + + - name: Upload Rocky Linux 8 overcloud host image artifact + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe playbook run \ + src/kayobe-config/etc/kayobe/ansible/pulp-host-image-upload.yml \ + -e image_path='/opt/kayobe/images/overcloud-rocky-linux-8' \ + -e os_distribution='rocky' + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: inputs.rocky + + # FIXME: Need EPEL on CentOS for debootstrap. It is disabled by default. + # Do this via config? + - name: Enable EPEL repository + run: | + sudo dnf config-manager --set-enabled epel + + - name: Build a Ubuntu Focal 20.04 overcloud host image + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe overcloud host image build --force-rebuild \ + -e os_distribution=ubuntu \ + -e stackhpc_overcloud_dib_name=overcloud-ubuntu-focal + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: inputs.ubuntu + + - name: Upload Ubuntu Focal 20.04 overcloud host image artifact + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe playbook run \ + src/kayobe-config/etc/kayobe/ansible/pulp-host-image-upload.yml \ + -e image_path='/opt/kayobe/images/overcloud-ubuntu-focal' \ + -e os_distribution='ubuntu' + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: inputs.ubuntu + + - name: Upload updated images artifact + uses: actions/upload-artifact@v3 + with: + name: Updated images list + path: /tmp/updated_images.txt + retention-days: 7 + if: always() + + - name: Clean up old images + run: | + sudo rm -rf /opt/kayobe/images/ + if: always() diff --git a/.github/workflows/overcloud-host-image-promote.yml b/.github/workflows/overcloud-host-image-promote.yml new file mode 100644 index 000000000..cacbd575e --- /dev/null +++ b/.github/workflows/overcloud-host-image-promote.yml @@ -0,0 +1,121 @@ +--- +name: Promote overcloud host image +on: + workflow_dispatch: + inputs: + os_image: + description: Image to promote + type: choice + required: true + default: 'CentOS Stream 8' + options: + - 'CentOS Stream 8' + - 'Rocky Linux 8' + - 'Ubuntu Focal 20.04' + image_tag: + description: Tag to promote + type: string + required: true +env: + ANSIBLE_FORCE_COLOR: True +jobs: + overcloud-host-image-promote: + name: Promote overcloud host image + if: github.repository == 'stackhpc/stackhpc-kayobe-config' + runs-on: [self-hosted, stackhpc-kayobe-config-kolla-builder] + steps: + - uses: actions/checkout@v3 + with: + path: src/kayobe-config + + - name: Clone StackHPC Kayobe repository + uses: actions/checkout@v3 + with: + repository: stackhpc/kayobe + ref: refs/heads/stackhpc/xena + path: src/kayobe + + # FIXME: Failed in kolla-ansible : Ensure the latest version of pip is installed + - name: Install dependencies + run: | + sudo dnf -y install python3-virtualenv + + - name: Setup networking + run: | + if ! ip l show breth1 >/dev/null 2>&1; then + sudo ip l add breth1 type bridge + fi + sudo ip l set breth1 up + if ! ip a show breth1 | grep 192.168.33.3/24; then + sudo ip a add 192.168.33.3/24 dev breth1 + fi + if ! ip l show dummy1 >/dev/null 2>&1; then + sudo ip l add dummy1 type dummy + fi + sudo ip l set dummy1 up + sudo ip l set dummy1 master breth1 + + - name: Install Kayobe + run: | + mkdir -p venvs && + pushd venvs && + python3 -m venv kayobe && + source kayobe/bin/activate && + pip install -U pip && + pip install ../src/kayobe + + - name: Bootstrap the control host + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe control host bootstrap + + - name: Configure the seed host + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe seed host configure + env: + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + + - name: Promote CentOS Stream 8 overcloud host image artifact + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe playbook run \ + src/kayobe-config/etc/kayobe/ansible/pulp-host-image-promote.yml \ + -e image_path='/opt/kayobe/images/overcloud-centos-stream-8' \ + -e os_distribution='centos' \ + -e os_release='8-stream' + env: + OVERCLOUD_HOST_IMAGE_TAG: ${{ inputs.image_tag }} + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: os_image == 'CentOS Stream 8' + + - name: Promote Rocky Linux 8 overcloud host image artifact + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe playbook run \ + src/kayobe-config/etc/kayobe/ansible/pulp-host-image-promote.yml \ + -e image_path='/opt/kayobe/images/overcloud-rocky-linux-8' \ + -e os_distribution='rocky' \ + -e os_release='8' + env: + OVERCLOUD_HOST_IMAGE_TAG: ${{ inputs.image_tag }} + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: os_image == 'Rocky Linux 8' + + - name: Promote Ubuntu Focal 20.04 overcloud host image artifact + run: | + source venvs/kayobe/bin/activate && + source src/kayobe-config/kayobe-env --environment ci-builder && + kayobe playbook run \ + src/kayobe-config/etc/kayobe/ansible/pulp-host-image-promote.yml \ + -e image_path='/opt/kayobe/images/overcloud-ubuntu-focal' \ + -e os_distribution='ubuntu' \ + -e os_release='focal' + env: + OVERCLOUD_HOST_IMAGE_TAG: ${{ inputs.image_tag }} + KAYOBE_VAULT_PASSWORD: ${{ secrets.KAYOBE_VAULT_PASSWORD }} + if: os_image == 'Ubuntu Focal 20.04' diff --git a/etc/kayobe/ansible/pulp-host-image-promote.yml b/etc/kayobe/ansible/pulp-host-image-promote.yml new file mode 100644 index 000000000..d93d71d51 --- /dev/null +++ b/etc/kayobe/ansible/pulp-host-image-promote.yml @@ -0,0 +1,40 @@ +--- +# Tag is the version of the image to promote, stored in an env variable named OVERCLOUD_HOST_IMAGE_TAG +- name: Promote an image to production + hosts: localhost + vars: + remote_pulp_url: "{{ stackhpc_release_pulp_url }}" + remote_pulp_username: "{{ stackhpc_image_repository_username }}" + remote_pulp_password: "{{ stackhpc_image_repository_password }}" + repository_name: "kayobe-images-{{ openstack_release }}-{{ os_distribution }}-{{ os_release }}" + base_path: "kayobe-images/{{ openstack_release }}/{{ os_distribution }}/{{ os_release }}" + promotion_tag: "{{ lookup('env', 'OVERCLOUD_HOST_IMAGE_TAG') }}" + tasks: + + - name: Check whether the image exists + pulp.squeezer.file_distribution: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + name: "{{ repository_name }}_{{ promotion_tag }}" + base_path: "{{ base_path }}/{{ promotion_tag }}" + register: distribution_details + + - name: Fail if the image does not exist + fail: + msg: "Image {{ promotion_tag }} does not exist" + when: distribution_details.distribution is none + + - name: Ensure production content guard is set + pulp.squeezer.file_distribution: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + name: "{{ repository_name }}_{{ promotion_tag }}" + base_path: "{{ base_path }}/{{ promotion_tag }}" + content_guard: release + state: present + + - name: Print version tag and os + debug: + msg: "Promoted tag: {{ promotion_tag }}" diff --git a/etc/kayobe/ansible/pulp-host-image-upload.yml b/etc/kayobe/ansible/pulp-host-image-upload.yml new file mode 100644 index 000000000..b2945c83f --- /dev/null +++ b/etc/kayobe/ansible/pulp-host-image-upload.yml @@ -0,0 +1,109 @@ +--- +- name: Upload and create a distribution for an image + hosts: localhost + vars: + remote_pulp_url: "{{ stackhpc_release_pulp_url }}" + remote_pulp_username: "{{ stackhpc_image_repository_username }}" + remote_pulp_password: "{{ stackhpc_image_repository_password }}" + repository_name: "kayobe-images-{{ openstack_release }}-{{ os_distribution }}-{{ os_release }}" + base_path: "kayobe-images/{{ openstack_release }}/{{ os_distribution }}/{{ os_release }}" + tasks: + - name: Get filename + find: + paths: "{{ image_path }}" + patterns: '*.qcow2' + register: found_files + + - name: Upload an artifact + pulp.squeezer.artifact: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + file: "{{ found_files.files[0].path }}" + state: present + + - name: Get sha256 hash + ansible.builtin.stat: + path: "{{ found_files.files[0].path }}" + checksum_algorithm: sha256 + register: file_stats + + - name: Create file content from artifact + pulp.squeezer.file_content: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + sha256: "{{ file_stats.stat.checksum }}" + relative_path: "{{ found_files.files[0].path | basename }}" + state: present + + - name: Ensure file repo exists + pulp.squeezer.file_repository: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + name: "{{ repository_name }}" + state: present + + - name: Add content to file repo + pulp.squeezer.file_repository_content: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + repository: "{{ repository_name }}" + present_content: + - relative_path: "{{ found_files.files[0].path | basename }}" + sha256: "{{ file_stats.stat.checksum }}" + + - name: Create a new publication to point to this version + pulp.squeezer.file_publication: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + repository: "{{ repository_name }}" + state: present + register: publication_details + + - name: Update distribution for latest version + pulp.squeezer.file_distribution: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + name: "{{ repository_name }}_latest" + base_path: "{{ base_path }}/latest" + publication: "{{ publication_details.publication.pulp_href }}" + content_guard: development + state: present + register: latest_distribution_details + + - name: Create distribution for given version + pulp.squeezer.file_distribution: + pulp_url: "{{ remote_pulp_url }}" + username: "{{ remote_pulp_username }}" + password: "{{ remote_pulp_password }}" + name: "{{ repository_name }}_{{ ansible_facts.date_time.iso8601_basic_short }}" + base_path: "{{ base_path }}/{{ ansible_facts.date_time.iso8601_basic_short }}" + publication: "{{ publication_details.publication.pulp_href }}" + content_guard: development + state: present + when: latest_distribution_details.changed + + - name: Update new images file with versioned path + lineinfile: + path: /tmp/updated_images.txt + line: "{{ remote_pulp_url }}/pulp/content/{{ base_path }}/\ + {{ ansible_facts.date_time.iso8601_basic_short }}/{{ found_files.files[0].path | basename }}" + create: true + when: latest_distribution_details.changed + + - name: Update new images file with latest path + lineinfile: + path: /tmp/updated_images.txt + line: "{{ remote_pulp_url }}/pulp/content/{{ base_path }}/\ + latest/{{ found_files.files[0].path | basename }}" + when: latest_distribution_details.changed + + - name: Print version tag + debug: + msg: "New tag: {{ ansible_facts.date_time.iso8601_basic_short }}" + when: latest_distribution_details.changed diff --git a/etc/kayobe/environments/ci-builder/overcloud-dib.yml b/etc/kayobe/environments/ci-builder/overcloud-dib.yml new file mode 100644 index 000000000..6a8f3b0f1 --- /dev/null +++ b/etc/kayobe/environments/ci-builder/overcloud-dib.yml @@ -0,0 +1,20 @@ +--- +# Overcloud host disk image configuration. + +############################################################################### +# Diskimage-builder configuration for overcloud host disk images. + +# Whether to build host disk images with DIB directly instead of through +# Bifrost. Setting it to true disables Bifrost image build and allows images to +# be built with the `kayobe overcloud host image build` command. Default value +# is False. This will change in a future release. +overcloud_dib_build_host_images: true + +# List of overcloud host disk images to build. Each element is a dict defining +# an image in a format accepted by the stackhpc.os-images role. Default is to +# build an image named "deployment_image" configured with the overcloud_dib_* +# variables defined below: {"name": "deployment_image", "elements": "{{ +# overcloud_dib_elements }}", "env": "{{ overcloud_dib_env_vars }}", +# "packages": "{{ overcloud_dib_packages }}"}. +overcloud_dib_host_images: + - "{{ stackhpc_overcloud_dib_host_image }}" diff --git a/etc/kayobe/overcloud-dib.yml b/etc/kayobe/overcloud-dib.yml index 9c34650ff..46a02830b 100644 --- a/etc/kayobe/overcloud-dib.yml +++ b/etc/kayobe/overcloud-dib.yml @@ -71,7 +71,7 @@ overcloud_dib_host_packages_extra: overcloud_dib_git_elements_extra: - repo: "https://github.com/stackhpc/stackhpc-image-elements" local: "{{ source_checkout_path }}/stackhpc-image-elements" - version: "v1.4.0" + version: "v1.5.0" elements_path: "elements" # List of git repositories containing Diskimage Builder (DIB) elements. See diff --git a/etc/kayobe/stackhpc-overcloud-dib.yml b/etc/kayobe/stackhpc-overcloud-dib.yml index 84fffbc0f..ab173b017 100644 --- a/etc/kayobe/stackhpc-overcloud-dib.yml +++ b/etc/kayobe/stackhpc-overcloud-dib.yml @@ -25,6 +25,7 @@ stackhpc_overcloud_dib_elements: - "cloud-init-datasources" - "{% if os_distribution in ['centos', 'rocky'] %}disable-selinux{% endif %}" - "enable-serial-console" + - "{% if kayobe_environment == 'ci-builder' %}etc-hosts{% endif %}" - "vm" - "block-device-efi" - "cloud-init" @@ -45,6 +46,9 @@ stackhpc_overcloud_dib_env_vars: # sometimes). # DIB_DISTRIBUTION_MIRROR: "{{ stackhpc_repo_ubuntu_focal_url if os_distribution == 'ubuntu' else '' }}" DIB_DRACUT_ENABLED_MODULES_DEFAULT_CONFIG: "{{ stackhpc_overcloud_dib_dracut_enabled_modules_default_config }}" + # FIXME: Workaround for lack of internal DNS on SMS lab. + DIB_ETC_HOSTS_EXTRA: | + 10.205.3.187 pulp-server pulp-server.internal.sms-cloud DIB_RELEASE: "{{ overcloud_dib_os_release }}" DIB_SUDOERS_FILENAME: "no-fqdn" # Avoid DNS queries during sudo commands, since we might not always have working DNS.