Chapter 3. Migrating databases to the control plane
Chapter 3. Migrating databases to the control plane To begin creating the control plane, enable back-end services and import the databases from your original Red Hat OpenStack Platform 17.1 deployment. 3.1. Retrieving topology-specific service configuration Before you migrate your databases to the Red Hat OpenStack Services on OpenShift (RHOSO) control plane, retrieve the topology-specific service configuration from your Red Hat OpenStack Platform (RHOSP) environment. You need this configuration for the following reasons: To check your current database for inaccuracies To ensure that you have the data you need before the migration To compare your RHOSP database with the adopted RHOSO database Prerequisites Define the following shell variables. Replace the example values with values that are correct for your environment: To get the value to set SOURCE_MARIADB_IP , query the puppet-generated configurations in a Controller node: Procedure Export the shell variables for the following outputs and test the connection to the RHOSP database: Note The nova , nova_api , and nova_cell0 databases are included in the same database host. Run mysqlcheck on the RHOSP database to check for inaccuracies: Get the Compute service (nova) cell mappings: Get the hostnames of the registered Compute services: Get the list of the mapped Compute service cells: Important After the RHOSP control plane services are shut down, if any of the exported values are lost, re-running the command fails because the control plane services are no longer running on the source cloud, and the data cannot be retrieved. To avoid data loss, preserve the exported values in an environment file before shutting down the control plane services. If neutron-sriov-nic-agent agents are running in your RHOSP deployment, get the configuration to use for the data plane adoption: Store the exported variables for future use: 3.2. Deploying back-end services Create the OpenStackControlPlane custom resource (CR) with the basic back-end services deployed, and disable all the Red Hat OpenStack Platform (RHOSP) 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 RHOSP 17.1. 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. Install the OpenStack Operators. For more information, see Installing and preparing the Operators in Deploying Red Hat OpenStack Services on OpenShift . If you enabled TLS everywhere (TLS-e) on the RHOSP environment, you must copy the tls root CA from the RHOSP environment to the rootca-internal issuer. There are free PVs available for MariaDB and RabbitMQ. Set the desired admin password for the control plane deployment. This can be the admin password from your original deployment or a different password: To use the existing RHOSP deployment password: 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 director Standalone, the passwords can be extracted: Procedure Ensure that you are using the Red Hat OpenShift Container Platform (RHOCP) namespace where you want the control plane to be deployed: Create the RHOSP secret. For more information, see Providing secure access to the Red Hat OpenStack Services on OpenShift services in Deploying Red Hat OpenStack Services on OpenShift . If the USDADMIN_PASSWORD is different than the password you set in osp-secret , amend the AdminPassword key in the osp-secret : Set service account passwords in osp-secret to match the service account passwords from the original deployment: If you enabled TLS-e in your RHOSP environment, in the spec:tls section, set the enabled parameter to true : apiVersion: core.openstack.org/v1beta1 kind: OpenStackControlPlane metadata: name: openstack 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 If you did not enable TLS-e, in the spec:tls section, set the enabled parameter to false : apiVersion: core.openstack.org/v1beta1 kind: OpenStackControlPlane metadata: name: openstack spec: tls: podLevel: enabled: false ingress: enabled: false Deploy the OpenStackControlPlane CR. Ensure that you only enable the DNS, MariaDB, Memcached, and RabbitMQ services. All other services must be disabled: USD oc apply -f - <<EOF apiVersion: core.openstack.org/v1beta1 kind: OpenStackControlPlane metadata: name: openstack spec: secret: osp-secret storageClass: local-storage 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: 192.168.122.80 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: {} mariadb: enabled: false templates: {} galera: enabled: true templates: openstack: secret: osp-secret replicas: 3 storageRequest: 500M openstack-cell1: secret: osp-secret replicas: 3 storageRequest: 500M 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: dbType: NB networkAttachment: internalapi ovndbcluster-sb: 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: 172.17.0.85 spec: type: LoadBalancer rabbitmq-cell1: override: service: metadata: annotations: metallb.universe.tf/address-pool: internalapi metallb.universe.tf/loadBalancerIPs: 172.17.0.86 spec: type: LoadBalancer telemetry: enabled: false swift: enabled: false template: swiftRing: ringReplicas: 1 swiftStorage: replicas: 0 swiftProxy: replicas: 1 EOF Select an existing <storage_class> in your RHOCP cluster. Verification Verify that MariaDB is running: 3.3. Configuring a Red Hat Ceph Storage back end If your Red Hat OpenStack Platform (RHOSP) 17.1 deployment uses a Red Hat Ceph Storage back end for any service, such as Image Service (glance), Block Storage service (cinder), Compute service (nova), or Shared File Systems service (manila), you must configure the custom resources (CRs) to use the same back end in the Red Hat OpenStack Services on OpenShift (RHOSO) 18.0 deployment. Note To run ceph commands, you must use SSH to connect to a Red Hat Ceph Storage node and run sudo cephadm shell . This generates a Ceph orchestrator container that enables you to run administrative commands against the Red Hat Ceph Storage cluster. If you deployed the Red Hat Ceph Storage cluster by using director, you can launch the cephadm shell from an RHOSP Controller node. Prerequisites The OpenStackControlPlane CR is created. If your RHOSP 17.1 deployment uses the Shared File Systems service, the openstack keyring is updated. Modify the openstack user so that you can use it across all RHOSP services: Using the same user across all services makes it simpler to create a common Red Hat Ceph Storage secret that includes the keyring and ceph.conf file and propagate the secret to all the services that need it. The following shell variables are defined. Replace the following example values with values that are correct for your environment: Procedure Create the ceph-conf-files secret that includes the Red Hat Ceph Storage configuration: The content of the file should be similar to the following example: apiVersion: v1 kind: Secret metadata: name: ceph-conf-files namespace: openstack stringData: ceph.client.openstack.keyring: | [client.openstack] key = <secret key> caps mgr = "allow *" caps mon = "allow r, profile rbd" caps osd = "pool=vms, profile rbd pool=volumes, profile rbd pool=images, allow rw pool manila_data' ceph.conf: | [global] fsid = 7a1719e8-9c59-49e2-ae2b-d7eb08c695d4 mon_host = 10.1.1.2,10.1.1.3,10.1.1.4 In your OpenStackControlPlane CR, inject ceph.conf and ceph.client.openstack.keyring to the RHOSP services that are defined in the propagation list. For example: USD oc patch openstackcontrolplane openstack --type=merge --patch ' spec: extraMounts: - name: v1 region: r1 extraVol: - propagation: - CinderVolume - CinderBackup - GlanceAPI - ManilaShare extraVolType: Ceph volumes: - name: ceph projected: sources: - secret: name: ceph-conf-files mounts: - name: ceph mountPath: "/etc/ceph" readOnly: true ' 3.4. Stopping Red Hat OpenStack Platform services Before you start the Red Hat OpenStack Services on OpenShift (RHOSO) adoption, you must stop the Red Hat OpenStack Platform (RHOSP) services to avoid inconsistencies in the data that you migrate for the data plane adoption. Inconsistencies are caused by resource changes after the database is copied to the new deployment. You should not stop the infrastructure management services yet, such as: Database RabbitMQ HAProxy Load Balancer Ceph-nfs Compute service Containerized modular libvirt daemons Object Storage service (swift) back-end services Prerequisites Ensure that there no long-running tasks that require the services that you plan to stop, such as instance live migrations, volume migrations, volume creation, backup and restore, attaching, detaching, and other similar operations: Collect the services topology-specific configuration. For more information, see Retrieving topology-specific service configuration . Define the following shell variables. The values are examples and refer to a single node standalone director deployment. Replace these example values with values that are correct for your environment: Procedure If your deployment enables CephFS through NFS as a back end for Shared File Systems service (manila), remove the following Pacemaker ordering and co-location constraints that govern the Virtual IP address of the ceph-nfs service and the manila-share service: Disable RHOSP control plane services: If the status of each service is OK , then the services stopped successfully. 3.5. Migrating databases to MariaDB instances Migrate your databases from the original Red Hat OpenStack Platform (RHOSP) deployment to the MariaDB instances in the Red Hat OpenShift Container Platform (RHOCP) cluster. Prerequisites Ensure that the control plane MariaDB and RabbitMQ are running, and that no other control plane services are running. Retrieve the topology-specific service configuration. For more information, see Retrieving topology-specific service configuration . Stop the RHOSP services. For more information, see Stopping Red Hat OpenStack Platform services . Ensure that there is network routability between the original MariaDB and the MariaDB for the control plane. Define the following shell variables. Replace the following example values with values that are correct for your environment: To get the value to set SOURCE_MARIADB_IP , query the puppet-generated configurations in a Controller node: Prepare the MariaDB adoption helper pod: Create a temporary volume claim and a pod for the database data copy. Edit the volume claim storage request if necessary, to give it enough space for the overcloud databases: oc apply -f - <<EOF --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mariadb-data spec: storageClassName: USDSTORAGE_CLASS accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: v1 kind: Pod metadata: name: mariadb-copy-data annotations: openshift.io/scc: anyuid k8s.v1.cni.cncf.io/networks: internalapi labels: app: adoption spec: containers: - image: USDMARIADB_IMAGE command: [ "sh", "-c", "sleep infinity"] name: adoption volumeMounts: - mountPath: /backup name: mariadb-data securityContext: allowPrivilegeEscalation: false capabilities: drop: ALL runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: mariadb-data persistentVolumeClaim: claimName: mariadb-data EOF Wait for the pod to be ready: Procedure Check that the source Galera database cluster members are online and synced: Get the count of source databases with the NOK (not-OK) status: Check that mysqlcheck had no errors: Test the connection to the control plane databases: Note You must transition Compute service (nova) services that are imported later into a superconductor architecture by deleting the old service records in the cell databases, starting with cell1 . New records are registered with different hostnames provided by the Compute service operator. All Compute services, except the Compute agent, have no internal state, and their service records can be safely deleted. You also need to rename the former default cell to cell1 . Create a dump of the original databases: Restore the databases from .sql files into the control plane MariaDB: Verification Compare the following outputs with the topology-specific service configuration. For more information, see Retrieving topology-specific service configuration . Check that the databases are imported correctly: Delete the mariadb-data pod and the mariadb-copy-data persistent volume claim that contains the database backup: Note Consider taking a snapshot of them before deleting. Note During the pre-checks and post-checks, the mariadb-client pod might return a pod security warning related to the restricted:latest security context constraint. This warning is due to default security context constraints and does not prevent the admission controller from creating a pod. You see a warning for the short-lived pod, but it does not interfere with functionality. For more information, see About pod security standards and warnings . 3.6. Migrating OVN data Migrate the data in the OVN databases from the original Red Hat OpenStack Platform deployment to ovsdb-server instances that are running in the Red Hat OpenShift Container Platform (RHOCP) cluster. Prerequisites The OpenStackControlPlane resource is created. NetworkAttachmentDefinition custom resources (CRs) for the original cluster are defined. Specifically, the internalapi network is defined. The original Networking service (neutron) and OVN northd are not running. There is network routability between the control plane services and the adopted cluster. The cloud is migrated to the Modular Layer 2 plug-in with Open Virtual Networking (ML2/OVN) mechanism driver. Define the following shell variables. Replace the example values with values that are correct for your environment: To get the value to set SOURCE_OVSDB_IP , query the puppet-generated configurations in a Controller node: Procedure Prepare a temporary PersistentVolume claim and the helper pod for the OVN backup. Adjust the storage requests for a large database, if needed: USD oc apply -f - <<EOF --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: ovn-data-cert namespace: openstack spec: commonName: ovn-data-cert secretName: ovn-data-cert issuerRef: name: rootca-internal --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ovn-data spec: storageClassName: USDSTORAGE_CLASS accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: v1 kind: Pod metadata: name: ovn-copy-data annotations: openshift.io/scc: anyuid k8s.v1.cni.cncf.io/networks: internalapi labels: app: adoption spec: containers: - image: USDOVSDB_IMAGE command: [ "sh", "-c", "sleep infinity"] name: adoption volumeMounts: - mountPath: /backup name: ovn-data - mountPath: /etc/pki/tls/misc name: ovn-data-cert readOnly: true securityContext: allowPrivilegeEscalation: false capabilities: drop: ALL runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: ovn-data persistentVolumeClaim: claimName: ovn-data - name: ovn-data-cert secret: secretName: ovn-data-cert EOF Wait for the pod to be ready: If the podified internalapi cidr is different than the source internalapi cidr, add an iptables accept rule on the Controller nodes: Back up your OVN databases: If you did not enable TLS everywhere, run the following command: If you enabled TLS everywhere, run the following command: Start the control plane OVN database services prior to import, with northd and ovn-controller disabled: USD oc patch openstackcontrolplane openstack --type=merge --patch ' spec: ovn: enabled: true template: ovnDBCluster: ovndbcluster-nb: dbType: NB storageRequest: 10G networkAttachment: internalapi ovndbcluster-sb: dbType: SB storageRequest: 10G networkAttachment: internalapi ovnNorthd: replicas: 0 ovnController: networkAttachment: tenant nodeSelector: ' Wait for the OVN database services to reach the Running phase: Fetch the OVN database IP addresses on the clusterIP service network: If you are using IPv6, adjust the address to the format expected by ovsdb-* tools: Upgrade the database schema for the backup files: If you did not enable TLS everywhere, use the following command: If you enabled TLS everywhere, use the following command: Restore the database backup to the new OVN database servers: If you did not enable TLS everywhere, use the following command: If you enabled TLS everywhere, use the following command: Check that the data was successfully migrated by running the following commands against the new database servers, for example: Start the control plane ovn-northd service to keep both OVN databases in sync: USD oc patch openstackcontrolplane openstack --type=merge --patch ' spec: ovn: enabled: true template: ovnNorthd: replicas: 1 ' If you are running OVN gateway services on RHOCP nodes, enable the control plane ovn-controller service: USD oc patch openstackcontrolplane openstack --type=json -p="[{'op': 'remove', 'path': '/spec/ovn/template/ovnController/nodeSelector'}]" Note Running OVN gateways on RHOCP nodes might be prone to data plane downtime during Open vSwitch upgrades. Consider running OVN gateways on dedicated Networker data plane nodes for production deployments instead. Delete the ovn-data helper pod and the temporary PersistentVolumeClaim that is used to store OVN database backup files: Note Consider taking a snapshot of the ovn-data helper pod and the temporary PersistentVolumeClaim before deleting them. For more information, see About volume snapshots in OpenShift Container Platform storage overview . Stop the adopted OVN database servers:
CONTROLLER1_SSH="ssh -i *<path to SSH key>* root@*<node IP>*" MARIADB_IMAGE=registry.redhat.io/rhoso/openstack-mariadb-rhel9:18.0 SOURCE_MARIADB_IP=172.17.0.2 SOURCE_DB_ROOT_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' MysqlRootPassword:' | awk -F ': ' '{ print USD2; }') MARIADB_CLIENT_ANNOTATIONS='--annotations=k8s.v1.cni.cncf.io/networks=internalapi' sudo grep -rI 'listen mysql' -A10 /var/lib/config-data/puppet-generated/ | grep bind export PULL_OPENSTACK_CONFIGURATION_DATABASES=USD(oc run mariadb-client USD{MARIADB_CLIENT_ANNOTATIONS} -q --image USD{MARIADB_IMAGE} -i --rm --restart=Never -- mysql -rsh "USDSOURCE_MARIADB_IP" -uroot -p"USDSOURCE_DB_ROOT_PASSWORD" -e 'SHOW databases;') echo "USDPULL_OPENSTACK_CONFIGURATION_DATABASES" export PULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK=USD(oc run mariadb-client USD{MARIADB_CLIENT_ANNOTATIONS} -q --image USD{MARIADB_IMAGE} -i --rm --restart=Never -- mysqlcheck --all-databases -h USDSOURCE_MARIADB_IP -u root -p"USDSOURCE_DB_ROOT_PASSWORD" | grep -v OK) echo "USDPULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK" export PULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS=USD(oc run mariadb-client USD{MARIADB_CLIENT_ANNOTATIONS} -q --image USD{MARIADB_IMAGE} -i --rm --restart=Never -- mysql -rsh "USD{SOURCE_MARIADB_IP}" -uroot -p"USD{SOURCE_DB_ROOT_PASSWORD}" nova_api -e 'select uuid,name,transport_url,database_connection,disabled from cell_mappings;') echo "USDPULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS" export PULL_OPENSTACK_CONFIGURATION_NOVA_COMPUTE_HOSTNAMES=USD(oc run mariadb-client USD{MARIADB_CLIENT_ANNOTATIONS} -q --image USD{MARIADB_IMAGE} -i --rm --restart=Never -- mysql -rsh "USDSOURCE_MARIADB_IP" -uroot -p"USDSOURCE_DB_ROOT_PASSWORD" nova_api -e "select host from nova.services where services.binary='nova-compute';") echo "USDPULL_OPENSTACK_CONFIGURATION_NOVA_COMPUTE_HOSTNAMES" export PULL_OPENSTACK_CONFIGURATION_NOVAMANAGE_CELL_MAPPINGS=USD(USDCONTROLLER1_SSH sudo podman exec -it nova_api nova-manage cell_v2 list_cells) echo "USDPULL_OPENSTACK_CONFIGURATION_NOVAMANAGE_CELL_MAPPINGS" SRIOV_AGENTS=USD oc run mariadb-client mysql -rsh "USDSOURCE_MARIADB_IP" -uroot -p"USDSOURCE_DB_ROOT_PASSWORD" ovs_neutron -e "select host, configurations from agents where agents.binary='neutron-sriov-nic-agent';" cat >~/.source_cloud_exported_variables <<EOF PULL_OPENSTACK_CONFIGURATION_DATABASES="USDPULL_OPENSTACK_CONFIGURATION_DATABASES" PULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK="USDPULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK" PULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS="USDPULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS" PULL_OPENSTACK_CONFIGURATION_NOVA_COMPUTE_HOSTNAMES="USDPULL_OPENSTACK_CONFIGURATION_NOVA_COMPUTE_HOSTNAMES" PULL_OPENSTACK_CONFIGURATION_NOVAMANAGE_CELL_MAPPINGS="USDPULL_OPENSTACK_CONFIGURATION_NOVAMANAGE_CELL_MAPPINGS" SRIOV_AGENTS="USDSRIOV_AGENTS" EOF ADMIN_PASSWORD=SomePassword ADMIN_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' AdminPassword:' | awk -F ': ' '{ print USD2; }') AODH_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' AodhPassword:' | awk -F ': ' '{ print USD2; }') BARBICAN_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' BarbicanPassword:' | awk -F ': ' '{ print USD2; }') CEILOMETER_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' CeilometerPassword:' | awk -F ': ' '{ print USD2; }') CINDER_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' CinderPassword:' | awk -F ': ' '{ print USD2; }') GLANCE_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' GlancePassword:' | awk -F ': ' '{ print USD2; }') HEAT_AUTH_ENCRYPTION_KEY=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' HeatAuthEncryptionKey:' | awk -F ': ' '{ print USD2; }') HEAT_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' HeatPassword:' | awk -F ': ' '{ print USD2; }') HEAT_STACK_DOMAIN_ADMIN_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' HeatStackDomainAdminPassword:' | awk -F ': ' '{ print USD2; }') IRONIC_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' IronicPassword:' | awk -F ': ' '{ print USD2; }') MANILA_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' ManilaPassword:' | awk -F ': ' '{ print USD2; }') NEUTRON_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' NeutronPassword:' | awk -F ': ' '{ print USD2; }') NOVA_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' NovaPassword:' | awk -F ': ' '{ print USD2; }') OCTAVIA_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' OctaviaPassword:' | awk -F ': ' '{ print USD2; }') PLACEMENT_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' PlacementPassword:' | awk -F ': ' '{ print USD2; }') SWIFT_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' SwiftPassword:' | awk -F ': ' '{ print USD2; }') oc project openstack oc set data secret/osp-secret "AdminPassword=USDADMIN_PASSWORD" oc set data secret/osp-secret "AodhPassword=USDAODH_PASSWORD" oc set data secret/osp-secret "BarbicanPassword=USDBARBICAN_PASSWORD" oc set data secret/osp-secret "CeilometerPassword=USDCEILOMETER_PASSWORD" oc set data secret/osp-secret "CinderPassword=USDCINDER_PASSWORD" oc set data secret/osp-secret "GlancePassword=USDGLANCE_PASSWORD" oc set data secret/osp-secret "HeatAuthEncryptionKey=USDHEAT_AUTH_ENCRYPTION_KEY" oc set data secret/osp-secret "HeatPassword=USDHEAT_PASSWORD" oc set data secret/osp-secret "HeatStackDomainAdminPassword=USDHEAT_STACK_DOMAIN_ADMIN_PASSWORD" oc set data secret/osp-secret "IronicPassword=USDIRONIC_PASSWORD" oc set data secret/osp-secret "IronicInspectorPassword=USDIRONIC_PASSWORD" oc set data secret/osp-secret "ManilaPassword=USDMANILA_PASSWORD" oc set data secret/osp-secret "MetadataSecret=USDMETADATA_SECRET" oc set data secret/osp-secret "NeutronPassword=USDNEUTRON_PASSWORD" oc set data secret/osp-secret "NovaPassword=USDNOVA_PASSWORD" oc set data secret/osp-secret "OctaviaPassword=USDOCTAVIA_PASSWORD" oc set data secret/osp-secret "PlacementPassword=USDPLACEMENT_PASSWORD" oc set data secret/osp-secret "SwiftPassword=USDSWIFT_PASSWORD" apiVersion: core.openstack.org/v1beta1 kind: OpenStackControlPlane metadata: name: openstack 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 apiVersion: core.openstack.org/v1beta1 kind: OpenStackControlPlane metadata: name: openstack spec: tls: podLevel: enabled: false ingress: enabled: false oc apply -f - <<EOF apiVersion: core.openstack.org/v1beta1 kind: OpenStackControlPlane metadata: name: openstack spec: secret: osp-secret storageClass: local-storage 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: 192.168.122.80 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: {} mariadb: enabled: false templates: {} galera: enabled: true templates: openstack: secret: osp-secret replicas: 3 storageRequest: 500M openstack-cell1: secret: osp-secret replicas: 3 storageRequest: 500M 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: dbType: NB networkAttachment: internalapi ovndbcluster-sb: 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: 172.17.0.85 spec: type: LoadBalancer rabbitmq-cell1: override: service: metadata: annotations: metallb.universe.tf/address-pool: internalapi metallb.universe.tf/loadBalancerIPs: 172.17.0.86 spec: type: LoadBalancer telemetry: enabled: false swift: enabled: false template: swiftRing: ringReplicas: 1 swiftStorage: replicas: 0 swiftProxy: replicas: 1 EOF oc get pod openstack-galera-0 -o jsonpath='{.status.phase}{"\n"}' oc get pod openstack-cell1-galera-0 -o jsonpath='{.status.phase}{"\n"}' ceph auth caps client.openstack mgr 'allow *' mon 'allow r, profile rbd' osd 'profile rbd pool=vms, profile rbd pool=volumes, profile rbd pool=images, allow rw pool manila_data' CEPH_SSH="ssh -i <path to SSH key> root@ <node IP> " CEPH_KEY=USD(USDCEPH_SSH "cat /etc/ceph/ceph.client.openstack.keyring | base64 -w 0") CEPH_CONF=USD(USDCEPH_SSH "cat /etc/ceph/ceph.conf | base64 -w 0") oc apply -f - <<EOF apiVersion: v1 data: ceph.client.openstack.keyring: USDCEPH_KEY ceph.conf: USDCEPH_CONF kind: Secret metadata: name: ceph-conf-files namespace: openstack type: Opaque EOF apiVersion: v1 kind: Secret metadata: name: ceph-conf-files namespace: openstack stringData: ceph.client.openstack.keyring: | [client.openstack] key = <secret key> caps mgr = "allow *" caps mon = "allow r, profile rbd" caps osd = "pool=vms, profile rbd pool=volumes, profile rbd pool=images, allow rw pool manila_data' ceph.conf: | [global] fsid = 7a1719e8-9c59-49e2-ae2b-d7eb08c695d4 mon_host = 10.1.1.2,10.1.1.3,10.1.1.4 oc patch openstackcontrolplane openstack --type=merge --patch ' spec: extraMounts: - name: v1 region: r1 extraVol: - propagation: - CinderVolume - CinderBackup - GlanceAPI - ManilaShare extraVolType: Ceph volumes: - name: ceph projected: sources: - secret: name: ceph-conf-files mounts: - name: ceph mountPath: "/etc/ceph" readOnly: true ' openstack server list --all-projects -c ID -c Status |grep -E '\| .+ing \|' openstack volume list --all-projects -c ID -c Status |grep -E '\| .+ing \|'| grep -vi error openstack volume backup list --all-projects -c ID -c Status |grep -E '\| .+ing \|' | grep -vi error openstack share list --all-projects -c ID -c Status |grep -E '\| .+ing \|'| grep -vi error openstack image list -c ID -c Status |grep -E '\| .+ing \|' CONTROLLER1_SSH="ssh -i <path to SSH key> root@ <controller-1 IP> " CONTROLLER2_SSH="ssh -i <path to SSH key> root@ <controller-2 IP> " CONTROLLER3_SSH="ssh -i <path to SSH key> root@ <controller-3 IP> " check the co-location and ordering constraints concerning "manila-share" sudo pcs constraint list --full remove these constraints sudo pcs constraint remove colocation-openstack-manila-share-ceph-nfs-INFINITY sudo pcs constraint remove order-ceph-nfs-openstack-manila-share-Optional Update the services list to be stopped ServicesToStop=("tripleo_aodh_api.service" "tripleo_aodh_api_cron.service" "tripleo_aodh_evaluator.service" "tripleo_aodh_listener.service" "tripleo_aodh_notifier.service" "tripleo_ceilometer_agent_central.service" "tripleo_ceilometer_agent_notification.service" "tripleo_horizon.service" "tripleo_keystone.service" "tripleo_barbican_api.service" "tripleo_barbican_worker.service" "tripleo_barbican_keystone_listener.service" "tripleo_cinder_api.service" "tripleo_cinder_api_cron.service" "tripleo_cinder_scheduler.service" "tripleo_cinder_volume.service" "tripleo_cinder_backup.service" "tripleo_collectd.service" "tripleo_glance_api.service" "tripleo_gnocchi_api.service" "tripleo_gnocchi_metricd.service" "tripleo_gnocchi_statsd.service" "tripleo_manila_api.service" "tripleo_manila_api_cron.service" "tripleo_manila_scheduler.service" "tripleo_neutron_api.service" "tripleo_placement_api.service" "tripleo_nova_api_cron.service" "tripleo_nova_api.service" "tripleo_nova_conductor.service" "tripleo_nova_metadata.service" "tripleo_nova_scheduler.service" "tripleo_nova_vnc_proxy.service" "tripleo_aodh_api.service" "tripleo_aodh_api_cron.service" "tripleo_aodh_evaluator.service" "tripleo_aodh_listener.service" "tripleo_aodh_notifier.service" "tripleo_ceilometer_agent_central.service" "tripleo_ceilometer_agent_compute.service" "tripleo_ceilometer_agent_ipmi.service" "tripleo_ceilometer_agent_notification.service" "tripleo_ovn_cluster_northd.service" "tripleo_ironic_neutron_agent.service" "tripleo_ironic_api.service" "tripleo_ironic_inspector.service" "tripleo_ironic_conductor.service") PacemakerResourcesToStop=("openstack-cinder-volume" "openstack-cinder-backup" "openstack-manila-share") echo "Stopping systemd OpenStack services" for service in USD{ServicesToStop[*]}; do for i in {1..3}; do SSH_CMD=CONTROLLERUSD{i}_SSH if [ ! -z "USD{!SSH_CMD}" ]; then echo "Stopping the USDservice in controller USDi" if USD{!SSH_CMD} sudo systemctl is-active USDservice; then USD{!SSH_CMD} sudo systemctl stop USDservice fi fi done done echo "Checking systemd OpenStack services" for service in USD{ServicesToStop[*]}; do for i in {1..3}; do SSH_CMD=CONTROLLERUSD{i}_SSH if [ ! -z "USD{!SSH_CMD}" ]; then if ! USD{!SSH_CMD} systemctl show USDservice | grep ActiveState=inactive >/dev/null; then echo "ERROR: Service USDservice still running on controller USDi" else echo "OK: Service USDservice is not running on controller USDi" fi fi done done echo "Stopping pacemaker OpenStack services" for i in {1..3}; do SSH_CMD=CONTROLLERUSD{i}_SSH if [ ! -z "USD{!SSH_CMD}" ]; then echo "Using controller USDi to run pacemaker commands" for resource in USD{PacemakerResourcesToStop[*]}; do if USD{!SSH_CMD} sudo pcs resource config USDresource &>/dev/null; then echo "Stopping USDresource" USD{!SSH_CMD} sudo pcs resource disable USDresource else echo "Service USDresource not present" fi done break fi done echo "Checking pacemaker OpenStack services" for i in {1..3}; do SSH_CMD=CONTROLLERUSD{i}_SSH if [ ! -z "USD{!SSH_CMD}" ]; then echo "Using controller USDi to run pacemaker commands" for resource in USD{PacemakerResourcesToStop[*]}; do if USD{!SSH_CMD} sudo pcs resource config USDresource &>/dev/null; then if ! USD{!SSH_CMD} sudo pcs resource status USDresource | grep Started; then echo "OK: Service USDresource is stopped" else echo "ERROR: Service USDresource is started" fi fi done break fi done PODIFIED_MARIADB_IP=USD(oc get svc --selector "mariadb/name=openstack" -ojsonpath='{.items[0].spec.clusterIP}') PODIFIED_CELL1_MARIADB_IP=USD(oc get svc --selector "mariadb/name=openstack-cell1" -ojsonpath='{.items[0].spec.clusterIP}') PODIFIED_DB_ROOT_PASSWORD=USD(oc get -o json secret/osp-secret | jq -r .data.DbRootPassword | base64 -d) The CHARACTER_SET and collation should match the source DB if the do not then it will break foreign key relationships for any tables that are created in the future as part of db sync CHARACTER_SET=utf8 COLLATION=utf8_general_ci STORAGE_CLASS=local-storage MARIADB_IMAGE=registry.redhat.io/rhoso/openstack-mariadb-rhel9:18.0 Replace with your environment's MariaDB Galera cluster VIP and backend IPs: SOURCE_MARIADB_IP=172.17.0.2 declare -A SOURCE_GALERA_MEMBERS SOURCE_GALERA_MEMBERS=( ["standalone.localdomain"]=172.17.0.100 # ) SOURCE_DB_ROOT_PASSWORD=USD(cat ~/overcloud-deploy/overcloud/overcloud-passwords.yaml | grep ' MysqlRootPassword:' | awk -F ': ' '{ print USD2; }') sudo grep -rI 'listen mysql' -A10 /var/lib/config-data/puppet-generated/ | grep bind apply -f - <<EOF --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mariadb-data spec: storageClassName: USDSTORAGE_CLASS accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: v1 kind: Pod metadata: name: mariadb-copy-data annotations: openshift.io/scc: anyuid k8s.v1.cni.cncf.io/networks: internalapi labels: app: adoption spec: containers: - image: USDMARIADB_IMAGE command: [ "sh", "-c", "sleep infinity"] name: adoption volumeMounts: - mountPath: /backup name: mariadb-data securityContext: allowPrivilegeEscalation: false capabilities: drop: ALL runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: mariadb-data persistentVolumeClaim: claimName: mariadb-data EOF oc wait --for condition=Ready pod/mariadb-copy-data --timeout=30s for i in "USD{!SOURCE_GALERA_MEMBERS[@]}"; do echo "Checking for the database node USDi WSREP status Synced" oc rsh mariadb-copy-data mysql -h "USD{SOURCE_GALERA_MEMBERS[USDi]}" -uroot -p"USDSOURCE_DB_ROOT_PASSWORD" -e "show global status like 'wsrep_local_state_comment'" | grep -qE "\bSynced\b" done oc rsh mariadb-copy-data mysql -h "USD{SOURCE_MARIADB_IP}" -uroot -p"USD{SOURCE_DB_ROOT_PASSWORD}" -e "SHOW databases;" . ~/.source_cloud_exported_variables test -z "USDPULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK" || [ "USDPULL_OPENSTACK_CONFIGURATION_MYSQLCHECK_NOK" = " " ] && echo "OK" || echo "CHECK FAILED" oc run mariadb-client --image USDMARIADB_IMAGE -i --rm --restart=Never -- mysql -rsh "USDPODIFIED_MARIADB_IP" -uroot -p"USDPODIFIED_DB_ROOT_PASSWORD" -e 'SHOW databases;' oc run mariadb-client --image USDMARIADB_IMAGE -i --rm --restart=Never -- mysql -rsh "USDPODIFIED_CELL1_MARIADB_IP" -uroot -p"USDPODIFIED_DB_ROOT_PASSWORD" -e 'SHOW databases;' oc rsh mariadb-copy-data << EOF mysql -h"USD{SOURCE_MARIADB_IP}" -uroot -p"USD{SOURCE_DB_ROOT_PASSWORD}" -N -e "show databases" | grep -E -v "schema|mysql|gnocchi|aodh" | while read dbname; do echo "Dumping \USD{dbname}"; mysqldump -h"USD{SOURCE_MARIADB_IP}" -uroot -p"USD{SOURCE_DB_ROOT_PASSWORD}" --single-transaction --complete-insert --skip-lock-tables --lock-tables=0 "\USD{dbname}" > /backup/"\USD{dbname}".sql; done EOF oc rsh mariadb-copy-data << EOF # db schemas to rename on import declare -A db_name_map db_name_map['nova']='nova_cell1' db_name_map['ovs_neutron']='neutron' db_name_map['ironic-inspector']='ironic_inspector' # db servers to import into declare -A db_server_map db_server_map['default']=USD{PODIFIED_MARIADB_IP} db_server_map['nova_cell1']=USD{PODIFIED_CELL1_MARIADB_IP} # db server root password map declare -A db_server_password_map db_server_password_map['default']=USD{PODIFIED_DB_ROOT_PASSWORD} db_server_password_map['nova_cell1']=USD{PODIFIED_DB_ROOT_PASSWORD} cd /backup for db_file in \USD(ls *.sql); do db_name=\USD(echo \USD{db_file} | awk -F'.' '{ print \USD1; }') if [[ -v "db_name_map[\USD{db_name}]" ]]; then echo "renaming \USD{db_name} to \USD{db_name_map[\USD{db_name}]}" db_name=\USD{db_name_map[\USD{db_name}]} fi db_server=\USD{db_server_map["default"]} if [[ -v "db_server_map[\USD{db_name}]" ]]; then db_server=\USD{db_server_map[\USD{db_name}]} fi db_password=\USD{db_server_password_map['default']} if [[ -v "db_server_password_map[\USD{db_name}]" ]]; then db_password=\USD{db_server_password_map[\USD{db_name}]} fi echo "creating \USD{db_name} in \USD{db_server}" mysql -h"\USD{db_server}" -uroot "-p\USD{db_password}" -e "CREATE DATABASE IF NOT EXISTS \USD{db_name} DEFAULT CHARACTER SET USD{CHARACTER_SET} DEFAULT COLLATE USD{COLLATION};" echo "importing \USD{db_name} into \USD{db_server}" mysql -h "\USD{db_server}" -uroot "-p\USD{db_password}" "\USD{db_name}" < "\USD{db_file}" done mysql -h "\USD{db_server_map['default']}" -uroot -p"\USD{db_server_password_map['default']}" -e "update nova_api.cell_mappings set name='cell1' where name='default';" mysql -h "\USD{db_server_map['nova_cell1']}" -uroot -p"\USD{db_server_password_map['nova_cell1']}" -e "delete from nova_cell1.services where host not like '%nova-cell1-%' and services.binary != 'nova-compute';" EOF . ~/.source_cloud_exported_variables use 'oc exec' and 'mysql -rs' to maintain formatting dbs=USD(oc exec openstack-galera-0 -c galera -- mysql -rs -uroot "-pUSDPODIFIED_DB_ROOT_PASSWORD" -e 'SHOW databases;') echo USDdbs | grep -Eq '\bkeystone\b' && echo "OK" || echo "CHECK FAILED" ensure neutron db is renamed from ovs_neutron echo USDdbs | grep -Eq '\bneutron\b' echo USDPULL_OPENSTACK_CONFIGURATION_DATABASES | grep -Eq '\bovs_neutron\b' && echo "OK" || echo "CHECK FAILED" ensure nova cell1 db is extracted to a separate db server and renamed from nova to nova_cell1 c1dbs=USD(oc exec openstack-cell1-galera-0 -c galera -- mysql -rs -uroot "-pUSDPODIFIED_DB_ROOT_PASSWORD" -e 'SHOW databases;') echo USDc1dbs | grep -Eq '\bnova_cell1\b' && echo "OK" || echo "CHECK FAILED" ensure default cell renamed to cell1, and the cell UUIDs retained intact novadb_mapped_cells=USD(oc exec openstack-galera-0 -c galera -- mysql -rs -uroot "-pUSDPODIFIED_DB_ROOT_PASSWORD" nova_api -e 'select uuid,name,transport_url,database_connection,disabled from cell_mappings;') uuidf='\S{8,}-\S{4,}-\S{4,}-\S{4,}-\S{12,}' left_behind=USD(comm -23 <(echo USDPULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS | grep -oE " USDuuidf \S+") <(echo USDnovadb_mapped_cells | tr -s "| " " " | grep -oE " USDuuidf \S+")) changed=USD(comm -13 <(echo USDPULL_OPENSTACK_CONFIGURATION_NOVADB_MAPPED_CELLS | grep -oE " USDuuidf \S+") <(echo USDnovadb_mapped_cells | tr -s "| " " " | grep -oE " USDuuidf \S+")) test USD(grep -Ec ' \S+USD' <<<USDleft_behind) -eq 1 && echo "OK" || echo "CHECK FAILED" default=USD(grep -E ' defaultUSD' <<<USDleft_behind) test USD(grep -Ec ' \S+USD' <<<USDchanged) -eq 1 && echo "OK" || echo "CHECK FAILED" grep -qE " USD(awk '{print USD1}' <<<USDdefault) cell1USD" <<<USDchanged && echo "OK" || echo "CHECK FAILED" ensure the registered Compute service name has not changed novadb_svc_records=USD(oc exec openstack-cell1-galera-0 -c galera -- mysql -rs -uroot "-pUSDPODIFIED_DB_ROOT_PASSWORD" nova_cell1 -e "select host from services where services.binary='nova-compute' order by host asc;") diff -Z <(echo USDnovadb_svc_records) <(echo USDPULL_OPENSTACK_CONFIGURATION_NOVA_COMPUTE_HOSTNAMES) && echo "OK" || echo "CHECK FAILED" oc delete pod mariadb-copy-data oc delete pvc mariadb-data STORAGE_CLASS=local-storage OVSDB_IMAGE=registry.redhat.io/rhoso/openstack-ovn-base-rhel9:18.0 SOURCE_OVSDB_IP=172.17.0.100 # For IPv4 SOURCE_OVSDB_IP=[fd00:bbbb::100] # For IPv6 grep -rI 'ovn_[ns]b_conn' /var/lib/config-data/puppet-generated/ oc apply -f - <<EOF --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: ovn-data-cert namespace: openstack spec: commonName: ovn-data-cert secretName: ovn-data-cert issuerRef: name: rootca-internal --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: ovn-data spec: storageClassName: USDSTORAGE_CLASS accessModes: - ReadWriteOnce resources: requests: storage: 10Gi --- apiVersion: v1 kind: Pod metadata: name: ovn-copy-data annotations: openshift.io/scc: anyuid k8s.v1.cni.cncf.io/networks: internalapi labels: app: adoption spec: containers: - image: USDOVSDB_IMAGE command: [ "sh", "-c", "sleep infinity"] name: adoption volumeMounts: - mountPath: /backup name: ovn-data - mountPath: /etc/pki/tls/misc name: ovn-data-cert readOnly: true securityContext: allowPrivilegeEscalation: false capabilities: drop: ALL runAsNonRoot: true seccompProfile: type: RuntimeDefault volumes: - name: ovn-data persistentVolumeClaim: claimName: ovn-data - name: ovn-data-cert secret: secretName: ovn-data-cert EOF oc wait --for=condition=Ready pod/ovn-copy-data --timeout=30s USDCONTROLLER1_SSH sudo iptables -I INPUT -s {PODIFIED_INTERNALAPI_NETWORK} -p tcp -m tcp --dport 6641 -m conntrack --ctstate NEW -j ACCEPT USDCONTROLLER1_SSH sudo iptables -I INPUT -s {PODIFIED_INTERNALAPI_NETWORK} -p tcp -m tcp --dport 6642 -m conntrack --ctstate NEW -j ACCEPT oc exec ovn-copy-data -- bash -c "ovsdb-client backup tcp:USDSOURCE_OVSDB_IP:6641 > /backup/ovs-nb.db" oc exec ovn-copy-data -- bash -c "ovsdb-client backup tcp:USDSOURCE_OVSDB_IP:6642 > /backup/ovs-sb.db" oc exec ovn-copy-data -- bash -c "ovsdb-client backup --ca-cert=/etc/pki/tls/misc/ca.crt --private-key=/etc/pki/tls/misc/tls.key --certificate=/etc/pki/tls/misc/tls.crt ssl:USDSOURCE_OVSDB_IP:6641 > /backup/ovs-nb.db" oc exec ovn-copy-data -- bash -c "ovsdb-client backup --ca-cert=/etc/pki/tls/misc/ca.crt --private-key=/etc/pki/tls/misc/tls.key --certificate=/etc/pki/tls/misc/tls.crt ssl:USDSOURCE_OVSDB_IP:6642 > /backup/ovs-sb.db" oc patch openstackcontrolplane openstack --type=merge --patch ' spec: ovn: enabled: true template: ovnDBCluster: ovndbcluster-nb: dbType: NB storageRequest: 10G networkAttachment: internalapi ovndbcluster-sb: dbType: SB storageRequest: 10G networkAttachment: internalapi ovnNorthd: replicas: 0 ovnController: networkAttachment: tenant nodeSelector: ' oc wait --for=jsonpath='{.status.phase}'=Running pod --selector=service=ovsdbserver-nb oc wait --for=jsonpath='{.status.phase}'=Running pod --selector=service=ovsdbserver-sb PODIFIED_OVSDB_NB_IP=USD(oc get svc --selector "statefulset.kubernetes.io/pod-name=ovsdbserver-nb-0" -ojsonpath='{.items[0].spec.clusterIP}') PODIFIED_OVSDB_SB_IP=USD(oc get svc --selector "statefulset.kubernetes.io/pod-name=ovsdbserver-sb-0" -ojsonpath='{.items[0].spec.clusterIP}') PODIFIED_OVSDB_NB_IP=[USDPODIFIED_OVSDB_NB_IP] PODIFIED_OVSDB_SB_IP=[USDPODIFIED_OVSDB_SB_IP] oc exec ovn-copy-data -- bash -c "ovsdb-client get-schema tcp:USDPODIFIED_OVSDB_NB_IP:6641 > /backup/ovs-nb.ovsschema && ovsdb-tool convert /backup/ovs-nb.db /backup/ovs-nb.ovsschema" oc exec ovn-copy-data -- bash -c "ovsdb-client get-schema tcp:USDPODIFIED_OVSDB_SB_IP:6642 > /backup/ovs-sb.ovsschema && ovsdb-tool convert /backup/ovs-sb.db /backup/ovs-sb.ovsschema" oc exec ovn-copy-data -- bash -c "ovsdb-client get-schema --ca-cert=/etc/pki/tls/misc/ca.crt --private-key=/etc/pki/tls/misc/tls.key --certificate=/etc/pki/tls/misc/tls.crt ssl:USDPODIFIED_OVSDB_NB_IP:6641 > /backup/ovs-nb.ovsschema && ovsdb-tool convert /backup/ovs-nb.db /backup/ovs-nb.ovsschema" oc exec ovn-copy-data -- bash -c "ovsdb-client get-schema --ca-cert=/etc/pki/tls/misc/ca.crt --private-key=/etc/pki/tls/misc/tls.key --certificate=/etc/pki/tls/misc/tls.crt ssl:USDPODIFIED_OVSDB_SB_IP:6642 > /backup/ovs-sb.ovsschema && ovsdb-tool convert /backup/ovs-sb.db /backup/ovs-sb.ovsschema" oc exec ovn-copy-data -- bash -c "ovsdb-client restore tcp:USDPODIFIED_OVSDB_NB_IP:6641 < /backup/ovs-nb.db" oc exec ovn-copy-data -- bash -c "ovsdb-client restore tcp:USDPODIFIED_OVSDB_SB_IP:6642 < /backup/ovs-sb.db" oc exec ovn-copy-data -- bash -c "ovsdb-client restore --ca-cert=/etc/pki/tls/misc/ca.crt --private-key=/etc/pki/tls/misc/tls.key --certificate=/etc/pki/tls/misc/tls.crt ssl:USDPODIFIED_OVSDB_NB_IP:6641 < /backup/ovs-nb.db" oc exec ovn-copy-data -- bash -c "ovsdb-client restore --ca-cert=/etc/pki/tls/misc/ca.crt --private-key=/etc/pki/tls/misc/tls.key --certificate=/etc/pki/tls/misc/tls.crt ssl:USDPODIFIED_OVSDB_SB_IP:6642 < /backup/ovs-sb.db" oc exec -it ovsdbserver-nb-0 -- ovn-nbctl show oc exec -it ovsdbserver-sb-0 -- ovn-sbctl list Chassis oc patch openstackcontrolplane openstack --type=merge --patch ' spec: ovn: enabled: true template: ovnNorthd: replicas: 1 ' oc patch openstackcontrolplane openstack --type=json -p="[{'op': 'remove', 'path': '/spec/ovn/template/ovnController/nodeSelector'}]" oc delete --ignore-not-found=true pod ovn-copy-data oc delete --ignore-not-found=true pvc ovn-data ServicesToStop=("tripleo_ovn_cluster_north_db_server.service" "tripleo_ovn_cluster_south_db_server.service") echo "Stopping systemd OpenStack services" for service in USD{ServicesToStop[*]}; do for i in {1..3}; do SSH_CMD=CONTROLLERUSD{i}_SSH if [ ! -z "USD{!SSH_CMD}" ]; then echo "Stopping the USDservice in controller USDi" if USD{!SSH_CMD} sudo systemctl is-active USDservice; then USD{!SSH_CMD} sudo systemctl stop USDservice fi fi done done echo "Checking systemd OpenStack services" for service in USD{ServicesToStop[*]}; do for i in {1..3}; do SSH_CMD=CONTROLLERUSD{i}_SSH if [ ! -z "USD{!SSH_CMD}" ]; then if ! USD{!SSH_CMD} systemctl show USDservice | grep ActiveState=inactive >/dev/null; then echo "ERROR: Service USDservice still running on controller USDi" else echo "OK: Service USDservice is not running on controller USDi" fi fi done done