:_mod-docs-content-type: PROCEDURE
[id="deploying-the-bare-metal-provisioning-service_{context}"]

= Deploying the {bare_metal}

[role="_abstract"]
To deploy the {bare_metal_first_ref}, you patch an existing `OpenStackControlPlane` custom resource (CR) that has the {bare_metal} disabled. The `ironic-operator` applies the configuration and starts the Bare Metal Provisioning services. After the services are running, the {bare_metal} automatically begins polling the power state of the bare-metal nodes that it manages.

[NOTE]
By default, {rhos_acro} versions {rhos_curr_ver} and later of the {bare_metal} include a new multi-tenant aware role-based access control (RBAC) model. As a result, bare-metal nodes might be missing when you run the `openstack baremetal node list` command after you adopt the {bare_metal}. Your nodes are not deleted. Due to the increased access restrictions in the RBAC model, you must identify which project owns the missing bare-metal nodes and set the `owner` field on each missing bare-metal node.

.Prerequisites

* You have imported the service databases into the control plane database.
* The {bare_metal} is disabled in the {rhos_acro} {rhos_curr_ver}. The following command should return a string of `false`:
+
----
$ oc get openstackcontrolplanes.core.openstack.org <name> -o jsonpath='{.spec.ironic.enabled}'
----
+
** Replace `<name>` with the name of your existing `OpenStackControlPlane` CR, for example, `openstack-control-plane`.
* The {identity_service_first_ref}, {networking_first_ref}, and {image_service_first_ref} are operational.
* The {networking_service} is configured with the ML2 baremetal mechanism driver. For more information, see xref:adopting-the-networking-service_adopt-control-plane[Adopting the {networking_service}].
+
[NOTE]
If you use the {bare_metal} in a Bare Metal as a Service configuration, do not adopt the {compute_service_first_ref} before you adopt the {bare_metal}.
* For the {bare_metal} conductor services, the services must be able to reach Baseboard Management Controllers of hardware that is configured to be managed by the {bare_metal}. If this hardware is unreachable, the nodes might enter "maintenance" state and be unavailable until connectivity is restored later.
* You have downloaded the `ironic.conf` file locally:
+
----
$CONTROLLER1_SSH cat /var/lib/config-data/puppet-generated/ironic/etc/ironic/ironic.conf > ironic.conf
----
+
[NOTE]
This configuration file must come from one of the Controller nodes and not a {OpenStackPreviousInstaller} undercloud node. The {OpenStackPreviousInstaller} undercloud node operates with different configuration that does not apply when you adopt the Overcloud Ironic deployment.
* If you are adopting the Ironic Inspector service, you need the value of the `IronicInspectorSubnets` {OpenStackPreviousInstaller} parameter. Use the same values to populate the `dhcpRanges` parameter in the {rhos_acro} environment.
* You have defined the following shell variables. Replace the following example values with values that apply to your environment:
+
----
$ alias openstack="oc exec -t openstackclient -- openstack"
----

.Procedure

. Patch the `OpenStackControlPlane` custom resource (CR) to deploy the {bare_metal}:
+
----
$ oc patch openstackcontrolplane openstack --type=merge --patch '
spec:
  ironic:
    enabled: true
    template:
      rpcTransport: oslo
      databaseInstance: openstack
      ironicAPI:
        replicas: 1
        override:
          service:
            internal:
              metadata:
                annotations:
                  metallb.universe.tf/address-pool: internalapi
                  metallb.universe.tf/allow-shared-ip: internalapi
                  metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>
              spec:
                type: LoadBalancer
      ironicConductors:
      - replicas: 1
        networkAttachments:
          - baremetal
        provisionNetwork: baremetal
        storageRequest: 10G
        customServiceConfig: |
          [neutron]
          cleaning_network=<cleaning network uuid>
          provisioning_network=<provisioning network uuid>
          rescuing_network=<rescuing network uuid>
          inspection_network=<introspection network uuid>
          [conductor]
          automated_clean=true
      ironicInspector:
        replicas: 1
        inspectionNetwork: baremetal
        networkAttachments:
          - baremetal
        dhcpRanges:
          - name: inspector-0
            cidr: 172.20.1.0/24
            start: 172.20.1.190
            end: 172.20.1.199
            gateway: 172.20.1.1
        serviceUser: ironic-inspector
        databaseAccount: ironic-inspector
        passwordSelectors:
          database: IronicInspectorDatabasePassword
          service: IronicInspectorPassword
      ironicNeutronAgent:
        replicas: 1
        messagingBus:
          cluster: rabbitmq
      secret: osp-secret
