summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2017-02-17 04:21:58 +0000
committerGerrit Code Review <review@openstack.org>2017-02-17 04:21:58 +0000
commit7b60653007e13c8ece27fc2fdaba94e8ecc6c4d3 (patch)
treef252cb0c48750c3a84c610ce207a2b979aff44ff
parentd87d73576de5c3bc404297f5fcdf91d76ef2ddd3 (diff)
parent6f6a31d595eec9d5c2735d91317c4d4742b920d7 (diff)
Merge "Only return share host for admins using shares API" into stable/ocata4.0.0.0rc24.0.0
-rw-r--r--etc/manila/policy.json1
-rw-r--r--manila/api/views/share_replicas.py2
-rw-r--r--manila/api/views/shares.py3
-rw-r--r--manila/share/api.py2
-rw-r--r--manila/tests/api/v1/test_shares.py82
-rw-r--r--manila/tests/api/v2/test_share_replicas.py2
-rw-r--r--manila/tests/api/v2/test_shares.py83
-rw-r--r--manila/tests/share/test_api.py23
-rw-r--r--manila_tempest_tests/tests/api/base.py3
-rw-r--r--manila_tempest_tests/tests/api/test_replication.py4
-rw-r--r--manila_tempest_tests/tests/api/test_replication_negative.py2
-rw-r--r--manila_tempest_tests/tests/api/test_shares.py2
-rw-r--r--manila_tempest_tests/tests/api/test_shares_actions.py19
-rw-r--r--manila_tempest_tests/tests/api/test_shares_negative.py6
-rw-r--r--manila_tempest_tests/tests/scenario/test_share_basic_ops.py2
-rw-r--r--releasenotes/notes/remove-host-field-from-shares-and-replicas-a087f85bc4a4ba45.yaml10
16 files changed, 130 insertions, 116 deletions
diff --git a/etc/manila/policy.json b/etc/manila/policy.json
index bc5e1bb..0b98432 100644
--- a/etc/manila/policy.json
+++ b/etc/manila/policy.json
@@ -22,6 +22,7 @@
22 "share:get": "rule:default", 22 "share:get": "rule:default",
23 "share:get_all": "rule:default", 23 "share:get_all": "rule:default",
24 "share:list_by_share_server_id": "rule:admin_api", 24 "share:list_by_share_server_id": "rule:admin_api",
25 "share:list_by_host": "rule:admin_api",
25 "share:update": "rule:default", 26 "share:update": "rule:default",
26 "share:access_get": "rule:default", 27 "share:access_get": "rule:default",
27 "share:access_get_all": "rule:default", 28 "share:access_get_all": "rule:default",
diff --git a/manila/api/views/share_replicas.py b/manila/api/views/share_replicas.py
index 1af2c48..5bcbeb2 100644
--- a/manila/api/views/share_replicas.py
+++ b/manila/api/views/share_replicas.py
@@ -54,7 +54,6 @@ class ReplicationViewBuilder(common.ViewBuilder):
54 'share_id': replica.get('share_id'), 54 'share_id': replica.get('share_id'),
55 'availability_zone': replica.get('availability_zone'), 55 'availability_zone': replica.get('availability_zone'),
56 'created_at': replica.get('created_at'), 56 'created_at': replica.get('created_at'),
57 'host': replica.get('host'),
58 'status': replica.get('status'), 57 'status': replica.get('status'),
59 'share_network_id': replica.get('share_network_id'), 58 'share_network_id': replica.get('share_network_id'),
60 'replica_state': replica.get('replica_state'), 59 'replica_state': replica.get('replica_state'),
@@ -63,6 +62,7 @@ class ReplicationViewBuilder(common.ViewBuilder):
63 62
64 if context.is_admin: 63 if context.is_admin:
65 replica_dict['share_server_id'] = replica.get('share_server_id') 64 replica_dict['share_server_id'] = replica.get('share_server_id')
65 replica_dict['host'] = replica.get('host')
66 66
67 self.update_versioned_resource_dict(request, replica_dict, replica) 67 self.update_versioned_resource_dict(request, replica_dict, replica)
68 return {'share_replica': replica_dict} 68 return {'share_replica': replica_dict}
diff --git a/manila/api/views/shares.py b/manila/api/views/shares.py
index 7af27a3..dab6183 100644
--- a/manila/api/views/shares.py
+++ b/manila/api/views/shares.py
@@ -80,7 +80,6 @@ class ViewBuilder(common.ViewBuilder):
80 'name': share.get('display_name'), 80 'name': share.get('display_name'),
81 'description': share.get('display_description'), 81 'description': share.get('display_description'),
82 'project_id': share.get('project_id'), 82 'project_id': share.get('project_id'),
83 'host': share_instance.get('host'),
84 'snapshot_id': share.get('snapshot_id'), 83 'snapshot_id': share.get('snapshot_id'),
85 'share_network_id': share_instance.get('share_network_id'), 84 'share_network_id': share_instance.get('share_network_id'),
86 'share_proto': share.get('share_proto'), 85 'share_proto': share.get('share_proto'),
@@ -92,12 +91,12 @@ class ViewBuilder(common.ViewBuilder):
92 'is_public': share.get('is_public'), 91 'is_public': share.get('is_public'),
93 'export_locations': export_locations, 92 'export_locations': export_locations,
94 } 93 }
95
96 self.update_versioned_resource_dict(request, share_dict, share) 94 self.update_versioned_resource_dict(request, share_dict, share)
97 95
98 if context.is_admin: 96 if context.is_admin:
99 share_dict['share_server_id'] = share_instance.get( 97 share_dict['share_server_id'] = share_instance.get(
100 'share_server_id') 98 'share_server_id')
99 share_dict['host'] = share_instance.get('host')
101 return {'share': share_dict} 100 return {'share': share_dict}
102 101
103 @common.ViewBuilder.versioned_method("2.2") 102 @common.ViewBuilder.versioned_method("2.2")
diff --git a/manila/share/api.py b/manila/share/api.py
index 08848cb..03f5c6a 100644
--- a/manila/share/api.py
+++ b/manila/share/api.py
@@ -1518,6 +1518,8 @@ class API(base.Base):
1518 is_public = strutils.bool_from_string(is_public, strict=True) 1518 is_public = strutils.bool_from_string(is_public, strict=True)
1519 1519
1520 # Get filtered list of shares 1520 # Get filtered list of shares
1521 if 'host' in search_opts:
1522 policy.check_policy(context, 'share', 'list_by_host')
1521 if 'share_server_id' in search_opts: 1523 if 'share_server_id' in search_opts:
1522 # NOTE(vponomaryov): this is project_id independent 1524 # NOTE(vponomaryov): this is project_id independent
1523 policy.check_policy(context, 'share', 'list_by_share_server_id') 1525 policy.check_policy(context, 'share', 'list_by_share_server_id')
diff --git a/manila/tests/api/v1/test_shares.py b/manila/tests/api/v1/test_shares.py
index c91fed4..572baf2 100644
--- a/manila/tests/api/v1/test_shares.py
+++ b/manila/tests/api/v1/test_shares.py
@@ -90,7 +90,6 @@ class ShareAPITest(test.TestCase):
90 'export_location': 'fake_location', 90 'export_location': 'fake_location',
91 'export_locations': ['fake_location', 'fake_location2'], 91 'export_locations': ['fake_location', 'fake_location2'],
92 'project_id': 'fakeproject', 92 'project_id': 'fakeproject',
93 'host': 'fakehost',
94 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 93 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
95 'share_proto': 'FAKEPROTO', 94 'share_proto': 'FAKEPROTO',
96 'metadata': {}, 95 'metadata': {},
@@ -123,6 +122,7 @@ class ShareAPITest(test.TestCase):
123 share['share_proto'] = share['share_proto'].upper() 122 share['share_proto'] = share['share_proto'].upper()
124 if admin: 123 if admin:
125 share['share_server_id'] = 'fake_share_server_id' 124 share['share_server_id'] = 'fake_share_server_id'
125 share['host'] = 'fakehost'
126 return {'share': share} 126 return {'share': share}
127 127
128 @ddt.data("1.0", "2.0", "2.1") 128 @ddt.data("1.0", "2.0", "2.1")
@@ -501,7 +501,6 @@ class ShareAPITest(test.TestCase):
501 'share_server_id': 'fake_share_server_id', 501 'share_server_id': 'fake_share_server_id',
502 'share_type_id': 'fake_share_type_id', 502 'share_type_id': 'fake_share_type_id',
503 'snapshot_id': 'fake_snapshot_id', 503 'snapshot_id': 'fake_snapshot_id',
504 'host': 'fake_host',
505 'share_network_id': 'fake_share_network_id', 504 'share_network_id': 'fake_share_network_id',
506 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1 505 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1
507 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2 506 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2
@@ -511,6 +510,8 @@ class ShareAPITest(test.TestCase):
511 'offset': '1', 510 'offset': '1',
512 'is_public': 'False', 511 'is_public': 'False',
513 } 512 }
513 if use_admin_context:
514 search_opts['host'] = 'fake_host'
514 # fake_key should be filtered for non-admin 515 # fake_key should be filtered for non-admin
515 url = '/shares?fake_key=fake_value' 516 url = '/shares?fake_key=fake_value'
516 for k, v in search_opts.items(): 517 for k, v in search_opts.items():
@@ -533,7 +534,6 @@ class ShareAPITest(test.TestCase):
533 'share_server_id': search_opts['share_server_id'], 534 'share_server_id': search_opts['share_server_id'],
534 'share_type_id': search_opts['share_type_id'], 535 'share_type_id': search_opts['share_type_id'],
535 'snapshot_id': search_opts['snapshot_id'], 536 'snapshot_id': search_opts['snapshot_id'],
536 'host': search_opts['host'],
537 'share_network_id': search_opts['share_network_id'], 537 'share_network_id': search_opts['share_network_id'],
538 'metadata': {'k1': 'v1'}, 538 'metadata': {'k1': 'v1'},
539 'extra_specs': {'k2': 'v2'}, 539 'extra_specs': {'k2': 'v2'},
@@ -541,6 +541,7 @@ class ShareAPITest(test.TestCase):
541 } 541 }
542 if use_admin_context: 542 if use_admin_context:
543 search_opts_expected.update({'fake_key': 'fake_value'}) 543 search_opts_expected.update({'fake_key': 'fake_value'})
544 search_opts_expected['host'] = search_opts['host']
544 share_api.API.get_all.assert_called_once_with( 545 share_api.API.get_all.assert_called_once_with(
545 req.environ['manila.context'], 546 req.environ['manila.context'],
546 sort_key=search_opts['sort_key'], 547 sort_key=search_opts['sort_key'],
@@ -590,7 +591,6 @@ class ShareAPITest(test.TestCase):
590 'share_server_id': 'fake_share_server_id', 591 'share_server_id': 'fake_share_server_id',
591 'share_type_id': 'fake_share_type_id', 592 'share_type_id': 'fake_share_type_id',
592 'snapshot_id': 'fake_snapshot_id', 593 'snapshot_id': 'fake_snapshot_id',
593 'host': 'fake_host',
594 'share_network_id': 'fake_share_network_id', 594 'share_network_id': 'fake_share_network_id',
595 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1 595 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1
596 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2 596 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2
@@ -600,6 +600,8 @@ class ShareAPITest(test.TestCase):
600 'offset': '1', 600 'offset': '1',
601 'is_public': 'False', 601 'is_public': 'False',
602 } 602 }
603 if use_admin_context:
604 search_opts['host'] = 'fake_host'
603 # fake_key should be filtered for non-admin 605 # fake_key should be filtered for non-admin
604 url = '/shares/detail?fake_key=fake_value' 606 url = '/shares/detail?fake_key=fake_value'
605 for k, v in search_opts.items(): 607 for k, v in search_opts.items():
@@ -630,7 +632,6 @@ class ShareAPITest(test.TestCase):
630 'share_server_id': search_opts['share_server_id'], 632 'share_server_id': search_opts['share_server_id'],
631 'share_type_id': search_opts['share_type_id'], 633 'share_type_id': search_opts['share_type_id'],
632 'snapshot_id': search_opts['snapshot_id'], 634 'snapshot_id': search_opts['snapshot_id'],
633 'host': search_opts['host'],
634 'share_network_id': search_opts['share_network_id'], 635 'share_network_id': search_opts['share_network_id'],
635 'metadata': {'k1': 'v1'}, 636 'metadata': {'k1': 'v1'},
636 'extra_specs': {'k2': 'v2'}, 637 'extra_specs': {'k2': 'v2'},
@@ -638,6 +639,7 @@ class ShareAPITest(test.TestCase):
638 } 639 }
639 if use_admin_context: 640 if use_admin_context:
640 search_opts_expected.update({'fake_key': 'fake_value'}) 641 search_opts_expected.update({'fake_key': 'fake_value'})
642 search_opts_expected['host'] = search_opts['host']
641 share_api.API.get_all.assert_called_once_with( 643 share_api.API.get_all.assert_called_once_with(
642 req.environ['manila.context'], 644 req.environ['manila.context'],
643 sort_key=search_opts['sort_key'], 645 sort_key=search_opts['sort_key'],
@@ -656,8 +658,9 @@ class ShareAPITest(test.TestCase):
656 shares[1]['share_type_id'], result['shares'][0]['share_type']) 658 shares[1]['share_type_id'], result['shares'][0]['share_type'])
657 self.assertEqual( 659 self.assertEqual(
658 shares[1]['snapshot_id'], result['shares'][0]['snapshot_id']) 660 shares[1]['snapshot_id'], result['shares'][0]['snapshot_id'])
659 self.assertEqual( 661 if use_admin_context:
660 shares[1]['instance']['host'], result['shares'][0]['host']) 662 self.assertEqual(
663 shares[1]['instance']['host'], result['shares'][0]['host'])
661 self.assertEqual( 664 self.assertEqual(
662 shares[1]['instance']['share_network_id'], 665 shares[1]['instance']['share_network_id'],
663 result['shares'][0]['share_network_id']) 666 result['shares'][0]['share_network_id'])
@@ -668,42 +671,41 @@ class ShareAPITest(test.TestCase):
668 def test_share_list_detail_with_search_opts_by_admin(self): 671 def test_share_list_detail_with_search_opts_by_admin(self):
669 self._share_list_detail_with_search_opts(use_admin_context=True) 672 self._share_list_detail_with_search_opts(use_admin_context=True)
670 673
671 def _list_detail_common_expected(self): 674 def _list_detail_common_expected(self, admin=False):
672 return { 675 share_dict = {
673 'shares': [ 676 'status': 'fakestatus',
677 'description': 'displaydesc',
678 'export_location': 'fake_location',
679 'export_locations': ['fake_location', 'fake_location2'],
680 'availability_zone': 'fakeaz',
681 'name': 'displayname',
682 'share_proto': 'FAKEPROTO',
683 'metadata': {},
684 'project_id': 'fakeproject',
685
686 'id': '1',
687 'snapshot_id': '2',
688 'snapshot_support': True,
689 'share_network_id': None,
690 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
691 'size': 1,
692 'share_type': '1',
693 'volume_type': '1',
694 'is_public': False,
695 'links': [
674 { 696 {
675 'status': 'fakestatus', 697 'href': 'http://localhost/v1/fake/shares/1',
676 'description': 'displaydesc', 698 'rel': 'self'
677 'export_location': 'fake_location', 699 },
678 'export_locations': ['fake_location', 'fake_location2'], 700 {
679 'availability_zone': 'fakeaz', 701 'href': 'http://localhost/fake/shares/1',
680 'name': 'displayname', 702 'rel': 'bookmark'
681 'share_proto': 'FAKEPROTO',
682 'metadata': {},
683 'project_id': 'fakeproject',
684 'host': 'fakehost',
685 'id': '1',
686 'snapshot_id': '2',
687 'snapshot_support': True,
688 'share_network_id': None,
689 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
690 'size': 1,
691 'share_type': '1',
692 'volume_type': '1',
693 'is_public': False,
694 'links': [
695 {
696 'href': 'http://localhost/v1/fake/shares/1',
697 'rel': 'self'
698 },
699 {
700 'href': 'http://localhost/fake/shares/1',
701 'rel': 'bookmark'
702 }
703 ],
704 } 703 }
705 ] 704 ],
706 } 705 }
706 if admin:
707 share_dict['host'] = 'fakehost'
708 return {'shares': [share_dict]}
707 709
708 def _list_detail_test_common(self, req, expected): 710 def _list_detail_test_common(self, req, expected):
709 self.mock_object(share_api.API, 'get_all', 711 self.mock_object(share_api.API, 'get_all',
diff --git a/manila/tests/api/v2/test_share_replicas.py b/manila/tests/api/v2/test_share_replicas.py
index 196a757..f847579 100644
--- a/manila/tests/api/v2/test_share_replicas.py
+++ b/manila/tests/api/v2/test_share_replicas.py
@@ -81,7 +81,6 @@ class ShareReplicasApiTest(test.TestCase):
81 81
82 if not summary: 82 if not summary:
83 expected_replica.update({ 83 expected_replica.update({
84 'host': replica['host'],
85 'availability_zone': None, 84 'availability_zone': None,
86 'created_at': None, 85 'created_at': None,
87 'share_network_id': replica['share_network_id'], 86 'share_network_id': replica['share_network_id'],
@@ -90,6 +89,7 @@ class ShareReplicasApiTest(test.TestCase):
90 89
91 if admin: 90 if admin:
92 expected_replica['share_server_id'] = replica['share_server_id'] 91 expected_replica['share_server_id'] = replica['share_server_id']
92 expected_replica['host'] = replica['host']
93 93
94 return replica, expected_replica 94 return replica, expected_replica
95 95
diff --git a/manila/tests/api/v2/test_shares.py b/manila/tests/api/v2/test_shares.py
index 8a99e38..72be15f 100644
--- a/manila/tests/api/v2/test_shares.py
+++ b/manila/tests/api/v2/test_shares.py
@@ -105,7 +105,6 @@ class ShareAPITest(test.TestCase):
105 'export_location': 'fake_location', 105 'export_location': 'fake_location',
106 'export_locations': ['fake_location', 'fake_location2'], 106 'export_locations': ['fake_location', 'fake_location2'],
107 'project_id': 'fakeproject', 107 'project_id': 'fakeproject',
108 'host': 'fakehost',
109 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1), 108 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
110 'share_proto': 'FAKEPROTO', 109 'share_proto': 'FAKEPROTO',
111 'metadata': {}, 110 'metadata': {},
@@ -140,6 +139,7 @@ class ShareAPITest(test.TestCase):
140 share['share_proto'] = share['share_proto'].upper() 139 share['share_proto'] = share['share_proto'].upper()
141 if admin: 140 if admin:
142 share['share_server_id'] = 'fake_share_server_id' 141 share['share_server_id'] = 'fake_share_server_id'
142 share['host'] = 'fakehost'
143 return {'share': share} 143 return {'share': share}
144 144
145 def test__revert(self): 145 def test__revert(self):
@@ -1414,7 +1414,6 @@ class ShareAPITest(test.TestCase):
1414 'share_server_id': 'fake_share_server_id', 1414 'share_server_id': 'fake_share_server_id',
1415 'share_type_id': 'fake_share_type_id', 1415 'share_type_id': 'fake_share_type_id',
1416 'snapshot_id': 'fake_snapshot_id', 1416 'snapshot_id': 'fake_snapshot_id',
1417 'host': 'fake_host',
1418 'share_network_id': 'fake_share_network_id', 1417 'share_network_id': 'fake_share_network_id',
1419 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1 1418 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1
1420 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2 1419 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2
@@ -1424,6 +1423,8 @@ class ShareAPITest(test.TestCase):
1424 'offset': '1', 1423 'offset': '1',
1425 'is_public': 'False', 1424 'is_public': 'False',
1426 } 1425 }
1426 if use_admin_context:
1427 search_opts['host'] = 'fake_host'
1427 # fake_key should be filtered for non-admin 1428 # fake_key should be filtered for non-admin
1428 url = '/shares?fake_key=fake_value' 1429 url = '/shares?fake_key=fake_value'
1429 for k, v in search_opts.items(): 1430 for k, v in search_opts.items():
@@ -1446,7 +1447,7 @@ class ShareAPITest(test.TestCase):
1446 'share_server_id': search_opts['share_server_id'], 1447 'share_server_id': search_opts['share_server_id'],
1447 'share_type_id': search_opts['share_type_id'], 1448 'share_type_id': search_opts['share_type_id'],
1448 'snapshot_id': search_opts['snapshot_id'], 1449 'snapshot_id': search_opts['snapshot_id'],
1449 'host': search_opts['host'], 1450
1450 'share_network_id': search_opts['share_network_id'], 1451 'share_network_id': search_opts['share_network_id'],
1451 'metadata': {'k1': 'v1'}, 1452 'metadata': {'k1': 'v1'},
1452 'extra_specs': {'k2': 'v2'}, 1453 'extra_specs': {'k2': 'v2'},
@@ -1454,6 +1455,7 @@ class ShareAPITest(test.TestCase):
1454 } 1455 }
1455 if use_admin_context: 1456 if use_admin_context:
1456 search_opts_expected.update({'fake_key': 'fake_value'}) 1457 search_opts_expected.update({'fake_key': 'fake_value'})
1458 search_opts_expected['host'] = search_opts['host']
1457 share_api.API.get_all.assert_called_once_with( 1459 share_api.API.get_all.assert_called_once_with(
1458 req.environ['manila.context'], 1460 req.environ['manila.context'],
1459 sort_key=search_opts['sort_key'], 1461 sort_key=search_opts['sort_key'],
@@ -1503,7 +1505,6 @@ class ShareAPITest(test.TestCase):
1503 'share_server_id': 'fake_share_server_id', 1505 'share_server_id': 'fake_share_server_id',
1504 'share_type_id': 'fake_share_type_id', 1506 'share_type_id': 'fake_share_type_id',
1505 'snapshot_id': 'fake_snapshot_id', 1507 'snapshot_id': 'fake_snapshot_id',
1506 'host': 'fake_host',
1507 'share_network_id': 'fake_share_network_id', 1508 'share_network_id': 'fake_share_network_id',
1508 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1 1509 'metadata': '%7B%27k1%27%3A+%27v1%27%7D', # serialized k1=v1
1509 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2 1510 'extra_specs': '%7B%27k2%27%3A+%27v2%27%7D', # serialized k2=v2
@@ -1513,6 +1514,8 @@ class ShareAPITest(test.TestCase):
1513 'offset': '1', 1514 'offset': '1',
1514 'is_public': 'False', 1515 'is_public': 'False',
1515 } 1516 }
1517 if use_admin_context:
1518 search_opts['host'] = 'fake_host'
1516 # fake_key should be filtered for non-admin 1519 # fake_key should be filtered for non-admin
1517 url = '/shares/detail?fake_key=fake_value' 1520 url = '/shares/detail?fake_key=fake_value'
1518 for k, v in search_opts.items(): 1521 for k, v in search_opts.items():
@@ -1545,7 +1548,6 @@ class ShareAPITest(test.TestCase):
1545 'share_server_id': search_opts['share_server_id'], 1548 'share_server_id': search_opts['share_server_id'],
1546 'share_type_id': search_opts['share_type_id'], 1549 'share_type_id': search_opts['share_type_id'],
1547 'snapshot_id': search_opts['snapshot_id'], 1550 'snapshot_id': search_opts['snapshot_id'],
1548 'host': search_opts['host'],
1549 'share_network_id': search_opts['share_network_id'], 1551 'share_network_id': search_opts['share_network_id'],
1550 'metadata': {'k1': 'v1'}, 1552 'metadata': {'k1': 'v1'},
1551 'extra_specs': {'k2': 'v2'}, 1553 'extra_specs': {'k2': 'v2'},
@@ -1553,6 +1555,7 @@ class ShareAPITest(test.TestCase):
1553 } 1555 }
1554 if use_admin_context: 1556 if use_admin_context:
1555 search_opts_expected.update({'fake_key': 'fake_value'}) 1557 search_opts_expected.update({'fake_key': 'fake_value'})
1558 search_opts_expected['host'] = search_opts['host']
1556 share_api.API.get_all.assert_called_once_with( 1559 share_api.API.get_all.assert_called_once_with(
1557 req.environ['manila.context'], 1560 req.environ['manila.context'],
1558 sort_key=search_opts['sort_key'], 1561 sort_key=search_opts['sort_key'],
@@ -1571,8 +1574,9 @@ class ShareAPITest(test.TestCase):
1571 shares[1]['share_type_id'], result['shares'][0]['share_type']) 1574 shares[1]['share_type_id'], result['shares'][0]['share_type'])
1572 self.assertEqual( 1575 self.assertEqual(
1573 shares[1]['snapshot_id'], result['shares'][0]['snapshot_id']) 1576 shares[1]['snapshot_id'], result['shares'][0]['snapshot_id'])
1574 self.assertEqual( 1577 if use_admin_context:
1575 shares[1]['instance']['host'], result['shares'][0]['host']) 1578 self.assertEqual(
1579 shares[1]['instance']['host'], result['shares'][0]['host'])
1576 self.assertEqual( 1580 self.assertEqual(
1577 shares[1]['instance']['share_network_id'], 1581 shares[1]['instance']['share_network_id'],
1578 result['shares'][0]['share_network_id']) 1582 result['shares'][0]['share_network_id'])
@@ -1583,42 +1587,40 @@ class ShareAPITest(test.TestCase):
1583 def test_share_list_detail_with_search_opts_by_admin(self): 1587 def test_share_list_detail_with_search_opts_by_admin(self):
1584 self._share_list_detail_with_search_opts(use_admin_context=True) 1588 self._share_list_detail_with_search_opts(use_admin_context=True)
1585 1589
1586 def _list_detail_common_expected(self): 1590 def _list_detail_common_expected(self, admin=False):
1587 return { 1591 share_dict = {
1588 'shares': [ 1592 'status': 'fakestatus',
1593 'description': 'displaydesc',
1594 'export_location': 'fake_location',
1595 'export_locations': ['fake_location', 'fake_location2'],
1596 'availability_zone': 'fakeaz',
1597 'name': 'displayname',
1598 'share_proto': 'FAKEPROTO',
1599 'metadata': {},
1600 'project_id': 'fakeproject',
1601 'id': '1',
1602 'snapshot_id': '2',
1603 'snapshot_support': True,
1604 'share_network_id': None,
1605 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
1606 'size': 1,
1607 'share_type': '1',
1608 'volume_type': '1',
1609 'is_public': False,
1610 'links': [
1589 { 1611 {
1590 'status': 'fakestatus', 1612 'href': 'http://localhost/v1/fake/shares/1',
1591 'description': 'displaydesc', 1613 'rel': 'self'
1592 'export_location': 'fake_location', 1614 },
1593 'export_locations': ['fake_location', 'fake_location2'], 1615 {
1594 'availability_zone': 'fakeaz', 1616 'href': 'http://localhost/fake/shares/1',
1595 'name': 'displayname', 1617 'rel': 'bookmark'
1596 'share_proto': 'FAKEPROTO',
1597 'metadata': {},
1598 'project_id': 'fakeproject',
1599 'host': 'fakehost',
1600 'id': '1',
1601 'snapshot_id': '2',
1602 'snapshot_support': True,
1603 'share_network_id': None,
1604 'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
1605 'size': 1,
1606 'share_type': '1',
1607 'volume_type': '1',
1608 'is_public': False,
1609 'links': [
1610 {
1611 'href': 'http://localhost/v1/fake/shares/1',
1612 'rel': 'self'
1613 },
1614 {
1615 'href': 'http://localhost/fake/shares/1',
1616 'rel': 'bookmark'
1617 }
1618 ],
1619 } 1618 }
1620 ] 1619 ],
1621 } 1620 }
1621 if admin:
1622 share_dict['host'] = 'fakehost'
1623 return {'shares': [share_dict]}
1622 1624
1623 def _list_detail_test_common(self, req, expected): 1625 def _list_detail_test_common(self, req, expected):
1624 self.mock_object(share_api.API, 'get_all', 1626 self.mock_object(share_api.API, 'get_all',
@@ -1692,7 +1694,6 @@ class ShareAPITest(test.TestCase):
1692 'metadata': {}, 1694 'metadata': {},
1693 'project_id': 'fakeproject', 1695 'project_id': 'fakeproject',
1694 'access_rules_status': 'active', 1696 'access_rules_status': 'active',
1695 'host': 'fakehost',
1696 'id': '1', 1697 'id': '1',
1697 'snapshot_id': '2', 1698 'snapshot_id': '2',
1698 'share_network_id': None, 1699 'share_network_id': None,
diff --git a/manila/tests/share/test_api.py b/manila/tests/share/test_api.py
index 5086f18..125a06a 100644
--- a/manila/tests/share/test_api.py
+++ b/manila/tests/share/test_api.py
@@ -249,24 +249,29 @@ class ShareAPITestCase(test.TestCase):
249 ctx, sort_dir='desc', sort_key='created_at', filters={}) 249 ctx, sort_dir='desc', sort_key='created_at', filters={})
250 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES, shares) 250 self.assertEqual(_FAKE_LIST_OF_ALL_SHARES, shares)
251 251
252 def test_get_all_non_admin_filter_by_share_server(self): 252 @ddt.data(
253 ({'share_server_id': 'fake_share_server'}, 'list_by_share_server_id'),
254 ({'host': 'fake_host'}, 'list_by_host'),
255 )
256 @ddt.unpack
257 def test_get_all_by_non_admin_using_admin_filter(self, filters, policy):
253 258
254 def fake_policy_checker(*args, **kwargs): 259 def fake_policy_checker(*args, **kwargs):
255 if 'list_by_share_server_id' == args[2] and not args[0].is_admin: 260 if policy == args[2] and not args[0].is_admin:
256 raise exception.NotAuthorized 261 raise exception.NotAuthorized
257 262
258 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False) 263 ctx = context.RequestContext('fake_uid', 'fake_pid_1', is_admin=False)
259 self.mock_object(share_api.policy, 'check_policy', 264 self.mock_object(
260 mock.Mock(side_effect=fake_policy_checker)) 265 share_api.policy, 'check_policy',
266 mock.Mock(side_effect=fake_policy_checker))
267
261 self.assertRaises( 268 self.assertRaises(
262 exception.NotAuthorized, 269 exception.NotAuthorized,
263 self.api.get_all, 270 self.api.get_all, ctx, filters)
264 ctx, 271
265 {'share_server_id': 'fake'},
266 )
267 share_api.policy.check_policy.assert_has_calls([ 272 share_api.policy.check_policy.assert_has_calls([
268 mock.call(ctx, 'share', 'get_all'), 273 mock.call(ctx, 'share', 'get_all'),
269 mock.call(ctx, 'share', 'list_by_share_server_id'), 274 mock.call(ctx, 'share', policy),
270 ]) 275 ])
271 276
272 def test_get_all_admin_filter_by_share_server_and_all_tenants(self): 277 def test_get_all_admin_filter_by_share_server_and_all_tenants(self):
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
index c84e513..260e85d 100644
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -671,7 +671,8 @@ class BaseSharesTest(test.BaseTestCase):
671 def get_pools_for_replication_domain(self): 671 def get_pools_for_replication_domain(self):
672 # Get the list of pools for the replication domain 672 # Get the list of pools for the replication domain
673 pools = self.admin_client.list_pools(detail=True)['pools'] 673 pools = self.admin_client.list_pools(detail=True)['pools']
674 instance_host = self.shares[0]['host'] 674 instance_host = self.admin_client.get_share(
675 self.shares[0]['id'])['host']
675 host_pool = [p for p in pools if p['name'] == instance_host][0] 676 host_pool = [p for p in pools if p['name'] == instance_host][0]
676 rep_domain = host_pool['capabilities']['replication_domain'] 677 rep_domain = host_pool['capabilities']['replication_domain']
677 pools_in_rep_domain = [p for p in pools if p['capabilities'][ 678 pools_in_rep_domain = [p for p in pools if p['capabilities'][
diff --git a/manila_tempest_tests/tests/api/test_replication.py b/manila_tempest_tests/tests/api/test_replication.py
index 1a1a7c9..589f47c 100644
--- a/manila_tempest_tests/tests/api/test_replication.py
+++ b/manila_tempest_tests/tests/api/test_replication.py
@@ -25,7 +25,7 @@ from manila_tempest_tests.tests.api import base
25CONF = config.CONF 25CONF = config.CONF
26_MIN_SUPPORTED_MICROVERSION = '2.11' 26_MIN_SUPPORTED_MICROVERSION = '2.11'
27SUMMARY_KEYS = ['share_id', 'id', 'replica_state', 'status'] 27SUMMARY_KEYS = ['share_id', 'id', 'replica_state', 'status']
28DETAIL_KEYS = SUMMARY_KEYS + ['availability_zone', 'host', 'updated_at', 28DETAIL_KEYS = SUMMARY_KEYS + ['availability_zone', 'updated_at',
29 'share_network_id', 'created_at'] 29 'share_network_id', 'created_at']
30 30
31 31
@@ -201,7 +201,7 @@ class ReplicationTest(base.BaseSharesMixedTest):
201 cleanup_in_class=False) 201 cleanup_in_class=False)
202 self.shares_v2_client.get_share_replica(share_replica2['id']) 202 self.shares_v2_client.get_share_replica(share_replica2['id'])
203 203
204 share_replicas = self.shares_v2_client.list_share_replicas( 204 share_replicas = self.admin_client.list_share_replicas(
205 share_id=self.shares[0]["id"]) 205 share_id=self.shares[0]["id"])
206 replica_host_set = {r['host'] for r in share_replicas} 206 replica_host_set = {r['host'] for r in share_replicas}
207 207
diff --git a/manila_tempest_tests/tests/api/test_replication_negative.py b/manila_tempest_tests/tests/api/test_replication_negative.py
index c5ee021..21a5ef2 100644
--- a/manila_tempest_tests/tests/api/test_replication_negative.py
+++ b/manila_tempest_tests/tests/api/test_replication_negative.py
@@ -185,7 +185,7 @@ class ReplicationNegativeTest(base.BaseSharesMixedTest):
185 hosts = [p['name'] for p in pools] 185 hosts = [p['name'] for p in pools]
186 self.create_share_replica(self.share1["id"], self.replica_zone, 186 self.create_share_replica(self.share1["id"], self.replica_zone,
187 cleanup_in_class=False) 187 cleanup_in_class=False)
188 share_host = self.share1['host'] 188 share_host = self.admin_client.get_share(self.share1['id'])['host']
189 189
190 for host in hosts: 190 for host in hosts:
191 if host != share_host: 191 if host != share_host:
diff --git a/manila_tempest_tests/tests/api/test_shares.py b/manila_tempest_tests/tests/api/test_shares.py
index 277f76e..a02b5f8 100644
--- a/manila_tempest_tests/tests/api/test_shares.py
+++ b/manila_tempest_tests/tests/api/test_shares.py
@@ -42,7 +42,7 @@ class SharesNFSTest(base.BaseSharesTest):
42 share = self.create_share(self.protocol) 42 share = self.create_share(self.protocol)
43 detailed_elements = {'name', 'id', 'availability_zone', 43 detailed_elements = {'name', 'id', 'availability_zone',
44 'description', 'project_id', 44 'description', 'project_id',
45 'host', 'created_at', 'share_proto', 'metadata', 45 'created_at', 'share_proto', 'metadata',
46 'size', 'snapshot_id', 'share_network_id', 46 'size', 'snapshot_id', 'share_network_id',
47 'status', 'share_type', 'volume_type', 'links', 47 'status', 'share_type', 'volume_type', 'links',
48 'is_public'} 48 'is_public'}
diff --git a/manila_tempest_tests/tests/api/test_shares_actions.py b/manila_tempest_tests/tests/api/test_shares_actions.py
index cfebdd3..0f59d7a 100644
--- a/manila_tempest_tests/tests/api/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/test_shares_actions.py
@@ -88,7 +88,7 @@ class SharesActionsTest(base.BaseSharesTest):
88 "status", "description", "links", "availability_zone", 88 "status", "description", "links", "availability_zone",
89 "created_at", "project_id", "volume_type", "share_proto", "name", 89 "created_at", "project_id", "volume_type", "share_proto", "name",
90 "snapshot_id", "id", "size", "share_network_id", "metadata", 90 "snapshot_id", "id", "size", "share_network_id", "metadata",
91 "host", "snapshot_id", "is_public", 91 "snapshot_id", "is_public",
92 ] 92 ]
93 if utils.is_microversion_lt(version, '2.9'): 93 if utils.is_microversion_lt(version, '2.9'):
94 expected_keys.extend(["export_location", "export_locations"]) 94 expected_keys.extend(["export_location", "export_locations"])
@@ -196,7 +196,7 @@ class SharesActionsTest(base.BaseSharesTest):
196 "status", "description", "links", "availability_zone", 196 "status", "description", "links", "availability_zone",
197 "created_at", "project_id", "volume_type", "share_proto", "name", 197 "created_at", "project_id", "volume_type", "share_proto", "name",
198 "snapshot_id", "id", "size", "share_network_id", "metadata", 198 "snapshot_id", "id", "size", "share_network_id", "metadata",
199 "host", "snapshot_id", "is_public", "share_type", 199 "snapshot_id", "is_public", "share_type",
200 ] 200 ]
201 if utils.is_microversion_lt(version, '2.9'): 201 if utils.is_microversion_lt(version, '2.9'):
202 keys.extend(["export_location", "export_locations"]) 202 keys.extend(["export_location", "export_locations"])
@@ -284,19 +284,6 @@ class SharesActionsTest(base.BaseSharesTest):
284 self.assertFalse(self.shares[1]['id'] in [s['id'] for s in shares]) 284 self.assertFalse(self.shares[1]['id'] in [s['id'] for s in shares])
285 285
286 @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND) 286 @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
287 def test_list_shares_with_detail_filter_by_host(self):
288 base_share = self.shares_client.get_share(self.shares[0]['id'])
289 filters = {'host': base_share['host']}
290
291 # list shares
292 shares = self.shares_client.list_shares_with_detail(params=filters)
293
294 # verify response
295 self.assertGreater(len(shares), 0)
296 for share in shares:
297 self.assertEqual(filters['host'], share['host'])
298
299 @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
300 @testtools.skipIf( 287 @testtools.skipIf(
301 not CONF.share.multitenancy_enabled, "Only for multitenancy.") 288 not CONF.share.multitenancy_enabled, "Only for multitenancy.")
302 def test_list_shares_with_detail_filter_by_share_network_id(self): 289 def test_list_shares_with_detail_filter_by_share_network_id(self):
@@ -407,7 +394,7 @@ class SharesActionsTest(base.BaseSharesTest):
407 394
408 keys = [ 395 keys = [
409 "status", "description", "links", "availability_zone", 396 "status", "description", "links", "availability_zone",
410 "created_at", "export_location", "share_proto", "host", 397 "created_at", "export_location", "share_proto",
411 "name", "snapshot_id", "id", "size", "project_id", "is_public", 398 "name", "snapshot_id", "id", "size", "project_id", "is_public",
412 ] 399 ]
413 [self.assertIn(key, sh.keys()) for sh in shares for key in keys] 400 [self.assertIn(key, sh.keys()) for sh in shares for key in keys]
diff --git a/manila_tempest_tests/tests/api/test_shares_negative.py b/manila_tempest_tests/tests/api/test_shares_negative.py
index 42204e1..3229f2f 100644
--- a/manila_tempest_tests/tests/api/test_shares_negative.py
+++ b/manila_tempest_tests/tests/api/test_shares_negative.py
@@ -194,6 +194,12 @@ class SharesAPIOnlyNegativeTest(base.BaseSharesTest):
194 'fake-type') 194 'fake-type')
195 195
196 @tc.attr(base.TAG_NEGATIVE, base.TAG_API) 196 @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
197 def test_list_by_user_with_host_filter(self):
198 self.assertRaises(lib_exc.Forbidden,
199 self.shares_v2_client.list_shares,
200 params={'host': 'fake_host'})
201
202 @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
197 def test_list_by_share_server_by_user(self): 203 def test_list_by_share_server_by_user(self):
198 self.assertRaises(lib_exc.Forbidden, 204 self.assertRaises(lib_exc.Forbidden,
199 self.shares_client.list_shares, 205 self.shares_client.list_shares,
diff --git a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
index cd77294..835e325 100644
--- a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
+++ b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
@@ -312,7 +312,7 @@ class ShareBasicOpsBase(manager.ShareScenarioTest):
312 instance = self.boot_instance(wait_until="BUILD") 312 instance = self.boot_instance(wait_until="BUILD")
313 self.create_share() 313 self.create_share()
314 instance = self.wait_for_active_instance(instance["id"]) 314 instance = self.wait_for_active_instance(instance["id"])
315 self.share = self.shares_client.get_share(self.share['id']) 315 self.share = self.shares_admin_v2_client.get_share(self.share['id'])
316 316
317 default_type = self.shares_v2_client.list_share_types( 317 default_type = self.shares_v2_client.list_share_types(
318 default=True)['share_type'] 318 default=True)['share_type']
diff --git a/releasenotes/notes/remove-host-field-from-shares-and-replicas-a087f85bc4a4ba45.yaml b/releasenotes/notes/remove-host-field-from-shares-and-replicas-a087f85bc4a4ba45.yaml
new file mode 100644
index 0000000..f620026
--- /dev/null
+++ b/releasenotes/notes/remove-host-field-from-shares-and-replicas-a087f85bc4a4ba45.yaml
@@ -0,0 +1,10 @@
1---
2critical:
3 - The "host" field is no longer returned in the JSON response of the /shares
4 and /share-replicas APIs when these APIs are invoked with non-admin
5 privileges. Applications that depend on this field must be updated as
6 necessary. The value of this field is privileged information and the
7 request context must specify administrator privileges when using these
8 APIs for the "host" field to be present. The use of "host" as a filter
9 key in the GET /shares API is controlled with the policy "list_by_host".
10 This policy defaults to "rule:admin_api".