From 205f3d828d5f8afc002c32714e7c67db10dbfa53 Mon Sep 17 00:00:00 2001
From: Dina Saparbaeva <dinas27@outlook.com>
Date: Tue, 2 Mar 2021 00:01:32 +0600
Subject: [PATCH] fixes  availability zone filter when creating a share from
 snapshot

Fixes bug #1915706 that was discovered in  Manila UI.
Issue is invalid input error being raised, even when
availability_zone provided is the same, as parent share's.
The reason is availability_zone is name and source_share_az
is id in the filter [1]. Now, regardless of availability_zone
provided is id or name, it will be always converted to a name.
And if availability_zone is the same as parent share's
operation will complete successfully.

[1] https://github.com/openstack/manila/blob/2e27c71877fdb601ba90b44c3573d8e50e099042/manila/share/api.py#L200

Closes-Bug: #1915706
Change-Id: I5039b7adf563d926053b423a4cc6e175d3f1e5cf
---
 manila/api/v1/shares.py            | 11 +++++++----
 manila/tests/api/v2/test_shares.py | 13 +++++++++----
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/manila/api/v1/shares.py b/manila/api/v1/shares.py
index ccec9a5f14..19e155ff0b 100644
--- a/manila/api/v1/shares.py
+++ b/manila/api/v1/shares.py
@@ -267,8 +267,10 @@ class ShareMixin(object):
         availability_zone = share.get('availability_zone')
         if availability_zone:
             try:
-                availability_zone_id = db.availability_zone_get(
-                    context, availability_zone).id
+                availability_zone_db = db.availability_zone_get(
+                    context, availability_zone)
+                availability_zone_id = availability_zone_db.id
+                availability_zone = availability_zone_db.name
             except exception.AvailabilityZoneNotFound as e:
                 raise exc.HTTPNotFound(explanation=six.text_type(e))
 
@@ -284,10 +286,11 @@ class ShareMixin(object):
                         "share group's one (%(sg_az)s).") % {
                             's_az': availability_zone_id, 'sg_az': sg_az_id}
                 raise exception.InvalidInput(msg)
-            availability_zone_id = sg_az_id
+            availability_zone = db.availability_zone_get(
+                context, sg_az_id).name
 
         kwargs = {
-            'availability_zone': availability_zone_id,
+            'availability_zone': availability_zone,
             'metadata': share.get('metadata'),
             'is_public': share.get('is_public', False),
             'share_group_id': share_group_id,
diff --git a/manila/tests/api/v2/test_shares.py b/manila/tests/api/v2/test_shares.py
index d4c803302e..80e97596f5 100644
--- a/manila/tests/api/v2/test_shares.py
+++ b/manila/tests/api/v2/test_shares.py
@@ -525,10 +525,12 @@ class ShareAPITest(test.TestCase):
     def test_share_create_with_sg_and_availability_zone(self):
         sg_id = 'fake_sg_id'
         az_id = 'bar_az_id'
+        az_name = 'fake_name'
         self.mock_object(share_api.API, 'create', self.create_mock)
         self.mock_object(
             db, 'availability_zone_get',
-            mock.Mock(return_value=type('ReqAZ', (object, ), {"id": az_id})))
+            mock.Mock(return_value=type(
+                'ReqAZ', (object, ), {"id": az_id, "name": az_name})))
         self.mock_object(
             db, 'share_group_get',
             mock.Mock(return_value={"availability_zone_id": az_id}))
@@ -543,7 +545,8 @@ class ShareAPITest(test.TestCase):
 
         self.controller.create(req, body)
 
-        db.availability_zone_get.assert_called_once_with(
+        self.assertEqual(db.availability_zone_get.call_count, 2)
+        db.availability_zone_get.assert_called_with(
             req.environ['manila.context'], az_id)
         db.share_group_get.assert_called_once_with(
             req.environ['manila.context'], sg_id)
@@ -557,16 +560,18 @@ class ShareAPITest(test.TestCase):
             is_public=False,
             metadata=None,
             snapshot_id=None,
-            availability_zone=az_id)
+            availability_zone=az_name)
 
     def test_share_create_with_sg_and_different_availability_zone(self):
         sg_id = 'fake_sg_id'
         sg_az = 'foo_az_id'
         req_az = 'bar_az_id'
+        req_az_name = 'fake_az_name'
         self.mock_object(share_api.API, 'create', self.create_mock)
         self.mock_object(
             db, 'availability_zone_get',
-            mock.Mock(return_value=type('ReqAZ', (object, ), {"id": req_az})))
+            mock.Mock(return_value=type('ReqAZ', (object, ), {
+                "id": req_az, "name": req_az_name})))
         self.mock_object(
             db, 'share_group_get',
             mock.Mock(return_value={"availability_zone_id": sg_az}))