├── .gitignore ├── .gitreview ├── CONTRIBUTING.rst ├── LICENSE ├── README.rst ├── dib ├── burn-in │ ├── README.rst │ ├── element-deps │ └── package-installs.yaml ├── element │ └── ironic-python-agent-podman │ │ ├── README.rst │ │ ├── element-deps │ │ ├── environment.d │ │ └── 10-setup.bash │ │ ├── package-installs.yaml │ │ └── pre-finalise.d │ │ ├── 10-ipa-podman-config │ │ ├── 20-ipa-config │ │ └── 30-ipa-steps ├── extra-hardware │ ├── README.rst │ ├── element-deps │ ├── environment.d │ │ └── 10-enable-rdo-deps.bash │ ├── install.d │ │ ├── extra-hardware-package-install │ │ │ └── package-installs-extra-hardware │ │ └── extra-hardware-source-install │ │ │ └── 80-extra-hardware-install │ ├── package-installs.yaml │ ├── pkg-map │ └── pre-install.d │ │ └── 10-enable-rdo-deps ├── ironic-python-agent-ramdisk │ ├── README.rst │ ├── element-deps │ ├── element-provides │ ├── environment.d │ │ ├── 01-debian-ipa.bash │ │ ├── 10-defaults.bash │ │ └── 20-ipa-distro-family.bash │ ├── extra-data.d │ │ └── 15-ssl-ca-copy │ ├── install.d │ │ ├── ironic-python-agent-ramdisk-package-install │ │ │ └── package-installs-ironic-python-agent-ramdisk │ │ └── ironic-python-agent-ramdisk-source-install │ │ │ ├── 60-ironic-python-agent-ramdisk-install │ │ │ ├── ironic-python-agent.conf │ │ │ ├── ironic-python-agent.init │ │ │ └── ironic-python-agent.service │ ├── package-installs.yaml │ ├── pkg-map │ ├── post-install.d │ │ ├── 80-ironic-python-agent-ramdisk │ │ └── 99-remove-extra-packages │ ├── source-repository-ironic-python-agent │ ├── source-repository-requirements │ ├── static │ │ ├── etc │ │ │ ├── ironic-python-agent.d │ │ │ │ └── README │ │ │ └── systemd │ │ │ │ └── system │ │ │ │ ├── ironic-agent-create-rescue-user.path │ │ │ │ ├── ironic-agent-create-rescue-user.service │ │ │ │ └── ironic-agent-resolve-config-drive.service │ │ └── usr │ │ │ └── local │ │ │ └── bin │ │ │ ├── ironic-python-agent-create-rescue-user.sh │ │ │ └── ironic-python-agent-resolve-configdrive.sh │ └── svc-map ├── ironic-python-agent-tls │ ├── README.rst │ ├── element-deps │ └── pre-finalise.d │ │ └── 10-configure-ipa-tls ├── ironic-ramdisk-base │ ├── README.rst │ ├── cleanup.d │ │ ├── 98-prepare-resolve-conf │ │ └── 99-ramdisk-create │ ├── element-deps │ └── environment.d │ │ └── 10-checksum.bash └── multipath-io │ ├── README.md │ ├── element-deps │ ├── package-installs.yaml │ └── static │ └── etc │ └── modules-load.d │ └── iscsi.conf ├── doc ├── requirements.txt └── source │ ├── admin │ ├── dib.rst │ ├── index.rst │ └── tinyipa.rst │ ├── conf.py │ ├── contributor │ └── index.rst │ ├── index.rst │ └── install │ └── index.rst ├── ironic_python_agent_builder └── __init__.py ├── playbooks └── ironic-python-agent-build-image │ ├── extra-logs.yaml │ ├── post.yaml │ ├── pre.yaml │ └── run.yaml ├── releasenotes ├── notes │ ├── .placeholder │ ├── add-efibootmgr-d2a456de6b999612.yaml │ ├── add-efivar-f83fdf2d797396dc.yaml │ ├── add-ntpdate-3db2f8565fed761e.yaml │ ├── add-nvme-cli-590e42735476a549.yaml │ ├── centos7-python3-185f1d35c37096c7.yaml │ ├── centos8-46a95956fd871c90.yaml │ ├── centos8-stream-d9c83190e987e07d.yaml │ ├── centos9-0f925822a2ab9e0a.yaml │ ├── clean-var-tmp-with-dib-builds-cd31a2cf70a7f935.yaml │ ├── create-ramdisk-random-devices-263f78a2ef40dbe2.yaml │ ├── debian-9a4fa6b2d3ef96d0.yaml │ ├── debian-arm64-fc3cc4949e3100d9.yaml │ ├── debian-firmware-1927601ebb779bc4.yaml │ ├── debian-ipa-cb5975e436cba525.yaml │ ├── dhcp-predictible-ifnames-b2a1d9e6471b6819.yaml │ ├── drop-python2-534124afa50f62dd.yaml │ ├── excess-firmware-removal-debian-06c49a8604122b1c.yaml │ ├── extra-hardware-73e3c9b5a0143bfa.yaml │ ├── ironic-lib-6a16f13fc6ec9a50.yaml │ ├── ironic-ramdisk-base-3bfb9b90ad416891.yaml │ ├── linux-firmware-9a6f8a9a32c5719d.yaml │ ├── lzma-bf4552b98dd5824a.yaml │ ├── lzma-compression-level-1ca346ba8d5b905a.yaml │ ├── multipath-0eb6a4f3b2ee22a3.yaml │ ├── network-manager-auto-dhcp-all-interfaces-rhel-centos-relese-gt-7-0c2054d0067c6e93.yaml │ ├── no-fedora-aa65bcc43f9d56fa.yaml │ ├── no-firmware-e2cb953037a3be8f.yaml │ ├── no-iscsi-5d132e6468acab0b.yaml │ ├── no-sdparm-f77de72b5c0d7859.yaml │ ├── no-suse-e15d8384c423251c.yaml │ ├── python2-removal-dee895550b1959af.yaml │ ├── remove-PYOPTIMIZE_TINYIPA-ebde63911d140209.yaml │ ├── selinux-permissive-a059f42bb66373a1.yaml │ ├── tinycore13-caba5a4998bdd628.yaml │ ├── tinyipa-ci-testing-ends-8748513e6512cf8f.yaml │ └── tinyipa-tgt-226f74125238c239.yaml └── source │ ├── 2023.1.rst │ ├── 2023.2.rst │ ├── 2024.1.rst │ ├── 2024.2.rst │ ├── 2025.1.rst │ ├── _static │ └── .placeholder │ ├── _templates │ └── .placeholder │ ├── conf.py │ ├── index.rst │ ├── unreleased.rst │ ├── wallaby.rst │ ├── xena.rst │ ├── yoga.rst │ └── zed.rst ├── requirements.txt ├── roles ├── ipa-build-dib-image │ ├── defaults │ │ └── main.yaml │ └── tasks │ │ ├── install.yaml │ │ └── main.yaml └── ipa-build-tinyipa-image │ ├── defaults │ └── main.yaml │ └── tasks │ └── main.yaml ├── setup.cfg ├── setup.py ├── tinyipa ├── .gitignore ├── Makefile ├── README.rst ├── add-ssh-tinyipa.sh ├── build-instance-images.sh ├── build-iso.sh ├── build-tinyipa.sh ├── build_files │ ├── bootlocal.sh │ ├── buildreqs.lst │ ├── buildreqs_python3.lst │ ├── dhcp.sh │ ├── fakeuname │ ├── finalreqs.lst │ ├── finalreqs_python3.lst │ ├── isolinux.cfg │ ├── modprobe.conf │ └── ntpdate ├── common.sh ├── finalise-tinyipa.sh ├── generate_tox_constraints.sh ├── install-deps.sh ├── tc-mirror.sh └── udhcpc.script ├── tools └── iso-image-create ├── tox.ini └── zuul.d ├── ironic-python-agent-builder-jobs.yaml └── project.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg* 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | sdist 13 | develop-eggs 14 | .installed.cfg 15 | 16 | # Installer logs 17 | pip-log.txt 18 | 19 | # Unit test / coverage reports 20 | cover/ 21 | .coverage* 22 | !.coveragerc 23 | .tox 24 | nosetests.xml 25 | .stestr 26 | .venv 27 | 28 | # Translations 29 | *.mo 30 | 31 | # Mr Developer 32 | .mr.developer.cfg 33 | .project 34 | .pydevproject 35 | 36 | # Complexity 37 | output/*.html 38 | output/*/index.html 39 | 40 | # Sphinx 41 | doc/build 42 | 43 | # pbr generates these 44 | AUTHORS 45 | ChangeLog 46 | 47 | # Editors 48 | *~ 49 | .*.swp 50 | .*sw? 51 | 52 | # Files created by releasenotes build 53 | releasenotes/build 54 | RELEASENOTES.rst 55 | releasenotes/notes/reno.cache 56 | -------------------------------------------------------------------------------- /.gitreview: -------------------------------------------------------------------------------- 1 | [gerrit] 2 | host=review.opendev.org 3 | port=29418 4 | project=openstack/ironic-python-agent-builder.git 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | If you would like to contribute to the development of OpenStack, you must 2 | follow the steps in this page: 3 | 4 | http://docs.openstack.org/infra/manual/developers.html 5 | 6 | If you already have a good understanding of how the system works and your 7 | OpenStack accounts are set up, you can skip to the development workflow 8 | section of this documentation to learn how changes to OpenStack should be 9 | submitted for review via the Gerrit tool: 10 | 11 | http://docs.openstack.org/infra/manual/developers.html#development-workflow 12 | 13 | Pull requests submitted through GitHub will be ignored. 14 | 15 | Bugs should be filed on Storyboard, not GitHub: 16 | 17 | https://storyboard.openstack.org/#!/project/948 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Ironic Python Agent Builder 3 | =========================== 4 | 5 | Tools and scripts to build a deployment, cleaning or inspection ramdisk 6 | based on `Ironic Python Agent`_. 7 | 8 | * Free software: Apache license 9 | * Documentation: https://docs.openstack.org/ironic-python-agent-builder 10 | * Source: https://opendev.org/openstack/ironic-python-agent-builder 11 | * Bugs: https://bugs.launchpad.net/ironic-python-agent-builder 12 | * Release Notes: https://docs.openstack.org/releasenotes/ironic-python-agent-builder/ 13 | 14 | .. _Ironic Python Agent: https://docs.openstack.org/ironic-python-agent 15 | -------------------------------------------------------------------------------- /dib/burn-in/README.rst: -------------------------------------------------------------------------------- 1 | ================================= 2 | Ironic Python Agent (IPA) Burn In 3 | ================================= 4 | 5 | This element adds packages needed to run burn-in tasks 6 | to the Ironic Python Agent (IPA) ramdisk. 7 | -------------------------------------------------------------------------------- /dib/burn-in/element-deps: -------------------------------------------------------------------------------- 1 | package-installs 2 | -------------------------------------------------------------------------------- /dib/burn-in/package-installs.yaml: -------------------------------------------------------------------------------- 1 | fio: 2 | fio-engine-libaio: 3 | when: 4 | - IPA_DISTRO_FAMILY = rh 5 | - DIB_RELEASE != 7 6 | - DIB_RELEASE != 8 7 | stress-ng: 8 | -------------------------------------------------------------------------------- /dib/element/ironic-python-agent-podman/README.rst: -------------------------------------------------------------------------------- 1 | ironic-python-agent-podman 2 | =========================== 3 | 4 | Adds Podman support and configuration files to ironic-python-agent-ramdisk. 5 | 6 | Compatibility 7 | ------------- 8 | This DIB element currently supports Debian-based images only. Additional 9 | distribution support may be added in the future. 10 | 11 | ironic-python-agent-config 12 | -------------------------- 13 | 14 | **allow_arbitrary_containers** 15 | - **Description:** Defines whether arbitrary containers are allowed. Set to true or false. 16 | - **Environment Variable:** ``DIB_ALLOW_ARBITRARY_CONTAINERS`` 17 | - **Default:** ``false`` 18 | 19 | **allowed_containers** 20 | - **Description:** Specifies a list of allowed container image URLs (ex "image1-url,image2-url"). 21 | - **Environment Variable:** ``DIB_ALLOWED_CONTAINERS`` 22 | - **Default:** Empty string (``""``) 23 | 24 | **container_steps_file** 25 | - **Description:** Specifies the path in the RAM to the YAML file containing container steps to be executed. 26 | - **Environment Variable:** ``DIB_CONTAINER_STEPS_FILE`` 27 | - **Default:** ``/etc/ironic-python-agent.d/mysteps.yaml`` 28 | 29 | **runner** 30 | - **Description:** Defines the container runtime to use, such as podman or docker. 31 | - **Environment Variable:** ``DIB_RUNNER`` 32 | - **Default:** ``podman`` 33 | 34 | **pull_options** 35 | - **Description:** Container pull options (e.g., --tls-verify=false). 36 | - **Environment Variable:** ``DIB_PULL_OPTIONS`` 37 | - **Default:** ``--tls-verify=false`` 38 | 39 | **run_options** 40 | - **Description:** Options passed when running the container (e.g., --rm --network=host). 41 | - **Environment Variable:** ``DIB_RUN_OPTIONS`` 42 | - **Default:** ``--rm --network=host --tls-verify=false`` 43 | 44 | ironic-python-agent-podman 45 | -------------------------- 46 | 47 | **podman_conf_file** 48 | - **Description:** The path to the configuration file created in the RAM. 49 | - **Environment Variable:** ``DIB_PODMAN_CONF_FILE`` 50 | - **Default:** ``/etc/containers/containers.conf`` 51 | 52 | ironic-python-agent-steps 53 | -------------------------- 54 | 55 | **steps_file_path** 56 | - **Description:** Path to the local step file to be copied to the RAM. 57 | - **Environment Variable:** ``DIB_STEPS_FILE_PATH`` 58 | - **Default:** ``/etc/mysteps.yaml`` 59 | 60 | Example mysteps.yaml 61 | -------------------- 62 | 63 | .. code-block:: yaml 64 | 65 | steps: 66 | - name: manage_container_cleanup 67 | image: docker://172.24.4.1:5000/cleaning-image:latest 68 | interface: deploy 69 | reboot_requested: true 70 | pull_options: 71 | - --tls-verify=false 72 | run_options: 73 | - --rm 74 | - --network=host 75 | - --tls-verify=false 76 | abortable: true 77 | priority: 20 78 | - name: manage_container_cleanup2 79 | image: docker://172.24.4.1:5000/cleaning-image2:latest 80 | interface: deploy 81 | reboot_requested: true 82 | pull_options: 83 | - --tls-verify=false 84 | run_options: 85 | - --rm 86 | - --network=host 87 | - --tls-verify=false 88 | abortable: true 89 | priority: 10 90 | 91 | Customization 92 | ------------- 93 | You can override any of the default values by setting the corresponding 94 | environment variables during the build process. This allows the configuration 95 | to be dynamically adapted without modifying the script. 96 | 97 | ironic-python-agent-podman 98 | =========================== 99 | 100 | Adds Podman support and configuration files to ironic-python-agent-ramdisk. 101 | 102 | Compatibility 103 | ------------- 104 | This DIB element currently supports Debian-based images only. Additional 105 | distribution support may be added in the future. 106 | 107 | ironic-python-agent-config 108 | -------------------------- 109 | 110 | **allow_arbitrary_containers** 111 | - **Description:** Defines whether arbitrary containers are allowed. Set to true or false. 112 | - **Environment Variable:** ``DIB_ALLOW_ARBITRARY_CONTAINERS`` 113 | - **Default:** ``false`` 114 | 115 | **allowed_containers** 116 | - **Description:** Specifies a list of allowed container image URLs (ex "image1-url,image2-url"). 117 | - **Environment Variable:** ``DIB_ALLOWED_CONTAINERS`` 118 | - **Default:** Empty string (``""``) 119 | 120 | **container_steps_file** 121 | - **Description:** Specifies the path in the RAM to the YAML file containing container steps to be executed. 122 | - **Environment Variable:** ``DIB_CONTAINER_STEPS_FILE`` 123 | - **Default:** ``/etc/ironic-python-agent.d/mysteps.yaml`` 124 | 125 | **runner** 126 | - **Description:** Defines the container runtime to use, such as podman or docker. 127 | - **Environment Variable:** ``DIB_RUNNER`` 128 | - **Default:** ``podman`` 129 | 130 | **pull_options** 131 | - **Description:** Container pull options (e.g., --tls-verify=false). 132 | - **Environment Variable:** ``DIB_PULL_OPTIONS`` 133 | - **Default:** ``--tls-verify=false`` 134 | 135 | **run_options** 136 | - **Description:** Options passed when running the container (e.g., --rm --network=host). 137 | - **Environment Variable:** ``DIB_RUN_OPTIONS`` 138 | - **Default:** ``--rm --network=host --tls-verify=false`` 139 | 140 | ironic-python-agent-podman 141 | -------------------------- 142 | 143 | **podman_conf_file** 144 | - **Description:** The path to the configuration file created in the RAM. 145 | - **Environment Variable:** ``DIB_PODMAN_CONF_FILE`` 146 | - **Default:** ``/etc/containers/containers.conf`` 147 | 148 | ironic-python-agent-steps 149 | -------------------------- 150 | 151 | **steps_file_path** 152 | - **Description:** Path to the local step file to be copied to the RAM. 153 | - **Environment Variable:** ``DIB_STEPS_FILE_PATH`` 154 | - **Default:** ``/etc/mysteps.yaml`` 155 | 156 | Example mysteps.yaml 157 | -------------------- 158 | 159 | .. code-block:: yaml 160 | 161 | steps: 162 | - name: manage_container_cleanup 163 | image: docker://172.24.4.1:5000/cleaning-image:latest 164 | interface: deploy 165 | reboot_requested: true 166 | pull_options: 167 | - --tls-verify=false 168 | run_options: 169 | - --rm 170 | - --network=host 171 | - --tls-verify=false 172 | abortable: true 173 | priority: 20 174 | - name: manage_container_cleanup2 175 | image: docker://172.24.4.1:5000/cleaning-image2:latest 176 | interface: deploy 177 | reboot_requested: true 178 | pull_options: 179 | - --tls-verify=false 180 | run_options: 181 | - --rm 182 | - --network=host 183 | - --tls-verify=false 184 | abortable: true 185 | priority: 10 186 | 187 | Customization 188 | ------------- 189 | You can override any of the default values by setting the corresponding 190 | environment variables during the build process. This allows the configuration 191 | to be dynamically adapted without modifying the script. 192 | -------------------------------------------------------------------------------- /dib/element/ironic-python-agent-podman/element-deps: -------------------------------------------------------------------------------- 1 | ironic-python-agent-ramdisk 2 | package-installs 3 | -------------------------------------------------------------------------------- /dib/element/ironic-python-agent-podman/environment.d/10-setup.bash: -------------------------------------------------------------------------------- 1 | # Podman Config 2 | PODMAN_CONF_INSIDEDIR=/etc/containers 3 | 4 | export PODMAN_CONF_FILE=${DIB_IPA_PODMAN_CONF_FILE:-$TMP_BUILD_DIR/mnt/$PODMAN_CONF_INSIDEDIR/containers.conf} 5 | 6 | # Ipa Config 7 | IPA_CONF_INSIDEDIR=/etc/ironic-python-agent.d 8 | export IPA_CONFFILE=$TMP_BUILD_DIR/mnt/$IPA_CONF_INSIDEDIR/ironic_python_agent.conf 9 | 10 | export ALLOW_ARBITRARY_CONTAINERS="${DIB_ALLOW_ARBITRARY_CONTAINERS:-false}" 11 | export ALLOWED_CONTAINERS="${DIB_ALLOWED_CONTAINERS:-""}" 12 | export CONTAINER_STEPS_FILE="${DIB_CONTAINER_STEPS_FILE:-/etc/ironic-python-agent.d/mysteps.yaml}" 13 | export RUNNER="${DIB_RUNNER:-podman}" 14 | export PULL_OPTIONS="${DIB_PULL_OPTIONS:---tls-verify=false}" 15 | export RUN_OPTIONS="${DIB_RUN_OPTIONS:---rm --network=host --tls-verify=false}" 16 | 17 | # Steps Config 18 | STEPS_INSIDEDIR=/etc/ironic-python-agent.d 19 | export STEPS_FILE=$TMP_BUILD_DIR/mnt/$STEPS_INSIDEDIR/mysteps.yaml 20 | 21 | export STEPS_FILE_PATH="${DIB_STEPS_FILE_PATH:-/etc/mysteps.yaml}" 22 | -------------------------------------------------------------------------------- /dib/element/ironic-python-agent-podman/package-installs.yaml: -------------------------------------------------------------------------------- 1 | podman: 2 | phase: install.d 3 | -------------------------------------------------------------------------------- /dib/element/ironic-python-agent-podman/pre-finalise.d/10-ipa-podman-config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Ensure the directory exists 4 | sudo mkdir -p $(dirname $PODMAN_CONF_FILE) 5 | 6 | # Create Podman configuration file inside the ramdisk with sudo tee 7 | echo "[engine] 8 | no_pivot_root = true" | sudo tee $PODMAN_CONF_FILE > /dev/null 9 | 10 | echo "Podman configuration written to $PODMAN_CONF_FILE" 11 | -------------------------------------------------------------------------------- /dib/element/ironic-python-agent-podman/pre-finalise.d/20-ipa-config: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Ensure the directory exists 4 | sudo mkdir -p $(dirname $IPA_CONFFILE) 5 | 6 | # Write the configuration inside the ramdisk 7 | cat <`_ 6 | python package to the Ironic Python Agent (IPA) ramdisk. It also installs 7 | several package dependencies of the ``hardware`` module. 8 | 9 | The ``hardware`` package provides improved hardware introspection capabilities 10 | and supports benchmarking. This functionality may be enabled by adding the 11 | ``extra-hardware`` collector in the ``[DEFAULT] inspection_collectors`` option 12 | or the ``ipa-inspection-collectors`` kernel command line argument. 13 | 14 | The following environment variables may be set to configure the element when 15 | doing a source-based installation: 16 | 17 | * ``DIB_IPA_HARDWARE_PACKAGE`` the full ``hardware`` Python package descriptor 18 | to use. If unset, ``DIB_IPA_HARDWARE_VERSION`` will be used. 19 | * ``DIB_IPA_HARDWARE_VERSION`` the version of the ``hardware`` package to 20 | install when ``DIB_IPA_HARDWARE_PACKAGE`` is unset. If unset, the latest 21 | version will be installed. 22 | * ``DIB_IPA_HARDWARE_RDO`` set to ``0`` to prevent the latest RDO package repositories 23 | being installed on CentOS-9-Stream (ignored when ``DIB_YUM_REPO_CONF`` is set). 24 | -------------------------------------------------------------------------------- /dib/extra-hardware/element-deps: -------------------------------------------------------------------------------- 1 | epel 2 | install-types 3 | ironic-python-agent-ramdisk 4 | package-installs 5 | pkg-map 6 | -------------------------------------------------------------------------------- /dib/extra-hardware/environment.d/10-enable-rdo-deps.bash: -------------------------------------------------------------------------------- 1 | 2 | if [[ "${DISTRO_NAME}${DIB_RELEASE}" =~ "centos9" ]]; then 3 | 4 | if [ -n "${DIB_YUM_REPO_CONF:-}" ] ; then 5 | # Always disable if DIB_YUM_REPO_CONF is defined 6 | export DIB_IPA_HARDWARE_RDO=0 7 | else 8 | # Default to enabled, but overridable by the host 9 | export DIB_IPA_HARDWARE_RDO=${DIB_IPA_HARDWARE_RDO:-1} 10 | fi 11 | else 12 | # Always disable if not centos-9 13 | export DIB_IPA_HARDWARE_RDO=0 14 | fi 15 | -------------------------------------------------------------------------------- /dib/extra-hardware/install.d/extra-hardware-package-install/package-installs-extra-hardware: -------------------------------------------------------------------------------- 1 | python-hardware 2 | -------------------------------------------------------------------------------- /dib/extra-hardware/install.d/extra-hardware-source-install/80-extra-hardware-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then 4 | set -x 5 | fi 6 | set -eu 7 | set -o pipefail 8 | 9 | export LC_ALL=C.UTF-8 10 | 11 | VENVDIR=/opt/ironic-python-agent 12 | UPPER_CONSTRAINTS=/tmp/requirements/upper-constraints.txt 13 | PACKAGE=${DIB_IPA_HARDWARE_PACKAGE:-hardware${DIB_IPA_HARDWARE_VERSION:+==}${DIB_IPA_HARDWARE_VERSION:-}} 14 | 15 | $VENVDIR/bin/pip install -c "$UPPER_CONSTRAINTS" "$PACKAGE" 16 | 17 | # Because the ironic-python-agent systemd unit does not activate the virtualenv 18 | # before executing the ironic-python-agent script, the PATH is not updated to 19 | # point to the bin directory in the virtual environment. We add this symlink so 20 | # that ironic-python-agent sees the hardware-detect tool in its PATH. 21 | ln -s $VENVDIR/bin/hardware-detect /usr/local/bin/hardware-detect 22 | -------------------------------------------------------------------------------- /dib/extra-hardware/package-installs.yaml: -------------------------------------------------------------------------------- 1 | ethtool: 2 | fio: 3 | fio-engine-libaio: 4 | when: 5 | - IPA_DISTRO_FAMILY = rh 6 | - DIB_RELEASE != 7 7 | - DIB_RELEASE != 8 8 | hdparm: 9 | infiniband-diags: 10 | lldpad: 11 | pciutils: 12 | smartmontools: 13 | sysbench: 14 | 15 | biosdevname: 16 | not-arch: aarch64,arm64,ppc64,ppc64el,ppc64le 17 | when: IPA_DISTRO_FAMILY = rh 18 | -------------------------------------------------------------------------------- /dib/extra-hardware/pkg-map: -------------------------------------------------------------------------------- 1 | { 2 | "release": { 3 | "rhel": { 4 | "7": { 5 | "python-hardware": "python-hardware" 6 | } 7 | }, 8 | "centos": { 9 | "7": { 10 | "python-hardware": "python-hardware" 11 | } 12 | } 13 | }, 14 | "family": { 15 | "redhat": { 16 | "python-hardware": "python3-hardware-detect" 17 | } 18 | }, 19 | "default": { 20 | "python-hardware": "python3-hardware" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /dib/extra-hardware/pre-install.d/10-enable-rdo-deps: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # It enables RDO deps repo when DIB_IPA_HARDWARE_RDO=1 3 | 4 | set -eux 5 | set -o pipefail 6 | 7 | if [ ${DIB_IPA_HARDWARE_RDO:-0} -ne 0 ]; then 8 | curl -o /etc/yum.repos.d/dlrn-deps.repo https://trunk.rdoproject.org/centos9-master/dlrn-deps.repo 9 | fi 10 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/README.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | ironic-python-agent-ramdisk 3 | =========================== 4 | Builds a ramdisk with ironic-python-agent. 5 | 6 | More information can be found at: 7 | https://docs.openstack.org/ironic-python-agent/latest/ 8 | 9 | Beyond installing the ironic-python-agent, this element does the following: 10 | 11 | * Installs the ``dhcp-all-interfaces`` so the node, upon booting, attempts to 12 | obtain an IP address on all available network interfaces. 13 | * Disables the ``iptables`` service on SysV and systemd based systems. 14 | * Disables the ``ufw`` service on Upstart based systems. 15 | * Installs packages required for the operation of the ironic-python-agent:: 16 | ``qemu-utils`` ``parted`` ``hdparm`` ``util-linux`` ``genisoimage`` 17 | * When installing from source, ``python-dev`` and ``gcc`` are also installed 18 | in order to support source based installation of ironic-python-agent and its 19 | dependencies. 20 | * Install the certificate if any, which is set to the environment variable 21 | ``DIB_IPA_CERT`` for validating the authenticity by ironic-python-agent. The 22 | certificate can be self-signed certificate or CA certificate. 23 | * Compresses initramfs with command specified in environment variable 24 | ``DIB_IPA_COMPRESS_CMD``, which is 'gzip' by default. This command should 25 | listen for raw data from stdin and write compressed data to stdout. Command 26 | can be with arguments. 27 | * Configures rescue mode if ``DIB_IPA_ENABLE_RESCUE`` is not set to ``false``. 28 | 29 | This element outputs three files: 30 | 31 | - ``$IMAGE-NAME.initramfs``: The deploy ramdisk file containing the 32 | ironic-python-agent (IPA) service. 33 | - ``$IMAGE-NAME.kernel``: The kernel binary file. 34 | 35 | .. note:: 36 | The package based install currently only enables the service when using the 37 | systemd init system. This can easily be changed if there is an agent 38 | package which includes upstart or sysv packaging. 39 | 40 | .. note:: 41 | Using the ramdisk will require at least 1.5GB of ram 42 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/element-deps: -------------------------------------------------------------------------------- 1 | ironic-ramdisk-base 2 | dhcp-all-interfaces 3 | ibft-interfaces 4 | install-static 5 | package-installs 6 | ensure-venv 7 | pkg-map 8 | source-repositories 9 | svc-map 10 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/element-provides: -------------------------------------------------------------------------------- 1 | ironic-python-agent 2 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/environment.d/01-debian-ipa.bash: -------------------------------------------------------------------------------- 1 | # IPA is built with non-free firmware by default. 2 | DIB_DEBIAN_NON_FREE=non-free-firmware 3 | if [[ "$DIB_RELEASE" == "bullseye" ]]; then 4 | # Starting with bookworm, firmware is in a separate repository 5 | DIB_DEBIAN_NON_FREE=non-free 6 | fi 7 | export DIB_DEBIAN_COMPONENTS=${DIB_DEBIAN_COMPONENTS:-main,contrib,$DIB_DEBIAN_NON_FREE} 8 | 9 | if [[ $DIB_DEBIAN_COMPONENTS =~ non-free ]]; then 10 | export IPA_DEBIAN_NONFREE=true 11 | else 12 | export IPA_DEBIAN_NONFREE=false 13 | fi 14 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/environment.d/10-defaults.bash: -------------------------------------------------------------------------------- 1 | export IPA_REMOVE_FIRMWARE=${IPA_REMOVE_FIRMWARE:-amdgpu,netronome,qcom,ti-communication,ti-keystone,ueagle-atm,rsi,mrvl,brcm,mediatek,ath10k,rtlwifi,rtw88,rtw89,libertas,ath11k} 2 | 3 | # NOTE(TheJulia): List of what each item represents for future context 4 | # amdgpu == AMD/ATI Radeon/Vega/Raven firmware for drivers 5 | # netronome == Netronome Agilio Smartnics 6 | # qcom = Qualcom SoC firmware 7 | # ti-communication == Texas Instruments SoC firmware 8 | # ti-keystone == Texas Instruments baseband firmware 9 | # ueagle-atm == ADSL/ATM interface card firmware 10 | # rsi == Redpine wifi chip firmware 11 | # mrvl == Marvell wifi chip and prestera ethernet switch ASIC firmware 12 | # brcm == Broadcom wifi firmware 13 | # mediatek == Mediatek wifi and SoC (think chromebook) firmware 14 | # ath10k == Qualcom Atheros 10k firmware 15 | # rtlwifi == Realtek Wifi firmware 16 | # rtw88 == Realtek wireless 17 | # rtw89 == Realtek wireless 18 | # libertas == Marvell libertas wifi 19 | # auth11k == Qualcomm atheros WLAN 20 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/environment.d/20-ipa-distro-family.bash: -------------------------------------------------------------------------------- 1 | if [[ $DISTRO_NAME =~ (fedora|centos|rhel) ]]; then 2 | export IPA_DISTRO_FAMILY=rh 3 | else 4 | export IPA_DISTRO_FAMILY=other 5 | fi 6 | 7 | if [[ ${DISTRO_NAME} =~ (centos|rhel) ]]; then 8 | export DIB_DHCP_NETWORK_MANAGER_AUTO=${DIB_DHCP_NETWORK_MANAGER_AUTO:-true} 9 | fi 10 | 11 | # NOTE(rpittau) force Python version to 3 for debian 12 | if [[ $DISTRO_NAME =~ debian ]]; then 13 | DIB_PYTHON_VERSION=3 14 | export DIB_PYTHON_VERSION 15 | fi 16 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/extra-data.d/15-ssl-ca-copy: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ ${DIB_DEBUG_TRACE:-0} -gt 0 ]; then 4 | set -x 5 | fi 6 | 7 | set -eu 8 | set -o pipefail 9 | 10 | if [ -n "${DIB_IPA_CERT:=}" ]; then 11 | cp $DIB_IPA_CERT $TMP_HOOKS_PATH/ipa-trusted-cert.pem 12 | fi 13 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/install.d/ironic-python-agent-ramdisk-package-install/package-installs-ironic-python-agent-ramdisk: -------------------------------------------------------------------------------- 1 | ironic-python-agent 2 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/install.d/ironic-python-agent-ramdisk-source-install/60-ironic-python-agent-ramdisk-install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then 4 | set -x 5 | fi 6 | set -eu 7 | set -o pipefail 8 | 9 | export LC_ALL=C.UTF-8 10 | 11 | SCRIPTDIR=$(dirname $0) 12 | IPADIR=/tmp/ironic-python-agent 13 | UPPER_CONSTRAINTS=/tmp/requirements/upper-constraints.txt 14 | VENVDIR=/opt/ironic-python-agent 15 | 16 | # define default python 17 | PYTHON_BIN="python3" 18 | if [[ "${DISTRO_NAME}${DIB_RELEASE}" =~ "centos9" ]]; then 19 | PYTHON_BIN="python3.12" 20 | fi 21 | 22 | # create the virtual environment using the default python 23 | $PYTHON_BIN -m venv $VENVDIR 24 | 25 | REQUIRED_PIP_STR="25.1.1" 26 | REQUIRED_PIP_TUPLE="(25, 1, 1)" 27 | 28 | HAS_PIP=$($VENVDIR/bin/python -c \ 29 | "import pip; print(tuple(map(int, pip.__version__.split('.'))) >= $REQUIRED_PIP_TUPLE)") 30 | if [ $HAS_PIP == "False" ]; then 31 | # NOTE(dtantsur): use a fixed version to avoid breakages 32 | $VENVDIR/bin/pip install "pip==$REQUIRED_PIP_STR" 33 | fi 34 | 35 | # Upgrade setuptools package for openSuse and in virtualenvs using Python 2.x 36 | # NOTE(rpittau): if we want to keep compatibility with Python 2.x, we need to 37 | # upgrade setuptools in the virtualenv as the default installed has issues 38 | # when parsing requirements. 39 | if [ "$DISTRO_NAME" == "opensuse" ]; then 40 | $VENVDIR/bin/pip install -U setuptools 41 | fi 42 | 43 | # For aarch64 platform, it seems it always tries to build wheels first for 44 | # python packages which have no wheels in PyPi. Although it will install the 45 | # source packages successfully at last. 46 | if [[ "$ARCH" =~ (arm64|aarch64) ]]; then 47 | $VENVDIR/bin/pip install wheel 48 | fi 49 | 50 | # install IPA inside the virtual environment 51 | $VENVDIR/bin/pip install -c $UPPER_CONSTRAINTS $IPADIR 52 | ln -s $VENVDIR/bin/ironic-python-agent /usr/local/bin/ 53 | ln -s $VENVDIR/bin/ironic-collect-introspection-data /usr/local/bin/ 54 | 55 | case "$DIB_INIT_SYSTEM" in 56 | upstart) 57 | install -D -g root -o root -m 0755 ${SCRIPTDIR}/ironic-python-agent.conf /etc/init/ironic-python-agent.conf 58 | ;; 59 | systemd) 60 | install -D -g root -o root -m 0644 ${SCRIPTDIR}/ironic-python-agent.service /usr/lib/systemd/system/ironic-python-agent.service 61 | ;; 62 | sysv) 63 | install -D -g root -o root -m 0755 ${SCRIPTDIR}/ironic-python-agent.init /etc/init.d/ironic-python-agent.init 64 | update-rc.d ironic-python-agent.init defaults 65 | ;; 66 | *) 67 | echo "Unsupported init system" 68 | exit 1 69 | ;; 70 | esac 71 | 72 | # Copying the self signed certificate for request library 73 | if [ -f /tmp/in_target.d/ipa-trusted-cert.pem ]; then 74 | cat /tmp/in_target.d/ipa-trusted-cert.pem >> $($VENVDIR/bin/python -c "import requests; print(requests.certs.where())") 75 | fi 76 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/install.d/ironic-python-agent-ramdisk-source-install/ironic-python-agent.conf: -------------------------------------------------------------------------------- 1 | # ironic-python-agent - OpenStack Ironic Python Agent 2 | # 3 | # The ironic-python-agent helps ironic in deploying instances. 4 | 5 | description "Ironic Python Agnet" 6 | 7 | start on runlevel [2345] 8 | stop on runlevel [!2345] 9 | 10 | respawn 11 | respawn limit 10 5 12 | umask 022 13 | 14 | expect stop 15 | 16 | console output 17 | 18 | pre-start script 19 | echo Starting Ironic Python Agent 20 | end script 21 | 22 | exec /usr/local/bin/ironic-python-agent --config-dir /etc/ironic-python-agent.d/ 23 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/install.d/ironic-python-agent-ramdisk-source-install/ironic-python-agent.init: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | ### BEGIN INIT INFO 3 | # Provides: ironic-python-agent 4 | # Required-Start: $local_fs networking 5 | # Required-Stop: $local_fs 6 | # Default-Start: S 7 | # Default-Stop: 0 6 8 | # X-Start-Before: 9 | # Short-Description: Ironic Python Agent 10 | # Description: Starts Ironic Python Agent for instance deployment 11 | ### END INIT INFO 12 | 13 | NAME=ironic-python-agent 14 | INIT_NAME=/etc/init.d/${NAME} 15 | SCRIPT_NAME=/usr/local/bin/${NAME} 16 | 17 | [ -x $SCRIPT_NAME ] || exit 0 18 | 19 | case "$1" in 20 | start) 21 | $SCRIPT_NAME --config-dir /etc/ironic-python-agent.d/ 22 | ;; 23 | stop) 24 | ;; 25 | *) 26 | echo "Usage: $INIT_NAME {start|stop}" 27 | exit 1 28 | ;; 29 | esac 30 | 31 | exit 0 32 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/install.d/ironic-python-agent-ramdisk-source-install/ironic-python-agent.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Ironic Python Agent 3 | After=network-online.target 4 | 5 | [Service] 6 | ConditionPathExists=!/etc/.rescued 7 | ExecStartPre=/sbin/modprobe vfat 8 | ExecStart=/usr/local/bin/ironic-python-agent --config-dir /etc/ironic-python-agent.d/ 9 | Restart=always 10 | RestartSec=30s 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | 15 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/package-installs.yaml: -------------------------------------------------------------------------------- 1 | curl: 2 | # dmidecode does not exist for ppc* arches so we use lshw 3 | dmidecode: 4 | not-arch: ppc64,ppc64el,ppc64le 5 | iptables: 6 | lshw: 7 | ipmitool: 8 | qemu-utils: 9 | # NOTE(dtantsur): gcc is not build-only because dkms requires it 10 | gcc: 11 | python: 12 | parted: 13 | hdparm: 14 | util-linux: 15 | genisoimage: 16 | gdisk: 17 | kmod: 18 | psmisc: 19 | dosfstools: 20 | mdadm: 21 | efibootmgr: 22 | not-arch: ppc64,ppc64el,ppc64le 23 | efivar: 24 | not-arch: ppc64,ppc64el,ppc64le 25 | chrony: 26 | e2fsprogs: 27 | nvme-cli: 28 | # This provides iscsistart which is required for iBFT support 29 | open-iscsi: 30 | # smartctl is required for ATA secure erase. 31 | smartmontools: 32 | 33 | libffi-dev: 34 | build-only: true 35 | libssl-dev: 36 | build-only: true 37 | python-dev: 38 | build-only: true 39 | 40 | # The base minimum element uninstalls firmware, but it's needed for bare metal. 41 | linux-firmware: 42 | phase: post-install.d 43 | when: IPA_DISTRO_FAMILY = rh 44 | 45 | firmware-linux-free: 46 | when: DISTRO_NAME = debian 47 | firmware-misc-nonfree: 48 | when: 49 | - DISTRO_NAME = debian 50 | - IPA_DEBIAN_NONFREE = true 51 | intel-microcode: 52 | arch: x86_64 53 | when: 54 | - DISTRO_NAME = debian 55 | - IPA_DEBIAN_NONFREE = true 56 | amd64-microcode: 57 | arch: x86_64 58 | when: 59 | - DISTRO_NAME = debian 60 | - IPA_DEBIAN_NONFREE = true 61 | 62 | # Packages needed by Debian 63 | # bsdextrautils provides the 'hexdump' command used by IPA. 64 | bsdextrautils: 65 | when: DISTRO_NAME = debian 66 | 67 | # Packages that should not normally be present on IPA images 68 | cloud-init: 69 | phase: post-install.d 70 | uninstall: true 71 | teamd: 72 | phase: post-install.d 73 | uninstall: true 74 | when: IPA_DISTRO_FAMILY = rh 75 | tuned: 76 | phase: post-install.d 77 | uninstall: true 78 | when: IPA_DISTRO_FAMILY = rh 79 | 80 | # Unnecessary packages to remove. We run all removals in pre-install phase, to 81 | # avoid breaking installs that happen in install phase. 82 | git: 83 | phase: pre-install.d 84 | uninstall: true 85 | man-db: 86 | phase: pre-install.d 87 | uninstall: true 88 | rsync: 89 | phase: pre-install.d 90 | uninstall: true 91 | 92 | # Distro-specific uninstalls 93 | kernel-debug-devel: 94 | phase: pre-install.d 95 | uninstall: true 96 | when: IPA_DISTRO_FAMILY = rh 97 | mozjs60: 98 | phase: pre-install.d 99 | uninstall: true 100 | when: IPA_DISTRO_FAMILY = rh 101 | plymouth: 102 | phase: pre-install.d 103 | uninstall: true 104 | when: IPA_DISTRO_FAMILY = rh 105 | python3-cairo: 106 | phase: pre-install.d 107 | uninstall: true 108 | when: IPA_DISTRO_FAMILY = rh 109 | python3-gobject-base: 110 | phase: pre-install.d 111 | uninstall: true 112 | when: IPA_DISTRO_FAMILY = rh 113 | yum: 114 | phase: pre-install.d 115 | uninstall: true 116 | when: DISTRO_NAME = fedora 117 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/pkg-map: -------------------------------------------------------------------------------- 1 | { 2 | "release": { 3 | "rhel": { 4 | "9": { 5 | "python": "python3.12", 6 | "python-dev": "python3.12-devel" 7 | } 8 | }, 9 | "centos": { 10 | "9-stream": { 11 | "python": "python3.12", 12 | "python-dev": "python3.12-devel" 13 | } 14 | }, 15 | "debian": { 16 | "bullseye": { 17 | "lshw": "lshw/bullseye-backports" 18 | } 19 | } 20 | }, 21 | "family": { 22 | "redhat": { 23 | "genisoimage": "xorriso", 24 | "libffi-dev": "libffi-devel", 25 | "libssl-dev": "openssl-devel", 26 | "open-iscsi": "iscsi-initiator-utils", 27 | "python-dev": "python3-devel", 28 | "qemu-utils": "qemu-img" 29 | }, 30 | "suse": { 31 | "qemu-utils": "qemu", 32 | "genisoimage": "mkisofs", 33 | "gdisk": "gptfdisk", 34 | "libffi-dev": "libffi-devel", 35 | "libssl-dev": "libopenssl-devel", 36 | "python-dev": "python3-devel", 37 | "git": "", 38 | "man-db": "" 39 | } 40 | }, 41 | "default": { 42 | "ironic-python-agent": "openstack-ironic-python-agent", 43 | "python": "python3", 44 | "python-dev": "python3-dev" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/post-install.d/80-ironic-python-agent-ramdisk: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then 4 | set -x 5 | fi 6 | set -eu 7 | set -o pipefail 8 | 9 | DIB_IPA_ENABLE_RESCUE=${DIB_IPA_ENABLE_RESCUE:-true} 10 | DIB_IPA_ENABLE_SYSTEMD_NETWORKD=${DIB_IPA_ENABLE_SYSTEMD_NETWORKD:-true} 11 | 12 | if $DIB_IPA_ENABLE_RESCUE; then 13 | # Make sure rescue works 14 | mkdir -p /etc/ipa-rescue-config 15 | fi 16 | 17 | case "$DIB_INIT_SYSTEM" in 18 | upstart) 19 | if [ -f /etc/init/ufw.conf ]; then 20 | mv /etc/init/ufw.conf /etc/init/ufw.conf.disabled 21 | fi 22 | if [ -f /etc/init/tgt.conf ]; then 23 | mv /etc/init/tgt.conf /etc/init/tgt.conf.disabled 24 | fi 25 | ;; 26 | systemd) 27 | if [[ $(systemctl --no-pager list-unit-files iptables) =~ 'enabled' ]]; then 28 | systemctl disable iptables.service 29 | fi 30 | systemctl enable $(svc-map ironic-python-agent).service 31 | if $DIB_IPA_ENABLE_RESCUE; then 32 | systemctl enable ironic-agent-create-rescue-user.path 33 | fi 34 | systemctl enable ironic-agent-resolve-config-drive.service 35 | # NOTE(rpittau) disable caching remote package index to prevent 36 | # delays due to failures. 37 | # This is a new service for dnf-based systems (e.g. Centos8) to speed 38 | # up subsequent dnf commands, for example automated updates, and 39 | # it's not really needed in the ipa-ramdisk as we shouldn't install 40 | # anything during runtime. 41 | if [[ ${IPA_DISTRO_FAMILY} == 'rh' ]]; then 42 | if [[ ${YUM} == 'dnf' ]]; then 43 | systemctl disable dnf-makecache.service 44 | systemctl disable dnf-makecache.timer 45 | fi 46 | fi 47 | 48 | # NOTE(drannou) debian by default is using networking instead of 49 | # systemd-networkd. In some usecase like rescue, we need IPA to 50 | # re-launch dhclient when modifications are made on the interface. 51 | # The easiest way to manage that is to activate systemd-networkd. 52 | if $DIB_IPA_ENABLE_SYSTEMD_NETWORKD; then 53 | if [[ $DISTRO_NAME =~ debian ]] ; then 54 | rm /etc/network/interfaces 55 | rm -rf /etc/network/interfaces.d 56 | echo "[Match] 57 | Name=en* 58 | 59 | [Network] 60 | DHCP=yes" > /etc/systemd/network/99-dhcp.network 61 | 62 | systemctl enable systemd-networkd 63 | fi 64 | fi 65 | if [ -e /usr/lib/systemd/system/glean-early.service ]; then 66 | # Disable Glean-early start 67 | # Under normal circumstances, glean-early attempts to mount a config 68 | # drive, configure ssh and a hostname. We only need the mount, and we 69 | # trigger that in ironic-agent-resolve-config-drive.service. 70 | # This is largely because glean uses /mnt/config by default, 71 | # where as cloud-init uses a random folder name. 72 | systemctl disable glean-early.service || true 73 | rm /usr/lib/systemd/system/glean-early.service 74 | fi 75 | ;; 76 | sysv) 77 | update-rc.d iptables disable 78 | ;; 79 | *) 80 | echo "Unsupported init system" 81 | exit 1 82 | ;; 83 | esac 84 | 85 | # Blocks out userdata from being acted upon by cloud-init if present. 86 | if [[ -x /etc/cloud/cloud.cfg.d ]]; then 87 | cat > /etc/cloud/cloud.cfg.d/94-ironic-python-agent-disable-userdata.cfg < /etc/sudoers.d/rescue 18 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/static/usr/local/bin/ironic-python-agent-resolve-configdrive.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eux 4 | set -o pipefail 5 | 6 | echo "Resolving the configuration drive for Ironic." 7 | 8 | PATH=/bin:/usr/bin:/sbin:/usr/sbin 9 | 10 | # Inspired by/based on glean-early.sh 11 | # https://opendev.org/opendev/glean/src/branch/master/glean/init/glean-early.sh 12 | 13 | # NOTE(TheJulia): We care about iso images, and would expect lower case as a 14 | # result. In the case of VFAT partitions, they would be upper case. 15 | CONFIG_DRIVE_LABEL="config-2" 16 | 17 | # Identify the number of devices 18 | device_count=$(lsblk -o PATH,LABEL | grep $CONFIG_DRIVE_LABEL | wc -l) 19 | 20 | # Identify if we have an a publisher id set 21 | publisher_id="" 22 | if grep -q "ir_pub_id" /proc/cmdline; then 23 | publisher_id=$(cat /proc/cmdline | sed -e 's/^.*ir_pub_id=//' -e 's/ .*$//') 24 | fi 25 | 26 | if [ $device_count -lt 1 ]; then 27 | # Nothing to do here, exit! 28 | exit 0 29 | else 30 | # We have *something* to do here. 31 | mkdir -p /mnt/config 32 | if [[ "${publisher_id}" != "" ]]; then 33 | # We need to enumerate through the devices, and obtain the 34 | for device in $(lsblk -o PATH,LABEL|grep config-2|cut -f1 -d" "); do 35 | device_id=$(udevadm info --query=property --property=ID_FS_PUBLISHER_ID $device | sed s/ID_FS_PUBLISHER_ID=//) 36 | if [[ "${publisher_id,,}" == "${device_id,,}" ]]; then 37 | # SUCCESS! Valid device! Do it! 38 | echo "Device ${device} matches the ${publisher_id}. Mounting..." 39 | mount -t iso9660 -o ro,mode=0700 "${device}" /mnt/config || true 40 | # We've mounted the device, the world is happy. 41 | exit 0 42 | else 43 | echo "Did not identify $device as a valid ISO for Ironic." 44 | fi 45 | done 46 | fi 47 | fi 48 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-ramdisk/svc-map: -------------------------------------------------------------------------------- 1 | ironic-python-agent: 2 | default: openstack-ironic-python-agent 3 | redhat: openstack-ironic-python-agent 4 | debian: ironic-python-agent 5 | opensuse: ironic-python-agent 6 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-tls/README.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | ironic-python-agent-tls 3 | ======================= 4 | Adds TLS support to ironic-python-agent-ramdisk. 5 | 6 | If enabled without any environment variables set to modify configuration, 7 | this element will enable TLS API support in IPA with a self-signed certificate 8 | and key created at build time. 9 | 10 | Optionally, you can provide your own SSL certificate and key, and optionally 11 | ca, via the following environment variables. They should be set to an 12 | accessible path on the build systems filesystem. If set, they will be copied 13 | into the built ramdisk, and IPA will be configured to use them. 14 | 15 | The environment variables are: 16 | - ``DIB_IPA_CERT_FILE`` should point to the TLS certificate for ramdisk use. 17 | - ``DIB_IPA_KEY_FILE`` should point to the private key matching 18 | ``DIB_IPA_CERT_FILE``. 19 | 20 | If having a certificate generated, you can configure how it's generated: 21 | - ``DIB_IPA_CERT_HOSTNAME`` the CN for the generated 22 | certificate. Defaults to "ipa-ramdisk.example.com". 23 | - ``DIB_IPA_CERT_EXPIRATION`` expiration, in days, for the certificate. 24 | Defaults to 1095 (three years). 25 | 26 | Note that the certificates generated by this element are self-signed, and 27 | any nodes using them will need to set agent_verify_ca=False in driver_info. 28 | 29 | This element can also configure client certificate validation in IPA. If you 30 | wish to validate client certificates, set ``DIB_IPA_CA_FILE`` to a CA file 31 | you wish IPA client connections to be validated against. This CA file will 32 | be copied into the built ramdisk, and IPA will be configured to use it. 33 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-tls/element-deps: -------------------------------------------------------------------------------- 1 | ironic-python-agent-ramdisk 2 | -------------------------------------------------------------------------------- /dib/ironic-python-agent-tls/pre-finalise.d/10-configure-ipa-tls: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This is the path inside the ramdisk, referenced in config files 4 | INSIDEDIR=/etc/ironic-python-agent.d/ 5 | 6 | # but when copying files from outside the ramdisk, we have to use the mounted 7 | # DIB filesystems 8 | KEYDIR=$TMP_BUILD_DIR/mnt/$INSIDEDIR 9 | 10 | CONFFILE=$KEYDIR/10-configure-tls.conf 11 | CACONFFILE=$KEYDIR/11-configure-client-cert-ca.conf 12 | 13 | if [[ -z $DIB_IPA_CERT_FILE ]] && [[ -z $DIB_IPA_KEY_FILE ]]; then 14 | echo "Both DIB_IPA_CERT_FILE and DIB_IPA_KEY_FILE are not set; generating self-signed cert" 15 | sudo openssl req -new -nodes -newkey rsa:4096 -days ${DIB_IPA_CERT_EXPIRATION:-1095} -x509 -subj "/C=US/ST=NA/L=NA/O=NA/CN=${DIB_IPA_CERT_HOSTNAME:-ipa-ramdisk.example.com}" -keyout $KEYDIR/agent.key -out $KEYDIR/agent.crt 16 | else 17 | sudo cp $DIB_IPA_CERT_FILE $KEYDIR/agent.crt 18 | sudo cp $DIB_IPA_KEY_FILE $KEYDIR/agent.key 19 | fi 20 | 21 | cat </dev/null ; then 29 | # We're keeping the contents of resolv.conf set in the elements, 30 | # so remove the old saved file 31 | sudo rm -f $TMP_MOUNT_PATH/etc/resolv.conf.ORIG 32 | else 33 | # Remove the resolv.conf we created and put the original (or 34 | # perhaps modified) version back. 35 | sudo rm -f $TMP_MOUNT_PATH/etc/resolv.conf 36 | # Note that we use -L and -f to test here as test (and bash [[) 37 | # return false with -e if the link target does not exist. 38 | if [ -L $TMP_MOUNT_PATH/etc/resolv.conf.ORIG ] || [ -f $TMP_MOUNT_PATH/etc/resolv.conf.ORIG ] ; then 39 | sudo mv $TMP_MOUNT_PATH/etc/resolv.conf.ORIG $TMP_MOUNT_PATH/etc/resolv.conf 40 | fi 41 | fi 42 | 43 | -------------------------------------------------------------------------------- /dib/ironic-ramdisk-base/cleanup.d/99-ramdisk-create: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # dib-lint: disable=safe_sudo 4 | 5 | if [ "${DIB_DEBUG_TRACE:-0}" -gt 0 ]; then 6 | set -x 7 | fi 8 | set -eu 9 | set -o pipefail 10 | 11 | 12 | [ -n "$TARGET_ROOT" ] 13 | 14 | USER=${USER:-$(whoami)} 15 | 16 | source $_LIB/img-functions 17 | 18 | IMAGE_PATH=$(readlink -f $IMAGE_NAME) 19 | cd $TARGET_ROOT 20 | 21 | DIB_IPA_COMPRESS_CMD="${DIB_IPA_COMPRESS_CMD:-gzip}" 22 | 23 | echo "#disabled" > ./tmp/fstab.new 24 | sudo mv ./tmp/fstab.new ./etc/fstab 25 | sudo ln -s ./sbin/init ./ 26 | 27 | # NOTE(TheJulia): Make a random and urandom entry to handle 28 | # long standing systemd bug cases where it may, depending on 29 | # underlying OS config/version, try to open the random number 30 | # generator before initializing. 31 | # This class of issue has appeared frequently with systemd, 32 | # https://github.com/systemd/systemd/issues/4167 is a commonly 33 | # referenced example of this behavior. 34 | if ! [ -a ./dev/random ]; then 35 | sudo mknod ./dev/random c 1 8 36 | fi 37 | if ! [ -a ./dev/urandom ]; then 38 | sudo mknod ./dev/urandom c 1 9 39 | fi 40 | 41 | # Note(JayF): to anyone trying to make this more configurable in the future, 42 | # there are significant hurdles around shell quoting if you try to put these 43 | # find commands into variables for making them more configurable. 44 | if [ "${DIB_IPA_MINIMAL_PRUNE:-0}" -gt 0 ]; then 45 | # Operator opted out of full ramdisk pruning; do not proactively remove 46 | # directories that may be in use by other elements/packages 47 | sudo find . -xdev \ 48 | -path './sys/*' -prune -o \ 49 | -path './tmp/*' -prune -o \ 50 | -path './boot/*' -prune -o \ 51 | -path './root/.cache' -prune -o \ 52 | -name '*.pyc' -prune -o \ 53 | -name '*.pyo' -prune -o \ 54 | -print | sudo cpio -o -H newc | ${DIB_IPA_COMPRESS_CMD} > ${IMAGE_PATH}.initramfs 55 | else 56 | # This performs a full prune, leading to the smallest possible ramdisk 57 | # size. This may break operator-configured packages or elements that 58 | # depend on pruned paths. 59 | # Note: The pci.ids, which is used by lshw, are located on Ubuntu 60 | # in /usr/share/misc. Therefore we are removing only the 61 | # ./usr/share/misc/m* (will remove the magic and magic.mgc files). 62 | # on RHEL pci.ids is locate on /usr/share/hwdata/pci.ids. 63 | sudo find . -xdev \ 64 | -path './sys/*' -prune -o \ 65 | -path './tmp/*' -prune -o \ 66 | -path './boot/*' -prune -o \ 67 | -path './root/.cache' -prune -o \ 68 | -path "*site-packages/babel/locale-data/*" -prune -o \ 69 | -path './usr/include/*' -prune -o \ 70 | -path './usr/lib/locale/*' -prune -o \ 71 | -path './usr/share/doc/*' -prune -o \ 72 | -path './usr/share/man/*' -prune -o \ 73 | -path './usr/share/GeoIP/*' -prune -o \ 74 | -path './usr/share/info/*' -prune -o \ 75 | -path './usr/share/licenses/*' -prune -o \ 76 | -path './usr/share/locale/*' -prune -o \ 77 | -path './usr/share/misc/m*' -prune -o \ 78 | -path './usr/src/kernels/*' -prune -o \ 79 | -path './var/cache/*' -prune -o \ 80 | -path './var/log/*' -prune -o \ 81 | -name '*.pyc' ! -path '*encodings/*' -prune -o \ 82 | -name '*.pyo' -prune -o \ 83 | -print | sudo cpio -o -H newc | ${DIB_IPA_COMPRESS_CMD} > ${IMAGE_PATH}.initramfs 84 | fi 85 | 86 | select_boot_kernel_initrd $TARGET_ROOT 87 | sudo cp $BOOTDIR/$KERNEL ${IMAGE_PATH}.kernel 88 | sudo chown $USER: ${IMAGE_PATH}.kernel 89 | if [[ -n "$DIB_CHECKSUM" && "$DIB_CHECKSUM" != "0" ]]; then 90 | pushd $(dirname ${IMAGE_PATH}) 91 | [[ "$DIB_CHECKSUM" == "1" ]] && DIB_CHECKSUM="md5,sha256" 92 | [[ "$DIB_CHECKSUM" == *md5* ]] && md5sum ${IMAGE_NAME}.initramfs ${IMAGE_NAME}.kernel > ${IMAGE_NAME}.md5 93 | [[ "$DIB_CHECKSUM" == *sha256* ]] && sha256sum ${IMAGE_NAME}.initramfs ${IMAGE_NAME}.kernel > ${IMAGE_NAME}.sha256 94 | popd 95 | fi 96 | # Output image sizes for debugging 97 | sudo ls -lh ${IMAGE_PATH}.* 98 | -------------------------------------------------------------------------------- /dib/ironic-ramdisk-base/element-deps: -------------------------------------------------------------------------------- 1 | no-final-image 2 | runtime-ssh-host-keys 3 | selinux-permissive 4 | -------------------------------------------------------------------------------- /dib/ironic-ramdisk-base/environment.d/10-checksum.bash: -------------------------------------------------------------------------------- 1 | export DIB_CHECKSUM=${DIB_CHECKSUM:-0} -------------------------------------------------------------------------------- /dib/multipath-io/README.md: -------------------------------------------------------------------------------- 1 | ============ 2 | multipath-io 3 | ============ 4 | Updates the ironic agent, installing multipath and iscsi packages, 5 | and enabling needed modules by default, to execute a modprobe for 6 | the needed drivers before it is started. -------------------------------------------------------------------------------- /dib/multipath-io/element-deps: -------------------------------------------------------------------------------- 1 | install-static 2 | package-installs -------------------------------------------------------------------------------- /dib/multipath-io/package-installs.yaml: -------------------------------------------------------------------------------- 1 | iscsi-initiator-utils: 2 | device-mapper-multipath: -------------------------------------------------------------------------------- /dib/multipath-io/static/etc/modules-load.d/iscsi.conf: -------------------------------------------------------------------------------- 1 | qla4xxx 2 | cxgb3i 3 | cxgb4i 4 | bnx2i 5 | be2iscsi 6 | iscsi_boot_sysfs 7 | iscsi_ibft 8 | iscsi_tcp 9 | target_core_mod -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | reno>=3.1.0 # Apache-2.0 2 | sphinx>=2.0.0,!=2.1.0 # BSD 3 | openstackdocstheme>=2.2.1 # Apache-2.0 4 | -------------------------------------------------------------------------------- /doc/source/admin/dib.rst: -------------------------------------------------------------------------------- 1 | diskimage-builder images 2 | ======================== 3 | 4 | Images built using diskimage-builder_ are recommended for production use on 5 | real hardware. The recommended distributions are: 6 | 7 | * CentOS Stream 9 8 | * Debian Bookworm (``debian-minimal`` element) 9 | 10 | The following should work but receive only limited testing and support: 11 | 12 | * Ubuntu 20.04 Focal 13 | * Debian Bullseye (``debian-minimal`` element) 14 | 15 | Building 16 | -------- 17 | 18 | ... with the helper script 19 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 | 21 | To build an image using ``ironic-python-agent-builder``, run: 22 | 23 | .. code-block:: shell 24 | 25 | ironic-python-agent-builder 26 | 27 | You can add other diskimage-builder_ elements via the ``-e`` flag: 28 | 29 | .. code-block:: shell 30 | 31 | ironic-python-agent-builder -e --release 9-stream centos 32 | 33 | You can specify the base name of the target images: 34 | 35 | .. code-block:: shell 36 | 37 | ironic-python-agent-builder -o my-ipa --release 9-stream centos 38 | 39 | You can specify the arch of the target image by setting ``ARCH`` environment 40 | variable (default is amd64): 41 | 42 | .. code-block:: shell 43 | 44 | export ARCH=aarch64 45 | ironic-python-agent-builder -o my-ipa --release 9-stream centos 46 | 47 | ... with diskimage-builder 48 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 | 50 | You can also use diskimage-builder_ directly. First you need to set the 51 | ``ELEMENTS_PATH`` variable to the correct location: 52 | 53 | * If installed with ``pip install --user``, use: 54 | 55 | .. code-block:: bash 56 | 57 | export ELEMENTS_PATH=$HOME/.local/share/ironic-python-agent-builder/dib 58 | 59 | * On Fedora/CentOS/RHEL (installed via ``sudo pip install`` or from packages): 60 | 61 | .. code-block:: bash 62 | 63 | export ELEMENTS_PATH=/usr/share/ironic-python-agent-builder/dib 64 | 65 | * On Debian and its derivatives, if installed with ``sudo pip install``: 66 | 67 | .. code-block:: bash 68 | 69 | export ELEMENTS_PATH=/usr/local/share/ironic-python-agent-builder/dib 70 | 71 | Now you can build an image adding the ``ironic-python-agent-ramdisk`` element, 72 | for example: 73 | 74 | .. code-block:: shell 75 | 76 | export DIB_RELEASE=9-stream 77 | disk-image-create -o ironic-python-agent \ 78 | ironic-python-agent-ramdisk centos 79 | 80 | To use a specific branch of ironic-python-agent, use: 81 | 82 | .. code-block:: bash 83 | 84 | export DIB_REPOREF_ironic_python_agent=origin/stable/queens 85 | export DIB_REPOREF_requirements=origin/stable/queens 86 | 87 | To build image for architectures other than amd64, you can either set the 88 | ``ARCH`` environment variable or use ``-a`` to specify the target 89 | architecture: 90 | 91 | .. code-block:: shell 92 | 93 | disk-image-create -a arm64 -o ironic-python-agent \ 94 | ironic-python-agent-ramdisk fedora 95 | 96 | ISO Images 97 | ~~~~~~~~~~ 98 | 99 | Additionally, the IPA ramdisk can be packaged inside of an ISO for use with 100 | some virtual media drivers. Use the ``iso-image-create`` script in 101 | ``ironic-python-agent-builder`` repository, passing it the initrd and the 102 | kernel, for example: 103 | 104 | .. code-block:: console 105 | 106 | ./tools/iso-image-create -o /path/to/output.iso -i /path/to/ipa.initrd -k /path/to/ipa.kernel 107 | 108 | This is a generic tool that can be used to combine any initrd and kernel into 109 | a suitable ISO for booting, and so should work against any IPA ramdisk. 110 | 111 | Advanced options 112 | ---------------- 113 | 114 | Disabling rescue 115 | ~~~~~~~~~~~~~~~~ 116 | 117 | By default rescue mode is enabled in the images. Since it allows to set root 118 | password on the ramdisk by anyone on the network, you may disable it if the 119 | rescue feature is not supported. Set the following before building the image: 120 | 121 | .. code-block:: bash 122 | 123 | export DIB_IPA_ENABLE_RESCUE=false 124 | 125 | SSH access 126 | ~~~~~~~~~~ 127 | 128 | SSH access can be added to DIB built IPA images with the dynamic-login_ 129 | or the devuser_ element. 130 | 131 | The *dynamic-login* element allows the operator to inject an SSH key at boot 132 | time via the kernel command line parameters: 133 | 134 | * Add ``sshkey="ssh-rsa "`` to ``pxe_append_params`` 135 | setting in the ``ironic.conf`` file. 136 | 137 | .. warning:: Quotation marks around the public key are important! 138 | 139 | * Restart the ironic-conductor. 140 | 141 | .. note:: 142 | This element is added to the published images by default. 143 | 144 | The *devuser* element allows creating a user at build time, for example: 145 | 146 | .. code-block:: bash 147 | 148 | export DIB_DEV_USER_USERNAME=username 149 | export DIB_DEV_USER_PWDLESS_SUDO=yes 150 | export DIB_DEV_USER_AUTHORIZED_KEYS=$HOME/.ssh/id_rsa.pub 151 | disk-image-create debian ironic-python-agent-ramdisk devuser 152 | 153 | Consistent Network Interface Naming 154 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 155 | 156 | Base cloud images normally disable consistent network interface naming 157 | by inserting an empty udev rule. Include ``stable-interface-names`` element 158 | if you want to have consistent network interface naming whenever it is 159 | required for instance image or deploy image. 160 | 161 | .. code-block:: bash 162 | 163 | ironic-python-agent-builder -e stable-interface-names --release 9-stream centos 164 | 165 | 166 | .. _diskimage-builder: https://docs.openstack.org/diskimage-builder 167 | .. _dynamic-login: https://docs.openstack.org/diskimage-builder/latest/elements/dynamic-login/README.html 168 | .. _devuser: https://docs.openstack.org/diskimage-builder/latest/elements/devuser/README.html 169 | 170 | Firmware Removal 171 | ~~~~~~~~~~~~~~~~ 172 | 173 | By default the element removes some firmware blobs to reduce the image size. 174 | The list can be found below this paragraph. The majority of these firmware 175 | images are used by SoCs, WI-FI chips, some GPUs and Smartnics which are 176 | unlikely to be encountered. If you want to override this, change the 177 | ``IPA_REMOVE_FIRMWARE`` environment variable to a comma-separated list 178 | of directories or files under ``/usr/lib/firmware``. 179 | Set it to an empty string to disable firmware removal. 180 | 181 | Firmware removed: 182 | 183 | * ``amdgpu`` 184 | * ``netronome`` 185 | * ``qcom`` 186 | * ``ti-communication`` 187 | * ``ti-keystone`` 188 | * ``ueagle-atm`` 189 | * ``rsi`` 190 | * ``mrvl`` 191 | * ``brcm`` 192 | * ``mediatek`` 193 | * ``ath10k`` 194 | * ``rtlwifi`` 195 | 196 | Available Elements 197 | ------------------ 198 | 199 | Ironic Python Agent (IPA) Extra Hardware 200 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 201 | 202 | This element adds the `hardware `_ 203 | python package to the Ironic Python Agent (IPA) ramdisk. It also installs 204 | several package dependencies of the ``hardware`` module. 205 | 206 | The ``hardware`` package provides improves hardware introspection capabilities 207 | and supports benchmarking. This functionality may be enabled by adding the 208 | ``extra-hardware`` collector in the ``[DEFAULT] inspection_collectors`` option 209 | or the ``ipa-inspection-collectors`` kernel command line argument. 210 | 211 | The following environment variables may be set to configure the element when 212 | doing a source-based installation: 213 | 214 | * ``DIB_IPA_HARDWARE_PACKAGE`` the full ``hardware`` Python package descriptor 215 | to use. If unset, ``DIB_IPA_HARDWARE_VERSION`` will be used. 216 | * ``DIB_IPA_HARDWARE_VERSION`` the version of the ``hardware`` package to 217 | install when ``DIB_IPA_HARDWARE_PACKAGE`` is unset. If unset, the latest 218 | version will be installed. 219 | 220 | ironic-python-agent-ramdisk 221 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 222 | 223 | Builds a ramdisk with ironic-python-agent. 224 | 225 | More information can be found at: 226 | https://docs.openstack.org/ironic-python-agent/latest/ 227 | 228 | Beyond installing the ironic-python-agent, this element does the following: 229 | 230 | * Installs the ``dhcp-all-interfaces`` so the node, upon booting, attempts to 231 | obtain an IP address on all available network interfaces. 232 | * Disables the ``iptables`` service on SysV and systemd based systems. 233 | * Disables the ``ufw`` service on Upstart based systems. 234 | * Installs packages required for the operation of the ironic-python-agent:: 235 | ``qemu-utils`` ``parted`` ``hdparm`` ``util-linux`` 236 | * When installing from source, ``python-dev`` and ``gcc`` are also installed 237 | in order to support source based installation of ironic-python-agent and its 238 | dependencies. 239 | * Install the certificate if any, which is set to the environment variable 240 | ``DIB_IPA_CERT`` for validating the authenticity by ironic-python-agent. The 241 | certificate can be self-signed certificate or CA certificate. 242 | * Compresses initramfs with command specified in environment variable 243 | ``DIB_IPA_COMPRESS_CMD``, which is 'gzip' by default. This command should 244 | listen for raw data from stdin and write compressed data to stdout. Command 245 | can be with arguments. 246 | * Configures rescue mode if ``DIB_IPA_ENABLE_RESCUE`` is not set to ``false``. 247 | 248 | This element outputs two files: 249 | 250 | * ``$IMAGE-NAME.initramfs``: The deploy ramdisk file containing the 251 | ironic-python-agent (IPA) service. 252 | * ``$IMAGE-NAME.kernel``: The kernel binary file. 253 | 254 | .. note:: 255 | The package based install currently only enables the service when using the 256 | systemd init system. This can easily be changed if there is an agent 257 | package which includes upstart or sysv packaging. 258 | 259 | .. note:: 260 | Using the ramdisk will require at least 1.5GB of ram 261 | 262 | ironic-python-agent-tls 263 | ~~~~~~~~~~~~~~~~~~~~~~~ 264 | 265 | Adds TLS support to ironic-python-agent-ramdisk. 266 | 267 | By default this element will enable TLS API support in IPA with a self-signed 268 | certificate and key created at build time. 269 | 270 | Optionally, you can provide your own SSL certificate and key, and optionally 271 | CA, via the following environment variables. They should be set to an 272 | accessible path on the build systems filesystem. If set, they will be copied 273 | into the built ramdisk, and IPA will be configured to use them. 274 | 275 | The environment variables are: 276 | 277 | * ``DIB_IPA_CERT_FILE`` should point to the TLS certificate for ramdisk use. 278 | * ``DIB_IPA_KEY_FILE`` should point to the private key matching 279 | ``DIB_IPA_CERT_FILE``. 280 | 281 | You can configure the generated certificate with the following environment 282 | variables: 283 | 284 | * ``DIB_IPA_CERT_HOSTNAME`` the CN for the generated certificate. Defaults to 285 | "ipa-ramdisk.example.com". 286 | * ``DIB_IPA_CERT_EXPIRATION`` expiration, in days, for the certificate. 287 | Defaults to 1095 (three years). 288 | 289 | Note that the certificates generated by this element are self-signed, and 290 | any nodes using them will need to set agent_verify_ca=False in driver_info. 291 | 292 | This element can also configure client certificate validation in IPA. If you 293 | wish to validate client certificates, set ``DIB_IPA_CA_FILE`` to a CA file 294 | you wish IPA client connections to be validated against. This CA file will 295 | be copied into the built ramdisk, and IPA will be configured to use it. 296 | 297 | -------------------------------------------------------------------------------- /doc/source/admin/index.rst: -------------------------------------------------------------------------------- 1 | ==================== 2 | Administrators guide 3 | ==================== 4 | 5 | This guide describes how to build and use an `Ironic Python Agent`_-based image 6 | using the builders provided in the **ironic-python-agent-builder** project. 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | dib 12 | tinyipa 13 | 14 | .. _Ironic Python Agent: https://docs.openstack.org/ironic-python-agent 15 | -------------------------------------------------------------------------------- /doc/source/admin/tinyipa.rst: -------------------------------------------------------------------------------- 1 | TinyIPA images 2 | ============== 3 | 4 | TinyIPA is an `Ironic Python Agent`_ image based on TinyCoreLinux_. It is very 5 | lightweight and thus very suitable for CI use. It may lack necessary drivers 6 | and the build process uses insecure communication, thus these images are not 7 | recommended for production usage. 8 | 9 | Requirements 10 | ------------ 11 | 12 | You need to have a git clone of **ironic-python-agent-builder**: 13 | 14 | .. code-block:: shell 15 | 16 | git clone https://opendev.org/openstack/ironic-python-agent-builder 17 | cd ironic-python-agent-builder/tinyipa 18 | 19 | Then you need to install some utilities. For the main build script: 20 | 21 | * wget 22 | * pip 23 | * unzip 24 | * sudo 25 | * awk 26 | * mksquashfs 27 | 28 | For building an ISO you'll also need: 29 | 30 | * mkisofs, genisoimage, or xorrisofs 31 | 32 | Building 33 | -------- 34 | 35 | Building ramdisk 36 | ~~~~~~~~~~~~~~~~ 37 | 38 | To create a new ramdisk, run: 39 | 40 | .. code-block:: shell 41 | 42 | make 43 | 44 | or: 45 | 46 | .. code-block:: shell 47 | 48 | ./build-tinyipa.sh && ./finalise-tinyipa.sh 49 | 50 | This will create two new files once completed: 51 | 52 | * ``tinyipa.vmlinuz`` - the kernel image 53 | * ``tinyipa.gz`` - the initramfs image 54 | 55 | Upload them to the Image service or another location where you want them to be 56 | hosted (an HTTP or FILE location in case of standalone ironic). 57 | 58 | Building ISO 59 | ~~~~~~~~~~~~ 60 | 61 | Once you've built tinyIPA it is possible to pack it into an ISO if required. To 62 | create a bootable ISO, run: 63 | 64 | .. code-block:: shell 65 | 66 | make iso 67 | 68 | or: 69 | 70 | .. code-block:: shell 71 | 72 | ./build-iso.sh 73 | 74 | This will create one new file once completed: 75 | 76 | * ``tinyipa.iso`` 77 | 78 | 79 | Cleaning up 80 | ~~~~~~~~~~~ 81 | 82 | To clean up the whole build environment, run: 83 | 84 | .. code-block:: shell 85 | 86 | make clean 87 | 88 | For cleaning up just the iso or just the ramdisk build: 89 | 90 | .. code-block:: shell 91 | 92 | make clean_iso 93 | 94 | or: 95 | 96 | .. code-block:: shell 97 | 98 | make clean_build 99 | 100 | Advanced options 101 | ---------------- 102 | 103 | Enabling/disabling SSH access to the ramdisk 104 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 105 | 106 | By default tinyIPA will be built with OpenSSH server installed but no 107 | public SSH keys authorized to access it. 108 | 109 | If you want to enable SSH access to the image, set ``AUTHORIZE_SSH`` variable 110 | in your shell before building tinyIPA: 111 | 112 | .. code-block:: bash 113 | 114 | export AUTHORIZE_SSH=true 115 | 116 | By default it will use public RSA or DSA keys of the user running the build. 117 | To provide a different public SSH key, export path to it in your shell before 118 | building tinyIPA: 119 | 120 | .. code-block:: bash 121 | 122 | export SSH_PUBLIC_KEY= 123 | 124 | If you want to disable SSH altogether, set ``INSTALL_SSH`` variable in your 125 | shell to ``false`` before building tinyIPA: 126 | 127 | .. code-block:: bash 128 | 129 | export INSTALL_SSH=false 130 | 131 | If you want to change the SSH access of a previously built tinyIPA image, 132 | use the make target ``addssh``: 133 | 134 | .. code-block:: shell 135 | 136 | make addssh 137 | 138 | This command will either use a local image specified by the 139 | ``TINYIPA_RAMDISK_FILE`` environment variable or download the version 140 | specified by the ``BRANCH_PATH`` environment variable (e.g. ``master`` or 141 | ``stable-queens``) from `tarballs.openstack.org 142 | `_. 143 | It will install and configure OpenSSH if needed and add public SSH keys for 144 | the user named ``tc`` using either the same ``SSH_PUBLIC_KEY`` shell variable 145 | or the public keys of the local user. 146 | 147 | Enabling biosdevname in the ramdisk 148 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 149 | 150 | If you want to collect BIOS given names of NICs in the inventory, set 151 | ``TINYIPA_REQUIRE_BIOSDEVNAME`` variable in your shell before building tinyIPA: 152 | 153 | .. code-block:: bash 154 | 155 | export TINYIPA_REQUIRE_BIOSDEVNAME=true 156 | 157 | 158 | .. _Ironic Python Agent: https://docs.openstack.org/ironic-python-agent 159 | .. _TinyCoreLinux: http://tinycorelinux.net 160 | -------------------------------------------------------------------------------- /doc/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import os 16 | import sys 17 | 18 | sys.path.insert(0, os.path.abspath('../..')) 19 | # -- General configuration ---------------------------------------------------- 20 | 21 | # Add any Sphinx extension module names here, as strings. They can be 22 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 23 | extensions = [ 24 | 'sphinx.ext.autodoc', 25 | 'openstackdocstheme', 26 | #'sphinx.ext.intersphinx', 27 | ] 28 | 29 | # autodoc generation is a bit aggressive and a nuisance when doing heavy 30 | # text edit cycles. 31 | # execute "export SPHINX_DEBUG=1" in your terminal to disable 32 | 33 | # The suffix of source filenames. 34 | source_suffix = '.rst' 35 | 36 | # The master toctree document. 37 | master_doc = 'index' 38 | 39 | # General information about the project. 40 | copyright = '2017, OpenStack Developers' 41 | 42 | # openstackdocstheme options 43 | openstackdocs_repo_name = 'openstack/ironic-python-agent-builder' 44 | openstackdocs_pdf_link = True 45 | openstackdocs_use_storyboard = True 46 | 47 | # If true, '()' will be appended to :func: etc. cross-reference text. 48 | add_function_parentheses = True 49 | 50 | # If true, the current module name will be prepended to all description 51 | # unit titles (such as .. function::). 52 | add_module_names = True 53 | 54 | # The name of the Pygments (syntax highlighting) style to use. 55 | pygments_style = 'native' 56 | 57 | # -- Options for HTML output -------------------------------------------------- 58 | 59 | # The theme to use for HTML and HTML Help pages. Major themes that come with 60 | # Sphinx are currently 'default' and 'sphinxdoc'. 61 | # html_theme_path = ["."] 62 | # html_theme = '_theme' 63 | # html_static_path = ['static'] 64 | html_theme = 'openstackdocs' 65 | 66 | # Output file base name for HTML help builder. 67 | htmlhelp_basename = 'ironic-python-agent-builderdoc' 68 | 69 | # Grouping the document tree into LaTeX files. List of tuples 70 | # (source start file, target name, title, author, documentclass 71 | # [howto/manual]). 72 | latex_documents = [ 73 | ('index', 74 | 'doc-ironic-python-agent-builder.tex', 75 | 'Ironic Python Agent Builder Documentation', 76 | 'OpenStack Developers', 'manual'), 77 | ] 78 | 79 | # Example configuration for intersphinx: refer to the Python standard library. 80 | #intersphinx_mapping = {'http://docs.python.org/': None} 81 | -------------------------------------------------------------------------------- /doc/source/contributor/index.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | Contributor Documentation 3 | =========================== 4 | 5 | .. include:: ../../../CONTRIBUTING.rst 6 | 7 | Testing changes in DIB images 8 | ============================= 9 | 10 | Testing a local ironic-python-agent change in :doc:`/admin/dib` requires 11 | rebuilding an image with the following procedure. 12 | 13 | #. Make sure your changes are committed to your local repository. DIB needs to 14 | know a branch name to use (``my-test-branch`` in the example below). 15 | 16 | #. Build an image as described in :doc:`/admin/dib`, providing a location of 17 | your local repository and the branch name, for example: 18 | 19 | .. code-block:: bash 20 | 21 | DIB_REPOLOCATION_ironic_python_agent=/home/user/path/to/repo \ 22 | DIB_REPOREF_ironic_python_agent=my-test-branch \ 23 | ironic-python-agent-builder -o my-ipa --release 9-stream centos 24 | 25 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../../README.rst 2 | 3 | Contents: 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | 8 | install/index 9 | admin/index 10 | contributor/index 11 | -------------------------------------------------------------------------------- /doc/source/install/index.rst: -------------------------------------------------------------------------------- 1 | ====================================== 2 | Installing Ironic Python Agent Builder 3 | ====================================== 4 | 5 | Download the ``ironic-python-agent-builder`` archive from 6 | `tarballs.openstack.org`_, install it from your distribution's repositories 7 | or use pip:: 8 | 9 | pip install --user diskimage-builder ironic-python-agent-builder 10 | 11 | In RDO_, the package is available since Train under a slightly different name:: 12 | 13 | sudo yum install -y openstack-ironic-python-agent-builder 14 | 15 | .. _tarballs.openstack.org: https://tarballs.openstack.org/ironic-python-agent-builder/ 16 | .. _RDO: https://rdoproject.org 17 | -------------------------------------------------------------------------------- /ironic_python_agent_builder/__init__.py: -------------------------------------------------------------------------------- 1 | # Licensed under the Apache License, Version 2.0 (the "License"); 2 | # you may not use this file except in compliance with the License. 3 | # You may obtain a copy of the License at 4 | # 5 | # http://www.apache.org/licenses/LICENSE-2.0 6 | # 7 | # Unless required by applicable law or agreed to in writing, software 8 | # distributed under the License is distributed on an "AS IS" BASIS, 9 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | # See the License for the specific language governing permissions and 11 | # limitations under the License. 12 | 13 | import argparse 14 | import os 15 | import shlex 16 | import subprocess 17 | import sys 18 | 19 | 20 | LOCATIONS = [ 21 | os.path.abspath('.'), 22 | # This accounts for pip installations on Ubuntu that go into /usr/local. 23 | # This logic converts e.g. /usr/local/bin/ironic-python-agent-builder 24 | # into /usr/local/share/ironic-python-agent-builder. 25 | os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), 26 | '..', 'share', 27 | 'ironic-python-agent-builder')), 28 | # This accounts for system-wide installations to /usr 29 | os.path.join(sys.prefix, 'share', 'ironic-python-agent-builder'), 30 | ] 31 | 32 | 33 | def find_elements_path(): 34 | for basedir in LOCATIONS: 35 | final = os.path.join(basedir, 'dib') 36 | if os.path.exists(os.path.join(final, 'ironic-python-agent-ramdisk')): 37 | return final 38 | 39 | sys.exit('ironic-python-agent-ramdisk element has not been found in any ' 40 | 'of the following locations: %s' % ', '.join(set(LOCATIONS))) 41 | 42 | 43 | def main(): 44 | parser = argparse.ArgumentParser() 45 | parser.add_argument("distribution", help="Distribution to use") 46 | parser.add_argument("-r", "--release", help="Distribution release to use") 47 | parser.add_argument("-o", "--output", help="Output base file name", 48 | default="ironic-python-agent") 49 | parser.add_argument("-e", "--element", action='append', default=[], 50 | help="Additional DIB element to use") 51 | parser.add_argument("-b", "--branch", 52 | help="If set, override the branch that is used for " 53 | "ironic-python-agent and requirements") 54 | parser.add_argument("-v", "--verbose", action='store_true', 55 | help="Enable verbose logging in diskimage-builder") 56 | parser.add_argument("--lzma", action='store_true', 57 | help="Use lzma compression for smaller images") 58 | parser.add_argument("--extra-args", 59 | help="Extra arguments to pass to diskimage-builder") 60 | parser.add_argument("--elements-path", 61 | help="Path(s) to custom DIB elements separated by " 62 | "a colon") 63 | # TODO(dtantsur): handle distribution == tinyipa 64 | args = parser.parse_args() 65 | if args.elements_path: 66 | os.environ['ELEMENTS_PATH'] = args.elements_path 67 | if 'ELEMENTS_PATH' in os.environ: 68 | os.environ['ELEMENTS_PATH'] += ":" + find_elements_path() 69 | else: 70 | os.environ['ELEMENTS_PATH'] = find_elements_path() 71 | if not os.environ.get('DIB_INSTALLTYPE_pip_and_virtualenv'): 72 | # DIB updates these to latest versions from source. However, we do the 73 | # same in our virtualenv, so it's not needed and just increases the 74 | # size of the image. 75 | os.environ['DIB_INSTALLTYPE_pip_and_virtualenv'] = 'package' 76 | if args.release: 77 | os.environ['DIB_RELEASE'] = args.release 78 | if args.branch: 79 | os.environ['DIB_REPOREF_ironic_python_agent'] = args.branch 80 | os.environ['DIB_REPOREF_requirements'] = args.branch 81 | if args.lzma: 82 | os.environ['DIB_IPA_COMPRESS_CMD'] = \ 83 | 'xz --format=lzma --compress --stdout -9' 84 | # Enable checksum generation by default 85 | if 'DIB_CHECKSUM' not in os.environ: 86 | os.environ['DIB_CHECKSUM'] = 'sha256' 87 | 88 | extra_args = shlex.split(args.extra_args) if args.extra_args else [] 89 | if args.verbose: 90 | extra_args.append("-x") 91 | try: 92 | subprocess.check_call(['disk-image-create', '-o', args.output, 93 | 'ironic-python-agent-ramdisk', 94 | args.distribution] + args.element + extra_args) 95 | except (EnvironmentError, subprocess.CalledProcessError) as exc: 96 | sys.exit(str(exc)) 97 | except KeyboardInterrupt: 98 | sys.exit(127) 99 | -------------------------------------------------------------------------------- /playbooks/ironic-python-agent-build-image/extra-logs.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | 3 | tasks: 4 | 5 | - name: Collect disk usage info 6 | shell: "df > {{ zuul_output_dir }}/logs/df.txt" 7 | become: yes 8 | -------------------------------------------------------------------------------- /playbooks/ironic-python-agent-build-image/post.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | 3 | tasks: 4 | 5 | - name: Ensure artifacts directory exists 6 | file: 7 | path: '{{ zuul.executor.work_root }}/artifacts/{{ image_type }}/files' 8 | state: directory 9 | delegate_to: localhost 10 | 11 | - name: Copy files from {{ ipa_raw_dir }} on node 12 | synchronize: 13 | src: '{{ ipa_raw_dir }}/' 14 | dest: '{{ zuul.executor.work_root }}/artifacts/{{ image_type }}/files/' 15 | mode: pull 16 | copy_links: true 17 | verify_host: true 18 | rsync_opts: 19 | - --include=/* 20 | - --prune-empty-dirs 21 | 22 | - name: Copy files from {{ ipa_tar_dir }} on node 23 | synchronize: 24 | src: '{{ ipa_tar_dir }}/' 25 | dest: '{{ zuul.executor.work_root }}/artifacts/{{ image_type }}/' 26 | mode: pull 27 | copy_links: true 28 | verify_host: true 29 | rsync_opts: 30 | - --include=/* 31 | - --prune-empty-dirs 32 | 33 | - name: Copy files from {{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent on node 34 | synchronize: 35 | src: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/' 36 | dest: '{{ zuul.executor.log_root }}' 37 | mode: pull 38 | copy_links: true 39 | verify_host: true 40 | rsync_opts: 41 | - --include=*/ 42 | - --exclude=* 43 | - --prune-empty-dirs 44 | -------------------------------------------------------------------------------- /playbooks/ironic-python-agent-build-image/pre.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | 3 | environment: 4 | PIP_BREAK_SYSTEM_PACKAGES: 1 5 | 6 | roles: 7 | - ensure-pip 8 | 9 | tasks: 10 | 11 | - import_role: 12 | name: ipa-build-dib-image 13 | tasks_from: install.yaml 14 | when: image_type == 'dib' 15 | -------------------------------------------------------------------------------- /playbooks/ironic-python-agent-build-image/run.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | 3 | environment: 4 | PIP_BREAK_SYSTEM_PACKAGES: 1 5 | 6 | tasks: 7 | 8 | - name: Create a target directory for raw images 9 | file: 10 | path: '{{ ipa_raw_dir }}' 11 | state: directory 12 | 13 | - name: Create a target directory for tarballs 14 | file: 15 | path: '{{ ipa_tar_dir }}' 16 | state: directory 17 | 18 | - include_role: 19 | name: ipa-build-{{ image_type }}-image 20 | -------------------------------------------------------------------------------- /releasenotes/notes/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/ironic-python-agent-builder/c1213ffe14089e99e70bc801b3c2efbf1869a308/releasenotes/notes/.placeholder -------------------------------------------------------------------------------- /releasenotes/notes/add-efibootmgr-d2a456de6b999612.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The efibootmgr package was added to tinyipa and dib images. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/add-efivar-f83fdf2d797396dc.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The efivar package was added to tinyipa and dib images. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/add-ntpdate-3db2f8565fed761e.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds packages required for ``ironic-python-agent`` to 5 | synchronize the system clock, namely ntpdate. The other 6 | dependency of the agent requires is ``hwclock``, however 7 | that package is provided by util-linux. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/add-nvme-cli-590e42735476a549.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds nvme-cli package required for ``ironic-python-agent`` to 5 | be able to fetch information from NVMe controllers and perform NVMe-native 6 | cleaning operations. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/centos7-python3-185f1d35c37096c7.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Supports building images for Ussuri+ on CentOS 7 using Python 3. This is 5 | not recommended but is necessary for some older hardware. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/centos8-46a95956fd871c90.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Building images for CentOS 7 and other distribution releases that default 5 | to Python 2 is deprecated. 6 | other: 7 | - | 8 | Since ironic-python-agent has removed support for Python 2, CentOS 8 images 9 | are now built and published on https://tarballs.openstack.org instead of 10 | CentOS 7 ones. The CentOS 7 images should not be used for Ussuri and later 11 | releases. 12 | -------------------------------------------------------------------------------- /releasenotes/notes/centos8-stream-d9c83190e987e07d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | The pre-built images now use CentOS Stream 8 instead of CentOS 8. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/centos9-0f925822a2ab9e0a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | CentOS 7 and 8 are no longer supported since OpenStack dropped support 5 | for Python 3.6. Please use CentOS 9 (Stream) instead. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/clean-var-tmp-with-dib-builds-cd31a2cf70a7f935.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes excess files being housed in /var/tmp inside of a ramdisk image 5 | which may, in some cases, result in a much larger ramdisk than expected. 6 | Files and folders in /var/tmp within a ramdisk are now removed prior to 7 | the ramdisk being packaged as part of a DIB based image build. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/create-ramdisk-random-devices-263f78a2ef40dbe2.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes issues with ramdisks potentially crashing when starting due to 5 | systemd attempting to access a random number generator before udevd has 6 | been launched. Depending on the mode of operation and underlying 7 | and configuration, i.e. in FIPS mode, the system could have crashed as 8 | a result. We will now always create the character devices devices, which 9 | can be used early in the boot sequence. 10 | -------------------------------------------------------------------------------- /releasenotes/notes/debian-9a4fa6b2d3ef96d0.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Fixes building images for Debian Bullseye and Bookworm. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/debian-arm64-fc3cc4949e3100d9.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | We now build and publish diskimage-builder debian based image on arm64. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/debian-firmware-1927601ebb779bc4.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Free firmware is now installed by default on Debian DIB builds. 5 | - | 6 | No longer tries to install ``biosdevname`` on non Red Hat systems 7 | (dropped from Ubuntu after Bionic, never present in Debian). 8 | upgrade: 9 | - | 10 | Non-free firmware is now installed by default on Debian DIB builds. 11 | Change the available repositories to disable: 12 | 13 | export DIB_DEBIAN_COMPONENTS=main 14 | -------------------------------------------------------------------------------- /releasenotes/notes/debian-ipa-cb5975e436cba525.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Debian images are now published using Bookworm instead of Bullseye. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/dhcp-predictible-ifnames-b2a1d9e6471b6819.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Add support for TinyIPA predictable device names in dhcp.sh script by changing 5 | of NETDEVICES variable. It will support any device from /proc/net/dev starting 6 | with e or p letter. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/drop-python2-534124afa50f62dd.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Python 2.7 support has been dropped. Last release of 5 | ironic-python-agent-builder to support Python 2.7 is OpenStack Train. The 6 | minimum version of Python now supported by ironic-python-agent-builder is 7 | Python 3.6. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/excess-firmware-removal-debian-06c49a8604122b1c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Excess hardware firmware on Debian based agent ramdisks is now automatically 5 | removed. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/extra-hardware-73e3c9b5a0143bfa.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds a new element ``extra-hardware`` for configuring extra hardware 5 | collection in the ramdisk. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/ironic-lib-6a16f13fc6ec9a50.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Supports installing ironic-lib from source in the DIB build. Set 5 | :: 6 | 7 | export IRONIC_LIB_FROM_SOURCE=true 8 | 9 | to use. 10 | -------------------------------------------------------------------------------- /releasenotes/notes/ironic-ramdisk-base-3bfb9b90ad416891.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The new element ``ironic-ramdisk-base`` can be used to build ramdisks 5 | without IPA itself or any of its dependencies. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/linux-firmware-9a6f8a9a32c5719d.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Installs ``linux-firmware`` on the DIB images since it's now uninstalled 5 | by the base elements on Red Hat operating systems. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/lzma-bf4552b98dd5824a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | The ``ironic-python-agent-builder`` CLI now supports ``--lzma`` flag to 5 | compress images with the LZMA algorithm. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/lzma-compression-level-1ca346ba8d5b905a.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Changes lzma compression level to 9 for smaller images. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/multipath-0eb6a4f3b2ee22a3.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Adds a new element ``multipath-io`` for configuring setups 5 | using multipath. 6 | 7 | -------------------------------------------------------------------------------- /releasenotes/notes/network-manager-auto-dhcp-all-interfaces-rhel-centos-relese-gt-7-0c2054d0067c6e93.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | On RHEL and CentOS 8 and later the *dhcp-all-interfaces* diskimage-builder 5 | element is now configured to only apply NetworkManager configuration by 6 | default. The *dhcp-all-interfaces* service will not be enabled. 7 | To re-enable the *dhcp-all-interfaces* service, set 8 | ``DIB_DHCP_NETWORK_MANAGER_AUTO=false`` in the environment. 9 | 10 | NetworkManager is quite capable to do automatic interface configuration. 11 | NetworkManager will by default try to auto-configure any interface with 12 | no configuration, it will use DHCP for IPv4 and Router Advertisements to 13 | decide how to initialize IPv6. 14 | 15 | -------------------------------------------------------------------------------- /releasenotes/notes/no-fedora-aa65bcc43f9d56fa.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | deprecations: 3 | - | 4 | Fedora is no longer explicitly supported for DIB-based builds. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/no-firmware-e2cb953037a3be8f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | features: 3 | - | 4 | Firmware for netronome, amdgpu, qcom, ti-communication, ti-keystone, 5 | ueagle-atm, rsi, mrvl, brcm, mediatek, ath10k, rtlwifi are now removed 6 | by default. Set ``IPA_REMOVE_FIRMWARE`` to override. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/no-iscsi-5d132e6468acab0b.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The ``iscsi`` deploy interface is no longer supported by the DIB builder, 5 | use ironic-python-agent-builder 2.7.0 or older for it. 6 | -------------------------------------------------------------------------------- /releasenotes/notes/no-sdparm-f77de72b5c0d7859.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Removes unnecessary requirement on ``sdparm`` (removed in python-hardware 5 | 0.20.0). 6 | -------------------------------------------------------------------------------- /releasenotes/notes/no-suse-e15d8384c423251c.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for openSUSE Leap 15.* has been removed. 5 | -------------------------------------------------------------------------------- /releasenotes/notes/python2-removal-dee895550b1959af.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | Support for python2 in ironic-python-agent was dropped in the Ussuri release 5 | however it was still possible to build (non-functional) python2 images for 6 | CentOS 7. This python2 support is now dropped from the image build also. As 7 | part of this change, the `pip-and-virtualenv` element is not longer a 8 | dependency, so any custom elements which depend on this element will need to 9 | either include it explicitly or migrate to the recommended `ensure-venv` 10 | element. -------------------------------------------------------------------------------- /releasenotes/notes/remove-PYOPTIMIZE_TINYIPA-ebde63911d140209.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | Removes support for ``PYOPTIMIZE_TINYIPA``, which now causes the TinyIPA 5 | image to be approximately 5 MB larger. This was due to an incompatibility 6 | with the ``oslo.privsep`` library dependency on ``pycparser`` which cannot 7 | load into precompiled python programs where the original source embedded 8 | documentation is not present. 9 | -------------------------------------------------------------------------------- /releasenotes/notes/selinux-permissive-a059f42bb66373a1.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | fixes: 3 | - | 4 | The DIB-based ramdisk is now always built with SELinux set to permissive. 5 | Enabling SELinux may result in broken ramdisks and does not make much 6 | sense for IPA anyway. 7 | -------------------------------------------------------------------------------- /releasenotes/notes/tinycore13-caba5a4998bdd628.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The tinyipa image is now built using tinycore 13.x 5 | -------------------------------------------------------------------------------- /releasenotes/notes/tinyipa-ci-testing-ends-8748513e6512cf8f.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | other: 3 | - | 4 | Due to the deprecation of Python 3.9 support in OpenStack and the 5 | evolution of python dependencies, CI test jobs for TinyIPA have 6 | been removed. Overall code to build the test images should expect 7 | to be removed from Ironic projects and tools as time progresses. 8 | -------------------------------------------------------------------------------- /releasenotes/notes/tinyipa-tgt-226f74125238c239.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | upgrade: 3 | - | 4 | The tinyIPA build no longer supports the ``iscsi`` deploy interface. Please 5 | use version 2.6.0 or older for this. 6 | -------------------------------------------------------------------------------- /releasenotes/source/2023.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2023.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/2023.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/2023.2.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2023.2 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2023.2 7 | -------------------------------------------------------------------------------- /releasenotes/source/2024.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2024.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2024.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/2024.2.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2024.2 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2024.2 7 | -------------------------------------------------------------------------------- /releasenotes/source/2025.1.rst: -------------------------------------------------------------------------------- 1 | =========================== 2 | 2025.1 Series Release Notes 3 | =========================== 4 | 5 | .. release-notes:: 6 | :branch: stable/2025.1 7 | -------------------------------------------------------------------------------- /releasenotes/source/_static/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/ironic-python-agent-builder/c1213ffe14089e99e70bc801b3c2efbf1869a308/releasenotes/source/_static/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/_templates/.placeholder: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstack/ironic-python-agent-builder/c1213ffe14089e99e70bc801b3c2efbf1869a308/releasenotes/source/_templates/.placeholder -------------------------------------------------------------------------------- /releasenotes/source/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 11 | # implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This file is execfile()d with the current directory set to its 16 | # containing dir. 17 | # 18 | # Note that not all possible configuration values are present in this 19 | # autogenerated file. 20 | # 21 | # All configuration values have a default; values that are commented out 22 | # serve to show the default. 23 | 24 | # If extensions (or modules to document with autodoc) are in another directory, 25 | # add these directories to sys.path here. If the directory is relative to the 26 | # documentation root, use os.path.abspath to make it absolute, like shown here. 27 | # sys.path.insert(0, os.path.abspath('.')) 28 | 29 | # -- General configuration ------------------------------------------------ 30 | 31 | # If your documentation needs a minimal Sphinx version, state it here. 32 | # needs_sphinx = '1.0' 33 | 34 | # Add any Sphinx extension module names here, as strings. They can be 35 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 36 | # ones. 37 | extensions = [ 38 | 'openstackdocstheme', 39 | 'reno.sphinxext', 40 | ] 41 | 42 | # Add any paths that contain templates here, relative to this directory. 43 | templates_path = ['_templates'] 44 | 45 | # The suffix of source filenames. 46 | source_suffix = '.rst' 47 | 48 | # The encoding of source files. 49 | # source_encoding = 'utf-8-sig' 50 | 51 | # The master toctree document. 52 | master_doc = 'index' 53 | 54 | # General information about the project. 55 | project = 'Ironic Python Agent Builder Release Notes' 56 | copyright = '2017, OpenStack Developers' 57 | 58 | # openstackdocstheme options 59 | openstackdocs_repo_name = 'openstack/ironic-python-agent-builder' 60 | openstackdocs_auto_name = False 61 | openstackdocs_use_storyboard = True 62 | 63 | # The version info for the project you're documenting, acts as replacement for 64 | # |version| and |release|, also used in various other places throughout the 65 | # built documents. 66 | # 67 | # The short X.Y version. 68 | # The full version, including alpha/beta/rc tags. 69 | release = '' 70 | # The short X.Y version. 71 | version = '' 72 | 73 | # The language for content autogenerated by Sphinx. Refer to documentation 74 | # for a list of supported languages. 75 | # language = None 76 | 77 | # There are two options for replacing |today|: either, you set today to some 78 | # non-false value, then it is used: 79 | # today = '' 80 | # Else, today_fmt is used as the format for a strftime call. 81 | # today_fmt = '%B %d, %Y' 82 | 83 | # List of patterns, relative to source directory, that match files and 84 | # directories to ignore when looking for source files. 85 | exclude_patterns = [] 86 | 87 | # The reST default role (used for this markup: `text`) to use for all 88 | # documents. 89 | # default_role = None 90 | 91 | # If true, '()' will be appended to :func: etc. cross-reference text. 92 | # add_function_parentheses = True 93 | 94 | # If true, the current module name will be prepended to all description 95 | # unit titles (such as .. function::). 96 | # add_module_names = True 97 | 98 | # If true, sectionauthor and moduleauthor directives will be shown in the 99 | # output. They are ignored by default. 100 | # show_authors = False 101 | 102 | # The name of the Pygments (syntax highlighting) style to use. 103 | pygments_style = 'native' 104 | 105 | # A list of ignored prefixes for module index sorting. 106 | # modindex_common_prefix = [] 107 | 108 | # If true, keep warnings as "system message" paragraphs in the built documents. 109 | # keep_warnings = False 110 | 111 | 112 | # -- Options for HTML output ---------------------------------------------- 113 | 114 | # The theme to use for HTML and HTML Help pages. See the documentation for 115 | # a list of builtin themes. 116 | html_theme = 'openstackdocs' 117 | 118 | # Theme options are theme-specific and customize the look and feel of a theme 119 | # further. For a list of options available for each theme, see the 120 | # documentation. 121 | # html_theme_options = {} 122 | 123 | # Add any paths that contain custom themes here, relative to this directory. 124 | # html_theme_path = [] 125 | 126 | # The name for this set of Sphinx documents. If None, it defaults to 127 | # " v documentation". 128 | # html_title = None 129 | 130 | # A shorter title for the navigation bar. Default is the same as html_title. 131 | # html_short_title = None 132 | 133 | # The name of an image file (relative to this directory) to place at the top 134 | # of the sidebar. 135 | # html_logo = None 136 | 137 | # The name of an image file (within the static path) to use as favicon of the 138 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 139 | # pixels large. 140 | # html_favicon = None 141 | 142 | # Add any paths that contain custom static files (such as style sheets) here, 143 | # relative to this directory. They are copied after the builtin static files, 144 | # so a file named "default.css" will overwrite the builtin "default.css". 145 | html_static_path = ['_static'] 146 | 147 | # Add any extra paths that contain custom files (such as robots.txt or 148 | # .htaccess) here, relative to this directory. These files are copied 149 | # directly to the root of the documentation. 150 | # html_extra_path = [] 151 | 152 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 153 | # using the given strftime format. 154 | # html_last_updated_fmt = '%b %d, %Y' 155 | 156 | # If true, SmartyPants will be used to convert quotes and dashes to 157 | # typographically correct entities. 158 | # html_use_smartypants = True 159 | 160 | # Custom sidebar templates, maps document names to template names. 161 | # html_sidebars = {} 162 | 163 | # Additional templates that should be rendered to pages, maps page names to 164 | # template names. 165 | # html_additional_pages = {} 166 | 167 | # If false, no module index is generated. 168 | # html_domain_indices = True 169 | 170 | # If false, no index is generated. 171 | # html_use_index = True 172 | 173 | # If true, the index is split into individual pages for each letter. 174 | # html_split_index = False 175 | 176 | # If true, links to the reST sources are added to the pages. 177 | # html_show_sourcelink = True 178 | 179 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 180 | # html_show_sphinx = True 181 | 182 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 183 | # html_show_copyright = True 184 | 185 | # If true, an OpenSearch description file will be output, and all pages will 186 | # contain a tag referring to it. The value of this option must be the 187 | # base URL from which the finished HTML is served. 188 | # html_use_opensearch = '' 189 | 190 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 191 | # html_file_suffix = None 192 | 193 | # Output file base name for HTML help builder. 194 | htmlhelp_basename = 'ironic_python_agent_builderReleaseNotesdoc' 195 | 196 | 197 | # -- Options for LaTeX output --------------------------------------------- 198 | 199 | latex_elements = { 200 | # The paper size ('letterpaper' or 'a4paper'). 201 | # 'papersize': 'letterpaper', 202 | 203 | # The font size ('10pt', '11pt' or '12pt'). 204 | # 'pointsize': '10pt', 205 | 206 | # Additional stuff for the LaTeX preamble. 207 | # 'preamble': '', 208 | } 209 | 210 | # Grouping the document tree into LaTeX files. List of tuples 211 | # (source start file, target name, title, 212 | # author, documentclass [howto, manual, or own class]). 213 | latex_documents = [ 214 | ('index', 'ironic_python_agent_builderReleaseNotes.tex', 215 | 'Ironic Python Agent Builder Release Notes Documentation', 216 | 'OpenStack Foundation', 'manual'), 217 | ] 218 | 219 | # The name of an image file (relative to this directory) to place at the top of 220 | # the title page. 221 | # latex_logo = None 222 | 223 | # For "manual" documents, if this is true, then toplevel headings are parts, 224 | # not chapters. 225 | # latex_use_parts = False 226 | 227 | # If true, show page references after internal links. 228 | # latex_show_pagerefs = False 229 | 230 | # If true, show URL addresses after external links. 231 | # latex_show_urls = False 232 | 233 | # Documents to append as an appendix to all manuals. 234 | # latex_appendices = [] 235 | 236 | # If false, no module index is generated. 237 | # latex_domain_indices = True 238 | 239 | 240 | # -- Options for manual page output --------------------------------------- 241 | 242 | # One entry per manual page. List of tuples 243 | # (source start file, name, description, authors, manual section). 244 | man_pages = [ 245 | ('index', 'ironic_python_agent_builderrereleasenotes', 246 | 'Ironic Python Agent Builder Release Notes Documentation', 247 | ['OpenStack Foundation'], 1) 248 | ] 249 | 250 | # If true, show URL addresses after external links. 251 | # man_show_urls = False 252 | 253 | 254 | # -- Options for Texinfo output ------------------------------------------- 255 | 256 | # Grouping the document tree into Texinfo files. List of tuples 257 | # (source start file, target name, title, author, 258 | # dir menu entry, description, category) 259 | texinfo_documents = [ 260 | ('index', 'ironic_python_agent_builder ReleaseNotes', 261 | 'Ironic Python Agent Builder Release Notes Documentation', 262 | 'OpenStack Foundation', 'ironic_python_agent_builderReleaseNotes', 263 | 'Release notes for Ironic Python Agent Builder.', 264 | 'Miscellaneous'), 265 | ] 266 | 267 | # Documents to append as an appendix to all manuals. 268 | # texinfo_appendices = [] 269 | 270 | # If false, no module index is generated. 271 | # texinfo_domain_indices = True 272 | 273 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 274 | # texinfo_show_urls = 'footnote' 275 | 276 | # If true, do not generate a @detailmenu in the "Top" node's menu. 277 | # texinfo_no_detailmenu = False 278 | 279 | # -- Options for Internationalization output ------------------------------ 280 | locale_dirs = ['locale/'] 281 | -------------------------------------------------------------------------------- /releasenotes/source/index.rst: -------------------------------------------------------------------------------- 1 | ========================================= 2 | Ironic Python Agent Builder Release Notes 3 | ========================================= 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | unreleased 9 | 2025.1 10 | 2024.2 11 | 2024.1 12 | 2023.2 13 | 2023.1 14 | zed 15 | yoga 16 | xena 17 | wallaby 18 | -------------------------------------------------------------------------------- /releasenotes/source/unreleased.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Current Series Release Notes 3 | ============================ 4 | 5 | .. release-notes:: 6 | 7 | -------------------------------------------------------------------------------- /releasenotes/source/wallaby.rst: -------------------------------------------------------------------------------- 1 | ============================ 2 | Wallaby Series Release Notes 3 | ============================ 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/wallaby 7 | -------------------------------------------------------------------------------- /releasenotes/source/xena.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Xena Series Release Notes 3 | ========================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/xena 7 | -------------------------------------------------------------------------------- /releasenotes/source/yoga.rst: -------------------------------------------------------------------------------- 1 | ========================= 2 | Yoga Series Release Notes 3 | ========================= 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/yoga 7 | -------------------------------------------------------------------------------- /releasenotes/source/zed.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | Zed Series Release Notes 3 | ======================== 4 | 5 | .. release-notes:: 6 | :branch: unmaintained/zed 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # The order of packages is significant, because pip processes them in the order 2 | # of appearance. Changing the order has an impact on the overall integration 3 | # process, which may cause wedges in the gate later. 4 | 5 | diskimage-builder>=3.4.0 # Apache-2.0 6 | 7 | -------------------------------------------------------------------------------- /roles/ipa-build-dib-image/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | image_distro: centos-minimal 2 | image_release: 3 | image_target_name: 4 | ipa_branch_path: '{{ zuul.branch | replace("/", "-") }}' 5 | ipa_source_path: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent' 6 | requirements_path: '{{ ansible_user_dir }}/src/opendev.org/openstack/requirements' 7 | ipa_raw_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_RAW' 8 | ipa_tar_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_TAR' 9 | dib_extra_args: 10 | dib_from_source: true 11 | dib_no_tmpfs: 0 12 | extra_elements: ["dynamic-login"] 13 | -------------------------------------------------------------------------------- /roles/ipa-build-dib-image/tasks/install.yaml: -------------------------------------------------------------------------------- 1 | - name: Install binary dependencies from diskimage-builder 2 | include_role: 3 | name: bindep 4 | vars: 5 | bindep_dir: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/diskimage-builder'].src_dir }}" 6 | 7 | - name: Install ironic-python-agent-builder 8 | pip: 9 | name: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/ironic-python-agent-builder'].src_dir }}" 10 | extra_args: -c "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/requirements'].src_dir }}/upper-constraints.txt" 11 | become: true 12 | 13 | # NOTE(dtantsur): installing requirements separately since DIB itself is in 14 | # upper-constraints and source installations cannot be constrained. 15 | 16 | - name: Install requirements for DIB (if installing from source) 17 | pip: 18 | requirements: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/diskimage-builder'].src_dir }}/requirements.txt" 19 | extra_args: -c "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/requirements'].src_dir }}/upper-constraints.txt" 20 | become: true 21 | when: dib_from_source 22 | 23 | - name: Install DIB (if installing from source) 24 | pip: 25 | name: "{{ ansible_user_dir }}/{{ zuul.projects['opendev.org/openstack/diskimage-builder'].src_dir }}" 26 | become: true 27 | when: dib_from_source 28 | 29 | -------------------------------------------------------------------------------- /roles/ipa-build-dib-image/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - name: Default to CentOS Stream 9 2 | set_fact: 3 | image_release: 9-stream 4 | when: 5 | - image_distro in ["centos-minimal", "centos"] 6 | - not image_release 7 | 8 | - name: Generate a nice target name for CentOS 9 | set_fact: 10 | image_target_name: centos{{ image_release }} 11 | when: 12 | - image_distro in ["centos-minimal", "centos"] 13 | - not image_target_name 14 | 15 | - name: Generate a nice target name for Debian 16 | set_fact: 17 | image_target_name: debian 18 | when: 19 | - image_distro in ["debian-minimal", "debian"] 20 | - not image_target_name 21 | 22 | - name: Generate image name 23 | set_fact: 24 | image_name: ipa-{{ image_target_name | default(image_distro, true) }}-{{ ipa_branch_path }} 25 | 26 | - name: Build a DIB image 27 | command: | 28 | ironic-python-agent-builder -o {{ image_name }} -b HEAD -v 29 | {{ "-r {}".format(image_release) if image_release else '' }} 30 | {% for element in extra_elements %} 31 | --element {{ element }} 32 | {% endfor %} 33 | {{ "--extra-args '{}'".format(dib_extra_args) if dib_extra_args else '' }} 34 | {{ image_distro }} 35 | environment: 36 | # Increase from the default value of 30 37 | DIB_DHCP_TIMEOUT: 60 38 | # Use or not tmpfs to build the image, default to use it. 39 | # As images become bigger and bigger, in the future we may 40 | # decide to switch to not use it by default since we have 41 | # enough disk space. 42 | DIB_NO_TMPFS: '{{ dib_no_tmpfs }}' 43 | # Use repositories checked out by Zuul (combined with -b HEAD above) 44 | DIB_REPOLOCATION_ironic_python_agent: '{{ ipa_source_path }}' 45 | DIB_REPOLOCATION_requirements: '{{ requirements_path }}' 46 | 47 | - name: Move the resulting files 48 | shell: | 49 | tar -czf "{{ ipa_tar_dir }}/{{ image_name }}.tar.gz" {{ image_name }}* 50 | mv {{ image_name }}* "{{ ipa_raw_dir }}" 51 | 52 | - name: Generate image checksums 53 | shell: 54 | cmd: sha256sum "{{ image_name }}.{{ item }}" > "{{ image_name }}.{{ item }}.sha256" 55 | chdir: "{{ ipa_raw_dir }}" 56 | with_items: 57 | - kernel 58 | - initramfs 59 | 60 | - name: Generate tarball checksum 61 | shell: 62 | cmd: sha256sum "{{ image_name }}.tar.gz" > "{{ image_name }}.tar.gz.sha256" 63 | chdir: "{{ ipa_tar_dir }}" 64 | -------------------------------------------------------------------------------- /roles/ipa-build-tinyipa-image/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | ipa_branch_path: '{{ zuul.branch | replace("/", "-") }}' 2 | ipa_raw_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_RAW' 3 | ipa_tar_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_TAR' 4 | tinyipa_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent-builder/tinyipa' 5 | -------------------------------------------------------------------------------- /roles/ipa-build-tinyipa-image/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - name: Build a TinyIPA image 2 | command: make 3 | args: 4 | chdir: '{{ tinyipa_dir }}' 5 | environment: 6 | BRANCH_PATH: '{{ ipa_branch_path }}' 7 | IPA_SOURCE_DIR: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent' 8 | 9 | - name: Build a TinyIPA iso 10 | command: make iso 11 | args: 12 | chdir: '{{ tinyipa_dir }}' 13 | environment: 14 | BRANCH_PATH: '{{ ipa_branch_path }}' 15 | IPA_SOURCE_DIR: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent' 16 | 17 | - name: Move resulting files 18 | shell: | 19 | mv tinyipa*.tar.gz* "{{ ipa_tar_dir }}" 20 | mv tinyipa*.* "{{ ipa_raw_dir }}" 21 | mv tiny-instance-uec*.tar.gz "{{ ipa_tar_dir }}" 22 | args: 23 | chdir: '{{ tinyipa_dir }}' 24 | 25 | # NOTE(sambetts) Must clean up chroot directories before 26 | # publisher rsync command tries and fails to read them 27 | - name: Clean up the environment 28 | command: make clean 29 | args: 30 | chdir: '{{ tinyipa_dir }}' 31 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | name = ironic-python-agent-builder 3 | summary = Tools and scripts to build Ironic Python Agent 4 | description_file = 5 | README.rst 6 | author = OpenStack 7 | author_email = openstack-discuss@lists.openstack.org 8 | home_page = https://docs.openstack.org/ironic-python-agent-builder/latest/ 9 | classifier = 10 | Environment :: OpenStack 11 | Intended Audience :: Information Technology 12 | Intended Audience :: System Administrators 13 | License :: OSI Approved :: Apache Software License 14 | Operating System :: POSIX :: Linux 15 | 16 | [entry_points] 17 | console_scripts = 18 | ironic-python-agent-builder = ironic_python_agent_builder:main 19 | 20 | [files] 21 | packages = 22 | ironic_python_agent_builder 23 | # TODO(dtantsur): figure out a sane way to distribute tinyipa scripts 24 | data_files = 25 | share/ironic-python-agent-builder/dib = dib/* 26 | 27 | [codespell] 28 | quiet-level = 4 29 | # Words to ignore: 30 | # ignore-words-list = example -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 Hewlett-Packard Development Company, L.P. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 12 | # implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | import setuptools 17 | 18 | setuptools.setup( 19 | setup_requires=['pbr>=2.0.0'], 20 | py_modules=[], 21 | pbr=True) 22 | -------------------------------------------------------------------------------- /tinyipa/.gitignore: -------------------------------------------------------------------------------- 1 | *.gz 2 | *.zip 3 | *.tar.gz 4 | tinyipabuild 5 | tinyipafinal 6 | *.vmlinuz 7 | vmlinuz64 8 | *.sha256 9 | *.iso 10 | *.tcz* 11 | squashfs-root 12 | syslinux* 13 | newiso 14 | -------------------------------------------------------------------------------- /tinyipa/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: default all dependencies build finalise addssh iso clean clean_build clean_iso 2 | default: dependencies build finalise instance-images 3 | 4 | all: dependencies build finalise iso instance-images 5 | 6 | dependencies: 7 | ./install-deps.sh 8 | 9 | build: 10 | ./build-tinyipa.sh 11 | 12 | finalise: 13 | ./finalise-tinyipa.sh 14 | 15 | addssh: 16 | ./add-ssh-tinyipa.sh 17 | 18 | iso: 19 | ./build-iso.sh 20 | 21 | instance-images: 22 | ./build-instance-images.sh 23 | 24 | clean: clean_build clean_iso 25 | 26 | clean_build: 27 | sudo -v 28 | sudo rm -rf tinyipabuild 29 | sudo rm -rf tinyipafinal 30 | sudo rm -rf tinyipaaddssh 31 | rm -f *tinyipa*.vmlinuz 32 | rm -f *tinyipa*.gz 33 | rm -f *tinyipa*.sha256 34 | rm -f build_files/corepure64.gz 35 | rm -f build_files/vmlinuz64 36 | rm -f build_files/*.tcz 37 | rm -f build_files/*.tcz.* 38 | rm -f tiny-instance-part*.img 39 | rm -f tiny-instance-uec*.tar.gz 40 | 41 | clean_iso: 42 | rm -rf newiso 43 | rm -f build_files/syslinux-4.06.tar.gz 44 | rm -rf build_files/syslinux-4.06 45 | rm -f tinyipa.iso 46 | -------------------------------------------------------------------------------- /tinyipa/README.rst: -------------------------------------------------------------------------------- 1 | ============================= 2 | Tiny Core Ironic Python Agent 3 | ============================= 4 | 5 | See 6 | https://docs.openstack.org/ironic-python-agent-builder/latest/admin/tinyipa.html 7 | -------------------------------------------------------------------------------- /tinyipa/add-ssh-tinyipa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Rebuild upstream pre-built tinyipa it to be usable with ansible-deploy. 4 | # 5 | # Downloads the pre-built tinyipa ramdisk from tarballs.openstack.org or 6 | # rebuilds a ramdisk under path set as TINYIPA_RAMDISK_FILE shell var. 7 | 8 | # During rebuild this script installs and configures OpenSSH server if needed 9 | # and makes required changes for Ansible + Python to work in compiled/optimized 10 | # Python environment. 11 | # 12 | # By default, id_rsa or id_dsa keys of the user performing the build 13 | # are baked into the image as authorized_keys for 'tc' user. 14 | # To supply different public ssh key, before running this script set 15 | # SSH_PUBLIC_KEY environment variable to point to absolute path to the key. 16 | # 17 | # This script produces "ansible-" ramdisk that can serve 18 | # as ramdisk for both ansible-deploy driver and agent-based Ironic drivers, 19 | 20 | set -ex 21 | WORKDIR=$(readlink -f $0 | xargs dirname) 22 | REBUILDDIR="$WORKDIR/tinyipaaddssh" 23 | DST_DIR=$REBUILDDIR 24 | source ${WORKDIR}/common.sh 25 | 26 | TINYCORE_MIRROR_URL=${TINYCORE_MIRROR_URL:-} 27 | BRANCH_PATH=${BRANCH_PATH:-master} 28 | TINYIPA_RAMDISK_FILE=${TINYIPA_RAMDISK_FILE:-} 29 | 30 | SSH_PUBLIC_KEY=${SSH_PUBLIC_KEY:-} 31 | 32 | SSHD_CONFIG_PATH="/usr/local/etc/ssh/sshd_config" 33 | SSH_RSA_KEY_PATH="/usr/local/etc/ssh/ssh_host_rsa_key" 34 | SSH_DSA_KEY_PATH="/usr/local/etc/ssh/ssh_host_dsa_key" 35 | SSH_ED25519_KEY_PATH="/usr/local/etc/ssh/ssh_host_ed25519_key" 36 | 37 | function validate_params { 38 | echo "Validating location of public SSH key" 39 | if [ -n "$SSH_PUBLIC_KEY" ]; then 40 | if [ -r "$SSH_PUBLIC_KEY" ]; then 41 | _found_ssh_key="$SSH_PUBLIC_KEY" 42 | fi 43 | else 44 | for fmt in rsa dsa; do 45 | if [ -r "$HOME/.ssh/id_$fmt.pub" ]; then 46 | _found_ssh_key="$HOME/.ssh/id_$fmt.pub" 47 | break 48 | fi 49 | done 50 | fi 51 | 52 | if [ -z $_found_ssh_key ]; then 53 | echo "Failed to find neither provided nor default SSH key" 54 | exit 1 55 | fi 56 | } 57 | 58 | function get_tinyipa { 59 | if [ -z $TINYIPA_RAMDISK_FILE ]; then 60 | mkdir -p $WORKDIR/build_files/cache 61 | cd $WORKDIR/build_files/cache 62 | wget -N https://tarballs.openstack.org/ironic-python-agent/tinyipa/files/tinyipa${BRANCH_EXT}.gz 63 | TINYIPA_RAMDISK_FILE="$WORKDIR/build_files/cache/tinyipa${BRANCH_EXT}.gz" 64 | fi 65 | } 66 | 67 | function unpack_ramdisk { 68 | 69 | if [ -d "$REBUILDDIR" ]; then 70 | sudo rm -rf "$REBUILDDIR" 71 | fi 72 | 73 | mkdir -p "$REBUILDDIR" 74 | 75 | # Extract rootfs from .gz file 76 | ( cd "$REBUILDDIR" && zcat "$TINYIPA_RAMDISK_FILE" | sudo cpio -i -H newc -d ) 77 | 78 | } 79 | 80 | function install_ssh { 81 | if [ ! -f "${REBUILDDIR}${SSHD_CONFIG_PATH}" ]; then 82 | # tinyipa was built without SSH server installed 83 | # Install and configure bare minimum for SSH access 84 | $TC_CHROOT_CMD tce-load -wic openssh 85 | # Configure OpenSSH 86 | $CHROOT_CMD cp ${SSHD_CONFIG_PATH}.orig $SSHD_CONFIG_PATH 87 | echo "PasswordAuthentication no" | $CHROOT_CMD tee -a $SSHD_CONFIG_PATH 88 | # Generate and configure host keys - RSA, DSA, Ed25519 89 | # NOTE(pas-ha) ECDSA host key will still be re-generated fresh on every image boot 90 | $CHROOT_CMD ssh-keygen -q -t rsa -N "" -f $SSH_RSA_KEY_PATH 91 | $CHROOT_CMD ssh-keygen -q -t dsa -N "" -f $SSH_DSA_KEY_PATH 92 | $CHROOT_CMD ssh-keygen -q -t ed25519 -N "" -f $SSH_ED25519_KEY_PATH 93 | echo "HostKey ${SSH_RSA_KEY_PATH}" | $CHROOT_CMD tee -a $SSHD_CONFIG_PATH 94 | echo "HostKey ${SSH_DSA_KEY_PATH}" | $CHROOT_CMD tee -a $SSHD_CONFIG_PATH 95 | echo "HostKey ${SSH_ED25519_KEY_PATH}" | $CHROOT_CMD tee -a $SSHD_CONFIG_PATH 96 | fi 97 | 98 | # setup new user SSH keys anyway 99 | $CHROOT_CMD mkdir -p /home/tc 100 | $CHROOT_CMD chown -R tc.staff /home/tc 101 | $TC_CHROOT_CMD mkdir -p /home/tc/.ssh 102 | cat $_found_ssh_key | $TC_CHROOT_CMD tee /home/tc/.ssh/authorized_keys 103 | $CHROOT_CMD chown tc.staff /home/tc/.ssh/authorized_keys 104 | $TC_CHROOT_CMD chmod 600 /home/tc/.ssh/authorized_keys 105 | } 106 | 107 | 108 | function rebuild_ramdisk { 109 | # Rebuild build directory into gz file 110 | ansible_basename="ansible-$(basename $TINYIPA_RAMDISK_FILE)" 111 | ( cd "$REBUILDDIR" && sudo find | sudo cpio -o -H newc | gzip -9 > "$WORKDIR/${ansible_basename}" ) 112 | # Output file created by this script and its size 113 | cd "$WORKDIR" 114 | echo "Produced files:" 115 | du -h "${ansible_basename}" 116 | } 117 | 118 | sudo -v 119 | 120 | 121 | validate_params 122 | get_tinyipa 123 | unpack_ramdisk 124 | setup_tce "$DST_DIR" 125 | 126 | # NOTE (pas-ha) default tinyipa is built without SSH access, enable it here 127 | install_ssh 128 | 129 | cleanup_tce "$DST_DIR" 130 | rebuild_ramdisk 131 | -------------------------------------------------------------------------------- /tinyipa/build-instance-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | WORKDIR=$(readlink -f $0 | xargs dirname) 5 | DST_DIR=$(mktemp -d) 6 | source ${WORKDIR}/common.sh 7 | PARTIMG="$WORKDIR/tiny-instance-part${BRANCH_EXT}.img" 8 | UECFILE="$WORKDIR/tiny-instance-uec${BRANCH_EXT}.tar.gz" 9 | fs_type='ext4' 10 | 11 | sudo rm -rf $PARTIMG $UECFILE 12 | sudo truncate --size=150M $PARTIMG 13 | 14 | sudo mkfs."${fs_type}" -F "$PARTIMG" -L "root" 15 | sudo mount -o loop "$PARTIMG" "$DST_DIR/" 16 | 17 | # Extract rootfs from .gz file 18 | ( cd "$DST_DIR" && zcat $WORKDIR/build_files/corepure64.gz | sudo cpio -i -H newc -d ) 19 | 20 | setup_tce $DST_DIR 21 | 22 | # NOTE(rpittau) change ownership of the tce info dir to prevent writing issues 23 | sudo chown $TC:$STAFF $DST_DIR/usr/local/tce.installed 24 | 25 | $TC_CHROOT_CMD tce-load -wci grub2-multi.tcz 26 | 27 | cleanup_tce $DST_DIR 28 | sudo umount $DST_DIR/ 29 | 30 | pushd $DST_DIR/ 31 | cp $WORKDIR/tinyipa${BRANCH_EXT}.gz $DST_DIR/tinyipa-initrd 32 | cp $WORKDIR/tinyipa${BRANCH_EXT}.vmlinuz $DST_DIR/tinyipa-vmlinuz 33 | cp $PARTIMG $DST_DIR/ 34 | 35 | tar -czf $UECFILE ./ 36 | 37 | popd 38 | 39 | sudo rm -rf $DST_DIR 40 | -------------------------------------------------------------------------------- /tinyipa/build-iso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | WORKDIR=$(readlink -f $0 | xargs dirname) 5 | SYSLINUX_VERSION="6.03" 6 | SYSLINUX_URL="https://www.kernel.org/pub/linux/utils/boot/syslinux/syslinux-${SYSLINUX_VERSION}.tar.gz" 7 | 8 | source ${WORKDIR}/common.sh 9 | 10 | cd ${WORKDIR}/build_files 11 | wget -N $SYSLINUX_URL && tar zxf syslinux-${SYSLINUX_VERSION}.tar.gz 12 | 13 | cd $WORKDIR 14 | rm -rf newiso 15 | mkdir -p newiso/boot/isolinux 16 | cp build_files/syslinux-${SYSLINUX_VERSION}/bios/core/isolinux.bin newiso/boot/isolinux/. 17 | cp build_files/isolinux.cfg newiso/boot/isolinux/. 18 | cp tinyipa${BRANCH_EXT}.gz newiso/boot/corepure64.gz 19 | cp tinyipa${BRANCH_EXT}.vmlinuz newiso/boot/vmlinuz64 20 | 21 | set +e 22 | ISO_BUILDER="" 23 | 24 | for builder in mkisofs genisoimage xorrisofs; do 25 | if $($builder --help); then 26 | ISO_BUILDER=$builder 27 | fi 28 | done 29 | if [ -z "$ISO_BUILDER" ]; then 30 | echo "Please install a ISO filesystem builder utility such as mkisofs, genisoimage, or xorrisofs." 31 | exit 1 32 | fi 33 | 34 | set -e 35 | $ISO_BUILDER -l -r -J -R -V TC-custom -no-emul-boot -boot-load-size 4 -boot-info-table -b boot/isolinux/isolinux.bin -c boot/isolinux/boot.cat -o tinyipa.iso newiso 36 | -------------------------------------------------------------------------------- /tinyipa/build-tinyipa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | WORKDIR=$(readlink -f $0 | xargs dirname) 5 | source ${WORKDIR}/common.sh 6 | 7 | IRONIC_LIB_SOURCE=${IRONIC_LIB_SOURCE:-} 8 | 9 | TC_RELEASE="15.x" 10 | QEMU_RELEASE="5.2.0" 11 | LSHW_RELEASE="B.02.18" 12 | BIOSDEVNAME_RELEASE="0.7.2" 13 | IPMITOOL_GIT_HASH="19d78782d795d0cf4ceefe655f616210c9143e62" 14 | 15 | CHROOT_CMD="sudo chroot $BUILDDIR /usr/bin/env -i PATH=$CHROOT_PATH http_proxy=$http_proxy https_proxy=$https_proxy no_proxy=$no_proxy" 16 | 17 | DOWNLOAD_RETRY_MAX=${DOWNLOAD_RETRY_MAX:-5} 18 | DOWNLOAD_RETRY_DELAY=${DOWNLOAD_RETRY_DELAY:-10} 19 | 20 | function download_with_retry() { 21 | local source_url=$1 22 | local destination_path=$2 23 | local attempts=1 24 | 25 | declare -A tar_flags=( 26 | ["tar.gz"]="z" 27 | ["tgz"]="z" 28 | ["tar.bz2"]="j" 29 | ["tbz2"]="j" 30 | ["tar.xz"]="J" 31 | ["txz"]="J" 32 | ) 33 | 34 | echo "Downloading $source_url to $destination_path" 35 | while [ $attempts -le $DOWNLOAD_RETRY_MAX ]; do 36 | for ext in "${!tar_flags[@]}"; do 37 | if [[ "$source_url" =~ \.${ext}$ ]]; then 38 | mkdir -p "$destination_path" 39 | if wget --timeout=30 --tries=3 -O - "$source_url" | tar -x${tar_flags[$ext]} -C "$destination_path" --strip-components=1 -f -; then 40 | echo "Successfully downloaded $source_url on attempt $attempts" 41 | return 0 42 | fi 43 | break 44 | fi 45 | done 46 | 47 | if [[ ! "$source_url" =~ \.tar\.[a-z]+$ ]]; then 48 | if wget --timeout=30 --tries=3 "$source_url" -O "${destination_path}"; then 49 | echo "Successfully downloaded $source_url on attempt $attempts" 50 | return 0 51 | fi 52 | fi 53 | 54 | echo "Download attempt $attempts failed for $source_url, retrying in $DOWNLOAD_RETRY_DELAY seconds..." 55 | sleep $DOWNLOAD_RETRY_DELAY 56 | attempts=$((attempts + 1)) 57 | done 58 | 59 | echo "Failed to download $source_url after $DOWNLOAD_RETRY_MAX attempts" 60 | return 1 61 | } 62 | 63 | function tce_load_with_retry() { 64 | local package=$1 65 | local attempts=1 66 | 67 | echo "Loading package $package with tce-load" 68 | while [ $attempts -le $DOWNLOAD_RETRY_MAX ]; do 69 | if sudo chroot --userspec=$TC:$STAFF $BUILDDIR /usr/bin/env -i PATH=$CHROOT_PATH http_proxy=$http_proxy https_proxy=$https_proxy no_proxy=$no_proxy tce-load -wci $package; then 70 | echo "Successfully loaded $package on attempt $attempts" 71 | return 0 72 | fi 73 | 74 | echo "tce-load attempt $attempts failed for $package, retrying in $DOWNLOAD_RETRY_DELAY seconds..." 75 | sleep $DOWNLOAD_RETRY_DELAY 76 | attempts=$((attempts + 1)) 77 | done 78 | 79 | echo "Failed to load $package with tce-load after $DOWNLOAD_RETRY_MAX attempts" 80 | return 1 81 | } 82 | 83 | echo "Building tinyipa:" 84 | 85 | # Ensure we have an extended sudo to prevent the need to enter a password over 86 | # and over again. 87 | sudo -v 88 | 89 | # If an old build directory exists remove it 90 | if [ -d "$BUILDDIR" ]; then 91 | sudo rm -rf "$BUILDDIR" 92 | fi 93 | 94 | ############################################## 95 | # Download and Cache Tiny Core Files 96 | ############################################## 97 | 98 | # Find a working TC mirror if none is explicitly provided 99 | choose_tc_mirror 100 | 101 | cd $WORKDIR/build_files 102 | download_with_retry "$TINYCORE_MIRROR_URL/$TC_RELEASE/x86_64/release/distribution_files/corepure64.gz" "corepure64.gz" 103 | download_with_retry "$TINYCORE_MIRROR_URL/$TC_RELEASE/x86_64/release/distribution_files/vmlinuz64" "vmlinuz64" 104 | cd $WORKDIR 105 | 106 | ######################################################## 107 | # Build Required Python Dependencies in a Build Directory 108 | ######################################################## 109 | 110 | # Make directory for building in 111 | mkdir "$BUILDDIR" 112 | 113 | # Extract rootfs from .gz file 114 | ( cd "$BUILDDIR" && zcat $WORKDIR/build_files/corepure64.gz | sudo cpio -i -H newc -d ) 115 | 116 | # Configure mirror 117 | sudo sh -c "echo $TINYCORE_MIRROR_URL > $BUILDDIR/opt/tcemirror" 118 | 119 | # Download Qemu-utils, Biosdevname and IPMItool source 120 | download_with_retry "https://download.qemu.org/qemu-${QEMU_RELEASE}.tar.xz" "${BUILDDIR}/tmp/qemu" 121 | download_with_retry "https://github.com/lyonel/lshw/archive/refs/tags/${LSHW_RELEASE}.tar.gz" "${BUILDDIR}/tmp/lshw" 122 | if $TINYIPA_REQUIRE_BIOSDEVNAME; then 123 | download_with_retry "https://linux.dell.com/biosdevname/biosdevname-${BIOSDEVNAME_RELEASE}/biosdevname-${BIOSDEVNAME_RELEASE}.tar.gz" "${BUILDDIR}/tmp/biosdevname" 124 | fi 125 | if $TINYIPA_REQUIRE_IPMITOOL; then 126 | git clone https://codeberg.org/IPMITool/ipmitool.git "${BUILDDIR}/tmp/ipmitool-src" 127 | cd "${BUILDDIR}/tmp/ipmitool-src" 128 | git reset $IPMITOOL_GIT_HASH --hard 129 | cd - 130 | fi 131 | 132 | # Create directory for python local mirror 133 | mkdir -p "$BUILDDIR/tmp/localpip" 134 | 135 | # Download IPA and requirements 136 | IPA_SOURCE_DIR=${IPA_SOURCE_DIR:-/opt/stack/ironic-python-agent} 137 | cd $IPA_SOURCE_DIR 138 | rm -rf *.egg-info 139 | pwd 140 | 141 | PYTHON_COMMAND="python3" 142 | $PYTHON_COMMAND setup.py sdist --dist-dir "$BUILDDIR/tmp/localpip" --quiet 143 | 144 | ls $BUILDDIR/tmp/localpip || true 145 | cp requirements.txt $BUILDDIR/tmp/ipa-requirements.txt 146 | 147 | if [ -n "$PYTHON_EXTRA_SOURCES_DIR_LIST" ]; then 148 | IFS="," read -ra PKGDIRS <<< "$PYTHON_EXTRA_SOURCES_DIR_LIST" 149 | for PKGDIR in "${PKGDIRS[@]}"; do 150 | PKG=$(cd "$PKGDIR" ; $PYTHON_COMMAND setup.py --name) 151 | pushd "$PKGDIR" 152 | rm -rf *.egg-info 153 | $PYTHON_COMMAND setup.py sdist --dist-dir "$BUILDDIR/tmp/localpip" --quiet 154 | if [[ -r requirements.txt ]]; then 155 | cp requirements.txt $BUILDDIR/tmp/${PKG}-requirements.txt 156 | fi 157 | popd 158 | done 159 | fi 160 | 161 | $WORKDIR/generate_tox_constraints.sh upper-constraints.txt 162 | cp upper-constraints.txt $BUILDDIR/tmp/upper-constraints.txt 163 | echo Using upper-constraints: 164 | cat upper-constraints.txt 165 | cd $WORKDIR 166 | 167 | sudo cp /etc/resolv.conf $BUILDDIR/etc/resolv.conf 168 | 169 | trap "sudo umount $BUILDDIR/proc; sudo umount $BUILDDIR/dev/pts" EXIT 170 | sudo mount --bind /proc $BUILDDIR/proc 171 | sudo mount --bind /dev/pts $BUILDDIR/dev/pts 172 | 173 | if [ -d /opt/stack/new ]; then 174 | CI_DIR=/opt/stack/new 175 | elif [ -d /opt/stack ]; then 176 | CI_DIR=/opt/stack 177 | else 178 | CI_DIR= 179 | fi 180 | 181 | if [ -n "$CI_DIR" ]; then 182 | # Running in CI environment, make checkouts available 183 | $CHROOT_CMD mkdir -p $CI_DIR 184 | for project in $(ls $CI_DIR); do 185 | if grep -q "$project" $BUILDDIR/tmp/upper-constraints.txt && 186 | [ -d "$CI_DIR/$project/.git" ]; then 187 | sudo cp -R "$CI_DIR/$project" $BUILDDIR/$CI_DIR/ 188 | fi 189 | done 190 | fi 191 | 192 | $CHROOT_CMD mkdir -m777 /etc/sysconfig/tcedir 193 | $CHROOT_CMD touch /etc/sysconfig/tcuser 194 | $CHROOT_CMD chmod a+rwx /etc/sysconfig/tcuser 195 | 196 | mkdir $BUILDDIR/tmp/overrides 197 | cp $WORKDIR/build_files/fakeuname $BUILDDIR/tmp/overrides/uname 198 | 199 | sudo cp $WORKDIR/build_files/ntpdate $BUILDDIR/bin/ntpdate 200 | 201 | PY_REQS="buildreqs_python3.lst" 202 | 203 | # NOTE(rpittau) change ownership of the tce info dir to prevent writing issues 204 | sudo chown $TC:$STAFF $BUILDDIR/usr/local/tce.installed 205 | 206 | while read line; do 207 | tce_load_with_retry "$line" 208 | done < <(paste $WORKDIR/build_files/$PY_REQS $WORKDIR/build_files/buildreqs.lst) 209 | 210 | TINYIPA_PYTHON_EXE="python3.9" 211 | 212 | PIP_COMMAND="$TINYIPA_PYTHON_EXE -m pip" 213 | 214 | # Build python wheels 215 | $CHROOT_CMD ${TINYIPA_PYTHON_EXE} -m ensurepip 216 | $CHROOT_CMD ${PIP_COMMAND} install --upgrade pip==${PIP_VERSION} wheel 217 | $CHROOT_CMD ${PIP_COMMAND} install pbr 218 | $CHROOT_CMD ${PIP_COMMAND} wheel -c /tmp/upper-constraints.txt --wheel-dir /tmp/wheels -r /tmp/ipa-requirements.txt 219 | 220 | if [ -n "$PYTHON_EXTRA_SOURCES_DIR_LIST" ]; then 221 | IFS="," read -ra PKGDIRS <<< "$PYTHON_EXTRA_SOURCES_DIR_LIST" 222 | for PKGDIR in "${PKGDIRS[@]}"; do 223 | PKG=$(cd "$PKGDIR" ; $PYTHON_COMMAND setup.py --name) 224 | if [[ -r $BUILDDIR/tmp/${PKG}-requirements.txt ]]; then 225 | $CHROOT_CMD ${PIP_COMMAND} wheel -c /tmp/upper-constraints.txt --wheel-dir /tmp/wheels -r /tmp/${PKG}-requirements.txt 226 | fi 227 | $CHROOT_CMD ${PIP_COMMAND} wheel -c /tmp/upper-constraints.txt --no-index --pre --wheel-dir /tmp/wheels --find-links=/tmp/localpip --find-links=/tmp/wheels ${PKG} 228 | done 229 | fi 230 | 231 | $CHROOT_CMD ${PIP_COMMAND} wheel -c /tmp/upper-constraints.txt --no-index --pre --wheel-dir /tmp/wheels --find-links=/tmp/localpip --find-links=/tmp/wheels ironic-python-agent 232 | echo Resulting wheels: 233 | ls -1 $BUILDDIR/tmp/wheels 234 | 235 | # Build qemu-utils 236 | rm -rf $WORKDIR/build_files/qemu-utils.tcz 237 | $CHROOT_CMD /bin/sh -c "cd /tmp/qemu && CFLAGS=-Wno-error ./configure --disable-system --disable-user --disable-linux-user --disable-bsd-user --disable-guest-agent --disable-blobs --enable-tools --python=/usr/local/bin/$TINYIPA_PYTHON_EXE && make && make install DESTDIR=/tmp/qemu-utils" 238 | find $BUILDDIR/tmp/qemu-utils/ -type f -executable | xargs file | awk -F ':' '/ELF/ {print $1}' | sudo xargs strip 239 | cd $WORKDIR/build_files && mksquashfs $BUILDDIR/tmp/qemu-utils qemu-utils.tcz && md5sum qemu-utils.tcz > qemu-utils.tcz.md5.txt 240 | # Create qemu-utils.tcz.dep 241 | echo "glib2.tcz" > qemu-utils.tcz.dep 242 | 243 | # Build lshw 244 | rm -rf $WORKDIR/build_files/lshw.tcz 245 | # NOTE(mjturek): We touch src/lshw.1 and clear src/po/Makefile to avoid building the man pages, as they aren't used and require large dependencies to build. 246 | $CHROOT_CMD /bin/sh -c "cd /tmp/lshw && touch src/lshw.1 && echo install: > src/po/Makefile && make && make install DESTDIR=/tmp/lshw-installed" 247 | find $BUILDDIR/tmp/lshw-installed/ -type f -executable | xargs file | awk -F ':' '/ELF/ {print $1}' | sudo xargs strip 248 | cd $WORKDIR/build_files && mksquashfs $BUILDDIR/tmp/lshw-installed lshw.tcz && md5sum lshw.tcz > lshw.tcz.md5.txt 249 | 250 | # Build biosdevname 251 | if $TINYIPA_REQUIRE_BIOSDEVNAME; then 252 | rm -rf $WORKDIR/build_files/biosdevname.tcz 253 | $CHROOT_CMD /bin/sh -c "cd /tmp/biosdevname-* && ./configure && make && make install DESTDIR=/tmp/biosdevname-installed" 254 | find $BUILDDIR/tmp/biosdevname-installed/ -type f -executable | xargs file | awk -F ':' '/ELF/ {print $1}' | sudo xargs strip 255 | cd $WORKDIR/build_files && mksquashfs $BUILDDIR/tmp/biosdevname-installed biosdevname.tcz && md5sum biosdevname.tcz > biosdevname.tcz.md5.txt 256 | fi 257 | 258 | if $TINYIPA_REQUIRE_IPMITOOL; then 259 | rm -rf $WORKDIR/build_files/ipmitool.tcz 260 | # NOTE(TheJulia): Explicitly add the libtool path since /usr/local/ is not in path from the chroot. 261 | $CHROOT_CMD /bin/sh -c "cd /tmp/ipmitool-src && env LIBTOOL='/usr/local/bin/libtool' ./bootstrap && ./configure && make && make install DESTDIR=/tmp/ipmitool" 262 | find $BUILDDIR/tmp/ipmitool/ -type f -executable | xargs file | awk -F ':' '/ELF/ {print $1}' | sudo xargs strip 263 | cd $WORKDIR/build_files && mksquashfs $BUILDDIR/tmp/ipmitool ipmitool.tcz && md5sum ipmitool.tcz > ipmitool.tcz.md5.txt 264 | fi 265 | -------------------------------------------------------------------------------- /tinyipa/build_files/bootlocal.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # put other system startup commands here 3 | 4 | #exec > /tmp/installlogs 2>&1 5 | set -ux 6 | 7 | echo "Starting bootlocal script:" 8 | date 9 | 10 | export HOME=/root 11 | 12 | # Start SSHd 13 | if [ -x /usr/local/etc/init.d/openssh ]; then 14 | echo "Starting OpenSSH server:" 15 | /usr/local/etc/init.d/openssh start 16 | fi 17 | 18 | # Start haveged 19 | if [ -x /usr/local/sbin/haveged ]; then 20 | echo "Starting haveged entropy daemon:" 21 | /usr/local/sbin/haveged 22 | fi 23 | 24 | # Maybe save some RAM? 25 | #rm -rf /tmp/builtin 26 | 27 | # Install IPA and dependencies 28 | if ! type "ironic-python-agent" > /dev/null ; then 29 | PIP_COMMAND="pip" 30 | if hash pip3 2>/dev/null; then 31 | PIP_COMMAND="pip3" 32 | fi 33 | $PIP_COMMAND install --no-index --find-links=file:///tmp/wheelhouse ironic_python_agent 34 | fi 35 | 36 | # Create ipa-rescue-config directory for rescue password 37 | sudo mkdir -p /etc/ipa-rescue-config 38 | 39 | # Setup DHCP network 40 | configure_dhcp_network() { 41 | for pidfile in `ls /var/run/udhcpc*.pid`; do 42 | kill `cat $pidfile` 43 | done 44 | 45 | # NOTE(TheJulia): We may need to add a short wait here as 46 | # network interface plugging actions may not be asynchronous. 47 | echo "Sleeping 30 sec as network interface is being updated" 48 | sleep 30 49 | INTERFACES=$(ip -o link |grep "LOWER_UP"|cut -f2 -d" "|sed 's/://'|grep -v "lo") 50 | for interface in $INTERFACES; do 51 | pidfile="/var/run/udhcpc/${interface}.pid" 52 | /sbin/udhcpc -b -p ${pidfile} -i ${interface} -s /opt/udhcpc.script >> /var/log/udhcpc.log 2>&1 53 | done 54 | echo "Completed DHCP client restart" 55 | echo "Outputting IP and Route information" 56 | ip addr || true 57 | ip route || true 58 | ip -6 route || true 59 | echo "Logging IPv4 sysctls" 60 | sysctl -a |grep ipv4 || true 61 | echo "Logging IPv6 sysctls" 62 | sysctl -a |grep ipv6 || true 63 | } 64 | 65 | # Configure networking, use custom udhcpc script to handle MTU option 66 | configure_dhcp_network 67 | 68 | mkdir -p /etc/ironic-python-agent.d/ 69 | 70 | if [ -d /sys/firmware/efi ] ; then 71 | echo "Make efivars available" 72 | mount -t efivarfs efivarfs /sys/firmware/efi/efivars 73 | fi 74 | 75 | # Run IPA 76 | echo "Starting Ironic Python Agent:" 77 | date 78 | ironic-python-agent --config-dir /etc/ironic-python-agent.d/ 2>&1 | tee /var/log/ironic-python-agent.log 79 | 80 | 81 | create_rescue_user() { 82 | crypted_pass=$(cat /etc/ipa-rescue-config/ipa-rescue-password) 83 | sudo adduser rescue -D -G root # no useradd 84 | echo "rescue:$crypted_pass" | sudo chpasswd -e 85 | sudo sh -c "echo \"rescue ALL=(ALL) NOPASSWD: ALL\" >> /etc/sudoers" # no suooers.d in tiny core. 86 | 87 | # Restart sshd with allowing password authentication 88 | sudo sed -i -e 's/^PasswordAuthentication no/PasswordAuthentication yes/' /usr/local/etc/ssh/sshd_config 89 | sudo /usr/local/etc/init.d/openssh restart 90 | } 91 | 92 | if [ -f /etc/ipa-rescue-config/ipa-rescue-password ]; then 93 | create_rescue_user || exit 0 94 | # The network might change during rescue, renew addresses in this case. 95 | configure_dhcp_network || exit 0 96 | else 97 | echo "IPA has exited. No rescue password file was defined." 98 | fi 99 | -------------------------------------------------------------------------------- /tinyipa/build_files/buildreqs.lst: -------------------------------------------------------------------------------- 1 | autoconf.tcz 2 | autogen-dev.tcz 3 | autogen.tcz 4 | automake.tcz 5 | bash.tcz 6 | binutils.tcz 7 | compiletc.tcz 8 | coreutils.tcz 9 | dmidecode.tcz 10 | gdisk.tcz 11 | git.tcz 12 | glib2-dev.tcz 13 | hdparm.tcz 14 | ipv6-netfilter-6.6.8-tinycore64.tcz 15 | libpci-dev.tcz 16 | libtool-dev.tcz 17 | libtool.tcz 18 | ninja.tcz 19 | parted.tcz 20 | pciutils.tcz 21 | pixman-dev.tcz 22 | raid-dm-6.6.8-tinycore64.tcz 23 | scsi-6.6.8-tinycore64.tcz 24 | udev-lib.tcz 25 | util-linux.tcz 26 | zlib_base-dev.tcz 27 | -------------------------------------------------------------------------------- /tinyipa/build_files/buildreqs_python3.lst: -------------------------------------------------------------------------------- 1 | python3.9.tcz 2 | python3.9-dev.tcz 3 | -------------------------------------------------------------------------------- /tinyipa/build_files/dhcp.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # The DHCP portion is now separated out, in order to not slow the boot down 3 | # only to wait for slow network cards 4 | . /etc/init.d/tc-functions 5 | 6 | # This waits until all devices have registered 7 | /sbin/udevadm settle --timeout=%UDEV_SETTLE_TIMEOUT% 8 | 9 | NETDEVICES="$(awk -F: '/^ *e.*:|^ *p.*:/{print $1}' /proc/net/dev 2>/dev/null)" 10 | echo "$0: Discovered network devices: $NETDEVICES" 11 | for DEVICE in $NETDEVICES; do 12 | ifconfig $DEVICE | grep -q "inet addr" 13 | if [ "$?" != 0 ]; then 14 | echo -e "\nNetwork device $DEVICE detected, DHCP broadcasting for IP." 15 | trap 2 3 11 16 | /sbin/udhcpc -b -i $DEVICE -x hostname:$(/bin/hostname) -p /var/run/udhcpc.$DEVICE.pid 2>&1 & 17 | trap "" 2 3 11 18 | sleep 1 19 | fi 20 | done 21 | 22 | -------------------------------------------------------------------------------- /tinyipa/build_files/fakeuname: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | S="Linux" 4 | N="box" 5 | R="6.6.8-tinycore64" 6 | P="unknown" 7 | V="#2017 SMP" 8 | M="x86_64" 9 | I="unknown" 10 | O="GNU/Linux" 11 | 12 | OPT_A=false 13 | OPT_S=false 14 | OPT_N=false 15 | OPT_R=false 16 | OPT_P=false 17 | OPT_V=false 18 | OPT_M=false 19 | OPT_I=false 20 | OPT_O=false 21 | 22 | if [ -z "$1" ]; then 23 | echo "-ASNRPVMIO" 24 | exit 1 25 | fi 26 | 27 | while :; do 28 | case $1 in 29 | -a) 30 | OPT_A=true 31 | shift 32 | ;; 33 | -s) 34 | OPT_S=true 35 | shift 36 | ;; 37 | -n) 38 | OPT_N=true 39 | shift 40 | ;; 41 | -r) 42 | OPT_R=true 43 | shift 44 | ;; 45 | -p) 46 | OPT_P=true 47 | shift 48 | ;; 49 | -v) 50 | OPT_V=true 51 | shift 52 | ;; 53 | -m) 54 | OPT_M=true 55 | shift 56 | ;; 57 | -i) 58 | OPT_I=true 59 | shift 60 | ;; 61 | -o) 62 | OPT_O=true 63 | shift 64 | ;; 65 | -rs) 66 | OPT_R=true 67 | OPT_S=true 68 | shift 69 | ;; 70 | *) 71 | if [ ! -z "$1" ]; then 72 | echo "uname -asnrpvmio" 73 | exit 1 74 | fi 75 | break 76 | ;; 77 | esac 78 | done 79 | 80 | if $OPT_A; then 81 | echo "$S $N $R $V $M $O" 82 | exit 0 83 | fi 84 | 85 | string='' 86 | if $OPT_S; then 87 | string="$string $S" 88 | fi 89 | if $OPT_N; then 90 | string="$string $N" 91 | fi 92 | if $OPT_R; then 93 | string="$string $R" 94 | fi 95 | if $OPT_P; then 96 | string="$string $P" 97 | fi 98 | if $OPT_V; then 99 | string="$string $V" 100 | fi 101 | if $OPT_M; then 102 | string="$string $M" 103 | fi 104 | if $OPT_I; then 105 | string="$string $I" 106 | fi 107 | if $OPT_O; then 108 | string="$string $O" 109 | fi 110 | echo $string 111 | -------------------------------------------------------------------------------- /tinyipa/build_files/finalreqs.lst: -------------------------------------------------------------------------------- 1 | bash.tcz 2 | coreutils.tcz 3 | dmidecode.tcz 4 | dosfstools.tcz 5 | efibootmgr.tcz 6 | efivar.tcz 7 | filesystems-6.6.8-tinycore64.tcz 8 | file.tcz 9 | gdisk.tcz 10 | glib2.tcz 11 | haveged.tcz 12 | hdparm.tcz 13 | iproute2.tcz 14 | ipv6-netfilter-6.6.8-tinycore64.tcz 15 | libxml2.tcz 16 | mdadm.tcz 17 | ntpclient.tcz 18 | parted.tcz 19 | pciutils.tcz 20 | popt.tcz 21 | raid-dm-6.6.8-tinycore64.tcz 22 | scsi-6.6.8-tinycore64.tcz 23 | smartmontools.tcz 24 | udev-lib.tcz 25 | util-linux.tcz 26 | -------------------------------------------------------------------------------- /tinyipa/build_files/finalreqs_python3.lst: -------------------------------------------------------------------------------- 1 | python3.9.tcz 2 | expat2.tcz 3 | -------------------------------------------------------------------------------- /tinyipa/build_files/isolinux.cfg: -------------------------------------------------------------------------------- 1 | display boot.msg 2 | default corepure64 3 | 4 | label corepure64 5 | kernel /boot/vmlinuz64 6 | initrd /boot/corepure64.gz 7 | append loglevel=3 syslog showapps boot_method=vmedia 8 | 9 | implicit 0 10 | -------------------------------------------------------------------------------- /tinyipa/build_files/modprobe.conf: -------------------------------------------------------------------------------- 1 | ipv6 2 | -------------------------------------------------------------------------------- /tinyipa/build_files/ntpdate: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if [ "$1" = "-v" ]; then 3 | echo "Magical ntpdate Wrapper 0.0.1" 4 | exit 0 5 | fi 6 | ntpclient -h $1 -s 7 | -------------------------------------------------------------------------------- /tinyipa/common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | WORKDIR=$(readlink -f $0 | xargs dirname) 4 | source ${WORKDIR}/tc-mirror.sh 5 | 6 | BUILDDIR="$WORKDIR/tinyipabuild" 7 | 8 | PIP_VERSION="21.3.1" 9 | 10 | TINYIPA_REQUIRE_BIOSDEVNAME=${TINYIPA_REQUIRE_BIOSDEVNAME:-false} 11 | TINYIPA_REQUIRE_IPMITOOL=${TINYIPA_REQUIRE_IPMITOOL:-true} 12 | 13 | # PYTHON_EXTRA_SOURCES_DIR_LIST is a csv list of python package dirs to include 14 | PYTHON_EXTRA_SOURCES_DIR_LIST=${PYTHON_EXTRA_SOURCES_DIR_LIST:-} 15 | 16 | # Allow an extension to be added to the generated files by specifying 17 | # $BRANCH_PATH e.g. export BRANCH_PATH=master results in tinyipa-master.gz etc 18 | BRANCH_EXT='' 19 | if [ -n "$BRANCH_PATH" ]; then 20 | BRANCH_EXT="-$BRANCH_PATH" 21 | fi 22 | export BRANCH_EXT 23 | 24 | TC=1001 25 | STAFF=50 26 | 27 | CHROOT_PATH="/tmp/overrides:/usr/local/sbin:/usr/local/bin:/apps/bin:/usr/sbin:/usr/bin:/sbin:/bin" 28 | CHROOT_CMD="sudo chroot $DST_DIR /usr/bin/env -i PATH=$CHROOT_PATH http_proxy=$http_proxy https_proxy=$https_proxy no_proxy=$no_proxy" 29 | TC_CHROOT_CMD="sudo chroot --userspec=$TC:$STAFF $DST_DIR /usr/bin/env -i PATH=$CHROOT_PATH http_proxy=$http_proxy https_proxy=$https_proxy no_proxy=$no_proxy" 30 | 31 | function setup_tce { 32 | # Setup resolv.conf, add mirrors, mount proc 33 | local dst_dir="$1" 34 | 35 | # Find a working TC mirror if none is explicitly provided 36 | choose_tc_mirror 37 | 38 | sudo cp $dst_dir/etc/resolv.conf $dst_dir/etc/resolv.conf.old 39 | sudo cp /etc/resolv.conf $dst_dir/etc/resolv.conf 40 | 41 | sudo cp -a $dst_dir/opt/tcemirror $dst_dir/opt/tcemirror.old 42 | sudo sh -c "echo $TINYCORE_MIRROR_URL > $dst_dir/opt/tcemirror" 43 | 44 | mkdir -p $dst_dir/tmp/builtin/optional 45 | $CHROOT_CMD chown -R tc.staff /tmp/builtin 46 | $CHROOT_CMD chmod -R a+w /tmp/builtin 47 | $CHROOT_CMD ln -sf /tmp/builtin /etc/sysconfig/tcedir 48 | echo "tc" | $CHROOT_CMD tee -a /etc/sysconfig/tcuser 49 | 50 | # Mount /proc for chroot commands 51 | sudo mount --bind /proc $dst_dir/proc 52 | } 53 | 54 | function cleanup_tce { 55 | local dst_dir="$1" 56 | 57 | # Unmount /proc and clean up everything 58 | sudo umount $dst_dir/proc 59 | sudo rm -rf $dst_dir/tmp/builtin 60 | sudo rm -rf $dst_dir/tmp/tcloop 61 | sudo rm -rf $dst_dir/usr/local/tce.installed 62 | sudo mv $dst_dir/opt/tcemirror.old $dst_dir/opt/tcemirror 63 | sudo mv $dst_dir/etc/resolv.conf.old $dst_dir/etc/resolv.conf 64 | sudo rm $dst_dir/etc/sysconfig/tcuser 65 | sudo rm $dst_dir/etc/sysconfig/tcedir 66 | } 67 | -------------------------------------------------------------------------------- /tinyipa/finalise-tinyipa.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | WORKDIR=$(readlink -f $0 | xargs dirname) 5 | FINALDIR="$WORKDIR/tinyipafinal" 6 | DST_DIR=$FINALDIR 7 | source ${WORKDIR}/common.sh 8 | 9 | BUILD_AND_INSTALL_TINYIPA=${BUILD_AND_INSTALL_TINYIPA:-true} 10 | INSTALL_SSH=${INSTALL_SSH:-true} 11 | AUTHORIZE_SSH=${AUTHORIZE_SSH:-false} 12 | 13 | SSH_PUBLIC_KEY=${SSH_PUBLIC_KEY:-} 14 | PYOPTIMIZE_TINYIPA=${PYOPTIMIZE_TINYIPA:-false} 15 | TINYIPA_UDEV_SETTLE_TIMEOUT=${TINYIPA_UDEV_SETTLE_TIMEOUT:-60} 16 | 17 | echo "Finalising tinyipa:" 18 | 19 | if [ -n "$PYTHON_EXTRA_SOURCES_DIR_LIST" ]; then 20 | IFS="," read -ra PKGDIRS <<< "$PYTHON_EXTRA_SOURCES_DIR_LIST" 21 | for PKGDIR in "${PKGDIRS[@]}"; do 22 | PKG=$(cd "$PKGDIR" ; python setup.py --name) 23 | done 24 | fi 25 | 26 | if $AUTHORIZE_SSH ; then 27 | echo "Validating location of public SSH key" 28 | if [ -n "$SSH_PUBLIC_KEY" ]; then 29 | if [ -f "$SSH_PUBLIC_KEY" ]; then 30 | _found_ssh_key="$SSH_PUBLIC_KEY" 31 | fi 32 | else 33 | for fmt in rsa dsa; do 34 | if [ -f "$HOME/.ssh/id_$fmt.pub" ]; then 35 | _found_ssh_key="$HOME/.ssh/id_$fmt.pub" 36 | break 37 | fi 38 | done 39 | fi 40 | 41 | if [ -z $_found_ssh_key ]; then 42 | echo "Failed to find neither provided nor default SSH key" 43 | exit 1 44 | fi 45 | fi 46 | 47 | sudo -v 48 | 49 | # Let's umount proc in case the old finalise process went sideways and 50 | # it's still mounted 51 | if grep -qs "$FINALDIR/proc" /proc/mounts; then 52 | sudo umount "$FINALDIR/proc" 53 | fi 54 | 55 | # Remove the old final chroot dir with all its content before starting a new 56 | # finalise process 57 | if [ -d "$FINALDIR" ]; then 58 | sudo rm -rf "$FINALDIR" 59 | fi 60 | 61 | mkdir "$FINALDIR" 62 | 63 | # Extract rootfs from .gz file 64 | ( cd "$FINALDIR" && zcat $WORKDIR/build_files/corepure64.gz | sudo cpio -i -H newc -d ) 65 | 66 | # Setup Final Dir 67 | setup_tce "$DST_DIR" 68 | 69 | # Modify ldconfig for x86-64 70 | $CHROOT_CMD cp /sbin/ldconfig /sbin/ldconfigold 71 | printf '#!/bin/sh\n/sbin/ldconfigold $@ | sed -r "s/libc6|ELF/libc6,x86-64/"' | $CHROOT_CMD tee -a /sbin/ldconfignew 72 | $CHROOT_CMD cp /sbin/ldconfignew /sbin/ldconfig 73 | $CHROOT_CMD chmod u+x /sbin/ldconfig 74 | 75 | # Copy python wheels from build to final dir 76 | cp -Rp "$BUILDDIR/tmp/wheels" "$FINALDIR/tmp/wheelhouse" 77 | 78 | cp $WORKDIR/build_files/qemu-utils.* $FINALDIR/tmp/builtin/optional 79 | cp $WORKDIR/build_files/lshw.* $FINALDIR/tmp/builtin/optional 80 | 81 | if $TINYIPA_REQUIRE_BIOSDEVNAME; then 82 | cp $WORKDIR/build_files/biosdevname.* $FINALDIR/tmp/builtin/optional 83 | fi 84 | if $TINYIPA_REQUIRE_IPMITOOL; then 85 | cp $WORKDIR/build_files/ipmitool.* $FINALDIR/tmp/builtin/optional 86 | fi 87 | 88 | mkdir $FINALDIR/tmp/overrides 89 | cp $WORKDIR/build_files/fakeuname $FINALDIR/tmp/overrides/uname 90 | 91 | sudo cp $WORKDIR/build_files/ntpdate $FINALDIR/bin/ntpdate 92 | sudo chmod 755 $FINALDIR/bin/ntpdate 93 | PY_REQS="finalreqs_python3.lst" 94 | 95 | # NOTE(rpittau) change ownership of the tce info dir to prevent writing issues 96 | sudo chown $TC:$STAFF $FINALDIR/usr/local/tce.installed 97 | 98 | while read line; do 99 | $TC_CHROOT_CMD tce-load -wic $line 100 | done < <(paste $WORKDIR/build_files/finalreqs.lst $WORKDIR/build_files/$PY_REQS) 101 | 102 | if $INSTALL_SSH ; then 103 | # Install and configure bare minimum for SSH access 104 | $TC_CHROOT_CMD tce-load -wic openssh 105 | # Configure OpenSSH 106 | $CHROOT_CMD cp /usr/local/etc/ssh/sshd_config.orig /usr/local/etc/ssh/sshd_config 107 | echo "PasswordAuthentication no" | $CHROOT_CMD tee -a /usr/local/etc/ssh/sshd_config 108 | # Generate and configure host keys - RSA, DSA, Ed25519 109 | # NOTE(pas-ha) ECDSA host key will still be re-generated fresh on every image boot 110 | $CHROOT_CMD ssh-keygen -t rsa -N "" -f /usr/local/etc/ssh/ssh_host_rsa_key 111 | $CHROOT_CMD ssh-keygen -t dsa -N "" -f /usr/local/etc/ssh/ssh_host_dsa_key 112 | $CHROOT_CMD ssh-keygen -t ed25519 -N "" -f /usr/local/etc/ssh/ssh_host_ed25519_key 113 | echo "HostKey /usr/local/etc/ssh/ssh_host_rsa_key" | $CHROOT_CMD tee -a /usr/local/etc/ssh/sshd_config 114 | echo "HostKey /usr/local/etc/ssh/ssh_host_dsa_key" | $CHROOT_CMD tee -a /usr/local/etc/ssh/sshd_config 115 | echo "HostKey /usr/local/etc/ssh/ssh_host_ed25519_key" | $CHROOT_CMD tee -a /usr/local/etc/ssh/sshd_config 116 | 117 | # setup user and SSH keys 118 | if $AUTHORIZE_SSH; then 119 | $CHROOT_CMD mkdir -p /home/tc 120 | $CHROOT_CMD chown -R tc.staff /home/tc 121 | $TC_CHROOT_CMD mkdir -p /home/tc/.ssh 122 | cat $_found_ssh_key | $TC_CHROOT_CMD tee /home/tc/.ssh/authorized_keys 123 | $CHROOT_CMD chown tc.staff /home/tc/.ssh/authorized_keys 124 | $TC_CHROOT_CMD chmod 600 /home/tc/.ssh/authorized_keys 125 | fi 126 | fi 127 | 128 | $TC_CHROOT_CMD tce-load -ic /tmp/builtin/optional/qemu-utils.tcz 129 | $TC_CHROOT_CMD tce-load -ic /tmp/builtin/optional/lshw.tcz 130 | if $TINYIPA_REQUIRE_BIOSDEVNAME; then 131 | $TC_CHROOT_CMD tce-load -ic /tmp/builtin/optional/biosdevname.tcz 132 | fi 133 | if $TINYIPA_REQUIRE_IPMITOOL; then 134 | $TC_CHROOT_CMD tce-load -ic /tmp/builtin/optional/ipmitool.tcz 135 | fi 136 | 137 | # Ensure tinyipa picks up installed kernel modules 138 | $CHROOT_CMD depmod -a `$WORKDIR/build_files/fakeuname -r` 139 | 140 | PIP_COMMAND="pip3" 141 | TINYIPA_PYTHON_EXE="python3" 142 | 143 | # Install pip 144 | # NOTE(rpittau): pip MUST be the same version used in the build script or 145 | # dragons will appear and put everything on fire 146 | $CHROOT_CMD ${TINYIPA_PYTHON_EXE} -m ensurepip 147 | $CHROOT_CMD ${PIP_COMMAND} install --upgrade pip==${PIP_VERSION} wheel 148 | 149 | # If flag is set install python now 150 | if $BUILD_AND_INSTALL_TINYIPA ; then 151 | if [ -n "$PYTHON_EXTRA_SOURCES_DIR_LIST" ]; then 152 | IFS="," read -ra PKGDIRS <<< "$PYTHON_EXTRA_SOURCES_DIR_LIST" 153 | for PKGDIR in "${PKGDIRS[@]}"; do 154 | PKG=$(cd "$PKGDIR" ; python setup.py --name) 155 | $CHROOT_CMD $PIP_COMMAND install --no-index --find-links=file:///tmp/wheelhouse --pre $PKG 156 | done 157 | fi 158 | 159 | $CHROOT_CMD $PIP_COMMAND install --no-index --find-links=file:///tmp/wheelhouse --pre ironic_python_agent 160 | 161 | rm -rf $FINALDIR/tmp/wheelhouse 162 | fi 163 | 164 | # Unmount /proc and clean up everything 165 | cleanup_tce "$DST_DIR" 166 | 167 | # Copy bootlocal.sh to opt 168 | sudo cp "$WORKDIR/build_files/bootlocal.sh" "$FINALDIR/opt/." 169 | 170 | # Copy udhcpc.script to opt 171 | sudo cp "$WORKDIR/udhcpc.script" "$FINALDIR/opt/" 172 | 173 | # Replace etc/init.d/dhcp.sh 174 | sudo cp "$WORKDIR/build_files/dhcp.sh" "$FINALDIR/etc/init.d/dhcp.sh" 175 | sudo sed -i "s/%UDEV_SETTLE_TIMEOUT%/$TINYIPA_UDEV_SETTLE_TIMEOUT/" "$FINALDIR/etc/init.d/dhcp.sh" 176 | 177 | # Disable ZSwap 178 | sudo sed -i '/# Main/a NOZSWAP=1' "$FINALDIR/etc/init.d/tc-config" 179 | # sudo cp $WORKDIR/build_files/tc-config $FINALDIR/etc/init.d/tc-config 180 | 181 | # Place ipv6 modprobe config so the kernel support loads. 182 | sudo cp "$WORKDIR/build_files/modprobe.conf" "$FINALDIR/etc/modproble.conf" 183 | 184 | # NOTE(rpittau): workaround for hwclock 185 | # The adjtime file used by hwclock in tinycore is /var/lib/hwclock/adjtime 186 | # but for some reason (bug?) the file is not created when hwclock is 187 | # invoked, causing hwclock to fail when using certain options, for example 188 | # --systohc. 189 | # We create the dir and the file to prevent that. 190 | $CHROOT_CMD mkdir -p /var/lib/hwclock 191 | $CHROOT_CMD touch /var/lib/hwclock/adjtime 192 | $CHROOT_CMD chmod 640 /var/lib/hwclock/adjtime 193 | 194 | if $PYOPTIMIZE_TINYIPA; then 195 | echo "WARNING: Precompilation is not compatible with oslo.privsep and is being ignored." 196 | fi 197 | 198 | # Delete unnecessary Babel .dat files 199 | find $FINALDIR -path "*babel/locale-data/*.dat" -not -path "*en_US*" | sudo xargs --no-run-if-empty rm 200 | 201 | # NOTE(pas-ha) Apparently on TinyCore Ansible's 'command' module is 202 | # not searching for executables in the '/usr/local/(s)bin' paths. 203 | # Thus we symlink everything from there to '/usr/(s)bin' which is being searched, 204 | # so that 'command' module picks full utilities installed by 'util-linux' 205 | # instead of built-in simplified BusyBox ones. 206 | set +x 207 | echo "Symlink all from /usr/local/sbin to /usr/sbin" 208 | pushd "$FINALDIR/usr/local/sbin" 209 | for target in *; do 210 | if [ ! -f "$FINALDIR/usr/sbin/$target" ]; then 211 | $CHROOT_CMD ln -sf "/usr/local/sbin/$target" "/usr/sbin/$target" 212 | fi 213 | done 214 | popd 215 | echo "Symlink all from /usr/local/bin to /usr/bin" 216 | # this also includes symlinking Python to the place expected by Ansible 217 | pushd "$FINALDIR/usr/local/bin" 218 | for target in *; do 219 | if [ ! -f "$FINALDIR/usr/bin/$target" ]; then 220 | $CHROOT_CMD ln -sf "/usr/local/bin/$target" "/usr/bin/$target" 221 | fi 222 | done 223 | popd 224 | # symlink bash to sh if /bin/sh is not there 225 | if [ ! -f "$FINALDIR/bin/sh" ]; then 226 | $CHROOT_CMD ln -sf "/bin/bash" "/bin/sh" 227 | fi 228 | set -x 229 | 230 | # Rebuild build directory into gz file 231 | ( cd "$FINALDIR" && sudo find | sudo cpio -o -H newc | gzip -9 > "$WORKDIR/tinyipa${BRANCH_EXT}.gz" ) 232 | 233 | # Copy vmlinuz to new name 234 | cp "$WORKDIR/build_files/vmlinuz64" "$WORKDIR/tinyipa${BRANCH_EXT}.vmlinuz" 235 | 236 | # Create tar.gz containing tinyipa files 237 | tar czf tinyipa${BRANCH_EXT}.tar.gz tinyipa${BRANCH_EXT}.gz tinyipa${BRANCH_EXT}.vmlinuz 238 | 239 | # Create sha256 files which will be uploaded by the publish jobs along with 240 | # the tinyipa ones in order to provide a way to verify the integrity of the tinyipa 241 | # builds. 242 | for f in tinyipa${BRANCH_EXT}.{gz,tar.gz,vmlinuz}; do 243 | sha256sum $f > $f.sha256 244 | done 245 | 246 | # Output files with sizes created by this script 247 | echo "Produced files:" 248 | du -h tinyipa${BRANCH_EXT}.gz tinyipa${BRANCH_EXT}.tar.gz tinyipa${BRANCH_EXT}.vmlinuz 249 | echo "Checksums: " tinyipa${BRANCH_EXT}.*sha256 250 | -------------------------------------------------------------------------------- /tinyipa/generate_tox_constraints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | SCRIPT_NAME=$(basename $0) 4 | COMMON_ROOT=$(dirname $0) 5 | DESTINATION="$1" 6 | TOX_INI=${2:-tox.ini} 7 | 8 | copy() { 9 | local src=$1 10 | local destination=$2 11 | 12 | if test -z "${src}"; then 13 | return 1 14 | fi 15 | 16 | if test -e "${src}"; then 17 | log "File '${src}' exists. Using as upper-constraints." 18 | cp "${src}" "${destination}" 19 | else 20 | log "File '${src}' not found. Skipping local file strategy." 21 | return 1 22 | fi 23 | return 0 24 | } 25 | 26 | download() { 27 | local url=$1 28 | local destination=$2 29 | 30 | if test -z "${url}"; then 31 | return 1 32 | else 33 | log "Downloading from '${url}'" 34 | curl -L ${url} -o "${destination}" 35 | fi 36 | return 0 37 | } 38 | 39 | log() { 40 | echo "${SCRIPT_NAME}: ${@}" 41 | } 42 | 43 | fail() { 44 | log ${@} 45 | exit 1 46 | } 47 | 48 | tox_constraints_is_not_null() { 49 | test "${TOX_CONSTRAINTS_FILE:-""}" != "" 50 | } 51 | 52 | copy_uc() { 53 | copy "${TOX_CONSTRAINTS_FILE:-""}" "${DESTINATION}" 54 | } 55 | 56 | download_uc() { 57 | download "${TOX_CONSTRAINTS_FILE:-""}" "${DESTINATION}" 58 | } 59 | 60 | copy_new_requirements_uc() { 61 | if [ -e "/opt/stack/new/requirements" ]; then 62 | copy "/opt/stack/new/requirements/upper-constraints.txt" "${DESTINATION}" 63 | elif [ -e "/opt/stack/requirements" ]; then 64 | copy "/opt/stack/requirements/upper-constraints.txt" "${DESTINATION}" 65 | else 66 | log "No local requirements repository, will download upper-constraints" 67 | # Allow the caller to handle the failure 68 | return 1 69 | fi 70 | } 71 | 72 | download_from_tox_ini_url() { 73 | local url 74 | # NOTE(mmitchell): This extracts the URL defined as the default value for 75 | # TOX_CONSTRAINTS_FILE in tox.ini. This is used by image 76 | # builders to avoid duplicating the default value in multiple 77 | # scripts. This is specially done to leverage the release 78 | # tools that automatically update the tox.ini when projects 79 | # are released. 80 | url=$(sed -n 's/^.*{env:TOX_CONSTRAINTS_FILE\:\([^}]*\)}.*$/\1/p' $TOX_INI | head -n1) 81 | log "tox.ini indicates '${url}' as fallback." 82 | download "${url}" "${DESTINATION}" 83 | } 84 | 85 | log "Generating local constraints file..." 86 | 87 | if tox_constraints_is_not_null; then 88 | log "TOX_CONSTRAINTS_FILE is defined as '${TOX_CONSTRAINTS_FILE:-""}'" 89 | copy_uc || download_uc || fail "Failed to copy or download file indicated in TOX_CONSTRAINTS_FILE." 90 | else 91 | log "TOX_CONSTRAINTS_FILE is not defined. Using fallback strategies." 92 | 93 | copy_new_requirements_uc || \ 94 | download_from_tox_ini_url || \ 95 | fail "Failed to download upper-constraints.txt from either CI or tox.ini location." 96 | fi 97 | -------------------------------------------------------------------------------- /tinyipa/install-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | COMMON_PACKAGES="wget unzip sudo gawk" 4 | APT_PACKAGES="${COMMON_PACKAGES} python3-pip squashfs-tools" 5 | YUM_PACKAGES="${APT_PACKAGES}" 6 | ZYPPER_PACKAGES="${COMMON_PACKAGES} python3-pip squashfs" 7 | 8 | echo "Installing dependencies:" 9 | 10 | # first zypper in case zypper-aptitude is installed 11 | if [ -x "/usr/bin/zypper" ]; then 12 | sudo -E zypper -n install -l ${ZYPPER_PACKAGES} 13 | elif [ -x "/usr/bin/apt-get" ]; then 14 | sudo -E apt-get update 15 | sudo -E apt-get install -y ${APT_PACKAGES} 16 | elif [ -x "/usr/bin/dnf" ]; then 17 | sudo -E dnf install -y ${YUM_PACKAGES} 18 | elif [ -x "/usr/bin/yum" ]; then 19 | sudo -E yum install -y ${YUM_PACKAGES} 20 | else 21 | echo "No supported package manager installed on system. Supported: apt, yum, dnf, zypper" 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /tinyipa/tc-mirror.sh: -------------------------------------------------------------------------------- 1 | 2 | #NOTE(pas-ha) 3 | # The first URL is the official TC repo, 4 | # the rest of the list is taken from 5 | # http://wiki.tinycorelinux.net/wiki:mirrors 6 | # as of time of this writing. 7 | # Only HTTP mirrors were considered with the following ordering 8 | # - those that were unavailable are moved to the bottom of the list 9 | # - those that already responded with 404 are moved to the very bottom 10 | 11 | # List Updated on 9-Dec-2019 12 | TC_MIRRORS="http://repo.tinycorelinux.net 13 | http://mirror.cedia.org.ec/tinycorelinux 14 | http://mirror.epn.edu.ec/tinycorelinux 15 | http://ftp.vim.org/os/Linux/distr/tinycorelinux 16 | http://mirrors.163.com/tinycorelinux 17 | " 18 | 19 | TINYCORE_MIRROR_URL=${TINYCORE_MIRROR_URL:-} 20 | 21 | # NOTE(TheJulia): Removed mirrors because they are out 22 | # of date 23 | # http://distro.ibiblio.org/tinycorelinux ~1.5 months out of sync. 24 | # http://mirrors.163.com/tinycorelinux - Two weeks out of date 25 | # ftp.vim.org and ftp.nluug.nl are the same host. 26 | # http://www.gtlib.gatech.edu/pub/tinycore - No longer mirrors tinycore 27 | # http://l4u-00.ninr.ru no longer mirrors. 28 | # http://kambing.ui.ac.id/tinycorelinux - Stopped mirroring at 9.x 29 | # http://tinycore.mirror.uber.com.au - Unreachable? 30 | function probe_url { 31 | wget -q --spider --tries 1 --timeout 10 "$1" 2>&1 32 | } 33 | 34 | function choose_tc_mirror { 35 | if [ -z ${TINYCORE_MIRROR_URL} ]; then 36 | for url in ${TC_MIRRORS}; do 37 | echo "Checking Tiny Core Linux mirror ${url}" 38 | if probe_url ${url} ; then 39 | echo "Check succeeded: ${url} is responding." 40 | TINYCORE_MIRROR_URL=${url} 41 | break 42 | else 43 | echo "Check failed: ${url} is not responding" 44 | fi 45 | done 46 | if [ -z ${TINYCORE_MIRROR_URL} ]; then 47 | echo "Failed to find working Tiny Core Linux mirror" 48 | exit 1 49 | fi 50 | else 51 | echo "Probing provided Tiny Core Linux mirror ${TINYCORE_MIRROR_URL}" 52 | if probe_url ${TINYCORE_MIRROR_URL} ; then 53 | echo "Check succeeded: ${TINYCORE_MIRROR_URL} is responding." 54 | else 55 | echo "Check failed: ${TINYCORE_MIRROR_URL} is not responding" 56 | exit 1 57 | fi 58 | fi 59 | } 60 | -------------------------------------------------------------------------------- /tinyipa/udhcpc.script: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # udhcpc script edited by Tim Riker 4 | 5 | # file created to be used for static network configuration as well 6 | 7 | [ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1 8 | 9 | RESOLV_CONF="/etc/resolv.conf" 10 | [ -n "$broadcast" ] && BROADCAST="broadcast $broadcast" 11 | [ -n "$subnet" ] && NETMASK="netmask $subnet" 12 | 13 | case "$1" in 14 | deconfig) 15 | /sbin/ifconfig $interface 0.0.0.0 16 | ;; 17 | 18 | renew|bound) 19 | /sbin/ifconfig $interface up 20 | /sbin/ifconfig $interface $ip $BROADCAST $NETMASK 21 | 22 | if [ -n "$router" ] ; then 23 | echo "deleting routers" 24 | while route del default gw 0.0.0.0 dev $interface ; do 25 | : 26 | done 27 | 28 | metric=0 29 | for i in $router ; do 30 | route add default gw $i dev $interface metric $((metric++)) 31 | done 32 | fi 33 | 34 | echo -n > $RESOLV_CONF 35 | [ -n "$domain" ] && echo search $domain >> $RESOLV_CONF 36 | for i in $dns ; do 37 | echo adding dns $i 38 | echo nameserver $i >> $RESOLV_CONF 39 | done 40 | [ -n "$mtu" ] && /sbin/ifconfig $interface mtu $mtu 41 | ;; 42 | esac 43 | 44 | exit 0 45 | 46 | -------------------------------------------------------------------------------- /tools/iso-image-create: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Copyright 2012 Hewlett-Packard Development Company, L.P. 4 | # All Rights Reserved. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); you may 7 | # not use this file except in compliance with the License. You may obtain 8 | # a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | # License for the specific language governing permissions and limitations 16 | # under the License. 17 | # 18 | # This script generates iso image from the given kernel and ramdisk 19 | 20 | SCRIPTNAME=`basename $0` 21 | TMP_BUILD_DIR="/tmp/$SCRIPTNAME.$$" 22 | QEMU_IMG="/usr/bin/qemu-img" 23 | MKISOFS="/usr/bin/mkisofs" 24 | 25 | 26 | function show_options() { 27 | 28 | echo "Usage: ${SCRIPTNAME} [options]" 29 | echo 30 | echo "Options:" 31 | 32 | echo " -o output filename " 33 | echo " -i initrd " 34 | echo " -k kernel " 35 | } 36 | 37 | function cleanup() { 38 | 39 | v_print "Cleaning up.." 40 | rm -rf $TMP_BUILD_DIR 41 | } 42 | 43 | function err_print() { 44 | echo "ERROR: $@" 1>&2; 45 | } 46 | 47 | function v_print() { 48 | 49 | echo "$*" 50 | } 51 | 52 | 53 | # Parse command line options 54 | ARGS=`getopt -o "o:i:k:" -l "output,initrd,kernel:" \ 55 | -n "$SCRIPTNAME" -- "$@"` 56 | if [ $? -ne 0 ]; 57 | then 58 | exit 1 59 | fi 60 | 61 | eval set -- "$ARGS" 62 | 63 | while true ; do 64 | case "$1" in 65 | -o) OUTPUT_FILENAME=$2; shift 2 ;; 66 | -i) INITRD=$2; shift 2 ;; 67 | -k) KERNEL=$2; shift 2 ;; 68 | # *) show_options ; exit 1 ;; 69 | --) shift; break ;; 70 | esac 71 | done 72 | 73 | # Verify whether kernel, initrd, and the image file is present 74 | if [ -z "$OUTPUT_FILENAME" ]; then 75 | err_print "Output filename not provided." 76 | show_options 77 | exit 1 78 | fi 79 | 80 | if [ -z "$INITRD" ]; then 81 | err_print "Initrd not provided." 82 | show_options 83 | exit 1 84 | fi 85 | 86 | if [ -z "$KERNEL" ]; then 87 | err_print "Kernel not provided." 88 | show_options 89 | exit 1 90 | fi 91 | 92 | # Create a temporary build directory for holiding the contents of iso 93 | TMP_IMAGE_DIR="$TMP_BUILD_DIR/image" 94 | v_print "Creating temporary directory $TMP_IMAGE_DIR" 95 | mkdir -p "$TMP_IMAGE_DIR" 96 | 97 | # Copy isolinux bin to the isolinux directory 98 | mkdir -p "$TMP_IMAGE_DIR/isolinux" 99 | v_print "Copying isolinux.bin" 100 | if [ -f /usr/share/syslinux/isolinux.bin ] 101 | then 102 | cp /usr/share/syslinux/isolinux.bin "$TMP_IMAGE_DIR/isolinux" 103 | 104 | elif [ -f /usr/lib/syslinux/isolinux.bin ] 105 | then 106 | cp /usr/lib/syslinux/isolinux.bin "$TMP_IMAGE_DIR/isolinux" 107 | 108 | elif [ -f /usr/lib/ISOLINUX/isolinux.bin ] 109 | then 110 | cp /usr/lib/ISOLINUX/isolinux.bin "$TMP_IMAGE_DIR/isolinux" 111 | 112 | else 113 | err_print "Could not find isolinux.bin. Install syslinux or isolinux?" 114 | cleanup 115 | exit 1 116 | fi 117 | 118 | # Copy ldlinux.c32 to the isolinux directory 119 | v_print "Copying ldlinux.c32" 120 | if [ -f /usr/share/syslinux/ldlinux.c32 ] 121 | then 122 | cp /usr/share/syslinux/ldlinux.c32 "$TMP_IMAGE_DIR/isolinux" 123 | elif [ -f /usr/lib/syslinux/modules/bios/ldlinux.c32 ] 124 | then 125 | cp /usr/lib/syslinux/modules/bios/ldlinux.c32 "$TMP_IMAGE_DIR/isolinux" 126 | fi 127 | 128 | # Copy initrd, kernel 129 | v_print "Copying kernel to $TMP_IMAGE_DIR/vmlinuz" 130 | cp $KERNEL "$TMP_IMAGE_DIR/vmlinuz" 131 | if [ $? -ne 0 ]; then 132 | err_print "Failed to copy $KERNEL to $TMP_IMAGE_DIR" 133 | cleanup 134 | exit 1 135 | fi 136 | 137 | v_print "Copying initrd to $TMP_IMAGE_DIR/initrd" 138 | cp $INITRD "$TMP_IMAGE_DIR/initrd" 139 | if [ $? -ne 0 ]; then 140 | err_print "Failed to copy $INITRD to $TMP_IMAGE_DIR" 141 | cleanup 142 | exit 1 143 | fi 144 | 145 | # Generate isolinux.cfg for default booting 146 | v_print "Generating isolinux.cfg" 147 | echo "\ 148 | DEFAULT install 149 | LABEL install 150 | menu label "Install image" 151 | kernel /vmlinuz 152 | append initrd=/initrd boot_method=vmedia -- 153 | TIMEOUT 5 154 | PROMPT 0 " > "$TMP_IMAGE_DIR/isolinux/isolinux.cfg" 155 | 156 | # Convert relative path output filename to absolute path 157 | echo $OUTPUT_FILENAME | grep -q '^/' 158 | if [ $? -ne 0 ]; then 159 | OUTPUT_FILENAME="$PWD/$OUTPUT_FILENAME" 160 | fi 161 | 162 | # Create the ISO 163 | v_print "Generating the ISO" 164 | cd $TMP_IMAGE_DIR && $MKISOFS -r -V "INSTALL_IMAGE" -cache-inodes -J -l -b isolinux/isolinux.bin -no-emul-boot -boot-load-size 4 -boot-info-table -o $OUTPUT_FILENAME . 165 | 166 | # Cleanup 167 | cleanup 168 | 169 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | minversion = 3.18.0 3 | envlist = pep8 4 | ignore_basepython_conflict = true 5 | 6 | [testenv] 7 | usedevelop = True 8 | basepython = python3 9 | setenv = 10 | VIRTUAL_ENV={envdir} 11 | PYTHONWARNINGS=default::DeprecationWarning 12 | deps = 13 | -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} 14 | -r{toxinidir}/doc/requirements.txt 15 | 16 | [testenv:pep8] 17 | deps = 18 | hacking~=6.1.0 # Apache-2.0 19 | flake8-import-order>=0.17.1 # LGPLv3 20 | doc8>=0.6.0 # Apache-2.0 21 | pycodestyle>=2.0.0,<3.0.0 # MIT 22 | commands = 23 | flake8 ironic_python_agent_builder 24 | doc8 doc/source README.rst CONTRIBUTING.rst 25 | 26 | [testenv:venv] 27 | commands = {posargs} 28 | 29 | [testenv:docs] 30 | usedevelop = False 31 | commands = sphinx-build -W -b html doc/source doc/build/html 32 | 33 | [testenv:pdf-docs] 34 | usedevelop = False 35 | allowlist_externals = make 36 | commands = sphinx-build -b latex doc/source doc/build/pdf 37 | make -C doc/build/pdf 38 | 39 | [testenv:releasenotes] 40 | usedevelop = False 41 | commands = 42 | sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html 43 | 44 | [flake8] 45 | exclude = .venv,.git,.tox,dist,doc,*lib/python*,*egg,build,tools,imagebuild/tinyipa/tinyipafinal,imagebuild/tinyipa/tinyipabuild 46 | import-order-style = pep8 47 | application-import-names = ironic_python_agent_builder 48 | # [H106] Don't put vim configuration in source files. 49 | # [H203] Use assertIs(Not)None to check for None. 50 | # [H204] Use assert(Not)Equal to check for equality. 51 | # [H205] Use assert(Greater|Less)(Equal) for comparison. 52 | # [H210] Require 'autospec', 'spec', or 'spec_set' in mock.patch/mock.patch.object calls 53 | # [H904] Delay string interpolations at logging calls. 54 | enable-extensions=H106,H203,H204,H205,H210,H904 55 | 56 | 57 | [testenv:codespell] 58 | description = 59 | Run codespell to check spelling 60 | deps = codespell 61 | # note(JayF): {posargs} lets us run `tox -ecodespell -- -w` to get codespell 62 | # to correct spelling issues in our code it's aware of. 63 | commands = 64 | codespell {posargs} -------------------------------------------------------------------------------- /zuul.d/ironic-python-agent-builder-jobs.yaml: -------------------------------------------------------------------------------- 1 | - job: 2 | name: ironic-python-agent-build-image-base 3 | parent: publish-openstack-artifacts 4 | nodeset: ubuntu-noble 5 | pre-run: playbooks/ironic-python-agent-build-image/pre.yaml 6 | run: playbooks/ironic-python-agent-build-image/run.yaml 7 | post-run: 8 | - playbooks/ironic-python-agent-build-image/post.yaml 9 | - playbooks/ironic-python-agent-build-image/extra-logs.yaml 10 | timeout: 1800 11 | required-projects: 12 | - openstack/requirements 13 | - openstack/ironic-python-agent 14 | - openstack/ironic-python-agent-builder 15 | vars: 16 | ipa_raw_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_RAW' 17 | ipa_tar_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_TAR' 18 | 19 | - job: 20 | name: ironic-python-agent-build-image-dib-centos9 21 | parent: ironic-python-agent-build-image-base 22 | required-projects: 23 | - openstack/diskimage-builder 24 | vars: 25 | image_type: 'dib' 26 | image_distro: 'centos' 27 | image_release: '9-stream' 28 | image_target_name: 'centos9' 29 | 30 | - job: 31 | name: ironic-python-agent-build-image-dib-debian 32 | parent: ironic-python-agent-build-image-base 33 | required-projects: 34 | - openstack/diskimage-builder 35 | vars: 36 | image_type: 'dib' 37 | image_distro: 'debian-minimal' 38 | image_release: 'bookworm' 39 | 40 | - job: 41 | name: ironic-python-agent-check-image-base 42 | parent: base 43 | nodeset: ubuntu-noble 44 | pre-run: playbooks/ironic-python-agent-build-image/pre.yaml 45 | run: playbooks/ironic-python-agent-build-image/run.yaml 46 | post-run: playbooks/ironic-python-agent-build-image/extra-logs.yaml 47 | timeout: 1800 48 | required-projects: 49 | - openstack/requirements 50 | - openstack/ironic-python-agent 51 | - openstack/ironic-python-agent-builder 52 | irrelevant-files: 53 | - ^.*\.rst$ 54 | - ^doc/.*$ 55 | - ^releasenotes/.*$ 56 | - ^setup.cfg$ 57 | - ^tools/.*$ 58 | - ^tox.ini$ 59 | vars: 60 | ipa_raw_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_RAW' 61 | ipa_tar_dir: '{{ ansible_user_dir }}/src/opendev.org/openstack/ironic-python-agent/UPLOAD_TAR' 62 | 63 | - job: 64 | name: ironic-python-agent-check-image-dib-centos9 65 | parent: ironic-python-agent-check-image-base 66 | required-projects: 67 | - openstack/diskimage-builder 68 | vars: 69 | image_type: 'dib' 70 | image_distro: 'centos' 71 | image_release: '9-stream' 72 | image_target_name: centos9 73 | 74 | - job: 75 | name: ironic-python-agent-check-image-dib-centos9-extra 76 | parent: ironic-python-agent-check-image-dib-centos9 77 | vars: 78 | extra_elements: ["extra-hardware"] 79 | 80 | - job: 81 | name: ironic-python-agent-check-image-dib-debian 82 | parent: ironic-python-agent-check-image-base 83 | required-projects: 84 | - openstack/diskimage-builder 85 | vars: 86 | image_type: 'dib' 87 | image_distro: 'debian-minimal' 88 | image_release: 'bookworm' 89 | 90 | - job: 91 | name: ironic-python-agent-check-image-dib-debian-bullseye 92 | parent: ironic-python-agent-check-image-dib-debian 93 | vars: 94 | image_release: 'bullseye' 95 | 96 | - job: 97 | name: ironic-python-agent-check-image-dib-debian-arm64 98 | parent: ironic-python-agent-check-image-dib-debian 99 | nodeset: debian-bullseye-arm64 100 | vars: 101 | image_target_name: debian-arm64 102 | 103 | - job: 104 | name: ironic-python-agent-build-image-dib-debian-arm64 105 | parent: ironic-python-agent-build-image-dib-debian 106 | nodeset: debian-bullseye-arm64 107 | vars: 108 | image_target_name: debian-arm64 109 | 110 | - job: 111 | name: ironic-python-agent-check-image-dib-debian-extra 112 | parent: ironic-python-agent-check-image-dib-debian 113 | vars: 114 | extra_elements: ["extra-hardware"] 115 | 116 | - job: 117 | name: ironic-python-agent-check-image-dib-ubuntu 118 | parent: ironic-python-agent-check-image-base 119 | required-projects: 120 | - openstack/diskimage-builder 121 | vars: 122 | image_type: 'dib' 123 | image_distro: 'ubuntu' 124 | image_release: 'noble' 125 | dib_no_tmpfs: '1' 126 | 127 | - job: 128 | name: ironic-python-agent-check-image-dib-ubuntu-arm64 129 | parent: ironic-python-agent-check-image-dib-ubuntu 130 | nodeset: ubuntu-noble-arm64 131 | vars: 132 | image_target_name: ubuntu-arm64 133 | 134 | 135 | - job: 136 | name: ironic-python-agent-builder-tox-codespell 137 | parent: openstack-tox 138 | timeout: 7200 139 | vars: 140 | tox_envlist: codespell 141 | -------------------------------------------------------------------------------- /zuul.d/project.yaml: -------------------------------------------------------------------------------- 1 | - project: 2 | templates: 3 | - publish-openstack-docs-pti 4 | - check-requirements 5 | - release-notes-jobs-python3 6 | check: 7 | jobs: 8 | - openstack-tox-pep8 9 | - ironic-standalone-ipa-src 10 | - ironic-python-agent-check-image-dib-centos9 11 | - ironic-python-agent-check-image-dib-centos9-extra 12 | - ironic-python-agent-check-image-dib-debian 13 | - ironic-python-agent-check-image-dib-debian-arm64 14 | - ironic-python-agent-check-image-dib-debian-extra 15 | # Non-voting jobs 16 | - ironic-python-agent-check-image-dib-debian-bullseye: 17 | voting: false 18 | - ironic-python-agent-check-image-dib-ubuntu: 19 | voting: false 20 | - ironic-python-agent-check-image-dib-ubuntu-arm64: 21 | voting: false 22 | - ipa-tempest-bios-ipmi-direct-src: 23 | voting: false 24 | - ipa-tempest-ironic-inspector-src: 25 | voting: false 26 | - ironic-python-agent-builder-tox-codespell: 27 | voting: false 28 | gate: 29 | jobs: 30 | - openstack-tox-pep8 31 | - ironic-standalone-ipa-src 32 | - ironic-python-agent-check-image-dib-centos9 33 | - ironic-python-agent-check-image-dib-centos9-extra 34 | - ironic-python-agent-check-image-dib-debian 35 | - ironic-python-agent-check-image-dib-debian-arm64 36 | - ironic-python-agent-check-image-dib-debian-extra 37 | post: 38 | jobs: 39 | - publish-openstack-python-branch-tarball 40 | - ironic-python-agent-build-image-dib-centos9: 41 | branches: master 42 | - ironic-python-agent-build-image-dib-debian: 43 | branches: master 44 | - ironic-python-agent-build-image-dib-debian-arm64: 45 | branches: master 46 | --------------------------------------------------------------------------------