:_mod-docs-content-type: PROCEDURE
[id="deploying-backend-services_{context}"]

= Deploying back-end services

[role="_abstract"]
Create the `OpenStackControlPlane` custom resource (CR) with the basic back-end services deployed, and disable all the {rhos_prev_long} ({OpenStackShort}) services. This CR is the foundation of the control plane.

.Prerequisites

* The cloud that you want to adopt is running, and it is on the latest minor version of {OpenStackShort} {rhos_prev_ver}.
* All control plane and data plane hosts of the source cloud are running, and continue to run throughout the adoption procedure.
* The `openstack-operator` is deployed, but `OpenStackControlPlane` is
not deployed.
ifeval::["{build}" != "downstream"]
+
For developer/CI environments, the {OpenStackShort} operator can be deployed
by running `make openstack` inside
https://github.com/openstack-k8s-operators/install_yamls[install_yamls]
repo.
+
For production environments, the deployment method will likely be
different.
endif::[]
ifeval::["{build}" == "downstream"]
* Install the OpenStack Operators. For more information, see link:https://docs.redhat.com/en/documentation/red_hat_openstack_services_on_openshift/{rhos_curr_ver}/html-single/deploying_red_hat_openstack_services_on_openshift/index#assembly_installing-and-preparing-the-Operators[Installing and preparing the Operators] in _Deploying Red Hat OpenStack Services on OpenShift_.
endif::[]

* If you enabled TLS everywhere (TLS-e) on the {OpenStackShort} environment, you must copy the `tls` root CA from the {OpenStackShort} environment to the `rootca-internal` issuer.

* There are free PVs available for Galera and RabbitMQ.
ifeval::["{build}" != "downstream"]
+
For developer/CI environments driven by install_yamls, make sure
you've run `make crc_storage`.
endif::[]
* Set the desired admin password for the control plane deployment. This can
be the admin password from your original deployment or a different password:
+
----
ADMIN_PASSWORD=SomePassword
----
+
To use the existing {OpenStackShort} deployment password:
+
----
declare -A TRIPLEO_PASSWORDS
TRIPLEO_PASSWORDS[default]="$HOME/overcloud-passwords.yaml"
ADMIN_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' AdminPassword:' | awk -F ': ' '{ print $2; }')
----
* Set the service password variables to match the original deployment.
Database passwords can differ in the control plane environment, but
you must synchronize the service account passwords.
+
For example, in developer environments with {OpenStackPreviousInstaller} Standalone, the passwords can be extracted:
+
----
AODH_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' AodhPassword:' | awk -F ': ' '{ print $2; }')
BARBICAN_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' BarbicanPassword:' | awk -F ': ' '{ print $2; }')
CEILOMETER_METERING_SECRET=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' CeilometerMeteringSecret:' | awk -F ': ' '{ print $2; }')
CEILOMETER_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' CeilometerPassword:' | awk -F ': ' '{ print $2; }')
CINDER_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' CinderPassword:' | awk -F ': ' '{ print $2; }')
GLANCE_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' GlancePassword:' | awk -F ': ' '{ print $2; }')
HEAT_AUTH_ENCRYPTION_KEY=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' HeatAuthEncryptionKey:' | awk -F ': ' '{ print $2; }')
HEAT_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' HeatPassword:' | awk -F ': ' '{ print $2; }')
HEAT_STACK_DOMAIN_ADMIN_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' HeatStackDomainAdminPassword:' | awk -F ': ' '{ print $2; }')
IRONIC_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' IronicPassword:' | awk -F ': ' '{ print $2; }')
MANILA_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' ManilaPassword:' | awk -F ': ' '{ print $2; }')
NEUTRON_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' NeutronPassword:' | awk -F ': ' '{ print $2; }')
NOVA_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' NovaPassword:' | awk -F ': ' '{ print $2; }')
OCTAVIA_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' OctaviaPassword:' | awk -F ': ' '{ print $2; }')
PLACEMENT_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' PlacementPassword:' | awk -F ': ' '{ print $2; }')
SWIFT_PASSWORD=$(cat ${TRIPLEO_PASSWORDS[default]} | grep ' SwiftPassword:' | awk -F ': ' '{ print $2; }')
----

.Procedure

. Ensure that you are using the {rhocp_long} namespace where you want the
control plane to be deployed:
+
----
$ oc project openstack
----

ifeval::["{build}" != "downstream"]
. Create the {OpenStackShort} secret.
+
The procedure for this will vary, but in developer/CI environments
you use `install_yamls`:
+
[source,yaml]
----
# in install_yamls
make input
----
endif::[]