'
----
+
where:

`<loadBalancer_IP>`::
Specifies the load balancer IP in your environment. If you use IPv6, change the load balancer IP to the load balancer IP in your environment, for example, `metallb.universe.tf/loadBalancerIPs: fd00:bbbb::80`.

`messagingBus.Cluster`::
For more information about RHOSO RabbitMQ clusters, see link:https://docs.redhat.com/en/documentation/red_hat_openstack_services_on_openshift/18.0/html/monitoring_high_availability_services/ref_rhoso-rabbitmq-clusters_ha-monitoring#con_understand-the-rabbitmq-interface-for-openstack-services[RHOSO RabbitMQ clusters] in _Monitoring high availability services_.

. Wait for the {bare_metal} control plane services CRs to become ready:
+
----
$ oc wait --for condition=Ready --timeout=300s ironics.ironic.openstack.org ironic
----

. Verify that the individual services are ready:
+
----
$ oc wait --for condition=Ready --timeout=300s ironicapis.ironic.openstack.org ironic-api
$ oc wait --for condition=Ready --timeout=300s ironicconductors.ironic.openstack.org ironic-conductor
$ oc wait --for condition=Ready --timeout=300s ironicinspectors.ironic.openstack.org ironic-inspector
$ oc wait --for condition=Ready --timeout=300s ironicneutronagents.ironic.openstack.org ironic-ironic-neutron-agent
----

. Update the DNS Nameservers on the provisioning, cleaning, and rescue networks:
+
[NOTE]
For name resolution to work for {bare_metal} operations, you must set the DNS nameserver to use the internal DNS servers in the {rhos_acro} control plane:
+
----
$ openstack subnet set --dns-nameserver 192.168.122.80 provisioning-subnet
----

. Verify that no {bare_metal} nodes are missing from the node list:
+
----
$ openstack baremetal node list
----
+
[IMPORTANT]
If the `openstack baremetal node list` command output reports an incorrect power status, wait a few minutes and re-run the command to see if the output syncs with the actual state of the hardware being managed. The time required for the {bare_metal} to review and reconcile the power state of bare-metal nodes depends on the number of operating conductors through the `replicas` parameter and which are present in the {bare_metal} deployment being adopted.

. If any {bare_metal} nodes are missing from the `openstack baremetal node list` command, temporarily disable the new RBAC policy to see the nodes again:
+
----
$ oc patch openstackcontrolplane openstack --type=merge --patch '
spec:
  ironic:
    enabled: true
    template:
      databaseInstance: openstack
      ironicAPI:
        replicas: 1
        customServiceConfig: |
          [oslo_policy]
          enforce_scope=false
          enforce_new_defaults=false
'
----
+
After this configuration is applied, the operator restarts the Ironic API service and disables the new RBAC policy that is enabled by default.

. View the bare-metal nodes that do not have an owner assigned:
+
----
$ openstack baremetal node list --long -c UUID -c Owner -c 'Provisioning State'
----

. Assign all bare-metal nodes with no owner to a new project, for example, the admin project:
+
----
ADMIN_PROJECT_ID=$(openstack project show -c id -f value --domain default admin)
for node in $(openstack baremetal node list -f json -c UUID -c Owner | jq -r '.[] | select(.Owner == null) | .UUID'); do openstack baremetal node set --owner $ADMIN_PROJECT_ID $node; done
----

. Re-apply the default RBAC by removing the `customServiceConfig` section or by setting the following values in the `customServiceConfig` section to `true`. For example:
+
----
$ oc patch openstackcontrolplane openstack --type=merge --patch '
spec:
  ironic:
    enabled: true
    template:
      databaseInstance: openstack
      ironicAPI:
        replicas: 1
        customServiceConfig: |
          [oslo_policy]
          enforce_scope=true
          enforce_new_defaults=true
'
----

.Verification

. Verify the list of endpoints:
+
----
$ openstack endpoint list |grep ironic
----

. Verify the list of bare-metal nodes:
+
----
$ openstack baremetal node list
----

. Reset the deploy images on all bare-metal nodes to use the new centrally configured images:
+
[NOTE]
After adoption, bare-metal nodes might still reference the old deployment's kernel and ramdisk
images in their `driver_info` fields. Resetting these values causes the {bare_metal} to use the
new centrally configured  `deploy_kernel` and `deploy_ramdisk` values from the `ironic.conf` file.
+
----
for node in $(openstack baremetal node list -c UUID -f value); do
  openstack baremetal node set $node \
    --driver-info deploy_ramdisk= \
    --driver-info deploy_kernel=
done
----
