python-openstackclient 10.0.0__py3-none-any.whl → 10.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. openstackclient/common/availability_zone.py +1 -1
  2. openstackclient/common/module.py +21 -27
  3. openstackclient/common/pagination.py +42 -4
  4. openstackclient/common/project_cleanup.py +1 -2
  5. openstackclient/common/quota.py +9 -5
  6. openstackclient/compute/v2/flavor.py +3 -1
  7. openstackclient/compute/v2/hypervisor.py +2 -0
  8. openstackclient/compute/v2/keypair.py +6 -2
  9. openstackclient/compute/v2/server.py +21 -12
  10. openstackclient/compute/v2/server_event.py +8 -1
  11. openstackclient/compute/v2/server_group.py +2 -0
  12. openstackclient/compute/v2/server_migration.py +3 -0
  13. openstackclient/compute/v2/server_volume.py +3 -1
  14. openstackclient/compute/v2/service.py +3 -1
  15. openstackclient/compute/v2/usage.py +2 -2
  16. openstackclient/identity/common.py +5 -1
  17. openstackclient/identity/v3/access_rule.py +6 -0
  18. openstackclient/identity/v3/application_credential.py +10 -3
  19. openstackclient/identity/v3/credential.py +4 -2
  20. openstackclient/identity/v3/domain.py +4 -2
  21. openstackclient/identity/v3/endpoint.py +57 -45
  22. openstackclient/identity/v3/federation_protocol.py +7 -5
  23. openstackclient/identity/v3/group.py +11 -10
  24. openstackclient/identity/v3/identity_provider.py +4 -1
  25. openstackclient/identity/v3/limit.py +5 -2
  26. openstackclient/identity/v3/mapping.py +36 -19
  27. openstackclient/identity/v3/project.py +18 -5
  28. openstackclient/identity/v3/region.py +4 -2
  29. openstackclient/identity/v3/registered_limit.py +3 -2
  30. openstackclient/identity/v3/role.py +2 -1
  31. openstackclient/identity/v3/role_assignment.py +3 -2
  32. openstackclient/identity/v3/service.py +4 -2
  33. openstackclient/identity/v3/service_provider.py +4 -2
  34. openstackclient/identity/v3/trust.py +8 -5
  35. openstackclient/identity/v3/user.py +38 -11
  36. openstackclient/image/v2/cache.py +2 -2
  37. openstackclient/image/v2/image.py +15 -9
  38. openstackclient/image/v2/metadef_namespaces.py +11 -10
  39. openstackclient/image/v2/metadef_objects.py +5 -5
  40. openstackclient/image/v2/metadef_properties.py +7 -4
  41. openstackclient/image/v2/task.py +11 -22
  42. openstackclient/network/utils.py +0 -41
  43. openstackclient/network/v2/address_group.py +13 -1
  44. openstackclient/network/v2/address_scope.py +13 -8
  45. openstackclient/network/v2/bgpvpn/bgpvpn.py +33 -19
  46. openstackclient/network/v2/bgpvpn/network_association.py +25 -13
  47. openstackclient/network/v2/bgpvpn/port_association.py +35 -21
  48. openstackclient/network/v2/bgpvpn/router_association.py +27 -14
  49. openstackclient/network/v2/default_security_group_rule.py +14 -6
  50. openstackclient/network/v2/floating_ip.py +12 -4
  51. openstackclient/network/v2/floating_ip_port_forwarding.py +12 -2
  52. openstackclient/network/v2/fwaas/group.py +34 -1
  53. openstackclient/network/v2/fwaas/rule.py +39 -3
  54. openstackclient/network/v2/ip_availability.py +13 -4
  55. openstackclient/network/v2/l3_conntrack_helper.py +14 -1
  56. openstackclient/network/v2/local_ip.py +4 -1
  57. openstackclient/network/v2/local_ip_association.py +4 -1
  58. openstackclient/network/v2/ndp_proxy.py +4 -1
  59. openstackclient/network/v2/network.py +87 -20
  60. openstackclient/network/v2/network_agent.py +32 -10
  61. openstackclient/network/v2/network_auto_allocated_topology.py +6 -5
  62. openstackclient/network/v2/network_flavor.py +19 -6
  63. openstackclient/network/v2/network_flavor_profile.py +20 -6
  64. openstackclient/network/v2/network_meter.py +19 -6
  65. openstackclient/network/v2/network_meter_rule.py +20 -2
  66. openstackclient/network/v2/network_qos_policy.py +15 -7
  67. openstackclient/network/v2/network_qos_rule.py +16 -1
  68. openstackclient/network/v2/network_qos_rule_type.py +16 -5
  69. openstackclient/network/v2/network_rbac.py +12 -5
  70. openstackclient/network/v2/network_segment.py +13 -1
  71. openstackclient/network/v2/network_segment_range.py +15 -3
  72. openstackclient/network/v2/network_trunk.py +4 -1
  73. openstackclient/network/v2/port.py +88 -12
  74. openstackclient/network/v2/router.py +27 -16
  75. openstackclient/network/v2/security_group.py +18 -49
  76. openstackclient/network/v2/security_group_rule.py +18 -5
  77. openstackclient/network/v2/subnet.py +15 -7
  78. openstackclient/network/v2/subnet_pool.py +13 -8
  79. openstackclient/network/v2/taas/tap_flow.py +13 -3
  80. openstackclient/network/v2/taas/tap_mirror.py +7 -4
  81. openstackclient/network/v2/taas/tap_service.py +4 -1
  82. openstackclient/object/v1/container.py +3 -1
  83. openstackclient/object/v1/object.py +3 -1
  84. openstackclient/tests/functional/identity/v3/common.py +34 -0
  85. openstackclient/tests/functional/identity/v3/test_application_credential.py +1 -1
  86. openstackclient/tests/functional/identity/v3/test_mapping.py +81 -0
  87. openstackclient/tests/functional/volume/v3/test_volume_group.py +163 -0
  88. openstackclient/tests/unit/common/test_limits.py +1 -1
  89. openstackclient/tests/unit/common/test_module.py +77 -44
  90. openstackclient/tests/unit/common/test_quota.py +9 -0
  91. openstackclient/tests/unit/compute/v2/fakes.py +1 -57
  92. openstackclient/tests/unit/compute/v2/test_agent.py +4 -4
  93. openstackclient/tests/unit/compute/v2/test_aggregate.py +1 -1
  94. openstackclient/tests/unit/compute/v2/test_console.py +2 -2
  95. openstackclient/tests/unit/compute/v2/test_console_connection.py +1 -1
  96. openstackclient/tests/unit/compute/v2/test_flavor.py +1 -1
  97. openstackclient/tests/unit/compute/v2/test_host.py +3 -3
  98. openstackclient/tests/unit/compute/v2/test_hypervisor.py +2 -2
  99. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -1
  100. openstackclient/tests/unit/compute/v2/test_keypair.py +1 -1
  101. openstackclient/tests/unit/compute/v2/test_server.py +15 -15
  102. openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -1
  103. openstackclient/tests/unit/compute/v2/test_server_event.py +2 -2
  104. openstackclient/tests/unit/compute/v2/test_server_group.py +1 -1
  105. openstackclient/tests/unit/compute/v2/test_server_image.py +1 -1
  106. openstackclient/tests/unit/compute/v2/test_server_migration.py +4 -4
  107. openstackclient/tests/unit/compute/v2/test_server_share.py +4 -4
  108. openstackclient/tests/unit/compute/v2/test_server_volume.py +2 -2
  109. openstackclient/tests/unit/compute/v2/test_service.py +3 -3
  110. openstackclient/tests/unit/compute/v2/test_usage.py +1 -1
  111. openstackclient/tests/unit/identity/v2_0/fakes.py +3 -7
  112. openstackclient/tests/unit/identity/v2_0/test_endpoint.py +1 -1
  113. openstackclient/tests/unit/identity/v2_0/test_project.py +1 -1
  114. openstackclient/tests/unit/identity/v2_0/test_role.py +1 -1
  115. openstackclient/tests/unit/identity/v2_0/test_role_assignment.py +1 -1
  116. openstackclient/tests/unit/identity/v2_0/test_service.py +1 -1
  117. openstackclient/tests/unit/identity/v2_0/test_token.py +2 -2
  118. openstackclient/tests/unit/identity/v2_0/test_user.py +1 -1
  119. openstackclient/tests/unit/identity/v3/fakes.py +5 -38
  120. openstackclient/tests/unit/identity/v3/test_access_rule.py +3 -3
  121. openstackclient/tests/unit/identity/v3/test_application_credential.py +4 -4
  122. openstackclient/tests/unit/identity/v3/test_credential.py +5 -5
  123. openstackclient/tests/unit/identity/v3/test_domain.py +5 -5
  124. openstackclient/tests/unit/identity/v3/test_endpoint.py +6 -6
  125. openstackclient/tests/unit/identity/v3/test_endpoint_group.py +1 -1
  126. openstackclient/tests/unit/identity/v3/test_group.py +8 -8
  127. openstackclient/tests/unit/identity/v3/test_implied_role.py +1 -1
  128. openstackclient/tests/unit/identity/v3/test_limit.py +5 -5
  129. openstackclient/tests/unit/identity/v3/test_mappings.py +163 -79
  130. openstackclient/tests/unit/identity/v3/test_project.py +28 -5
  131. openstackclient/tests/unit/identity/v3/test_protocol.py +3 -3
  132. openstackclient/tests/unit/identity/v3/test_region.py +5 -5
  133. openstackclient/tests/unit/identity/v3/test_registered_limit.py +5 -5
  134. openstackclient/tests/unit/identity/v3/test_role.py +8 -8
  135. openstackclient/tests/unit/identity/v3/test_role_assignment.py +1 -1
  136. openstackclient/tests/unit/identity/v3/test_service.py +5 -5
  137. openstackclient/tests/unit/identity/v3/test_token.py +2 -2
  138. openstackclient/tests/unit/identity/v3/test_trust.py +4 -4
  139. openstackclient/tests/unit/identity/v3/test_user.py +73 -6
  140. openstackclient/tests/unit/network/v2/fakes.py +5 -77
  141. openstackclient/tests/unit/network/v2/fwaas/test_group.py +28 -2
  142. openstackclient/tests/unit/network/v2/fwaas/test_rule.py +28 -3
  143. openstackclient/tests/unit/network/v2/test_address_group.py +24 -0
  144. openstackclient/tests/unit/network/v2/test_address_scope.py +24 -0
  145. openstackclient/tests/unit/network/v2/test_floating_ip.py +24 -0
  146. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +24 -0
  147. openstackclient/tests/unit/network/v2/test_ip_availability.py +25 -0
  148. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +29 -3
  149. openstackclient/tests/unit/network/v2/test_network.py +74 -12
  150. openstackclient/tests/unit/network/v2/test_network_agent.py +50 -1
  151. openstackclient/tests/unit/network/v2/test_network_flavor.py +24 -0
  152. openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +24 -0
  153. openstackclient/tests/unit/network/v2/test_network_meter.py +24 -0
  154. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +24 -0
  155. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +24 -0
  156. openstackclient/tests/unit/network/v2/test_network_rbac.py +24 -0
  157. openstackclient/tests/unit/network/v2/test_network_segment.py +24 -0
  158. openstackclient/tests/unit/network/v2/test_network_segment_range.py +24 -0
  159. openstackclient/tests/unit/network/v2/test_port.py +166 -0
  160. openstackclient/tests/unit/network/v2/test_router.py +28 -7
  161. openstackclient/tests/unit/network/v2/test_security_group.py +22 -0
  162. openstackclient/tests/unit/network/v2/test_security_group_rule.py +25 -0
  163. openstackclient/tests/unit/network/v2/test_subnet.py +28 -4
  164. openstackclient/tests/unit/network/v2/test_subnet_pool.py +24 -0
  165. openstackclient/tests/unit/volume/v2/fakes.py +20 -140
  166. openstackclient/tests/unit/volume/v2/test_volume_backup.py +5 -9
  167. openstackclient/tests/unit/volume/v2/test_volume_snapshot.py +6 -0
  168. openstackclient/tests/unit/volume/v3/fakes.py +204 -100
  169. openstackclient/tests/unit/volume/v3/test_backup_record.py +114 -0
  170. openstackclient/tests/unit/volume/v3/test_consistency_group.py +720 -0
  171. openstackclient/tests/unit/volume/v3/test_consistency_group_snapshot.py +354 -0
  172. openstackclient/tests/unit/volume/v3/test_qos_specs.py +455 -0
  173. openstackclient/tests/unit/volume/v3/test_volume_attachment.py +2 -0
  174. openstackclient/tests/unit/volume/v3/test_volume_backend.py +158 -0
  175. openstackclient/tests/unit/volume/v3/test_volume_backup.py +5 -9
  176. openstackclient/tests/unit/volume/v3/test_volume_group_type.py +65 -0
  177. openstackclient/tests/unit/volume/v3/test_volume_host.py +115 -0
  178. openstackclient/tests/unit/volume/v3/test_volume_snapshot.py +6 -0
  179. openstackclient/volume/v2/volume.py +4 -2
  180. openstackclient/volume/v2/volume_backup.py +2 -3
  181. openstackclient/volume/v2/volume_snapshot.py +3 -4
  182. openstackclient/volume/v3/backup_record.py +94 -0
  183. openstackclient/volume/v3/consistency_group.py +400 -0
  184. openstackclient/volume/v3/consistency_group_snapshot.py +225 -0
  185. openstackclient/volume/v3/qos_specs.py +389 -0
  186. openstackclient/volume/v3/volume.py +4 -2
  187. openstackclient/volume/v3/volume_attachment.py +5 -1
  188. openstackclient/volume/v3/volume_backend.py +130 -0
  189. openstackclient/volume/v3/volume_backup.py +2 -3
  190. openstackclient/volume/v3/volume_group_snapshot.py +4 -6
  191. openstackclient/volume/v3/volume_group_type.py +1 -1
  192. openstackclient/volume/v3/volume_host.py +74 -0
  193. openstackclient/volume/v3/volume_message.py +3 -1
  194. openstackclient/volume/v3/volume_snapshot.py +2 -1
  195. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/METADATA +3 -4
  196. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/RECORD +202 -188
  197. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/entry_points.txt +24 -24
  198. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/AUTHORS +5 -0
  199. python_openstackclient-10.1.0.dist-info/pbr.json +1 -0
  200. python_openstackclient-10.0.0.dist-info/pbr.json +0 -1
  201. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/WHEEL +0 -0
  202. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/licenses/LICENSE +0 -0
  203. {python_openstackclient-10.0.0.dist-info → python_openstackclient-10.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,455 @@
1
+ # Copyright 2015 iWeb Technologies Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+ # not use this file except in compliance with the License. You may obtain
5
+ # a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+ # License for the specific language governing permissions and limitations
13
+ # under the License.
14
+
15
+ import copy
16
+ from unittest import mock
17
+ from unittest.mock import call
18
+
19
+ from osc_lib.cli import format_columns
20
+ from osc_lib import exceptions
21
+ from osc_lib import utils
22
+
23
+ from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
24
+ from openstackclient.volume.v3 import qos_specs
25
+
26
+
27
+ class TestQos(volume_fakes.TestVolume):
28
+ def setUp(self):
29
+ super().setUp()
30
+
31
+ self.qos_mock = self.volume_client.qos_specs
32
+ self.qos_mock.reset_mock()
33
+
34
+ self.types_mock = self.volume_client.volume_types
35
+ self.types_mock.reset_mock()
36
+
37
+
38
+ class TestQosAssociate(TestQos):
39
+ volume_type = volume_fakes.create_one_volume_type()
40
+ qos_spec = volume_fakes.create_one_qos()
41
+
42
+ def setUp(self):
43
+ super().setUp()
44
+
45
+ self.qos_mock.get.return_value = self.qos_spec
46
+ self.types_mock.get.return_value = self.volume_type
47
+ # Get the command object to test
48
+ self.cmd = qos_specs.AssociateQos(self.app, None)
49
+
50
+ def test_qos_associate(self):
51
+ arglist = [self.qos_spec.id, self.volume_type.id]
52
+ verifylist = [
53
+ ('qos_spec', self.qos_spec.id),
54
+ ('volume_type', self.volume_type.id),
55
+ ]
56
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
57
+
58
+ result = self.cmd.take_action(parsed_args)
59
+
60
+ self.qos_mock.associate.assert_called_with(
61
+ self.qos_spec.id, self.volume_type.id
62
+ )
63
+ self.assertIsNone(result)
64
+
65
+
66
+ class TestQosCreate(TestQos):
67
+ columns = ('consumer', 'id', 'name', 'properties')
68
+
69
+ def setUp(self):
70
+ super().setUp()
71
+
72
+ self.new_qos_spec = volume_fakes.create_one_qos()
73
+ self.qos_mock.create.return_value = self.new_qos_spec
74
+
75
+ self.data = (
76
+ self.new_qos_spec.consumer,
77
+ self.new_qos_spec.id,
78
+ self.new_qos_spec.name,
79
+ format_columns.DictColumn(self.new_qos_spec.specs),
80
+ )
81
+
82
+ # Get the command object to test
83
+ self.cmd = qos_specs.CreateQos(self.app, None)
84
+
85
+ def test_qos_create_without_properties(self):
86
+ arglist = [
87
+ self.new_qos_spec.name,
88
+ ]
89
+ verifylist = [
90
+ ('name', self.new_qos_spec.name),
91
+ ]
92
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
93
+
94
+ columns, data = self.cmd.take_action(parsed_args)
95
+
96
+ self.qos_mock.create.assert_called_with(
97
+ self.new_qos_spec.name, {'consumer': 'both'}
98
+ )
99
+
100
+ self.assertEqual(self.columns, columns)
101
+ self.assertCountEqual(self.data, data)
102
+
103
+ def test_qos_create_with_consumer(self):
104
+ arglist = [
105
+ '--consumer',
106
+ self.new_qos_spec.consumer,
107
+ self.new_qos_spec.name,
108
+ ]
109
+ verifylist = [
110
+ ('consumer', self.new_qos_spec.consumer),
111
+ ('name', self.new_qos_spec.name),
112
+ ]
113
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
114
+
115
+ columns, data = self.cmd.take_action(parsed_args)
116
+
117
+ self.qos_mock.create.assert_called_with(
118
+ self.new_qos_spec.name, {'consumer': self.new_qos_spec.consumer}
119
+ )
120
+
121
+ self.assertEqual(self.columns, columns)
122
+ self.assertCountEqual(self.data, data)
123
+
124
+ def test_qos_create_with_properties(self):
125
+ arglist = [
126
+ '--consumer',
127
+ self.new_qos_spec.consumer,
128
+ '--property',
129
+ 'foo=bar',
130
+ '--property',
131
+ 'iops=9001',
132
+ self.new_qos_spec.name,
133
+ ]
134
+ verifylist = [
135
+ ('consumer', self.new_qos_spec.consumer),
136
+ ('property', self.new_qos_spec.specs),
137
+ ('name', self.new_qos_spec.name),
138
+ ]
139
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
140
+
141
+ columns, data = self.cmd.take_action(parsed_args)
142
+
143
+ self.qos_mock.create.assert_called_with(
144
+ self.new_qos_spec.name,
145
+ {
146
+ 'consumer': self.new_qos_spec.consumer,
147
+ 'foo': 'bar',
148
+ 'iops': '9001',
149
+ },
150
+ )
151
+
152
+ self.assertEqual(self.columns, columns)
153
+ self.assertCountEqual(self.data, data)
154
+
155
+
156
+ class TestQosDelete(TestQos):
157
+ qos_specs = volume_fakes.create_qoses(count=2)
158
+
159
+ def setUp(self):
160
+ super().setUp()
161
+
162
+ self.qos_mock.get = volume_fakes.get_qoses(self.qos_specs)
163
+ # Get the command object to test
164
+ self.cmd = qos_specs.DeleteQos(self.app, None)
165
+
166
+ def test_qos_delete(self):
167
+ arglist = [self.qos_specs[0].id]
168
+ verifylist = [('qos_specs', [self.qos_specs[0].id])]
169
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
170
+
171
+ result = self.cmd.take_action(parsed_args)
172
+
173
+ self.qos_mock.delete.assert_called_with(self.qos_specs[0].id, False)
174
+ self.assertIsNone(result)
175
+
176
+ def test_qos_delete_with_force(self):
177
+ arglist = ['--force', self.qos_specs[0].id]
178
+ verifylist = [('force', True), ('qos_specs', [self.qos_specs[0].id])]
179
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
180
+
181
+ result = self.cmd.take_action(parsed_args)
182
+
183
+ self.qos_mock.delete.assert_called_with(self.qos_specs[0].id, True)
184
+ self.assertIsNone(result)
185
+
186
+ def test_delete_multiple_qoses(self):
187
+ arglist = []
188
+ for q in self.qos_specs:
189
+ arglist.append(q.id)
190
+ verifylist = [
191
+ ('qos_specs', arglist),
192
+ ]
193
+
194
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
195
+ result = self.cmd.take_action(parsed_args)
196
+
197
+ calls = []
198
+ for q in self.qos_specs:
199
+ calls.append(call(q.id, False))
200
+ self.qos_mock.delete.assert_has_calls(calls)
201
+ self.assertIsNone(result)
202
+
203
+ def test_delete_multiple_qoses_with_exception(self):
204
+ arglist = [
205
+ self.qos_specs[0].id,
206
+ 'unexist_qos',
207
+ ]
208
+ verifylist = [
209
+ ('qos_specs', arglist),
210
+ ]
211
+
212
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
213
+
214
+ find_mock_result = [self.qos_specs[0], exceptions.CommandError]
215
+ with mock.patch.object(
216
+ utils, 'find_resource', side_effect=find_mock_result
217
+ ) as find_mock:
218
+ try:
219
+ self.cmd.take_action(parsed_args)
220
+ self.fail('CommandError should be raised.')
221
+ except exceptions.CommandError as e:
222
+ self.assertEqual(
223
+ '1 of 2 QoS specifications failed to delete.', str(e)
224
+ )
225
+
226
+ find_mock.assert_any_call(self.qos_mock, self.qos_specs[0].id)
227
+ find_mock.assert_any_call(self.qos_mock, 'unexist_qos')
228
+
229
+ self.assertEqual(2, find_mock.call_count)
230
+ self.qos_mock.delete.assert_called_once_with(
231
+ self.qos_specs[0].id, False
232
+ )
233
+
234
+
235
+ class TestQosDisassociate(TestQos):
236
+ volume_type = volume_fakes.create_one_volume_type()
237
+ qos_spec = volume_fakes.create_one_qos()
238
+
239
+ def setUp(self):
240
+ super().setUp()
241
+
242
+ self.qos_mock.get.return_value = self.qos_spec
243
+ self.types_mock.get.return_value = self.volume_type
244
+ # Get the command object to test
245
+ self.cmd = qos_specs.DisassociateQos(self.app, None)
246
+
247
+ def test_qos_disassociate_with_volume_type(self):
248
+ arglist = [
249
+ '--volume-type',
250
+ self.volume_type.id,
251
+ self.qos_spec.id,
252
+ ]
253
+ verifylist = [
254
+ ('volume_type', self.volume_type.id),
255
+ ('qos_spec', self.qos_spec.id),
256
+ ]
257
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
258
+
259
+ result = self.cmd.take_action(parsed_args)
260
+
261
+ self.qos_mock.disassociate.assert_called_with(
262
+ self.qos_spec.id, self.volume_type.id
263
+ )
264
+ self.assertIsNone(result)
265
+
266
+ def test_qos_disassociate_with_all_volume_types(self):
267
+ arglist = [
268
+ '--all',
269
+ self.qos_spec.id,
270
+ ]
271
+ verifylist = [('qos_spec', self.qos_spec.id)]
272
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
273
+
274
+ result = self.cmd.take_action(parsed_args)
275
+
276
+ self.qos_mock.disassociate_all.assert_called_with(self.qos_spec.id)
277
+ self.assertIsNone(result)
278
+
279
+
280
+ class TestQosList(TestQos):
281
+ qos_specs = volume_fakes.create_qoses(count=2)
282
+ qos_association = volume_fakes.create_one_qos_association()
283
+
284
+ columns = (
285
+ 'ID',
286
+ 'Name',
287
+ 'Consumer',
288
+ 'Associations',
289
+ 'Properties',
290
+ )
291
+ data = []
292
+ for q in qos_specs:
293
+ data.append(
294
+ (
295
+ q.id,
296
+ q.name,
297
+ q.consumer,
298
+ format_columns.ListColumn([qos_association.name]),
299
+ format_columns.DictColumn(q.specs),
300
+ )
301
+ )
302
+
303
+ def setUp(self):
304
+ super().setUp()
305
+
306
+ self.qos_mock.list.return_value = self.qos_specs
307
+ self.qos_mock.get_associations.return_value = [self.qos_association]
308
+
309
+ # Get the command object to test
310
+ self.cmd = qos_specs.ListQos(self.app, None)
311
+
312
+ def test_qos_list(self):
313
+ arglist = []
314
+ verifylist = []
315
+
316
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
317
+
318
+ columns, data = self.cmd.take_action(parsed_args)
319
+ self.qos_mock.list.assert_called_with()
320
+
321
+ self.assertEqual(self.columns, columns)
322
+ self.assertCountEqual(self.data, list(data))
323
+
324
+ def test_qos_list_no_association(self):
325
+ self.qos_mock.reset_mock()
326
+ self.qos_mock.get_associations.side_effect = [
327
+ [self.qos_association],
328
+ exceptions.NotFound("NotFound"),
329
+ ]
330
+
331
+ arglist = []
332
+ verifylist = []
333
+
334
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
335
+
336
+ columns, data = self.cmd.take_action(parsed_args)
337
+ self.qos_mock.list.assert_called_with()
338
+
339
+ self.assertEqual(self.columns, columns)
340
+
341
+ ex_data = copy.deepcopy(self.data)
342
+ ex_data[1] = (
343
+ self.qos_specs[1].id,
344
+ self.qos_specs[1].name,
345
+ self.qos_specs[1].consumer,
346
+ format_columns.ListColumn(None),
347
+ format_columns.DictColumn(self.qos_specs[1].specs),
348
+ )
349
+ self.assertCountEqual(ex_data, list(data))
350
+
351
+
352
+ class TestQosSet(TestQos):
353
+ qos_spec = volume_fakes.create_one_qos()
354
+
355
+ def setUp(self):
356
+ super().setUp()
357
+
358
+ self.qos_mock.get.return_value = self.qos_spec
359
+ # Get the command object to test
360
+ self.cmd = qos_specs.SetQos(self.app, None)
361
+
362
+ def test_qos_set_with_properties_with_id(self):
363
+ arglist = [
364
+ '--no-property',
365
+ '--property',
366
+ 'a=b',
367
+ '--property',
368
+ 'c=d',
369
+ self.qos_spec.id,
370
+ ]
371
+ new_property = {"a": "b", "c": "d"}
372
+ verifylist = [
373
+ ('no_property', True),
374
+ ('property', new_property),
375
+ ('qos_spec', self.qos_spec.id),
376
+ ]
377
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
378
+
379
+ result = self.cmd.take_action(parsed_args)
380
+
381
+ self.qos_mock.unset_keys.assert_called_with(
382
+ self.qos_spec.id,
383
+ list(self.qos_spec.specs.keys()),
384
+ )
385
+ self.qos_mock.set_keys.assert_called_with(
386
+ self.qos_spec.id, {"a": "b", "c": "d"}
387
+ )
388
+ self.assertIsNone(result)
389
+
390
+
391
+ class TestQosShow(TestQos):
392
+ qos_spec = volume_fakes.create_one_qos()
393
+ qos_association = volume_fakes.create_one_qos_association()
394
+
395
+ columns = ('associations', 'consumer', 'id', 'name', 'properties')
396
+ data = (
397
+ format_columns.ListColumn([qos_association.name]),
398
+ qos_spec.consumer,
399
+ qos_spec.id,
400
+ qos_spec.name,
401
+ format_columns.DictColumn(qos_spec.specs),
402
+ )
403
+
404
+ def setUp(self):
405
+ super().setUp()
406
+
407
+ self.qos_mock.get.return_value = self.qos_spec
408
+ self.qos_mock.get_associations.return_value = [self.qos_association]
409
+
410
+ # Get the command object to test
411
+ self.cmd = qos_specs.ShowQos(self.app, None)
412
+
413
+ def test_qos_show(self):
414
+ arglist = [self.qos_spec.id]
415
+ verifylist = [('qos_spec', self.qos_spec.id)]
416
+
417
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
418
+
419
+ columns, data = self.cmd.take_action(parsed_args)
420
+ self.qos_mock.get.assert_called_with(self.qos_spec.id)
421
+
422
+ self.assertEqual(self.columns, columns)
423
+ self.assertCountEqual(self.data, tuple(data))
424
+
425
+
426
+ class TestQosUnset(TestQos):
427
+ qos_spec = volume_fakes.create_one_qos()
428
+
429
+ def setUp(self):
430
+ super().setUp()
431
+
432
+ self.qos_mock.get.return_value = self.qos_spec
433
+ # Get the command object to test
434
+ self.cmd = qos_specs.UnsetQos(self.app, None)
435
+
436
+ def test_qos_unset_with_properties(self):
437
+ arglist = [
438
+ '--property',
439
+ 'iops',
440
+ '--property',
441
+ 'foo',
442
+ self.qos_spec.id,
443
+ ]
444
+ verifylist = [
445
+ ('property', ['iops', 'foo']),
446
+ ('qos_spec', self.qos_spec.id),
447
+ ]
448
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
449
+
450
+ result = self.cmd.take_action(parsed_args)
451
+
452
+ self.qos_mock.unset_keys.assert_called_with(
453
+ self.qos_spec.id, ['iops', 'foo']
454
+ )
455
+ self.assertIsNone(result)
@@ -495,6 +495,7 @@ class TestVolumeAttachmentList(TestVolumeAttachment):
495
495
  },
