From 617eed474182c20d89a370ea576f6db056cba41f Mon Sep 17 00:00:00 2001 From: Jake Hutchinson Date: Wed, 21 Feb 2024 14:19:00 +0000 Subject: [PATCH] Register baremetal compute nodes in Ironic This patch adds experimental functionallity to enroll baremetal nodes into Ironic using Kayobe via a new playbook 'baremetal-compute-register.yml' and adds 'kayobe baremetal compute register' into the Kayobe CLI. Depends-On: I719fc8042742fe8b3b0312658aec39317a1bc358 Change-Id: I988b082b539acfc2710d42e89bcac5b7a1eb526a --- ansible/baremetal-compute-register.yml | 78 +++++++++++++++++++ doc/source/administration/bare-metal.rst | 56 +++++++++++++ kayobe/cli/commands.py | 8 ++ kayobe/tests/unit/cli/test_commands.py | 19 +++++ .../baremetal-enroll-e01693210f95675c.yaml | 6 ++ setup.cfg | 3 + 6 files changed, 170 insertions(+) create mode 100644 ansible/baremetal-compute-register.yml create mode 100644 releasenotes/notes/baremetal-enroll-e01693210f95675c.yaml diff --git a/ansible/baremetal-compute-register.yml b/ansible/baremetal-compute-register.yml new file mode 100644 index 000000000..f233e09ba --- /dev/null +++ b/ansible/baremetal-compute-register.yml @@ -0,0 +1,78 @@ +--- + +- name: Register baremetal compute nodes + hosts: controllers[0] + vars: + venv: "{{ virtualenv_path }}/openstack-cli" + tasks: + - name: Set up openstack cli virtualenv + pip: + virtualenv: "{{ venv }}" + name: + - python-openstackclient + - python-ironicclient + state: latest + virtualenv_command: "python3.{{ ansible_facts.python.version.minor }} -m venv" + extra_args: "{% if pip_upper_constraints_file %}-c {{ pip_upper_constraints_file }}{% endif %}" + +- name: Ensure baremetal compute nodes are registered in ironic + hosts: baremetal-compute + gather_facts: false + tags: + - baremetal + vars: + venv: "{{ virtualenv_path }}/openstack-cli" + controller_host: "{{ groups['controllers'][0] }}" + tasks: + - name: Check Ironic variables are defined + ansible.builtin.assert: + that: + - ironic_driver is defined + - ironic_driver_info is defined + - ironic_properties is defined + - ironic_resource_class is defined + fail_msg: One or more Ironic variables are undefined. + + - block: + - name: Show baremetal node + ansible.builtin.command: + cmd: "{{ venv }}/bin/openstack baremetal node show {{ inventory_hostname }}" + register: node_show + failed_when: + - '"HTTP 404" not in node_show.stderr' + - node_show.rc != 0 + changed_when: false + + # NOTE: The openstack.cloud.baremetal_node module cannot be used in this + # script due to requiring a MAC address pre-defined, instead, this should + # be discovered by inpsection following this script. + # + # NOTE: IPMI address must be passed with Redfish address to ensure existing + # Ironic nodes match with new nodes during inspection. + - name: Create baremetal nodes + ansible.builtin.shell: + cmd: | + {{ venv }}/bin/openstack baremetal node create \ + --name {{ inventory_hostname }} \ + --driver {{ ironic_driver }} \ + {% for key, value in ironic_driver_info.items() %} + --driver-info {{ key }}={{ value }} \ + {% endfor %} + {% for key, value in ironic_properties.items() %} + --property {{ key }}={{ value }} \ + {% endfor %} + --resource-class {{ ironic_resource_class }} + when: + - node_show.rc != 0 + + - name: Manage baremetal nodes + ansible.builtin.command: + cmd: "{{ venv }}/bin/openstack baremetal node manage {{ inventory_hostname }} --wait" + when: + - node_show.rc != 0 + delegate_to: "{{ controller_host }}" + vars: + # NOTE: Without this, the controller's ansible_host variable will not + # be respected when using delegate_to. + ansible_host: "{{ hostvars[controller_host].ansible_host | default(controller_host) }}" + environment: "{{ openstack_auth_env }}" diff --git a/doc/source/administration/bare-metal.rst b/doc/source/administration/bare-metal.rst index fe8490064..40cf52e3c 100644 --- a/doc/source/administration/bare-metal.rst +++ b/doc/source/administration/bare-metal.rst @@ -13,6 +13,62 @@ By default these commands wait for the state transition to complete for each node. This behavior can be changed by overriding the variable ``baremetal_compute_wait`` via ``-e baremetal_compute_wait=False`` +Register +-------- + +This is an experimental workflow and acts as an alternative to enrolling nodes +through inspection where nodes can be registered in Ironic via kayobe given these +nodes are defined in the Kayobe inventory, an example hosts file for group r1 is below: + +.. code-block:: ini + + [r1] + hv100 ipmi_address=1.2.3.4 + ... + + [baremetal-compute:children] + r1 + +You should also define a group_vars file for this group containing the Ironic +vars, this could be in ``etc/kayobe/inventory/group_vars/r1/ironic_vars`` or +in the environment you are using. + +.. code-block:: yaml + + ironic_driver: redfish + + ironic_driver_info: + redfish_system_id: "{{ ironic_redfish_system_id }}" + redfish_address: "{{ ironic_redfish_address }}" + redfish_username: "{{ ironic_redfish_username }}" + redfish_password: "{{ ironic_redfish_password }}" + redfish_verify_ca: "{{ ironic_redfish_verify_ca }}" + ipmi_address: "{{ ipmi_address }}" + + ironic_properties: + capabilities: "{{ ironic_capabilities }}" + + ironic_resource_class: "example_resouce_class" + ironic_redfish_system_id: "/redfish/v1/Systems/System.Embedded.1" + ironic_redfish_verify_ca: "{{ inspector_rule_var_redfish_verify_ca }}" + ironic_redfish_address: "{{ ipmi_address }}" + ironic_redfish_username: "{{ inspector_redfish_username }}" + ironic_redfish_password: "{{ inspector_redfish_password }}" + ironic_capabilities: "boot_option:local,boot_mode:uefi" + +It's essential that the Ironic username and password match the BMC username +and password for your nodes, if the username and password combination is +not the same for the entire group you will need to adjust your configuration +accordingly. The IPMI address should also match the BMC address for your node. + +Once this has been completed you can begin enrolling the Ironic nodes:: + + (kayobe) $ kayobe baremetal compute register + +Inspector is not used to discover nodes and no node inspection will take place on +enrollment, nodes will automatically be placed into ``manageable`` state. To inspect, +you should use ``kayobe baremetal compute inspect`` following enrollment. + Manage ------ diff --git a/kayobe/cli/commands.py b/kayobe/cli/commands.py index 24c412722..7b059b9b5 100644 --- a/kayobe/cli/commands.py +++ b/kayobe/cli/commands.py @@ -1858,6 +1858,14 @@ class NetworkConnectivityCheck(KayobeAnsibleMixin, VaultMixin, Command): playbooks = _build_playbook_list("network-connectivity") self.run_kayobe_playbooks(parsed_args, playbooks) +class BaremetalComputeRegister(KayobeAnsibleMixin, VaultMixin, Command): + """Register baremetal compute nodes in Ironic.""" + + def take_action(self, parsed_args): + self.app.LOG.debug("Register baremetal compute nodes in Ironic.") + playbooks = _build_playbook_list("baremetal-compute-register") + self.run_kayobe_playbooks(parsed_args, playbooks) + class BaremetalComputeInspect(KayobeAnsibleMixin, VaultMixin, Command): """Perform hardware inspection on baremetal compute nodes.""" diff --git a/kayobe/tests/unit/cli/test_commands.py b/kayobe/tests/unit/cli/test_commands.py index d21227f11..83739c678 100644 --- a/kayobe/tests/unit/cli/test_commands.py +++ b/kayobe/tests/unit/cli/test_commands.py @@ -2169,6 +2169,25 @@ class TestCase(unittest.TestCase): ] self.assertListEqual(expected_calls, mock_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, + "run_kayobe_playbooks") + def test_baremetal_compute_register(self, mock_run): + command = commands.BaremetalComputeRegister(TestApp(), []) + parser = command.get_parser("test") + parsed_args = parser.parse_args([]) + result = command.run(parsed_args) + self.assertEqual(0, result) + expected_calls = [ + mock.call( + mock.ANY, + [ + utils.get_data_files_path( + "ansible", "baremetal-compute-register.yml"), + ], + ), + ] + self.assertListEqual(expected_calls, mock_run.call_args_list) + @mock.patch.object(commands.KayobeAnsibleMixin, "run_kayobe_playbooks") def test_baremetal_compute_inspect(self, mock_run): diff --git a/releasenotes/notes/baremetal-enroll-e01693210f95675c.yaml b/releasenotes/notes/baremetal-enroll-e01693210f95675c.yaml new file mode 100644 index 000000000..88a304146 --- /dev/null +++ b/releasenotes/notes/baremetal-enroll-e01693210f95675c.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + This patch adds experimental functionallity to enroll baremetal nodes + into Ironic using Kayobe via a new playbook 'baremetal-compute-register.yml' + and adds 'kayobe baremetal compute register' into the Kayobe CLI. diff --git a/setup.cfg b/setup.cfg index e1a3ca85a..ce9dcb69e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -39,6 +39,7 @@ console_scripts= kayobe-vault-password-helper = kayobe.cmd.kayobe_vault_password_helper:main kayobe.cli= + baremetal_compute_register = kayobe.cli.commands:BaremetalComputeRegister baremetal_compute_inspect = kayobe.cli.commands:BaremetalComputeInspect baremetal_compute_introspection_data_save = kayobe.cli.commands:BaremetalComputeIntrospectionDataSave baremetal_compute_manage = kayobe.cli.commands:BaremetalComputeManage @@ -106,6 +107,8 @@ kayobe.cli= infra_vm_host_package_update = kayobe.cli.commands:InfraVMHostPackageUpdate infra_vm_service_deploy = kayobe.cli.commands:InfraVMServiceDeploy +kayobe.cli.baremetal_compute_register = + hooks = kayobe.cli.commands:HookDispatcher kayobe.cli.baremetal_compute_inspect = hooks = kayobe.cli.commands:HookDispatcher kayobe.cli.baremetal_compute_introspection_data_save =