ifeval::["{build}" == "downstream"]
. Create the {OpenStackShort} secret. For more information, see link:https://docs.redhat.com/en/documentation/red_hat_openstack_services_on_openshift/{rhos_curr_ver}/html-single/deploying_red_hat_openstack_services_on_openshift/index#proc_providing-secure-access-to-the-RHOSO-services_preparing[Providing secure access to the Red Hat OpenStack Services on OpenShift services] in _Deploying Red Hat OpenStack Services on OpenShift_.
endif::[]

. If the `$ADMIN_PASSWORD` is different than the password you set
in `osp-secret`, amend the `AdminPassword` key in the `osp-secret`:
+
----
$ oc set data secret/osp-secret "AdminPassword=$ADMIN_PASSWORD"
----

. Set service account passwords in `osp-secret` to match the service
account passwords from the original deployment:
+
----
$ oc set data secret/osp-secret "AodhPassword=$AODH_PASSWORD"
$ oc set data secret/osp-secret "BarbicanPassword=$BARBICAN_PASSWORD"
$ oc set data secret/osp-secret "CeilometerPassword=$CEILOMETER_PASSWORD"
$ oc set data secret/osp-secret "CinderPassword=$CINDER_PASSWORD"
$ oc set data secret/osp-secret "GlancePassword=$GLANCE_PASSWORD"
$ oc set data secret/osp-secret "HeatAuthEncryptionKey=$HEAT_AUTH_ENCRYPTION_KEY"
$ oc set data secret/osp-secret "HeatPassword=$HEAT_PASSWORD"
$ oc set data secret/osp-secret "HeatStackDomainAdminPassword=$HEAT_STACK_DOMAIN_ADMIN_PASSWORD"
$ oc set data secret/osp-secret "IronicPassword=$IRONIC_PASSWORD"
$ oc set data secret/osp-secret "IronicInspectorPassword=$IRONIC_PASSWORD"
$ oc set data secret/osp-secret "ManilaPassword=$MANILA_PASSWORD"
$ oc set data secret/osp-secret "MetadataSecret=$METADATA_SECRET"
$ oc set data secret/osp-secret "NeutronPassword=$NEUTRON_PASSWORD"
$ oc set data secret/osp-secret "NovaPassword=$NOVA_PASSWORD"
$ oc set data secret/osp-secret "OctaviaPassword=$OCTAVIA_PASSWORD"
$ oc set data secret/osp-secret "PlacementPassword=$PLACEMENT_PASSWORD"
$ oc set data secret/osp-secret "SwiftPassword=$SWIFT_PASSWORD"
----

ifeval::["{build_variant}" != "ospdo"]
. Deploy the `OpenStackControlPlane` CR. Ensure that you only enable the DNS, Galera, Memcached, and RabbitMQ services. All other services must
be disabled:
+
[source,shell]
----
$ oc apply -f - <<EOF
apiVersion: core.openstack.org/v1beta1
kind: OpenStackControlPlane
metadata:
  name: openstack
spec:
  secret: osp-secret
  storageClass: <storage_class>

  barbican:
    enabled: false
    template:
      barbicanAPI: {}
      barbicanWorker: {}
      barbicanKeystoneListener: {}

  cinder:
    enabled: false
    template:
      cinderAPI: {}
      cinderScheduler: {}
      cinderBackup: {}
      cinderVolumes: {}

  dns:
    template:
      override:
        service:
          metadata:
            annotations:
              metallb.universe.tf/address-pool: ctlplane
              metallb.universe.tf/allow-shared-ip: ctlplane
              metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>

          spec:
            type: LoadBalancer
      options:
      - key: server
        values:
        - 192.168.122.1
      replicas: 1

  glance:
    enabled: false
    template:
      glanceAPIs: {}

  heat:
    enabled: false
    template: {}

  horizon:
    enabled: false
    template: {}

  ironic:
    enabled: false
    template:
      ironicConductors: []

  keystone:
    enabled: false
    template: {}

  manila:
    enabled: false
    template:
      manilaAPI: {}
      manilaScheduler: {}
      manilaShares: {}

  galera:
    enabled: true
    templates:
      openstack:
        secret: osp-secret
        replicas: 3
        storageRequest: 5G
      openstack-cell1:
        secret: osp-secret
        replicas: 3
        storageRequest: 5G
      openstack-cell2:
        secret: osp-secret
        replicas: 1
        storageRequest: 5G
      openstack-cell3:
        secret: osp-secret
        replicas: 1
        storageRequest: 5G
  memcached:
    enabled: true
    templates:
      memcached:
        replicas: 3

  neutron:
    enabled: false
    template: {}

  nova:
    enabled: false
    template: {}

  ovn:
    enabled: false
    template:
      ovnController:
        networkAttachment: tenant
        nodeSelector:
          node: non-existing-node-name
      ovnNorthd:
        replicas: 0
      ovnDBCluster:
        ovndbcluster-nb:
          replicas: 3
          dbType: NB
          networkAttachment: internalapi
        ovndbcluster-sb:
          replicas: 3
          dbType: SB
          networkAttachment: internalapi

  placement:
    enabled: false
    template: {}

  rabbitmq:
    templates:
      rabbitmq:
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>
            spec:
              type: LoadBalancer
      rabbitmq-cell1:
        persistence:
          storage: 1G
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>

            spec:
              type: LoadBalancer
      rabbitmq-cell2:
        persistence:
          storage: 1G
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>
            spec:
              type: LoadBalancer
      rabbitmq-cell3:
        persistence:
          storage: 1G
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>
            spec:
              type: LoadBalancer
  telemetry:
    enabled: false
  tls:
    podLevel:
      enabled: false
    ingress:
      enabled: false
  swift:
    enabled: false
    template:
      swiftRing:
        ringReplicas: 3
      swiftStorage:
        replicas: 0
      swiftProxy:
        replicas: 2