496
496
  marker=None,
497
497
  limit=None,
498
+ max_items=None,
498
499
  )
499
500
  self.assertEqual(self.columns, columns)
500
501
  self.assertCountEqual(tuple(self.data), data)
@@ -535,6 +536,7 @@ class TestVolumeAttachmentList(TestVolumeAttachment):
535
536
  },
536
537
  marker='volume-attachment-id',
537
538
  limit=2,
539
+ max_items=None,
538
540
  )
539
541
  self.assertEqual(self.columns, columns)
540
542
  self.assertCountEqual(tuple(self.data), data)
@@ -0,0 +1,158 @@
1
+ #
2
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may
3
+ # not use this file except in compliance with the License. You may obtain
4
+ # a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
+ # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
+ # License for the specific language governing permissions and limitations
12
+ # under the License.
13
+ #
14
+
15
+ from osc_lib.cli import format_columns
16
+
17
+ from openstackclient.tests.unit.volume.v3 import fakes as volume_fakes
18
+ from openstackclient.volume.v3 import volume_backend
19
+
20
+
21
+ class TestShowVolumeCapability(volume_fakes.TestVolume):
22
+ """Test backend capability functionality."""
23
+
24
+ # The capability to be listed
25
+ capability = volume_fakes.create_one_capability()
26
+
27
+ def setUp(self):
28
+ super().setUp()
29
+
30
+ # Assign return value to capabilities mock
31
+ self.volume_sdk_client.get_capabilities.return_value = self.capability
32
+
33
+ # Get the command object to test
34
+ self.cmd = volume_backend.ShowCapability(self.app, None)
35
+
36
+ def test_capability_show(self):
37
+ self.set_volume_api_version('3.0')
38
+
39
+ arglist = [
40
+ 'fake',
41
+ ]
42
+ verifylist = [
43
+ ('host', 'fake'),
44
+ ]
45
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
46
+
47
+ # In base command class Lister in cliff, abstract method take_action()
48
+ # returns a tuple containing the column names and an iterable
49
+ # containing the data to be listed.
50
+ columns, data = self.cmd.take_action(parsed_args)
51
+
52
+ expected_columns = [
53
+ 'Title',
54
+ 'Key',
55
+ 'Type',
56
+ 'Description',
57
+ ]
58
+
59
+ # confirming if all expected columns are present in the result.
60
+ self.assertEqual(expected_columns, columns)
61
+
62
+ capabilities = [
63
+ 'Compression',
64
+ 'Replication',
65
+ 'QoS',
66
+ 'Thin Provisioning',
67
+ ]
68
+
69
+ # confirming if all expected values are present in the result.
70
+ for cap in data:
71
+ self.assertIn(cap[0], capabilities)
72
+
73
+ # checking if proper call was made to get capabilities
74
+ self.volume_sdk_client.get_capabilities.assert_called_with(
75
+ 'fake',
76
+ )
77
+
78
+
79
+ class TestListVolumePool(volume_fakes.TestVolume):
80
+ """Tests for volume backend pool listing."""
81
+
82
+ # The pool to be listed
83
+ pools = volume_fakes.create_one_pool()
84
+
85
+ def setUp(self):
86
+ super().setUp()
87
+
88
+ self.volume_sdk_client.backend_pools.return_value = [self.pools]
89
+
90
+ # Get the command object to test
91
+ self.cmd = volume_backend.ListPool(self.app, None)
92
+
93
+ def test_pool_list(self):
94
+ self.set_volume_api_version('3.0')
95
+
96
+ arglist = []
97
+ verifylist = []
98
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
99
+
100
+ # In base command class Lister in cliff, abstract method take_action()
101
+ # returns a tuple containing the column names and an iterable
102
+ # containing the data to be listed.
103
+ columns, data = self.cmd.take_action(parsed_args)
104
+
105
+ expected_columns = [
106
+ 'Name',
107
+ ]
108
+
109
+ # confirming if all expected columns are present in the result.
110
+ self.assertEqual(expected_columns, columns)
111
+
112
+ datalist = ((self.pools.name,),)
113
+
114
+ # confirming if all expected values are present in the result.
115
+ self.assertEqual(datalist, tuple(data))
116
+
117
+ # checking if proper call was made to list pools
118
+ self.volume_sdk_client.backend_pools.assert_called_with(
119
+ detailed=False,
120
+ )
121
+
122
+ # checking if long columns are present in output
123
+ self.assertNotIn("total_volumes", columns)
124
+ self.assertNotIn("storage_protocol", columns)
125
+
126
+ def test_service_list_with_long_option(self):
127
+ self.set_volume_api_version('3.0')
128
+
129
+ arglist = ['--long']
130
+ verifylist = [('long', True)]
131
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
132
+
133
+ # In base command class Lister in cliff, abstract method take_action()
134
+ # returns a tuple containing the column names and an iterable
135
+ # containing the data to be listed.
136
+ columns, data = self.cmd.take_action(parsed_args)
137
+
138
+ expected_columns = [
139
+ 'Name',
140
+ 'Capabilities',
141
+ ]
142
+
143
+ # confirming if all expected columns are present in the result.
144
+ self.assertEqual(expected_columns, columns)
145
+
146
+ datalist = (
147
+ (
148
+ self.pools.name,
149
+ format_columns.DictColumn(self.pools.capabilities),
150
+ ),
151
+ )
152
+
153
+ # confirming if all expected values are present in the result.
154
+ self.assertEqual(datalist, tuple(data))
155
+
156
+ self.volume_sdk_client.backend_pools.assert_called_with(
157
+ detailed=True,
158
+ )
@@ -393,6 +393,7 @@ class TestBackupList(volume_fakes.TestVolume):
393
393
  all_tenants=False,
