From e998b6886602575127ebe613e56cee3a5a01c6c6 Mon Sep 17 00:00:00 2001
From: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Date: Thu, 26 Oct 2023 20:26:34 +0300
Subject: [PATCH] Add region name to trove-guestagent

In a shared keystone multi-region setup, we must set the region_name
when using any of the OpenStack clients. Without the region name,
clients may attempt to use the API endpoints in the wrong region.
Backups currently fail if there are multiple regions created in the
same keystone catalog, due to the fact that the trove guest agent
attempts to connect to the S3 endpoint in another region.

Story: 2010950
Task: 48994

Change-Id: I9bd497c85c6eba67485840d07a80cca8eed27994
Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
---
 backup/main.py                                     |  1 +
 backup/storage/swift.py                            | 12 +++++++++---
 trove/guestagent/datastore/mysql_common/service.py |  3 ++-
 trove/guestagent/datastore/postgres/service.py     |  3 ++-
 trove/guestagent/datastore/service.py              |  3 ++-
 5 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/backup/main.py b/backup/main.py
index 833ce7e742..64fa47bae9 100644
--- a/backup/main.py
+++ b/backup/main.py
@@ -52,6 +52,7 @@ cli_opts = [
     cfg.StrOpt('db-datadir'),
     cfg.StrOpt('os-token'),
     cfg.StrOpt('os-auth-url'),
+    cfg.StrOpt('os-region-name'),
     cfg.StrOpt('os-tenant-id'),
     cfg.StrOpt('swift-container', default='database_backups'),
     cfg.DictOpt('swift-extra-metadata'),
diff --git a/backup/storage/swift.py b/backup/storage/swift.py
index 38ec6761c7..a3226a1e24 100644
--- a/backup/storage/swift.py
+++ b/backup/storage/swift.py
@@ -36,9 +36,14 @@ def _get_user_keystone_session(auth_url, token, tenant_id):
     return session.Session(auth=auth, verify=False)
 
 
-def _get_service_client(auth_url, token, tenant_id):
+def _get_service_client(auth_url, token, tenant_id, region_name=None):
     sess = _get_user_keystone_session(auth_url, token, tenant_id)
-    return swiftclient.Connection(session=sess)
+    os_options = None
+    if region_name:
+        os_options = {
+            'region_name': region_name
+        }
+    return swiftclient.Connection(session=sess, os_options=os_options)
 
 
 def _set_attr(original):
@@ -111,7 +116,8 @@ class StreamReader(object):
 class SwiftStorage(base.Storage):
     def __init__(self):
         self.client = _get_service_client(CONF.os_auth_url, CONF.os_token,
-                                          CONF.os_tenant_id)
+                                          CONF.os_tenant_id,
+                                          region_name=CONF.os_region_name)
 
     def save(self, stream, metadata=None, container='database_backups'):
         """Persist data from the stream to swift.
diff --git a/trove/guestagent/datastore/mysql_common/service.py b/trove/guestagent/datastore/mysql_common/service.py
index 5cbc8ef1f4..7dbb01a8f7 100644
--- a/trove/guestagent/datastore/mysql_common/service.py
+++ b/trove/guestagent/datastore/mysql_common/service.py
@@ -698,6 +698,7 @@ class BaseMySqlApp(service.BaseDbApp):
         backup_driver = self.get_backup_strategy()
         user_token = context.auth_token
         auth_url = CONF.service_credentials.auth_url
+        region_name = CONF.service_credentials.region_name
         user_tenant = context.project_id
         image = self.get_backup_image()
         name = 'db_restore'
@@ -707,7 +708,7 @@ class BaseMySqlApp(service.BaseDbApp):
             f'/usr/bin/python3 main.py --nobackup '
             f'--storage-driver={storage_driver} --driver={backup_driver} '
             f'--os-token={user_token} --os-auth-url={auth_url} '
-            f'--os-tenant-id={user_tenant} '
+            f'--os-tenant-id={user_tenant} --os-region-name={region_name} '
             f'--restore-from={backup_info["location"]} '
             f'--restore-checksum={backup_info["checksum"]}'
         )
diff --git a/trove/guestagent/datastore/postgres/service.py b/trove/guestagent/datastore/postgres/service.py
index 7d5fbfb4f2..d53332ba68 100644
--- a/trove/guestagent/datastore/postgres/service.py
+++ b/trove/guestagent/datastore/postgres/service.py
@@ -275,7 +275,8 @@ class PgSqlApp(service.BaseDbApp):
 
         os_cred = (f"--os-token={context.auth_token} "
                    f"--os-auth-url={CONF.service_credentials.auth_url} "
-                   f"--os-tenant-id={context.project_id}")
+                   f"--os-tenant-id={context.project_id} "
+                   f"--os-region-name={CONF.service_credentials.region_name}")
 
         command = (
             f'/usr/bin/python3 main.py --nobackup '
diff --git a/trove/guestagent/datastore/service.py b/trove/guestagent/datastore/service.py
index 2134da2f9e..5d2a9f85ac 100644
--- a/trove/guestagent/datastore/service.py
+++ b/trove/guestagent/datastore/service.py
@@ -463,7 +463,8 @@ class BaseDbApp(object):
         image = self.get_backup_image()
         os_cred = (f"--os-token={context.auth_token} "
                    f"--os-auth-url={CONF.service_credentials.auth_url} "
-                   f"--os-tenant-id={context.project_id}")
+                   f"--os-tenant-id={context.project_id} "
+                   f"--os-region-name={CONF.service_credentials.region_name}")
 
         db_userinfo = ''
         if need_dbuser: