diff --git a/bifrost/cli.py b/bifrost/cli.py index 61df4fd4a..1e4b86e35 100644 --- a/bifrost/cli.py +++ b/bifrost/cli.py @@ -159,6 +159,7 @@ def cmd_install(args): use_cirros=args.testenv, use_tinyipa=args.testenv, developer_mode=args.develop, + enable_prometheus_exporter=args.enable_prometheus_exporter, extra_vars=args.extra_vars, **kwargs) log("Ironic is installed and running, try it yourself:\n", @@ -230,6 +231,9 @@ def parse_args(): action='store_true', default=False, help='enable full disk cleaning between ' 'deployments (can take a lot of time)') + install.add_argument('--enable-prometheus-exporter', action='store_true', + default=False, + help='Enable Ironic Prometheus Exporter') install.add_argument('-e', '--extra-vars', action='append', help='additional vars to pass to ansible') diff --git a/doc/source/install/index.rst b/doc/source/install/index.rst index c704f3cdd..51375ca5c 100644 --- a/doc/source/install/index.rst +++ b/doc/source/install/index.rst @@ -248,6 +248,9 @@ Additionally, the following parameters can be useful: Using Bifrost to install older versions of Ironic may work, but is not guaranteed. +``--enable-prometheus-exporter`` + Enable the Ironic Prometheus Exporter service. + See the built-in documentation for more details: .. code-block:: bash diff --git a/playbooks/ci/run.yaml b/playbooks/ci/run.yaml index 6daa32d47..100a14185 100644 --- a/playbooks/ci/run.yaml +++ b/playbooks/ci/run.yaml @@ -16,3 +16,4 @@ TEST_VM_NODE_DRIVER: "{{ test_driver | default('ipmi') }}" NOAUTH_MODE: "{{ noauth_mode | default(false) | bool | lower }}" ENABLE_TLS: "{{ enable_tls | default(false) | bool | lower }}" + ENABLE_PROMETHEUS_EXPORTER: "{{ enable_prometheus_exporter | default(false) | bool | lower }}" diff --git a/playbooks/roles/bifrost-ironic-install/defaults/main.yml b/playbooks/roles/bifrost-ironic-install/defaults/main.yml index 04d04d86c..7798e994d 100644 --- a/playbooks/roles/bifrost-ironic-install/defaults/main.yml +++ b/playbooks/roles/bifrost-ironic-install/defaults/main.yml @@ -19,6 +19,7 @@ ironicinspector_source_install: true ironicinspectorclient_source_install: false sushy_source_install: false staging_drivers_source_install: true +prometheus_exporter_source_install: true # Setting to utilize diskimage-builder to create a bootable image. create_image_via_dib: true dib_image_type: vm @@ -110,6 +111,7 @@ 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 mysql_username: "root" mysql_password: "" disable_dnsmasq_dns: True @@ -124,6 +126,7 @@ 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 +prometheus_exporter_git_folder: /opt/stack/ironic-prometheus-exporter enabled_hardware_types: "ipmi,redfish,manual-management,ilo" default_deploy_interface: "direct" @@ -351,3 +354,14 @@ 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 + +# Enable Ironic Prometheus Exporter +enable_prometheus_exporter: false +prometheus_exporter_host: "{{ internal_ip }}" +prometheus_exporter_port: 9608 +# directory to save the node metrics +prometheus_exporter_data_dir: /var/lib/ironic-prometheus-exporter/data +# interval to collect sensor data +sensor_data_interval: 90 +# sensor data should be collected from undeployed nodes +sensor_data_undeployed_nodes: false diff --git a/playbooks/roles/bifrost-ironic-install/tasks/install.yml b/playbooks/roles/bifrost-ironic-install/tasks/install.yml index 8069dfc2c..6105c7ee3 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/install.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/install.yml @@ -119,3 +119,7 @@ package: openstacksdk sourcedir: "{{ openstacksdk_git_folder }}" source_install: "{{ openstacksdk_source_install }}" + +- name: "Install Ironic Prometheus Exporter" + include_tasks: prometheus_exporter_install.yml + when: enable_prometheus_exporter | bool diff --git a/playbooks/roles/bifrost-ironic-install/tasks/prometheus_exporter_install.yml b/playbooks/roles/bifrost-ironic-install/tasks/prometheus_exporter_install.yml new file mode 100644 index 000000000..487f3087c --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/prometheus_exporter_install.yml @@ -0,0 +1,27 @@ +# 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: "Install gunicorn" + include_role: + name: bifrost-pip-install + vars: + package: gunicorn + +- name: "Ironic Prometheus Exporter - install" + include_role: + name: bifrost-pip-install + vars: + package: ironic-prometheus-exporter + sourcedir: "{{ prometheus_exporter_git_folder }}" + source_install: "{{ prometheus_exporter_source_install }}" + extra_args: "--no-cache-dir {{ pip_opts }}" diff --git a/playbooks/roles/bifrost-ironic-install/tasks/prometheus_exporter_start.yml b/playbooks/roles/bifrost-ironic-install/tasks/prometheus_exporter_start.yml new file mode 100644 index 000000000..d92eacf84 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/tasks/prometheus_exporter_start.yml @@ -0,0 +1,38 @@ +# 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 up IPE data dir" + file: + name: "{{ prometheus_exporter_data_dir }}" + owner: ironic + group: ironic + state: directory + mode: '0750' + +- name: "Ensure IPE Flask Application is configured on systemd" + template: + src: ironic-prometheus-exporter.service.j2 + dest: /etc/systemd/system/ironic-prometheus-exporter.service + owner: root + group: root + mode: 0644 + become: true + register: ironic_prometheus_exporter_service_file + +- name: "Ensure IPE Flask Application systemd service is started and enabled" + systemd: + name: ironic-prometheus-exporter + enabled: yes + state: started + daemon_reload: "{{ ironic_prometheus_exporter_service_file.changed }}" + become: true diff --git a/playbooks/roles/bifrost-ironic-install/tasks/start.yml b/playbooks/roles/bifrost-ironic-install/tasks/start.yml index 12a27338e..61942ff86 100644 --- a/playbooks/roles/bifrost-ironic-install/tasks/start.yml +++ b/playbooks/roles/bifrost-ironic-install/tasks/start.yml @@ -48,6 +48,10 @@ - xinetd - nginx +- name: "Start ironic-prometheus-exporter" + include: prometheus_exporter_start.yml + when: enable_prometheus_exporter | bool and not skip_start | bool + # Multiple dnsmasqs are likely running, so lets tell the service manager # to at least try stopping dnsmasq for us. - name: "Stop dnsmasq explicitly." diff --git a/playbooks/roles/bifrost-ironic-install/templates/ironic-prometheus-exporter.service.j2 b/playbooks/roles/bifrost-ironic-install/templates/ironic-prometheus-exporter.service.j2 new file mode 100644 index 000000000..b8917e430 --- /dev/null +++ b/playbooks/roles/bifrost-ironic-install/templates/ironic-prometheus-exporter.service.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=Ironic Prometheus Exporter Flask App + +[Service] +Type=simple +Restart=on-failure +ExecStart={{ bifrost_venv_dir }}/bin/gunicorn ironic_prometheus_exporter.app.wsgi:application \ + --bind {{ prometheus_exporter_host }}:{{ prometheus_exporter_port}} \ + --env IRONIC_CONFIG=/etc/ironic/ironic.conf \ + --workers 2 --threads 2 --access-logfile=- --error-logfile=- diff --git a/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 b/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 index 87abc48d1..6feb822c5 100644 --- a/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 +++ b/playbooks/roles/bifrost-ironic-install/templates/ironic.conf.j2 @@ -94,6 +94,11 @@ deploy_kernel = {{ ipa_kernel_url }} deploy_ramdisk = {{ ipa_ramdisk_url }} rescue_kernel = {{ ipa_kernel_url }} rescue_ramdisk = {{ ipa_ramdisk_url }} +{% if enable_prometheus_exporter | bool %} +send_sensor_data = true +send_sensor_data_for_undeployed_nodes = {{ sensor_data_undeployed_nodes }} +send_sensor_data_interval = {{ sensor_data_interval }} +{% endif %} [database] connection = mysql+pymysql://{{ ironic.database.username }}:{{ ironic.database.password }}@{{ ironic.database.host }}/{{ ironic.database.name }}?charset=utf8 @@ -196,3 +201,10 @@ http_basic_auth_user_file = /etc/ironic/htpasswd username = {{ admin_username }} password = {{ admin_password }} {% endif %} + +{% if enable_prometheus_exporter | bool %} +[oslo_messaging_notifications] +driver = prometheus_exporter +transport_url = fake:// +location = {{ prometheus_exporter_data_dir }} +{% endif %} diff --git a/playbooks/roles/bifrost-prep-for-install/defaults/main.yml b/playbooks/roles/bifrost-prep-for-install/defaults/main.yml index 839243344..0162a6bc3 100644 --- a/playbooks/roles/bifrost-prep-for-install/defaults/main.yml +++ b/playbooks/roles/bifrost-prep-for-install/defaults/main.yml @@ -15,6 +15,7 @@ keystone_git_url: "{{ git_url_root }}/openstack/keystone" sushy_git_url: "{{ git_url_root }}/openstack/sushy" ipa_git_url: "{{ git_url_root }}/openstack/ironic-python-agent" ipa_builder_git_url: "{{ git_url_root }}/openstack/ironic-python-agent-builder" +prometheus_exporter_git_url: "{{ git_url_root }}/openstack/ironic-prometheus-exporter" # *_git_folder can be overridden by local clones for offline installs ironicclient_git_folder: "{{ git_root}}/python-ironicclient" ironic_git_folder: "{{ git_root}}/ironic" @@ -28,6 +29,7 @@ keystone_git_folder: "{{ git_root}}/keystone" sushy_git_folder: "{{ git_root}}/sushy" ipa_git_folder: "{{ git_root}}/ironic-python-agent" ipa_builder_git_folder: "{{ git_root}}/ironic-python-agent-builder" +prometheus_exporter_git_folder: "{{ git_root}}/ironic-prometheus-exporter" # *git_branch can be overridden for stable branch testing git_branch: master ironicclient_git_branch: "{{ git_branch }}" @@ -42,6 +44,7 @@ keystone_git_branch: "{{ git_branch }}" sushy_git_branch: "{{ git_branch }}" ipa_git_branch: "{{ git_branch }}" ipa_builder_git_branch: master +prometheus_exporter_git_branch: "{{ git_branch }}" # disable source install to prevent cloning ironicclient_source_install: false openstacksdk_source_install: false @@ -49,7 +52,9 @@ ironicinspector_source_install: true ironicinspectorclient_source_install: false sushy_source_install: false staging_drivers_source_install: true +prometheus_exporter_source_install: true enable_keystone: false +enable_prometheus_exporter: false update_repos: true force_update_repos: true @@ -114,6 +119,11 @@ bifrost_install_sources: git_url: "{{ ipa_builder_git_url }}" git_branch: "{{ ipa_builder_git_branch }}" name: ironic-python-agent-builder + - git_folder: "{{ prometheus_exporter_git_folder }}" + git_url: "{{ prometheus_exporter_git_url }}" + git_branch: "{{ prometheus_exporter_git_branch }}" + name: ironic-prometheus-exporter + source_install: "{{ enable_prometheus_exporter }}" # 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/releasenotes/notes/add-ipe-1f57e04d2881215f.yaml b/releasenotes/notes/add-ipe-1f57e04d2881215f.yaml new file mode 100644 index 000000000..7d7597196 --- /dev/null +++ b/releasenotes/notes/add-ipe-1f57e04d2881215f.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Adds support to install the Ironic Prometheus Exporter. It can be done + through the ``bifrost-cli`` using ``--enable-prometheus-exporter`` option, + or when setting `enable_prometheus_expoter=True` when deploying. diff --git a/scripts/test-bifrost.sh b/scripts/test-bifrost.sh index a3540f745..91850f9e9 100755 --- a/scripts/test-bifrost.sh +++ b/scripts/test-bifrost.sh @@ -14,6 +14,7 @@ ZUUL_BRANCH=${ZUUL_BRANCH:-} CLI_TEST=${CLI_TEST:-false} BOOT_MODE=${BOOT_MODE:-} ENABLE_TLS=${ENABLE_TLS:-false} +ENABLE_PROMETHEUS_EXPORTER=${ENABLE_PROMETHEUS_EXPORTER:-false} # Set defaults for ansible command-line options to drive the different # tests. @@ -180,6 +181,7 @@ ${ANSIBLE} -vvvv \ -e wait_for_node_deploy=${WAIT_FOR_DEPLOY} \ -e not_enrolled_data_file=${BAREMETAL_DATA_FILE}.rest \ -e enable_tls=${ENABLE_TLS} \ + -e enable_prometheus_exporter=${ENABLE_PROMETHEUS_EXPORTER} \ -e generate_tls=${ENABLE_TLS} \ -e skip_install=${CLI_TEST} \ -e skip_package_install=${CLI_TEST} \ diff --git a/zuul.d/bifrost-jobs.yaml b/zuul.d/bifrost-jobs.yaml index b7316234b..6cb7c6afa 100644 --- a/zuul.d/bifrost-jobs.yaml +++ b/zuul.d/bifrost-jobs.yaml @@ -82,10 +82,12 @@ nodeset: ubuntu-bionic required-projects: - openstack/keystone + - openstack/ironic-prometheus-exporter vars: enable_keystone: true enable_tls: true test_driver: redfish + enable_prometheus_exporter: true - job: name: bifrost-integration-tinyipa-ubuntu-focal @@ -120,10 +122,12 @@ nodeset: centos-8 required-projects: - openstack/keystone + - openstack/ironic-prometheus-exporter vars: enable_keystone: true enable_tls: true test_driver: redfish + enable_prometheus_exporter: true - job: name: bifrost-integration-tinyipa-debian-buster