EOF
----
+
where:

<storage_class>::
Specifies an existing storage class in your {OpenShiftShort} cluster.

<loadBalancer_IP>::
Specifies the LoadBalancer IP address. If you use IPv6, change the load balancer IPs to the IPs in your environment, for example:
+
----
...
metallb.universe.tf/allow-shared-ip: ctlplane
metallb.universe.tf/loadBalancerIPs: fd00:aaaa::80
...
metallb.universe.tf/address-pool: internalapi
metallb.universe.tf/loadBalancerIPs: fd00:bbbb::85
...
metallb.universe.tf/address-pool: internalapi
metallb.universe.tf/loadBalancerIPs: fd00:bbbb::86
----

* `galera.openstack-cell1` provides the required infrastructure database and messaging services for the Compute cells, for example, `cell1`, `cell2`, and `cell3`. Adjust the values for fields such as `replicas`, `storage`, or `storageRequest`, for each Compute cell as needed.
* `spec.tls` specifies whether TLS-e is enabled. If you enabled TLS-e in your {OpenStackShort} environment, set `tls` to the following:
+
----
spec:
  ...
  tls:
    podLevel:
      enabled: true
      internal:
        ca:
          customIssuer: rootca-internal
      libvirt:
        ca:
          customIssuer: rootca-internal
      ovn:
        ca:
          customIssuer: rootca-internal
    ingress:
      ca:
        customIssuer: rootca-internal
      enabled: true
----
endif::[]

ifeval::["{build_variant}" == "ospdo"]
. Deploy the `OpenStackControlPlane` CR. Ensure that you only enable the DNS, Galera, Memcached, and RabbitMQ services. All other services must
be disabled:
+
[source,shell]
----
$ oc apply -f - <<EOF
apiVersion: core.openstack.org/v1beta1
kind: OpenStackControlPlane
metadata:
  name: openstack
spec:
  secret: osp-secret
  storageClass: <storage_class>


  barbican:
    enabled: false
    template:
      barbicanAPI: {}
      barbicanWorker: {}
      barbicanKeystoneListener: {}

  cinder:
    enabled: false
    template:
      cinderAPI: {}
      cinderScheduler: {}
      cinderBackup: {}
      cinderVolumes: {}

  dns:
    template:
      override:
        service:
          metadata:
            annotations:
              metallb.universe.tf/address-pool: <address_pool>
              metallb.universe.tf/allow-shared-ip: <address_pool>
              metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>
          spec:
            type: LoadBalancer
      options:
      - key: server
        values:
        - 192.168.122.1
      replicas: 1

  glance:
    enabled: false
    template:
      glanceAPIs: {}

  heat:
    enabled: false
    template: {}

  horizon:
    enabled: false
    template: {}

  ironic:
    enabled: false
    template:
      ironicConductors: []

  keystone:
    enabled: false
    template: {}

  manila:
    enabled: false
    template:
      manilaAPI: {}
      manilaScheduler: {}
      manilaShares: {}

  galera:
    enabled: true
    templates:
      openstack:
        secret: osp-secret
        replicas: 3
        storageRequest: 5G
      openstack-cell1:
        secret: osp-secret
        replicas: 3
        storageRequest: 5G
      openstack-cell2:
        secret: osp-secret
        replicas: 1
        storageRequest: 5G
      openstack-cell3:
        secret: osp-secret
        replicas: 1
        storageRequest: 5G
  memcached:
    enabled: true
    templates:
      memcached:
        replicas: 3

  neutron:
    enabled: false
    template: {}

  nova:
    enabled: false
    template: {}

  ovn:
    enabled: false
    template:
      ovnController:
        networkAttachment: tenant
        nodeSelector:
          node: non-existing-node-name
      ovnNorthd:
        replicas: 0
      ovnDBCluster:
        ovndbcluster-nb:
          replicas: 3
          dbType: NB
          networkAttachment: <networkAttachment_name>
        ovndbcluster-sb:
          replicas: 3
          dbType: SB
          networkAttachment: <networkAttachment_name>

  placement:
    enabled: false
    template: {}

  rabbitmq:
    templates:
      rabbitmq:
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: 172.17.0.85
            spec:
              type: LoadBalancer
      rabbitmq-cell1:
        persistence:
          storage: 1G
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: <networkAttachment_name>
                metallb.universe.tf/loadBalancerIPs: <loadBalancer_IP>
            spec:
              type: LoadBalancer
      rabbitmq-cell2:
        persistence:
          storage: 1G
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: 172.17.0.87
            spec:
              type: LoadBalancer
      rabbitmq-cell3:
        persistence:
          storage: 1G
        override:
          service:
            metadata:
              annotations:
                metallb.universe.tf/address-pool: internalapi
                metallb.universe.tf/loadBalancerIPs: 172.17.0.88
            spec:
              type: LoadBalancer
  telemetry:
    enabled: false

  tls:
    podLevel:
      enabled: false
    ingress:
      enabled: false

  swift:
    enabled: false
    template:
      swiftRing:
        ringReplicas: 3
      swiftStorage:
        replicas: 0
      swiftProxy:
        replicas: 2