394
394
  marker=None,
395
395
  limit=None,
396
+ max_items=None,
396
397
  project_id=None,
397
398
  )
398
399
  self.assertEqual(self.columns, columns)
@@ -444,6 +445,7 @@ class TestBackupList(volume_fakes.TestVolume):
444
445
  all_tenants=True,
445
446
  marker=self.backups[0].id,
446
447
  limit=3,
448
+ max_items=None,
447
449
  project_id=project.id,
448
450
  )
449
451
  self.assertEqual(self.columns_long, columns)
@@ -494,9 +496,7 @@ class TestBackupRestore(volume_fakes.TestVolume):
494
496
 
495
497
  columns, data = self.cmd.take_action(parsed_args)
496
498
  self.volume_sdk_client.restore_backup.assert_called_with(
497
- self.backup.id,
498
- volume_id=None,
499
- name=None,
499
+ self.backup.id, volume=None, name=None
500
500
  )
501
501
 
502
502
  self.assertEqual(self.columns, columns)
@@ -518,9 +518,7 @@ class TestBackupRestore(volume_fakes.TestVolume):
518
518
 
519
519
  columns, data = self.cmd.take_action(parsed_args)
520
520
  self.volume_sdk_client.restore_backup.assert_called_with(
521
- self.backup.id,
522
- volume_id=None,
523
- name=self.backup.volume_id,
521
+ self.backup.id, volume=None, name=self.backup.volume_id
524
522
  )
525
523
 
526
524
  self.assertEqual(self.columns, columns)
@@ -541,9 +539,7 @@ class TestBackupRestore(volume_fakes.TestVolume):
541
539
 
542
540
  columns, data = self.cmd.take_action(parsed_args)
543
541
  self.volume_sdk_client.restore_backup.assert_called_with(
544
- self.backup.id,
545
- volume_id=self.volume.id,
546
- name=None,
542
+ self.backup.id, volume=self.volume.id, name=None
547
543
  )
548
544
 
549
545
  self.assertEqual(self.columns, columns)