From 4143fa7ed2d4a33e0e83000379183d65f30c8710 Mon Sep 17 00:00:00 2001 From: Dmitry Tantsur Date: Fri, 7 Jul 2023 10:38:45 +0200 Subject: [PATCH 1/2] Remove the ability to install and use ironic-inspector The project will be phased out in this release cycle, so Bifrost cannot use it any more. Note that some parameters still have "inspector" in their names for legacy reasons. They should be renamed (with deprecation) separately. Assisted-By: Claude Code Change-Id: I02381966a9af4d7cb1e35355ad85745221f8fde3 Signed-off-by: Dmitry Tantsur --- doc/source/user/architecture.rst | 33 +--- doc/source/user/howto.rst | 5 - playbooks/ci/run.yaml | 1 - .../roles/bifrost-ironic-install/README.md | 39 +---- .../bifrost-ironic-install/defaults/main.yml | 37 ----- .../tasks/bootstrap.yml | 8 +- .../tasks/create_tftpboot.yml | 11 +- .../tasks/inspector_bootstrap.yml | 156 ------------------ .../tasks/inspector_install.yml | 30 ---- .../tasks/inspector_start.yml | 35 ---- .../bifrost-ironic-install/tasks/install.yml | 4 - .../tasks/keystone_setup_inspector.yml | 144 ---------------- .../bifrost-ironic-install/tasks/start.yml | 5 +- .../bifrost-ironic-install/tasks/validate.yml | 36 ---- .../templates/default-boot-ipxe.j2 | 10 ++ .../templates/inspector-default-boot-ipxe.j2 | 10 -- .../templates/ironic-inspector.conf.j2 | 96 ----------- .../templates/ironic.conf.j2 | 30 ---- .../nginx_conf.d_bifrost-ironic.conf.j2 | 19 --- .../defaults/main.yml | 2 - .../tasks/validate.yml | 8 - .../templates/clouds.yaml.j2 | 8 - .../templates/logrotate.conf.j2 | 5 - .../roles/bifrost-prep-for-install/README.md | 6 - .../defaults/main.yml | 21 --- .../roles/bifrost-test-inspection/README.md | 2 +- .../notes/no-inspector-2995fa195b715fe4.yaml | 5 + scripts/collect-test-info.sh | 2 - scripts/test-bifrost.sh | 2 - zuul.d/bifrost-jobs.yaml | 15 -- zuul.d/project.yaml | 4 - 31 files changed, 35 insertions(+), 754 deletions(-) delete mode 100644 playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml delete mode 100644 playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml delete mode 100644 playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml delete mode 100644 playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml create mode 100644 playbooks/roles/bifrost-ironic-install/templates/default-boot-ipxe.j2 delete mode 100644 playbooks/roles/bifrost-ironic-install/templates/inspector-default-boot-ipxe.j2 delete mode 100644 playbooks/roles/bifrost-ironic-install/templates/ironic-inspector.conf.j2 create mode 100644 releasenotes/notes/no-inspector-2995fa195b715fe4.yaml diff --git a/doc/source/user/architecture.rst b/doc/source/user/architecture.rst index eae5e982f..3d8ed6628 100644 --- a/doc/source/user/architecture.rst +++ b/doc/source/user/architecture.rst @@ -13,14 +13,6 @@ ironic_ Ironic is the main service that provides bare metal capabilities. Its `bare metal API`_ is served on TCP port 6385. -ironic-inspector_ - Inspector is an auxiliary service that provides `in-band inspection`_. - Its `introspection API`_ is served on TCP port 5050. - - Inspector is deprecated and can be enabled by setting - ``enable_inspector=true``. Otherwise, Ironic's `native in-band inspection`_ - is used. - mariadb_ MariaDB is used as a database to persistently store information. @@ -35,9 +27,8 @@ nginx_ Uses HTTP port 8080 by default (can be changed via the ``file_url_port`` parameter). - When TLS is enabled, Nginx serves as a TLS proxy for Ironic and Inspector. - It listens on ports 6385 and 5050 and passes requests to the services - via unix sockets. + When TLS is enabled, Nginx serves as a TLS proxy for Ironic. It listens on + port 6385 and passes requests to the service via a unix socket. dnsmasq_ Dnsmasq is used as a DHCP and TFTP server (but not for DNS by default) @@ -51,7 +42,7 @@ The following components can be enabled if needed: keystone_ Keystone is an OpenStack Identity service. It can be used to provide - sophisticated authentication to Ironic and Inspector instead of HTTP basic + sophisticated authentication to Ironic instead of HTTP basic authentication. Its `identity API`_ is served using uWSGI and Nginx on the port 5000, the systemd service is called ``uwsgi@keystone-public``. @@ -92,7 +83,7 @@ Parameters 192.168.122.1 This IP address is used for all provisioning traffic: TFTP, iPXE, - call-backs to Ironic and Inspector. It is also used for the traffic between + and call-backs to Ironic. It is also used for the traffic between the services. ``public_ip`` @@ -129,11 +120,11 @@ Log locations ~~~~~~~~~~~~~ journald - is used for logging from most services. For example, to get Inspector logs: + is used for logging from most services. For example, to get Ironic logs: .. code-block:: console - $ sudo journalctl -u ironic-inspector + $ sudo journalctl -u ironic ``/var/log/ironic/deploy`` contains tarballs with ramdisk logs from deployment or cleaning. The file @@ -148,10 +139,6 @@ journald $ less journal # for ramdisks that use systemd, e.g. DIB-built $ less var/log/ironic-python-agent.log # for tinyIPA and similar -``/var/log/ironic-inspector/ramdisk`` - contains tarballs with ramdisk logs from inspection. They are very similar - to ramdisk logs from deployment and cleaning. - ``/var/log/nginx/`` contains logs for serving files (iPXE scripts, images, virtual media ISOs). @@ -190,15 +177,11 @@ Runtime locations when cleaning or deploying. ``/run/ironic`` - When TLS is enabled, this directory contains unix sockets of Ironic and - Inspector, which Nginx uses to pass requests. + When TLS is enabled, this directory contains the unix socket of Ironic, + that Nginx uses to pass requests. .. _ironic: https://docs.openstack.org/ironic/latest/ .. _bare metal API: https://docs.openstack.org/api-ref/baremetal/ -.. _ironic-inspector: https://docs.openstack.org/ironic-inspector/latest/ -.. _in-band inspection: https://docs.openstack.org/ironic/latest/admin/inspection/inspector.html -.. _introspection API: https://docs.openstack.org/api-ref/baremetal-introspection/ -.. _native in-band inspection: https://docs.openstack.org/ironic/latest/admin/inspection/index.html .. _mariadb: https://mariadb.org/ .. _nginx: https://nginx.org/ .. _dnsmasq: https://dnsmasq.org/ diff --git a/doc/source/user/howto.rst b/doc/source/user/howto.rst index f6951ab11..217cf767d 100644 --- a/doc/source/user/howto.rst +++ b/doc/source/user/howto.rst @@ -22,11 +22,6 @@ example: export OS_CLOUD=bifrost baremetal node list -.. note:: - Previously, a separate cloud ``bifrost-inspector`` was provided for - introspection commands. It is now deprecated, the main ``bifrost`` cloud - should always be used. - Environment variables --------------------- diff --git a/playbooks/ci/run.yaml b/playbooks/ci/run.yaml index 90c71e1df..327e2c1fa 100644 --- a/playbooks/ci/run.yaml +++ b/playbooks/ci/run.yaml @@ -23,4 +23,3 @@ ENABLE_TLS: "{{ enable_tls | default(false) | bool | lower }}" ENABLE_PROMETHEUS_EXPORTER: "{{ enable_prometheus_exporter | default(false) | bool | lower }}" USE_VMEDIA: "{{ use_vmedia | default(false) | bool | lower }}" - USE_INSPECTOR: "{{ use_inspector | default(false) | bool | lower }}" diff --git a/playbooks/roles/bifrost-ironic-install/README.md b/playbooks/roles/bifrost-ironic-install/README.md index c8fc07160..ea9a6e0b4 100644 --- a/playbooks/roles/bifrost-ironic-install/README.md +++ b/playbooks/roles/bifrost-ironic-install/README.md @@ -25,7 +25,7 @@ bifrost-ironic-install role. testing: false Enables no-authentication mode where no authentication is used for accessing -API services. The default setting of ``true`` makes ironic and ironic-inspector +API services. The default setting of ``true`` makes ironic either use keystone (if ``enable_keystone`` is true) or HTTP basic auth (use ``admin_username``/``admin_password`` and ``default_username``/``default_password`` to configure). @@ -196,9 +196,6 @@ remote_syslog_port: String value, default is 514. If set, custom port is ironic_log_dir: String value, default undefined. If set, it specifies a a non-default log directory for ironic. -inspector_log_dir: String value, default undefined. If set, it specifies a - non-default log directory for inspector. - nginx_log_dir: String value, default /var/log/nginx. It specifies a log directory for nginx. @@ -207,9 +204,9 @@ fast_track: Boolean setting to enable ironic to leverage an already running immediately as opposed to waiting for a complete system reboot. power_off_after_inspection: Boolean setting governing the behavior - of ironic-inspector's processing. + of inspection. The default is to not power-off machines - effectively enabling the Inspection to + effectively enabling moving from Inspection to Deployment without the need to reboot the physical machine. @@ -222,22 +219,7 @@ enable_credential_less_deploy: Boolean setting that enables the experimental ### Hardware Inspection Support -Bifrost also supports the installation of ironic-inspector in standalone -mode, which enables the user to allow for identification of the system -properties via a workflow. - -enable_inspector: Boolean value, default true. Set this value to false to - prevent installing ironic-inspector. - -inspector_debug: Boolean value, default true. Enables debug level logging - for inspector. Note that this default may change in - future. - -inspector_manage_firewall: Boolean value, default false. Controls whether - ironic-inspector should manage the firewall - rules of the host. Bifrost's installation playbook - adds the rule to permit the callback traffic, - so you shouldn't need to enable this. +Bifrost also supports identification of the system properties via a workflow. inspector_port_addition: Defines which MAC addresses to add as ports during introspection. Possible values are `all`, `active`, @@ -247,10 +229,6 @@ inspector_keep_ports: Defines which ports on a node to keep after introspection. Possible values are `all`, `present`, and `added`. The default value is `present`. -inspector_store_ramdisk_logs: Boolean value, default true. Controls if the - inspector agent will retain logs from the - ramdisk that called the inspector service. - enable_inspector_discovery: Boolean value, default false. This instructs inspector to add new nodes that are discovered via PXE booting on the same network to ironic. @@ -266,11 +244,6 @@ inspector_extra_kernel_options: String value, default undefined. Extra kernel parameters for the inspector default PXE configuration. -inspector_processing_hooks: String value containing a comma-separated list, - default undefined. Use this to specify a - non-default list of comma-separated processing - hooks for inspector. - ### Virtual Environment Install Bifrost installs ironic and other services into a python virtual environment @@ -315,10 +288,6 @@ Please note, if the hostname is set to something besides``localhost``, then the playbook will not attempt to create databases, database users, and grant privileges. -Similarly, if hardware introspection support is installed, the -nearly identical data structure for inspector can be found in the -same file named ``ironic_inspector``. - Notes ----- diff --git a/playbooks/roles/bifrost-ironic-install/defaults/main.yml b/playbooks/roles/bifrost-ironic-install/defaults/main.yml index 7a207171c..64845af6b 100644 --- a/playbooks/roles/bifrost-ironic-install/defaults/main.yml +++ b/playbooks/roles/bifrost-ironic-install/defaults/main.yml @@ -18,8 +18,6 @@ file_url_port: "8080" file_url_port_tls: "8083" ironicclient_source_install: false openstacksdk_source_install: false -ironicinspector_source_install: true -ironicinspectorclient_source_install: false sushy_source_install: false staging_drivers_source_install: true prometheus_exporter_source_install: true @@ -174,8 +172,6 @@ ironicclient_git_url: https://opendev.org/openstack/python-ironicclient openstacksdk_git_url: https://opendev.org/openstack/openstacksdk ironic_git_url: https://opendev.org/openstack/ironic staging_drivers_git_url: https://opendev.org/x/ironic-staging-drivers -ironicinspector_git_url: https://opendev.org/openstack/ironic-inspector -ironicinspectorclient_git_url: https://opendev.org/openstack/python-ironic-inspector-client ipa_git_url: https://opendev.org/openstack/ironic-python-agent ipa_builder_git_url: https://opendev.org/openstack/ironic-python-agent-builder prometheus_exporter_git_url: https://opendev.org/openstack/ironic-prometheus-exporter @@ -187,8 +183,6 @@ openstacksdk_git_folder: /opt/stack/openstacksdk dib_git_folder: /opt/stack/diskimage-builder reqs_git_folder: /opt/stack/requirements staging_drivers_git_folder: /opt/stack/ironic-staging-drivers -ironicinspector_git_folder: /opt/stack/ironic-inspector -ironicinspectorclient_git_folder: /opt/stack/python-ironic-inspector-client sushy_git_folder: /opt/stack/sushy ipa_git_folder: /opt/stack/ironic-python-agent ipa_builder_git_folder: /opt/stack/ironic-python-agent-builder @@ -276,19 +270,9 @@ inventory_dns: False # Several NTP servers can be specified, separated by commas. # dnsmasq_ntp_servers: -# Settings to enable the use of inspector -enable_inspector: false -inspector_debug: true -inspector_manage_firewall: false - # Set ironic_log_dir to use a non-default log directory for ironic. #ironic_log_dir: /var/log/ironic -# Set inspector_log_dir to use a non-default log directory for inspector. -#inspector_log_dir: -inspector_ramdisk_logs_local_path: /var/log/ironic-inspector/ramdisk - -inspector_store_ramdisk_logs: true # Note: inspector_port_addition has three valid values: all, active, pxe inspector_port_addition: "pxe" @@ -299,10 +283,6 @@ inspector_keep_ports: "present" # PXE configuration. inspector_extra_kernel_options: "ipa-inspection-collectors=default,logs" -# Set inspector_processing_hooks to specify a non-default comma-separated -# list of processing hooks for inspector. -#inspector_processing_hooks: - enable_inspector_discovery: false inspector_default_node_driver: "{{ 'manual-management' if enable_credential_less_deploy | bool else 'ipmi' }}" @@ -338,7 +318,6 @@ enable_keystone: false # Service URLs used for communication with them. api_protocol: "{{ 'https' if enable_tls | bool else 'http' }}" ironic_api_url: "{{ api_protocol }}://{{ internal_ip }}:6385" -ironic_inspector_api_url: "{{ api_protocol }}://{{ internal_ip }}:5050" keystone_api_url: "{{ api_protocol }}://{{ internal_ip }}:5000/v3" # Directory (on the controller) to keep the passwords @@ -373,21 +352,6 @@ ironic: password: "{{ ironic_db_password }}" host: "localhost" -ironic_inspector: - service_catalog: - username: "ironic_inspector" - password: "{{ service_password }}" - auth_url: "{{ keystone_api_url }}" - project_name: "service" - keystone: - default_username: "{{ default_username }}" - default_password: "{{ default_password }}" - database: - name: "inspector" - username: "inspector" - password: "{{ ironic_db_password }}" - host: "localhost" - # NOTE(dtantsur): keep in sync with bifrost-keystone-install keystone: debug: true @@ -420,7 +384,6 @@ vmedia_enable_tls: "{{ enable_tls }}" tls_root: /etc/bifrost tls_certificate_path: "{{ tls_root }}/bifrost.crt" ironic_private_key_path: /etc/ironic/ironic.pem -ironic_inspector_private_key_path: /etc/ironic-inspector/inspector.pem httpboot_private_key_path: /etc/nginx/httpboot.pem # If true, the conductor's JSON RPC will be available globally (and with TLS) expose_json_rpc: false diff --git a/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml b/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml index 95f802899..29a230a52 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/bootstrap.yml @@ -245,10 +245,6 @@ state: directory mode: "0755" -- name: "Install ironic-inspector to permit use of inspection interface" - include_tasks: inspector_bootstrap.yml - when: enable_inspector | bool - - name: "Get ironic install location" shell: echo $(dirname $(which ironic)) register: ironic_install_prefix @@ -478,9 +474,9 @@ - ansible_os_family == 'RedHat' - ansible_selinux.status == 'enabled' block: - - name: "Allow nginx, ironic, inspector and IPA ports on SELinux" + - name: "Allow nginx, ironic and IPA ports on SELinux" seport: - ports: "{{ file_url_port }},{{ file_url_port_tls }},6385,5050,9999" + ports: "{{ file_url_port }},{{ file_url_port_tls }},6385,9999" proto: tcp setype: http_port_t state: present diff --git a/playbooks/roles/bifrost-ironic-install/tasks/create_tftpboot.yml b/playbooks/roles/bifrost-ironic-install/tasks/create_tftpboot.yml index e8197ea24..7f4588c48 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/create_tftpboot.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/create_tftpboot.yml @@ -174,17 +174,12 @@ # TODO(TheJulia): The pxelinux folder is statically coded in ironic. # For now, we need to use it, but we can patch that. -- name: "Inspector - Place default tftp boot file in {{ http_boot_folder }}/pxelinux.cfg/" +- name: "Place default tftp boot file in {{ http_boot_folder }}/pxelinux.cfg/" template: - src: inspector-default-boot-ipxe.j2 + src: default-boot-ipxe.j2 dest: "{{ http_boot_folder }}/pxelinux.cfg/default" owner: ironic group: ironic mode: "0644" vars: - inspection_callback_url: >- - {%- if enable_inspector | bool -%} - {{ api_protocol }}://{{ internal_ip }}:5050/v1/continue - {%- else -%} - {{ api_protocol }}://{{ internal_ip }}:6385/v1/continue_inspection - {%- endif -%} + inspection_callback_url: "{{ api_protocol }}://{{ internal_ip }}:6385/v1/continue_inspection" diff --git a/playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml b/playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml deleted file mode 100644 index b81a4aaa7..000000000 --- a/playbooks/roles/bifrost-ironic-install/tasks/inspector_bootstrap.yml +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright (c) 2015 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. ---- -- name: "Set MySQL socket fact for Red Hat family" - set_fact: - mysql_socket_path: "/var/lib/mysql/mysql.sock" - when: ansible_os_family | lower == 'redhat' - -- name: "Set MySQL socket fact for Debian family" - set_fact: - mysql_socket_path: "/var/run/mysqld/mysqld.sock" - when: ansible_os_family | lower == 'debian' - -- name: "Set MySQL socket fact for other systems" - set_fact: - mysql_socket_path: "/var/run/mysql/mysql.sock" - when: ansible_os_family | lower not in ['redhat', 'debian'] - -- name: "MySQL - Create database" - mysql_db: - login_unix_socket: "{{ mysql_socket_path | default(omit) }}" - login_user: "{{ mysql_username }}" - login_password: "{{ mysql_password }}" - name: "{{ ironic_inspector.database.name }}" - state: present - encoding: utf8 - when: ironic_inspector.database.host == 'localhost' - -- name: "MySQL - Create user for inspector" - mysql_user: - login_unix_socket: "{{ mysql_socket_path | default(omit) }}" - login_user: "{{ mysql_username }}" - login_password: "{{ mysql_password }}" - name: "{{ ironic_inspector.database.username }}" - password: "{{ ironic_inspector.database.password }}" - priv: "{{ ironic_inspector.database.name }}.*:ALL" - state: present - when: ironic_inspector.database.host == 'localhost' - -- name: "Inspector - Ensure /etc/ironic-inspector/ exists" - file: - dest: /etc/ironic-inspector - owner: ironic - group: ironic - mode: "0755" - state: directory - -- name: "Remove old rootwrap locations" - file: - name: "{{ item }}" - state: absent - loop: - - "/etc/ironic-inspector/rootwrap.conf" - - "/etc/ironic-inspector/rootwrap.d" - - "{{ ironic_rootwrap_dir }}/ironic-inspector-rootwrap" - -- name: "Generate htpasswd(s) for ironic-inspector" - htpasswd: - path: /etc/ironic-inspector/htpasswd - crypt_scheme: bcrypt - name: "{{ item.name }}" - password: "{{ item.password }}" - owner: ironic - group: ironic - mode: "0600" - loop: - - name: "{{ admin_username }}" - password: "{{ admin_password }}" - - name: "{{ default_username }}" - password: "{{ default_password }}" - loop_control: - label: "{{ item.name }}" - when: - - not noauth_mode | bool - - not enable_keystone | bool - -- name: "Generate TLS parameters" - include_role: - name: bifrost-tls - vars: - dest_private_key_path: "{{ ironic_inspector_private_key_path }}" - dest_private_key_owner: ironic - dest_private_key_group: ironic - when: enable_tls | bool - -- name: "Populate keystone for ironic-inspector " - include_tasks: keystone_setup_inspector.yml - when: enable_keystone | bool - -- name: "Inspector - Place Configuration" - template: - src: ironic-inspector.conf.j2 - dest: /etc/ironic-inspector/inspector.conf - owner: ironic - group: ironic - mode: "0640" - -- name: "Inspector - Create the log directories (if requested)" - file: - name: "{{ item }}" - state: directory - owner: ironic - group: ironic - mode: "0700" - loop: - - "{{ inspector_log_dir | default('') }}" - - "{{ inspector_ramdisk_logs_local_path | default('') }}" - when: item | length > 0 -- name: "Upgrade inspector DB Schema" - command: ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade - become: true - environment: "{{ bifrost_venv_env }}" -- name: "Inspector - Get ironic-inspector install location" - shell: echo $(dirname $(which ironic-inspector)) - register: ironic_install_prefix - environment: "{{ bifrost_venv_env }}" -- name: "Inspector - Place service" - template: - src: systemd_template.j2 - dest: "{{ init_dest_dir }}ironic-inspector.service" - owner: root - group: root - vars: - service_path: "{{ ironic_install_prefix.stdout | default('') }}" - service_name: 'ironic-inspector' - config_file: '/etc/ironic-inspector/inspector.conf' -- name: "Inspector - Explicitly permit TCP/5050 for ironic-inspector callback" - iptables: - chain: INPUT - action: insert - protocol: tcp - destination_port: 5050 - in_interface: "{{ network_interface }}" - jump: ACCEPT - when: not use_firewalld | bool - -- name: "Inspector - Enable port in firewalld" - firewalld: - port: "5050/tcp" - zone: "{{ 'libvirt' if testing | bool else firewalld_internal_zone }}" - state: enabled - permanent: yes - immediate: yes - when: use_firewalld | bool diff --git a/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml b/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml deleted file mode 100644 index 8ffc79c85..000000000 --- a/playbooks/roles/bifrost-ironic-install/tasks/inspector_install.yml +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2015 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. ---- -- name: "Inspector - install" - include_role: - name: bifrost-pip-install - vars: - package: ironic-inspector - sourcedir: "{{ ironicinspector_git_folder }}" - source_install: "{{ ironicinspector_source_install }}" - -- name: "Inspector - client install" - include_role: - name: bifrost-pip-install - vars: - package: python-ironic-inspector-client - sourcedir: "{{ ironicinspectorclient_git_folder }}" - source_install: "{{ ironicinspectorclient_source_install }}" diff --git a/playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml b/playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml deleted file mode 100644 index f93c76442..000000000 --- a/playbooks/roles/bifrost-ironic-install/tasks/inspector_start.yml +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2015 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. ---- -- name: "Inspector - (re)starting ironic-inspector service" - service: - name: ironic-inspector - state: restarted - enabled: yes - when: enable_inspector | bool - -- name: "Stop inspector if it is disabled" - service: - name: ironic-inspector - state: stopped - enabled: no - ignore_errors: true - when: not enable_inspector | bool - -- name: "Remove inspector if it is disabled" - file: - path: "{{ init_dest_dir }}ironic-inspector.service" - state: absent - when: not enable_inspector | bool diff --git a/playbooks/roles/bifrost-ironic-install/tasks/install.yml b/playbooks/roles/bifrost-ironic-install/tasks/install.yml index c7f77abc9..2cf6e372b 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/install.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/install.yml @@ -152,10 +152,6 @@ sourcedir: "{{ ironic_git_folder }}" source_install: true -- name: "Install ironic-inspector to permit use of inspection interface" - include_tasks: inspector_install.yml - when: enable_inspector | bool - - name: "Install ironic-staging-drivers" include_tasks: staging_install.yml when: staging_drivers_include | bool diff --git a/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml b/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml deleted file mode 100644 index 2d5e465b9..000000000 --- a/playbooks/roles/bifrost-ironic-install/tasks/keystone_setup_inspector.yml +++ /dev/null @@ -1,144 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. ---- - -# TODO(TheJulia): The user and project domains are hardcoded in this. -# We should likely address that at some point, however I think a user -# should be the driver of that work. - -- name: "Error if credentials are undefined." - fail: - msg: | - Credentials are missing or undefined, unable to proceed. - Please consult roled defaults/main.yml. - when: > - keystone is undefined or keystone.bootstrap is undefined or - keystone.bootstrap.username is undefined or - keystone.bootstrap.password is undefined or - keystone.bootstrap.project_name is undefined or - ironic_inspector.service_catalog.auth_url is undefined or - ironic_inspector.service_catalog.username is undefined or - ironic_inspector.service_catalog.password is undefined or - ironic_inspector.keystone is undefined or - ironic_inspector.keystone.default_username is undefined or - ironic_inspector.keystone.default_password is undefined - -- name: "Configure keystone auth" - set_fact: - keystone_auth: - auth_url: "{{ ironic.service_catalog.auth_url | default(keystone_api_url) }}" - username: "{{ keystone.bootstrap.username }}" - password: "{{ keystone.bootstrap.password }}" - project_name: "admin" - project_domain_id: "default" - user_domain_id: "default" - no_log: true - -- name: "Create service user for ironic-inspector" - openstack.cloud.identity_user: - name: "{{ ironic_inspector.service_catalog.username }}" - password: "{{ ironic_inspector.service_catalog.password }}" - state: present - domain: "default" - default_project: "{{ ironic_inspector.service_catalog.project_name | default('service') }}" - auth: "{{ keystone_auth }}" - wait: yes - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - -- name: "Associate ironic_inspector user to admin role" - openstack.cloud.role_assignment: - user: "{{ ironic_inspector.service_catalog.username }}" - role: admin - project: "{{ ironic_inspector.service_catalog.project_name | default('service') }}" - auth: "{{ keystone_auth }}" - wait: yes - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - -- name: "Create keystone service record for ironic-inspector" - openstack.cloud.catalog_service: - state: present - name: ironic-inspector - service_type: baremetal-introspection - description: OpenStack Baremetal Introspection Service - auth: "{{ keystone_auth }}" - wait: yes - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - register: introspection_catalog_service - -- name: "Create ironic-inspector admin endpoint" - openstack.cloud.endpoint: - state: present - service: "{{ introspection_catalog_service.service.id }}" - endpoint_interface: admin - url: "{{ ironic_inspector.keystone.admin_url | default(ironic_inspector_api_url) }}" - region: "{{ keystone.bootstrap.region_name | default('RegionOne') }}" - auth: "{{ keystone_auth }}" - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - -- name: "Setting external ironic-inspector public URL" - set_fact: - ironic_inspector_public_url: "{{ api_protocol }}://{{ public_ip }}:5050/" - when: public_ip is defined - -- name: "Create ironic-inspector public endpoint" - openstack.cloud.endpoint: - state: present - service: "{{ introspection_catalog_service.service.id }}" - endpoint_interface: public - url: "{{ ironic_inspector.keystone.public_url | default(ironic_inspector_public_url) | default(ironic_inspector_api_url) }}" - region: "{{ keystone.bootstrap.region_name | default('RegionOne') }}" - auth: "{{ keystone_auth }}" - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - -- name: "Setting internal ironic-inspector URL" - set_fact: - ironic_inspector_private_url: "{{ api_protocol }}://{{ private_ip }}:5050/" - when: private_ip is defined and private_ip | length > 0 - -- name: "Create ironic-inspector internal endpoint" - openstack.cloud.endpoint: - state: present - service: "{{ introspection_catalog_service.service.id }}" - endpoint_interface: internal - url: "{{ ironic_inspector.keystone.internal_url | default(ironic_inspector_private_url) | default(ironic_inspector_api_url) }}" - region: "{{ keystone.bootstrap.region_name | default('RegionOne') }}" - auth: "{{ keystone_auth }}" - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - -- name: "Create inspector_user user" - openstack.cloud.identity_user: - name: "{{ ironic_inspector.keystone.default_username }}" - password: "{{ ironic_inspector.keystone.default_password }}" - default_project: "baremetal" - domain: "default" - auth: "{{ keystone_auth }}" - update_password: always - wait: yes - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" - -- name: "Associate inspector_user with admin role" - openstack.cloud.role_assignment: - user: "{{ ironic_inspector.keystone.default_username }}" - role: "admin" - project: baremetal - auth: "{{ keystone_auth }}" - wait: yes - ca_cert: "{{ tls_certificate_path | default(omit) }}" - environment: "{{ bifrost_venv_env }}" diff --git a/playbooks/roles/bifrost-ironic-install/tasks/start.yml b/playbooks/roles/bifrost-ironic-install/tasks/start.yml index 189db955a..f31c9978b 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/start.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/start.yml @@ -31,9 +31,6 @@ state: started enabled: yes -- name: "Start/stop ironic-inspector" - include_tasks: inspector_start.yml - - name: "Stop old ironic services" service: name: "{{ item }}" @@ -43,6 +40,7 @@ loop: - ironic-api - ironic-conductor + - ironic-inspector - name: "Remove old ironic services" file: @@ -51,6 +49,7 @@ loop: - ironic-api - ironic-conductor + - ironic-inspector - name: "Start ironic" service: diff --git a/playbooks/roles/bifrost-ironic-install/tasks/validate.yml b/playbooks/roles/bifrost-ironic-install/tasks/validate.yml index 1d07b6f3d..08bf4a3c6 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/validate.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/validate.yml @@ -58,39 +58,3 @@ retries: 6 delay: 5 until: conductor_list is not failed - -- name: "Authentication environment - no-auth inspector version" - set_fact: - testing_env: - OS_AUTH_TYPE: none - OS_ENDPOINT: "{{ ironic_inspector_api_url }}" - when: - - noauth_mode | bool - - enable_inspector | bool - -- name: "Authentication environment - HTTP basic inspector version" - set_fact: - testing_env: - OS_AUTH_TYPE: http_basic - OS_ENDPOINT: "{{ ironic_inspector_api_url }}" - OS_USERNAME: "{{ admin_username }}" - OS_PASSWORD: "{{ admin_password }}" - when: - - not noauth_mode | bool - - not enable_keystone | bool - - enable_inspector | bool - no_log: yes - -- name: "Set OS_CACERT if required" - set_fact: - testing_env: "{{ testing_env | combine({'OS_CACERT': tls_certificate_path}) }}" - when: enable_tls | bool - -- name: "Validate introspection API access" - command: baremetal introspection list - environment: "{{ testing_env | combine(bifrost_venv_env) }}" - register: introspection_list - retries: 6 - delay: 5 - until: introspection_list is not failed - when: enable_inspector | bool diff --git a/playbooks/roles/bifrost-ironic-install/templates/default-boot-ipxe.j2 b/playbooks/roles/bifrost-ironic-install/templates/default-boot-ipxe.j2 new file mode 100644 index 000000000..e1e021c16 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/templates/default-boot-ipxe.j2 @@ -0,0 +1,10 @@ +#!ipxe + +dhcp || reboot + +goto introspect + +:introspect +kernel {{ ipa_kernel_url }} ipa-inspection-callback-url={{ api_protocol }}://{{ internal_ip }}:6385/v1/continue_inspection {% if fast_track | bool %}ipa-api-url={{ api_protocol }}://{{ internal_ip }}:6385{% endif %} systemd.journald.forward_to_console=yes BOOTIF=${mac} nofb nomodeset vga=normal console=ttyS0 {{ inspector_extra_kernel_options | default('') }} ipa-insecure=1 initrd={{ ipa_ramdisk_url | basename }} +initrd {{ ipa_ramdisk_url }} +boot diff --git a/playbooks/roles/bifrost-ironic-install/templates/inspector-default-boot-ipxe.j2 b/playbooks/roles/bifrost-ironic-install/templates/inspector-default-boot-ipxe.j2 deleted file mode 100644 index 19c8c1f9e..000000000 --- a/playbooks/roles/bifrost-ironic-install/templates/inspector-default-boot-ipxe.j2 +++ /dev/null @@ -1,10 +0,0 @@ -#!ipxe - -dhcp || reboot - -goto introspect - -:introspect -kernel {{ ipa_kernel_url }} ipa-inspection-callback-url={{ inspection_callback_url }} {% if fast_track | bool %}ipa-api-url={{ api_protocol }}://{{ internal_ip }}:6385{% endif %} systemd.journald.forward_to_console=yes BOOTIF=${mac} nofb nomodeset vga=normal {% if testing | bool %}console=ttyS0{% endif %} {{ inspector_extra_kernel_options | default('') }} ipa-insecure=1 {% if inspector_debug | bool %}ipa-debug=1{% endif %} initrd={{ ipa_ramdisk_url | basename }} -initrd {{ ipa_ramdisk_url }} -boot diff --git a/playbooks/roles/bifrost-ironic-install/templates/ironic-inspector.conf.j2 b/playbooks/roles/bifrost-ironic-install/templates/ironic-inspector.conf.j2 deleted file mode 100644 index 68642b5f8..000000000 --- a/playbooks/roles/bifrost-ironic-install/templates/ironic-inspector.conf.j2 +++ /dev/null @@ -1,96 +0,0 @@ -# {{ ansible_managed }} - -[DEFAULT] -{% if enable_keystone | bool %} -auth_strategy = keystone -{% elif noauth_mode | bool %} -auth_strategy = noauth -{% else %} -auth_strategy = http_basic -http_basic_auth_user_file = /etc/ironic-inspector/htpasswd -{% endif %} -debug = {{ inspector_debug | bool }} - -{% if inspector_log_dir | default("") != "" %} -log_dir = {{ inspector_log_dir }} -{% endif %} - -transport_url = fake:// - -{% if enable_tls | bool %} -# TLS is handled by nginx is proxy mode -listen_address = 127.0.0.1 -listen_unix_socket = /run/ironic/ironic-inspector.socket -# Nginx should be able to write to the socket, access will be further limited -# by the containing directory. -listen_unix_socket_mode = 0660 -{% else %} -listen_address = {{ internal_ip }} -{% endif %} - -[database] -connection=mysql+pymysql://{{ ironic_inspector.database.username }}:{{ ironic_inspector.database.password }}@{{ ironic_inspector.database.host }}/{{ ironic_inspector.database.name }}?charset=utf8 - -[pxe_filter] -{% if inspector_manage_firewall | bool | default('false') == false %} -driver = noop -{% else %} -driver = iptables -{% endif %} - -[ironic] -{% if enable_keystone | bool %} -os_region = {{ keystone.bootstrap.region_name | default('RegionOne') }} -project_name = baremetal -username = {{ ironic_inspector.keystone.default_username }} -password = {{ ironic_inspector.keystone.default_password }} -auth_url = {{ ironic_inspector.service_catalog.auth_url }} -auth_type = password -user_domain_id = default -project_domain_id = default -{% elif noauth_mode | bool %} -auth_type = none -endpoint_override = {{ ironic_api_url }} -{% else %} -auth_type = http_basic -endpoint_override = {{ ironic_api_url }} -username = {{ admin_username }} -password = {{ admin_password }} -{% endif %} -{% if enable_tls | bool %} -cafile = {{ tls_certificate_path }} -{% endif %} - -{% if enable_keystone is defined and enable_keystone | bool == true %} -[keystone_authtoken] -auth_plugin = password -auth_url = {{ ironic_inspector.service_catalog.auth_url }} -username = {{ ironic_inspector.service_catalog.username }} -password = {{ ironic_inspector.service_catalog.password }} -user_domain_id = default -project_name = service -project_domain_id = default -{% if enable_tls | bool %} -cafile = {{ tls_certificate_path }} -{% endif %} -{% endif %} - -[processing] -add_ports = {{ inspector_port_addition | default('pxe') }} -keep_ports = {{ inspector_keep_ports | default('present') }} -{% if inspector_ramdisk_logs_local_path | default("") != "" %} -ramdisk_logs_dir = {{ inspector_ramdisk_logs_local_path }} -{% endif %} -always_store_ramdisk_logs = {{ inspector_store_ramdisk_logs | default('true') | bool }} -{% if inspector_processing_hooks is defined %} -processing_hooks = {{ inspector_processing_hooks }} -{% endif %} -store_data = database -power_off = {{ power_off_after_inspection }} - -{% if enable_inspector_discovery | bool %} -node_not_found_hook = enroll - -[discovery] -enroll_node_driver = {{ inspector_default_node_driver }} -{% endif %} diff --git a/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 b/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 index c6442aa67..cee54f400 100644 --- a/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 +++ b/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 @@ -7,13 +7,8 @@ debug = {{ ironic_debug | bool }} # control instead of ironic, noop is the only available network driver. enabled_network_interfaces = noop default_deploy_interface = {{ default_deploy_interface }} -{% if enable_inspector | bool == true %} -enabled_inspect_interfaces = no-inspect,inspector,agent -default_inspect_interface = inspector -{% else %} enabled_inspect_interfaces = no-inspect,agent default_inspect_interface = agent -{% endif %} enabled_bios_interfaces = {{ enabled_bios_interfaces }} enabled_boot_interfaces = {{ enabled_boot_interfaces }} enabled_firmware_interfaces = {{ enabled_firmware_interfaces }} @@ -157,31 +152,6 @@ extra_kernel_params = {{ inspector_extra_kernel_options | default('') }} require_managed_boot = False add_ports = {{ inspector_port_addition | default('pxe') }} keep_ports = {{ inspector_keep_ports | default('present') }} -{% if enable_inspector | bool %} -{% if enable_keystone | bool %} -auth_type = password -auth_url = {{ ironic.service_catalog.auth_url }} -username = {{ ironic.service_catalog.username }} -password = {{ ironic.service_catalog.password }} -user_domain_id = default -project_name = {{ ironic.service_catalog.project_name }} -project_domain_id = default -region_name = {{ keystone.bootstrap.region_name | default('RegionOne')}} -# NOTE(dtantsur): this has to be on internal IP even if public IPs are used -callback_endpoint_override = {{ api_protocol }}://{{ internal_ip }}:5050 -{% elif noauth_mode | bool %} -auth_type=none -endpoint_override = {{ ironic_inspector_api_url }} -{% else %} -auth_type = http_basic -endpoint_override = {{ ironic_inspector_api_url }} -username = {{ admin_username }} -password = {{ admin_password }} -{% endif %} -{% if enable_tls | bool %} -cafile = {{ tls_certificate_path }} -{% endif %} -{% endif %} [auto_discovery] enabled = {{ enable_inspector_discovery | bool }} diff --git a/playbooks/roles/bifrost-ironic-install/templates/nginx_conf.d_bifrost-ironic.conf.j2 b/playbooks/roles/bifrost-ironic-install/templates/nginx_conf.d_bifrost-ironic.conf.j2 index 5ff38aebc..34b5ca56b 100644 --- a/playbooks/roles/bifrost-ironic-install/templates/nginx_conf.d_bifrost-ironic.conf.j2 +++ b/playbooks/roles/bifrost-ironic-install/templates/nginx_conf.d_bifrost-ironic.conf.j2 @@ -14,22 +14,3 @@ server { proxy_set_header X-Forwarded-Port 6385; } } - -{% if enable_inspector | bool %} -server { - listen 5050 ssl http2; - server_name {{ ansible_hostname }}; - - ssl_certificate {{ tls_certificate_path }}; - ssl_certificate_key {{ ironic_inspector_private_key_path }}; - - location / { - proxy_pass http://unix:/run/ironic/ironic-inspector.socket:; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Port 5050; - } -} -{% endif %} diff --git a/playbooks/roles/bifrost-keystone-client-config/defaults/main.yml b/playbooks/roles/bifrost-keystone-client-config/defaults/main.yml index 56273bc81..3084b211b 100644 --- a/playbooks/roles/bifrost-keystone-client-config/defaults/main.yml +++ b/playbooks/roles/bifrost-keystone-client-config/defaults/main.yml @@ -5,7 +5,6 @@ ans_network_interface: "{{ network_interface | replace('-', '_') }}" internal_ip: "{{ hostvars[inventory_hostname]['ansible_' + ans_network_interface]['ipv4']['address'] }}" enable_tls: false -enable_inspector: false skip_start: False skip_validation: "{{ skip_start }}" @@ -13,7 +12,6 @@ skip_validation: "{{ skip_start }}" # Service URLs used for communication with them. api_protocol: "{{ 'https' if enable_tls | bool else 'http' }}" ironic_api_url: "{{ api_protocol }}://{{ internal_ip }}:6385" -ironic_inspector_api_url: "{{ api_protocol }}://{{ internal_ip }}:5050" # Ensure that Ansible is using python interpreter and dependencies inside the bifrost virtual environment bifrost_venv_dir: "{{ lookup('env', 'VENV') or '/opt/stack/bifrost' }}" diff --git a/playbooks/roles/bifrost-keystone-client-config/tasks/validate.yml b/playbooks/roles/bifrost-keystone-client-config/tasks/validate.yml index 4615d7352..7eb40b348 100644 --- a/playbooks/roles/bifrost-keystone-client-config/tasks/validate.yml +++ b/playbooks/roles/bifrost-keystone-client-config/tasks/validate.yml @@ -22,11 +22,6 @@ command: baremetal --debug node list environment: "{{ bifrost_venv_env | combine({'OS_CLOUD': testing_cloud_name}) }}" - - name: "List introspection rules using CLI and clouds.yaml" - command: baremetal --debug introspection rule list - environment: "{{ bifrost_venv_env | combine({'OS_CLOUD': testing_cloud_name}) }}" - when: enable_inspector | bool - - name: "List services using CLI and clouds.yaml" command: openstack --debug service list environment: "{{ bifrost_venv_env | combine({'OS_CLOUD': 'bifrost-admin'}) }}" @@ -43,9 +38,6 @@ executable: /bin/bash environment: "{{ bifrost_venv_env }}" - # FIXME(dtantsur): openrc provides no overrides for ironic-inspector, so we - # cannot test it. - - name: "List services using CLI and openrc" shell: | set -e diff --git a/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 b/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 index 6e214d579..f9f66ae39 100644 --- a/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 +++ b/playbooks/roles/bifrost-keystone-client-config/templates/clouds.yaml.j2 @@ -26,15 +26,9 @@ clouds: auth_type: "none" auth: endpoint: {{ ironic_api_url }} - baremetal_introspection_endpoint_override: {{ ironic_inspector_api_url }} {% if enable_tls | bool %} cacert: "{{ tls_certificate_path }}" {% endif %} - # Deprecated - bifrost-inspector: - auth_type: "none" - auth: - endpoint: {{ ironic_inspector_api_url }} {% if enable_tls | bool %} cacert: "{{ tls_certificate_path }}" {% endif %} @@ -45,7 +39,6 @@ clouds: username: "{{ default_username }}" password: "{{ default_password }}" endpoint: {{ ironic_api_url }} - baremetal_introspection_endpoint_override: {{ ironic_inspector_api_url }} {% if enable_tls | bool %} cacert: "{{ tls_certificate_path }}" {% endif %} @@ -55,7 +48,6 @@ clouds: username: "{{ admin_username }}" password: "{{ admin_password }}" endpoint: {{ ironic_api_url }} - baremetal_introspection_endpoint_override: {{ ironic_inspector_api_url }} {% if enable_tls | bool %} cacert: "{{ tls_certificate_path }}" {% endif %} diff --git a/playbooks/roles/bifrost-logrotate-install/templates/logrotate.conf.j2 b/playbooks/roles/bifrost-logrotate-install/templates/logrotate.conf.j2 index 100877509..95485a6b3 100644 --- a/playbooks/roles/bifrost-logrotate-install/templates/logrotate.conf.j2 +++ b/playbooks/roles/bifrost-logrotate-install/templates/logrotate.conf.j2 @@ -46,8 +46,3 @@ maxsize {{ logrotate_file_maxsize }} { } {% endif %} -{% if inspector_log_dir is defined %} -"{{ inspector_log_dir }}/*.log" -{ -} -{% endif %} \ No newline at end of file diff --git a/playbooks/roles/bifrost-prep-for-install/README.md b/playbooks/roles/bifrost-prep-for-install/README.md index 3d7c38aac..e487bb262 100644 --- a/playbooks/roles/bifrost-prep-for-install/README.md +++ b/playbooks/roles/bifrost-prep-for-install/README.md @@ -61,12 +61,6 @@ openstacksdk_git_branch: Branch to install, defaults to the value of dib_git_branch: Branch to install, defaults to "master". -ironicinspector_git_branch: Branch to install, defaults to the value of - git_branch. - -ironicinspectorclient_git_branch: Branch to install, defaults to - the value of git_branch. - reqs_git_branch: Branch to install, defaults to the value of git_branch. staging_drivers_git_branch: Branch to install, defaults to the value of diff --git a/playbooks/roles/bifrost-prep-for-install/defaults/main.yml b/playbooks/roles/bifrost-prep-for-install/defaults/main.yml index b05404448..51738aa87 100644 --- a/playbooks/roles/bifrost-prep-for-install/defaults/main.yml +++ b/playbooks/roles/bifrost-prep-for-install/defaults/main.yml @@ -7,8 +7,6 @@ dib_git_url: "{{ git_url_root }}/openstack/diskimage-builder" ironicclient_git_url: "{{ git_url_root }}/openstack/python-ironicclient" openstacksdk_git_url: "{{ git_url_root }}/openstack/openstacksdk" ironic_git_url: "{{ git_url_root }}/openstack/ironic" -ironicinspector_git_url: "{{ git_url_root }}/openstack/ironic-inspector" -ironicinspectorclient_git_url: "{{ git_url_root }}/openstack/python-ironic-inspector-client" reqs_git_url: "{{ git_url_root }}/openstack/requirements" staging_drivers_git_url: "{{ git_url_root }}/x/ironic-staging-drivers" keystone_git_url: "{{ git_url_root }}/openstack/keystone" @@ -19,8 +17,6 @@ prometheus_exporter_git_url: "{{ git_url_root }}/openstack/ironic-prometheus-exp # *_git_folder can be overridden by local clones for offline installs ironicclient_git_folder: "{{ git_root }}/python-ironicclient" ironic_git_folder: "{{ git_root }}/ironic" -ironicinspector_git_folder: "{{ git_root }}/ironic-inspector" -ironicinspectorclient_git_folder: "{{ git_root }}/python-ironic-inspector-client" openstacksdk_git_folder: "{{ git_root }}/openstacksdk" dib_git_folder: "{{ git_root }}/diskimage-builder" reqs_git_folder: "{{ git_root }}/requirements" @@ -36,8 +32,6 @@ ironicclient_git_branch: "{{ git_branch }}" ironic_git_branch: "{{ git_branch }}" openstacksdk_git_branch: "{{ git_branch }}" dib_git_branch: master -ironicinspector_git_branch: "{{ git_branch }}" -ironicinspectorclient_git_branch: "{{ git_branch }}" reqs_git_branch: "{{ git_branch }}" staging_drivers_git_branch: "{{ git_branch }}" keystone_git_branch: "{{ git_branch }}" @@ -48,12 +42,9 @@ prometheus_exporter_git_branch: "{{ git_branch }}" # disable source install to prevent cloning ironicclient_source_install: false openstacksdk_source_install: false -ironicinspector_source_install: true -ironicinspectorclient_source_install: false sushy_source_install: false staging_drivers_source_install: true prometheus_exporter_source_install: true -enable_inspector: false enable_keystone: false enable_prometheus_exporter: false staging_drivers_include: false @@ -83,18 +74,6 @@ bifrost_install_sources: git_url: "{{ dib_git_url }}" git_branch: "{{ dib_git_branch }}" name: dib - - git_folder: "{{ ironicinspector_git_folder }}" - git_url: "{{ ironicinspector_git_url }}" - git_branch: "{{ ironicinspector_git_branch }}" - name: ironicinspector - source_install: "{{ ironicinspector_source_install }}" - enabled: "{{ enable_inspector }}" - - git_folder: "{{ ironicinspectorclient_git_folder }}" - git_url: "{{ ironicinspectorclient_git_url }}" - git_branch: "{{ ironicinspectorclient_git_branch }}" - name: ironicinspectorclient - source_install: "{{ ironicinspectorclient_source_install }}" - enabled: "{{ enable_inspector }}" - git_folder: "{{ reqs_git_folder }}" git_url: "{{ reqs_git_url }}" git_branch: "{{ reqs_git_branch }}" diff --git a/playbooks/roles/bifrost-test-inspection/README.md b/playbooks/roles/bifrost-test-inspection/README.md index 01edf7be7..6d7c6290e 100644 --- a/playbooks/roles/bifrost-test-inspection/README.md +++ b/playbooks/roles/bifrost-test-inspection/README.md @@ -1,7 +1,7 @@ bifrost-test-inspection ======================= -Tests nodes that have been inspected by ironic inspector. +Tests nodes that have been inspected by ironic. Requirements ------------ diff --git a/releasenotes/notes/no-inspector-2995fa195b715fe4.yaml b/releasenotes/notes/no-inspector-2995fa195b715fe4.yaml new file mode 100644 index 000000000..2a99d41bf --- /dev/null +++ b/releasenotes/notes/no-inspector-2995fa195b715fe4.yaml @@ -0,0 +1,5 @@ +--- +upgrade: + - | + Supports for installing or using ironic-inspector has been completely + removed. diff --git a/scripts/collect-test-info.sh b/scripts/collect-test-info.sh index 031c26222..0801e9bb0 100755 --- a/scripts/collect-test-info.sh +++ b/scripts/collect-test-info.sh @@ -76,7 +76,6 @@ sudo chown -R $USER ${LOG_LOCATION}/all sudo systemctl > ${LOG_LOCATION}/all-services.txt sudo journalctl -u libvirtd &> ${LOG_LOCATION}/libvirtd.log sudo journalctl -u ironic &> ${LOG_LOCATION}/ironic.log -sudo journalctl -u ironic-inspector &> ${LOG_LOCATION}/ironic-inspector.log sudo journalctl -u dnsmasq &> ${LOG_LOCATION}/dnsmasq.log sudo journalctl -u vbmcd &> ${LOG_LOCATION}/vbmcd.log sudo journalctl -u redfish-emulator &> ${LOG_LOCATION}/redfish-emulator.log @@ -106,7 +105,6 @@ if which openstack; then fi sudo cp -a "/var/log/ironic/deploy" ${LOG_LOCATION}/deploy-ramdisk -sudo cp -a "/var/log/ironic-inspector/ramdisk" ${LOG_LOCATION}/inspection-ramdisk # general info sudo ps auxf &> ${LOG_LOCATION}/ps.txt diff --git a/scripts/test-bifrost.sh b/scripts/test-bifrost.sh index 56b2055ab..e8991b936 100755 --- a/scripts/test-bifrost.sh +++ b/scripts/test-bifrost.sh @@ -35,7 +35,6 @@ TEST_VM_NUM_NODES=1 DOWNLOAD_CUSTOM_DEPLOY_IMAGE=true TESTING_USER=cirros TEST_PLAYBOOK="test-bifrost.yaml" -USE_INSPECTOR=${USE_INSPECTOR:-false} INSPECT_NODES=true INVENTORY_DHCP=false INVENTORY_DHCP_STATIC_IP=false @@ -200,7 +199,6 @@ ${ANSIBLE} -vvvv \ -e test_vm_num_nodes=${TEST_VM_NUM_NODES} \ -e inventory_dhcp=${INVENTORY_DHCP} \ -e inventory_dhcp_static_ip=${INVENTORY_DHCP_STATIC_IP} \ - -e enable_inspector=${USE_INSPECTOR} \ -e inspect_nodes=${INSPECT_NODES} \ -e redeploy_nodes=${REDEPLOY_NODES} \ -e download_ipa=${DOWNLOAD_IPA} \ diff --git a/zuul.d/bifrost-jobs.yaml b/zuul.d/bifrost-jobs.yaml index c86b1d2ce..d8d6d72a6 100644 --- a/zuul.d/bifrost-jobs.yaml +++ b/zuul.d/bifrost-jobs.yaml @@ -14,8 +14,6 @@ - ^doc/.*$ - ^ironic/locale/.*$ - ^ironic/tests/.*$ - - ^ironic_inspector/locale/.*$ - - ^ironic_inspector/test/.*$ - ^releasenotes/.*$ - ^setup.cfg$ - ^test-requirements.txt$ @@ -28,7 +26,6 @@ - openstack/bifrost - openstack/diskimage-builder - openstack/ironic - - openstack/ironic-inspector - openstack/ironic-python-agent - openstack/ironic-python-agent-builder - openstack/requirements @@ -110,12 +107,6 @@ parent: bifrost-integration-tinyipa-keystone-ubuntu-jammy nodeset: ubuntu-noble -- job: - name: bifrost-integration-inspector-ubuntu-jammy - parent: bifrost-integration-tinyipa-ubuntu-jammy - vars: - use_inspector: true - - job: name: bifrost-integration-redfish-vmedia-uefi-ubuntu-noble parent: bifrost-integration-tinyipa-ubuntu-noble @@ -177,12 +168,6 @@ test_driver: redfish enable_prometheus_exporter: true -- job: - name: bifrost-integration-inspector-centos-10 - parent: bifrost-integration-tinyipa-centos-10 - vars: - use_inspector: true - - job: name: bifrost-integration-tinyipa-debian-bullseye parent: bifrost-integration-tinyipa diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml index 07e0b4465..0d56a72fc 100644 --- a/zuul.d/project.yaml +++ b/zuul.d/project.yaml @@ -20,8 +20,6 @@ - bifrost-integration-redfish-vmedia-uefi-ubuntu-noble - bifrost-integration-redfish-vmedia-uefi-ubuntu-jammy - bifrost-integration-redfish-vmedia-uefi-debian-bookworm - - bifrost-integration-inspector-centos-10 - - bifrost-integration-inspector-ubuntu-jammy - bifrost-upgrade-ubuntu-jammy - bifrost-upgrade-keystone-ubuntu-noble # Non-voting jobs @@ -79,8 +77,6 @@ - bifrost-integration-redfish-vmedia-uefi-ubuntu-noble - bifrost-integration-redfish-vmedia-uefi-ubuntu-jammy - bifrost-integration-redfish-vmedia-uefi-debian-bookworm - - bifrost-integration-inspector-centos-10 - - bifrost-integration-inspector-ubuntu-jammy - bifrost-upgrade-ubuntu-jammy - bifrost-upgrade-keystone-ubuntu-noble experimental: From 12fa61977f072f685e8a81782c5de6394f31db40 Mon Sep 17 00:00:00 2001 From: Riccardo Pittau Date: Sun, 19 Oct 2025 11:42:13 +0200 Subject: [PATCH 2/2] Remove support for Python 3.9 Change-Id: Ife6c17d5b36333b47a42cd7da15fb25d36c2b183 Signed-off-by: Riccardo Pittau --- .../notes/remove-py39-5e2f5eacb4380407.yaml | 4 + scripts/install-deps.sh | 6 - setup.cfg | 3 +- upper-constraints-cs9-py39.txt | 599 ------------------ 4 files changed, 5 insertions(+), 607 deletions(-) create mode 100644 releasenotes/notes/remove-py39-5e2f5eacb4380407.yaml delete mode 100644 upper-constraints-cs9-py39.txt diff --git a/releasenotes/notes/remove-py39-5e2f5eacb4380407.yaml b/releasenotes/notes/remove-py39-5e2f5eacb4380407.yaml new file mode 100644 index 000000000..ea79ffec7 --- /dev/null +++ b/releasenotes/notes/remove-py39-5e2f5eacb4380407.yaml @@ -0,0 +1,4 @@ +--- +upgrade: + - | + Python 3.9 is not supported anymore. diff --git a/scripts/install-deps.sh b/scripts/install-deps.sh index 2354dec5c..82a29b2d0 100755 --- a/scripts/install-deps.sh +++ b/scripts/install-deps.sh @@ -72,12 +72,6 @@ case ${ID,,} in # NOTE(rpittau): epel repos are installed but the content is purged # in the CI images, we remove them and reinstall later sudo -E ${PKG_MANAGER} remove -y epel-release epel-next-release - - if [[ $NAME == 'CentOS Stream' ]] && [[ $VERSION == 9 ]]; then - export CONSTRAINTS_FILE="$BIFROST_HOME/upper-constraints-cs9-py39.txt" - export UPPER_CONSTRAINTS_FILE=$CONSTRAINTS_FILE - export TOX_CONSTRAINTS_FILE=$CONSTRAINTS_FILE - fi ;; *) echo "ERROR: Supported package manager not found. Supported: apt, dnf, yum, zypper"; exit 1;; diff --git a/setup.cfg b/setup.cfg index 5d8e81a0e..bf9ea7d49 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ description_file = author = OpenStack author_email = openstack-discuss@lists.openstack.org home_page = https://docs.openstack.org/bifrost/latest/ -python_requires = >=3.9 +python_requires = >=3.10 classifier = Environment :: OpenStack Intended Audience :: Information Technology @@ -17,7 +17,6 @@ classifier = Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 - Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 Programming Language :: Python :: 3.11 Programming Language :: Python :: 3.12 diff --git a/upper-constraints-cs9-py39.txt b/upper-constraints-cs9-py39.txt deleted file mode 100644 index e918bc473..000000000 --- a/upper-constraints-cs9-py39.txt +++ /dev/null @@ -1,599 +0,0 @@ -voluptuous===0.15.2 -chardet===5.2.0 -enum-compat===0.0.3 -rsa===4.9.1 -restructuredtext-lint===1.4.0 -netmiko===4.6.0 -sshtunnel===0.4.0 -PasteDeploy===3.1.0 -typing===3.7.4.3 -Routes===2.5.1 -rtslib-fb===2.2.3 -oslo.limit===2.7.0 -tzdata===2025.2 -smmap===5.0.2 -confget===5.1.2 -XStatic-Angular-Bootstrap===2.5.0.0 -WebOb===1.8.9 -sphinxcontrib-actdiag===3.0.0 -pecan===1.6.0 -os-api-ref===3.1.0 -python-ldap===3.4.4 -oslo.concurrency===7.1.0 -websocket-client===1.8.0 -osprofiler===4.3.0 -os-resource-classes===1.1.0 -mypy_extensions===1.1.0 -tabulate===0.9.0 -python-ironic-inspector-client===5.3.1 -lxml===6.0.0 -vintage===0.4.1 -rst2txt===1.1.0 -setproctitle===1.3.6 -pytest===8.4.1 -python-slugify===8.0.4 -cursive===0.2.3 -oslo.service===4.2.2 -django-appconf===1.1.0 -ntc_templates===7.9.0 -sphinxcontrib-nwdiag===2.0.0 -rbd-iscsi-client===0.1.8 -requests-aws===0.1.8 -alabaster===0.7.16;python_version=='3.9' -alabaster===1.0.0;python_version>='3.10' -pbr===6.1.1 -munch===4.0.0 -waiting===1.5.0 -attrs===25.3.0 -microversion-parse===2.0.0 -jwcrypto===1.5.6 -Pint===0.23;python_version=='3.9' -Pint===0.24.4;python_version>='3.10' -oslo.i18n===6.5.1 -jsonpath-rw-ext===1.2.2 -python-mistralclient===5.4.0 -oslo.context===6.0.0 -rcssmin===1.1.2 -pycadf===4.0.1 -grpcio===1.73.1 -sniffio===1.3.1 -fixtures===4.2.5 -neutron-lib===3.20.0 -XStatic-FileSaver===1.3.2.0 -jaraco.functools===4.2.1 -oslo.metrics===0.12.0 -storage-interfaces===1.0.5 -pydantic===1.10.22 -persist-queue===1.0.0 -pystache===0.6.8 -XStatic-Font-Awesome===4.7.0.0 -nose===1.3.7 -waitress===3.0.2 -os-refresh-config===14.0.0 -pysnmp===7.1.21 -Mako===1.3.10 -sphinxcontrib-htmlhelp===2.1.0 -XStatic-jQuery===3.5.1.1 -ddt===1.7.2 -XStatic-Graphlib===2.1.7.0 -pyserial===3.5 -moto===5.1.6 -infi.dtypes.wwn===0.1.1 -python-freezerclient===6.0.0 -python-vitrageclient===5.2.0 -py-pure-client===1.70.2 -krest===1.3.7 -psycopg2===2.9.10 -networkx===3.2.1;python_version=='3.9' -networkx===3.4.2;python_version>='3.10' -cheroot===10.0.1 -XStatic-Angular===1.8.2.2 -types-requests===2.31.0.6 -zuul-sphinx===0.7.0 -ply===3.11 -google-api-core===2.25.1 -requests-toolbelt===1.0.0 -simplejson===3.20.1 -types-paramiko===3.5.0.20250516 -python-swiftclient===4.8.0 -pyOpenSSL===24.2.1 -monasca-common===3.8.0 -hyperframe===6.1.0 -zeroconf===0.147.0 -scipy===1.13.1;python_version=='3.9' -scipy===1.15.3;python_version>='3.10' -opentelemetry-exporter-otlp===1.34.1 -python-gnupg===0.5.4 -rsd-lib===1.2.0 -XStatic-Jasmine===2.4.1.2 -googleapis-common-protos===1.70.0 -python-glanceclient===4.8.0;python_version=='3.9' -python-glanceclient===4.9.0;python_version>='3.10' -prometheus_client===0.22.1 -jaraco.classes===3.4.0 -debtcollector===3.0.0 -responses===0.25.7 -croniter===6.0.0 -horizon===25.4.0 -octavia-lib===3.9.0 -python-watcherclient===4.8.0 -MarkupSafe===3.0.2 -types-python-dateutil===2.9.0.20250516 -ruamel.yaml.clib===0.2.12 -doc8===1.1.2;python_version=='3.9' -doc8===2.0.0;python_version>='3.10' -pymongo===4.13.2 -python-cloudkittyclient===5.3.1 -soupsieve===2.7 -sqlparse===0.5.3 -oslotest===5.0.1 -jsonpointer===3.0.0 -defusedxml===0.7.1 -opentelemetry-sdk===1.34.1 -netaddr===1.3.0 -pyghmi===1.6.2 -sphinxcontrib-blockdiag===3.0.0 -aiosqlite===0.21.0 -thrift===0.22.0 -gnocchiclient===7.2.0 -wcwidth===0.2.13 -sphinxcontrib.datatemplates===0.11.0 -jsonpath-rw===1.4.0 -prettytable===3.16.0 -vine===5.1.0 -pathspec===0.12.1 -taskflow===6.0.1 -arrow===1.3.0 -semantic-version===2.10.0 -async-timeout===5.0.1;python_version=='3.10' -async-timeout===5.0.1;python_version=='3.9' -virtualbmc===3.2.0 -SQLAlchemy===2.0.41 -pyroute2===0.8.1 -google-auth===2.40.3 -kazoo===2.10.0 -pyspnego===0.11.2 -XStatic-roboto-fontface===0.5.0.0 -pyudev===0.24.3 -eventlet===0.40.1 -openstack-doc-tools===4.0.1 -oslo.messaging===17.0.0 -jira===3.8.0 -PyJWT===2.10.1 -typing_extensions===4.14.1 -XStatic-lodash===4.16.4.2 -zVMCloudConnector===1.6.3 -paramiko===3.5.1 -ifaddr===0.2.0 -reno===4.1.0 -ncclient===0.6.19 -imagesize===1.4.1 -pydot===4.0.1 -urllib3===1.26.20 -graphviz===0.21 -PyKMIP===0.10.0 -python-observabilityclient===1.0.0 -whereto===0.4.0 -pywbem===1.7.3 -python-subunit===1.4.4 -tornado===6.5.1 -pycparser===2.22 -mock===5.2.0 -PyYAML===6.0.2 -beautifulsoup4===4.13.4 -ovs===3.5.1 -cryptography===43.0.3 -httpcore===1.0.9 -URLObject===2.4.3 -psycopg2-binary===2.9.10 -glance_store===4.10.0;python_version=='3.9' -glance_store===5.0.0;python_version>='3.10' -openstack-release-test===8.1.0 -requests-mock===1.12.1 -os-apply-config===14.0.0 -gunicorn===23.0.0 -storpool===7.3.0 -textfsm===1.1.3 -python-3parclient===4.2.14 -django-compressor===4.5.1 -libvirt-python===11.5.0 -python-zunclient===5.2.1 -tzlocal===5.3.1 -sphinxcontrib-jsmath===1.0.1 -python-novaclient===18.10.0 -pact===1.12.0 -bcrypt===4.0.1 -exceptiongroup===1.3.0;python_version=='3.10' -exceptiongroup===1.3.0;python_version=='3.9' -os-client-config===2.1.0;python_version=='3.9' -os-client-config===2.3.0;python_version>='3.10' -XStatic-Angular-Gettext===2.4.1.0 -h11===0.16.0 -Pygments===2.19.2 -XStatic-Hogan===2.0.0.3 -XStatic-objectpath===1.2.1.0 -python-manilaclient===5.5.0 -sphinxcontrib-serializinghtml===2.0.0 -requests===2.32.4 -snowballstemmer===3.0.1 -Jinja2===3.1.6 -XStatic-Bootstrap-SCSS===3.4.1.0 -pyzabbix===1.3.1 -ptyprocess===0.7.0 -threadloop===1.0.2 -amqp===5.3.1 -ruamel.yaml===0.18.14 -websockify===0.13.0 -gssapi===1.9.0 -XStatic-JQuery.quicksearch===2.0.3.2 -pyasn1_modules===0.4.1 -mpmath===1.3.0 -python-binary-memcached===0.31.4 -jaraco.context===6.0.1 -django-debreach===2.1.0 -sphinx-feature-classification===2.0.0 -XStatic-JQuery-Migrate===3.3.2.1 -pytest-html===4.1.1 -appdirs===1.4.4 -google-auth-httplib2===0.2.0 -daiquiri===3.2.5.1;python_version=='3.9' -daiquiri===3.3.0;python_version>='3.10' -influxdb===5.3.2 -funcparserlib===2.0.0a0 -passlib===1.7.4 -cliff===4.9.1;python_version=='3.9' -cliff===4.10.0;python_version>='3.10' -os-brick===6.12.0 -scp===0.15.0 -python-zaqarclient===3.0.1;python_version=='3.9' -python-zaqarclient===4.0.0;python_version>='3.10' -ldappool===3.0.0 -hpack===4.1.0 -joblib===1.5.1 -google-api-python-client===2.175.0 -castellan===5.4.0 -oslo.versionedobjects===3.7.0 -enmerkar===0.7.1 -webcolors===24.11.1 -aodhclient===3.8.0;python_version=='3.9' -aodhclient===3.9.0;python_version>='3.10' -autobahn===24.4.2 -SQLAlchemy-Utils===0.41.2 -retryz===0.1.9 -pluggy===1.6.0 -coverage===7.9.2 -freezegun===1.5.2 -mdurl===0.1.2 -toml===0.10.2 -pycdlib===1.14.0 -pyperclip===1.9.0 -cassandra-driver===3.29.2 -XStatic-Angular-Schema-Form===0.8.13.0 -opentelemetry-exporter-otlp-proto-http===1.34.1 -gabbi===3.1.0 -nwdiag===3.0.0 -XStatic-bootswatch===3.3.7.0 -pytest-xdist===3.8.0 -XStatic-JS-Yaml===3.8.1.0 -XStatic-term.js===0.0.7.0 -oslo.log===7.2.0 -nodeenv===1.9.1 -gossip===2.4.0 -suds-community===1.2.0 -os_vif===4.2.0 -qrcode===8.2 -oslo.middleware===6.6.0 -XStatic-mdi===1.6.50.2 -uritemplate===4.2.0 -docutils===0.21.2 -threadpoolctl===3.6.0 -os-ken===3.1.0 -ujson===5.10.0 -selenium===3.141.0 -pytest-subtests===0.14.2 -mistral-lib===3.3.1;python_version=='3.9' -mistral-lib===3.4.0;python_version>='3.10' -dogtag-pki===11.2.1 -XStatic-Angular-UUID===0.0.4.0 -sphinxcontrib-seqdiag===3.0.0 -os-win===5.9.0 -capacity===1.3.14 -markdown-it-py===3.0.0 -retrying===1.4.0 -XStatic-Dagre===0.6.4.1 -platformdirs===4.3.8 -pydotplus===2.0.2 -boto3===1.39.3 -jeepney===0.9.0 -stestr===4.2.0 -pillow===11.3.0 -infoblox-client===0.6.1 -pysmi-lextudio===1.4.3 -oslo.serialization===5.7.0 -warlock===2.1.0 -exabgp===4.2.25 -aiomysql===0.2.0 -types-simplejson===3.20.0.20250326 -sphinxcontrib-httpdomain===1.8.1 -metalsmith===2.5.0 -s3transfer===0.13.0 -text-unidecode===1.3 -sphinxcontrib-svg2pdfconverter===1.3.0 -oslo.vmware===4.6.0 -XStatic-moment===2.8.4.3 -autopage===0.5.2 -gitdb===4.0.12 -python-monascaclient===2.8.0 -ldap3===2.9.1 -opentelemetry-api===1.34.1 -automaton===3.2.0 -types-urllib3===1.26.25.14 -os-service-types===1.7.0;python_version=='3.9' -os-service-types===1.8.0;python_version>='3.10' -keyring===25.6.0 -elementpath===4.8.0 -wsgi_intercept===1.13.1 -jsonschema-specifications===2025.4.1 -testscenarios===0.5.0 -sphinxcontrib-pecanwsme===0.11.0 -sadisplay===0.4.9 -infinisdk===258.0.2 -rich-argparse===1.7.1 -packaging===25.0 -opentelemetry-exporter-otlp-proto-grpc===1.34.1 -XStatic-Dagre-D3===0.4.17.0 -psutil===7.0.0 -txaio===23.6.1;python_version=='3.9' -txaio===25.6.1;python_version>='3.10' -elasticsearch===2.4.1 -django-nose===1.4.7 -asgiref===3.9.0 -XStatic-JQuery.TableSorter===2.14.5.2 -pifpaf===3.3.0 -blockdiag===3.0.0 -testtools===2.7.2 -infi.dtypes.iqn===0.4.0 -XStatic-tv4===1.2.7.0 -XStatic-JSEncrypt===2.3.1.1 -python-cinderclient===9.7.0 -keystonemiddleware===10.10.0;python_version=='3.9' -keystonemiddleware===10.11.0;python_version>='3.10' -django-formtools===2.5.1 -XStatic-Spin===1.2.5.3 -rich===14.0.0 -os-traits===3.5.0 -typepy===1.3.4 -SecretStorage===3.3.3 -opentracing===2.4.0 -XStatic-Rickshaw===1.5.1.0 -iso8601===2.1.0 -tooz===7.0.0 -idna===3.10 -yamlloader===1.5.1 -protobuf===5.29.5 -sushy===5.7.0 -python-neutronclient===11.6.0 -types-setuptools===80.9.0.20250529 -pika===1.3.2 -oslo.cache===3.11.0 -WebTest===3.0.6 -os-collect-config===14.0.0 -edgegrid-python===2.0.1 -python-octaviaclient===3.11.1 -pysaml2===7.5.2 -requests-oauthlib===2.0.0 -oslo.reports===3.5.1 -pysnmp-lextudio===5.0.33 -bitmath===1.3.3.1 -ceilometermiddleware===3.7.0;python_version=='3.9' -ceilometermiddleware===3.8.0;python_version>='3.10' -testrepository===0.0.21 -sympy===1.14.0 -Logbook===1.8.2 -PyNaCl===1.5.0 -osc-lib===4.0.2;python_version=='3.9' -osc-lib===4.1.0;python_version>='3.10' -python-consul===1.1.0 -more-itertools===10.7.0 -seqdiag===3.0.0 -numpy===2.0.0;python_version=='3.9' -numpy===2.2.6;python_version>='3.10' -msgpack===1.1.1 -Sphinx===7.4.7;python_version=='3.9' -Sphinx===8.1.3;python_version>='3.10' -oslo.config===10.0.0 -openstackdocstheme===3.5.0 -osc-placement===4.6.0 -rpds-py===0.26.0 -zake===0.2.2 -flux===1.3.5 -pysnmpcrypto===0.0.4 -flexparser===0.4 -krb5===0.7.1 -PyMySQL===1.1.1 -uhashring===2.4 -kubernetes===33.1.0 -httplib2===0.22.0 -betamax===0.9.0 -construct===2.10.70 -pytest-metadata===3.1.1 -pyparsing===3.2.3 -geomet===0.2.1.post1 -opentelemetry-exporter-otlp-proto-common===1.34.1 -distlib===0.3.9 -XStatic-Moment-Timezone===0.5.22.0 -dogpile.cache===1.4.0 -python-barbicanclient===7.1.0 -salt===3007.5 -opentelemetry-semantic-conventions===0.55b1 -api-object-schema===2.0.0 -blinker===1.9.0 -aenum===3.1.15 -WSME===0.12.1 -tomli===2.2.1;python_version=='3.10' -tomli===2.2.1;python_version=='3.9' -oslo.upgradecheck===2.5.0 -sherlock===0.4.1 -stevedore===5.4.1 -pywinrm===0.5.0 -botocore===1.39.3 -xmltodict===0.14.2 -pyasn1===0.6.0 -oslo.rootwrap===7.6.0 -Django===4.2.23 -pexpect===4.9.0 -cmd2===2.7.0 -python-json-logger===3.3.0 -redis===6.2.0 -jmespath===1.0.1 -click===8.1.8;python_version=='3.9' -click===8.2.1;python_version>='3.10' -XStatic-smart-table===1.4.13.2 -kuryr-lib===3.2.0 -scrypt===0.8.27 -jsonpatch===1.33 -libsass===0.23.0 -os-testr===3.0.0 -cotyledon===2.0.0 -xattr===1.1.4 -systemd-python===235 -python-memcached===1.62 -openstacksdk===4.5.0;python_version=='3.9' -openstacksdk===4.6.0;python_version>='3.10' -infi.dtypes.nqn===0.1.0 -six===1.17.0 -h2===4.2.0 -dulwich===0.23.1 -dfs-sdk===1.2.27 -sentinels===1.0.0 -kombu===5.5.4 -distro===1.9.0 -zstd===1.5.7.2 -yaql===3.1.0 -durationpy===0.10 -requestsexceptions===1.4.0 -testresources===2.0.2 -falcon===4.0.2 -tomlkit===0.13.3 -etcd3gw===2.4.2 -Flask-RESTful===0.3.10 -GitPython===3.1.44 -requests_ntlm===1.3.0 -python-ironicclient===5.12.0 -babel===2.17.0 -XStatic===1.0.3 -XStatic-Angular-FileUpload===12.2.13.0 -python-openstackclient===8.0.0;python_version=='3.9' -python-openstackclient===8.1.0;python_version>='3.10' -pyzmq===27.0.0 -oslo.db===17.3.0 -simplegeneric===0.8.1 -python-pcre===0.7 -yappi===1.6.10 -mbstrdecoder===1.1.4 -pymemcache===4.0.0 -wrapt===1.17.2 -oslo.privsep===3.7.0 -sphinxcontrib-apidoc===0.6.0 -oslo.policy===4.5.1 -hvac===2.3.0 -pyeclib===1.6.4 -repoze.lru===0.7 -rfc3986===2.0.0 -tenacity===9.1.2 -python-designateclient===6.3.0 -future===1.0.0 -pytest-cov===4.1.0 -reactivex===4.0.4 -Paste===3.10.1 -pytest-django===4.11.1 -jaeger-client===4.8.0 -XStatic-Json2yaml===0.1.1.0 -boto===2.49.0 -hyperlink===21.0.0 -mitba===1.1.1 -python-masakariclient===8.6.0 -Werkzeug===3.1.3 -APScheduler===3.11.0 -xmlschema===2.5.1 -python-troveclient===8.8.0 -cachez===0.1.2 -XStatic-Bootstrap-Datepicker===1.4.0.0 -netifaces===0.11.0 -cachetools===5.5.2 -flexcache===0.3 -sphinxcontrib-qthelp===2.0.0 -keystoneauth1===5.11.1 -statsd===4.0.1 -proto-plus===1.26.1 -python-keystoneclient===5.6.0 -diskimage-builder===3.39.0 -heat-translator===3.2.0 -python-magnumclient===4.8.1 -docker===7.1.0 -storops===1.2.11 -anyio===4.9.0 -XStatic-Angular-lrdragndrop===1.0.2.6 -ovsdbapp===2.12.0 -aniso8601===10.0.1 -rjsmin===1.2.2 -icalendar===6.3.1 -decorator===5.2.1 -DateTimeRange===2.3.1 -cffi===1.17.1 -python-cyborgclient===2.5.0 -futurist===3.1.1 -jsonschema===4.24.0 -sphinxcontrib-devhelp===2.0.0 -python-blazarclient===4.3.0;python_version=='3.9' -python-blazarclient===4.4.0;python_version>='3.10' -alembic===1.16.2 -execnet===2.1.1 -sphinxcontrib-programoutput===0.18 -storpool.spopenstack===3.2.0 -dnspython===2.7.0 -oauthlib===3.3.1 -zipp===3.23.0 -greenlet===3.2.3 -XStatic-Angular-Vis===4.16.0.0 -iniconfig===2.1.0 -referencing===0.36.2 -confluent-kafka===2.11.0 -backports.tarfile===1.2.0 -xvfbwrapper===0.2.13 -influxdb-client===1.49.0 -tosca-parser===2.13.0 -python-consul2===0.1.5 -charset-normalizer===3.4.2 -Flask===3.1.1 -httpx===0.28.1 -sqlalchemy-filters===0.13.0 -sphinxcontrib-runcmd===0.2.0 -confspirator===0.3.0 -fasteners===0.19 -importlib-metadata===6.2.1;python_version=='3.9' -importlib-metadata===8.7.0;python_version>='3.10' -sortedcontainers===2.4.0 -python-linstor===1.25.3 -filelock===3.18.0 -python-tackerclient===2.3.0 -python-heatclient===4.2.0;python_version=='3.9' -python-heatclient===4.3.0;python_version>='3.10' -oslo.utils===9.0.0 -requests-kerberos===0.15.0 -itsdangerous===2.2.0 -XStatic-jquery-ui===1.13.0.1 -monasca-statsd===2.7.0 -python-dateutil===2.9.0.post0 -virtualenv===20.31.2 -colorama===0.4.6 -confetti===2.5.3 -ironic-lib===7.0.0 -pytz===2025.2 -opentelemetry-proto===1.34.1 -XStatic-D3===3.5.17.0 -actdiag===3.0.0 -sysv-ipc===1.1.0 -sphinxcontrib-applehelp===2.0.0 -scikit-learn===1.6.1;python_version=='3.9' -scikit-learn===1.7.0;python_version>='3.10'