EOF
----
+
where:

<storage_class>::
Specifies an existing storage class in your {OpenShiftShort} cluster.

<address_pool>::
Specifies name of your network definition.

<loadBalancer_IP>::
Specifies the LoadBalancer IP address. If you use IPv6, change the load balancer IPs to the IPs in your environment, for example:
+
----
...
metallb.universe.tf/allow-shared-ip: ctlplane
metallb.universe.tf/loadBalancerIPs: fd00:aaaa::80
...
metallb.universe.tf/address-pool: internalapi
metallb.universe.tf/loadBalancerIPs: fd00:bbbb::85
...
metallb.universe.tf/address-pool: internalapi
metallb.universe.tf/loadBalancerIPs: fd00:bbbb::86
----

<networkAttachment_name>::
Specifies the name of your network.

* `galera.openstack-cell1` provides the required infrastructure database and messaging services for the Compute cells, for example, `cell1`, `cell2`, and `cell3`. Adjust the values for fields such as `replicas`, `storage`, or `storageRequest`, for each Compute cell as needed.
* `spec.tls` specifies whether TLS-e is enabled. If you enabled TLS-e in your {OpenStackShort} environment, set `tls` to the following:
+
----
spec:
  ...
  tls:
    podLevel:
      enabled: true
      internal:
        ca:
          customIssuer: rootca-internal
      libvirt:
        ca:
          customIssuer: rootca-internal
      ovn:
        ca:
          customIssuer: rootca-internal
    ingress:
      ca:
        customIssuer: rootca-internal
      enabled: true
----
endif::[]



.Verification

* Verify that the Galera and RabbitMQ status is `Running` for all defined cells:
+
----
$ RENAMED_CELLS="cell1 cell2 cell3"
$ oc get pod openstack-galera-0 -o jsonpath='{.status.phase}{"\n"}'
$ oc get pod rabbitmq-server-0 -o jsonpath='{.status.phase}{"\n"}'
$ for CELL in $(echo $RENAMED_CELLS); do
>     oc get pod openstack-$CELL-galera-0 -o jsonpath='{.status.phase}{"\n"}'
>     oc get pod rabbitmq-$CELL-server-0 -o jsonpath='{.status.phase}{"\n"}'
> done
----
+
The given cells names are later referred to by using the environment variable `RENAMED_CELLS`.
During the database migration procedure, the Nova cells are renamed. `RENAMED_CELLS` variable represents the new cell names used in the RHOSO deployment.

* Ensure that the statuses of all the Rabbitmq and Galera CRs are `Setup complete`:
+
----
$ oc get Rabbitmqs,Galera
NAME                                                                  STATUS   MESSAGE
rabbitmq.rabbitmq.openstack.org/rabbitmq                              True     Setup complete
rabbitmq.rabbitmq.openstack.org/rabbitmq-cell1                        True     Setup complete

NAME                                                               READY   MESSAGE
galera.mariadb.openstack.org/openstack                             True     Setup complete
galera.mariadb.openstack.org/openstack-cell1                       True     Setup complete
----

* Verify that the `OpenStackControlPlane` CR is waiting for deployment
  of the `openstackclient` pod:
+
----
$ oc get OpenStackControlPlane openstack
NAME        STATUS    MESSAGE
openstack   Unknown   OpenStackControlPlane Client not started
----
