python-openstackclient 8.2.0__py3-none-any.whl → 8.3.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 (226) hide show
  1. openstackclient/api/object_store_v1.py +4 -1
  2. openstackclient/command.py +27 -0
  3. openstackclient/common/availability_zone.py +1 -1
  4. openstackclient/common/clientmanager.py +59 -21
  5. openstackclient/common/configuration.py +1 -1
  6. openstackclient/common/extension.py +1 -1
  7. openstackclient/common/limits.py +1 -1
  8. openstackclient/common/module.py +4 -2
  9. openstackclient/common/project_cleanup.py +10 -8
  10. openstackclient/common/quota.py +23 -6
  11. openstackclient/common/versions.py +1 -2
  12. openstackclient/compute/v2/agent.py +1 -1
  13. openstackclient/compute/v2/aggregate.py +6 -5
  14. openstackclient/compute/v2/console.py +5 -3
  15. openstackclient/compute/v2/console_connection.py +1 -1
  16. openstackclient/compute/v2/flavor.py +1 -1
  17. openstackclient/compute/v2/host.py +1 -1
  18. openstackclient/compute/v2/hypervisor.py +1 -1
  19. openstackclient/compute/v2/hypervisor_stats.py +1 -1
  20. openstackclient/compute/v2/keypair.py +1 -1
  21. openstackclient/compute/v2/server.py +76 -27
  22. openstackclient/compute/v2/server_backup.py +1 -1
  23. openstackclient/compute/v2/server_event.py +1 -1
  24. openstackclient/compute/v2/server_group.py +4 -2
  25. openstackclient/compute/v2/server_image.py +1 -1
  26. openstackclient/compute/v2/server_migration.py +1 -1
  27. openstackclient/compute/v2/server_volume.py +1 -1
  28. openstackclient/compute/v2/service.py +1 -1
  29. openstackclient/compute/v2/usage.py +6 -4
  30. openstackclient/identity/common.py +2 -1
  31. openstackclient/identity/v2_0/catalog.py +3 -2
  32. openstackclient/identity/v2_0/ec2creds.py +1 -1
  33. openstackclient/identity/v2_0/endpoint.py +1 -1
  34. openstackclient/identity/v2_0/project.py +17 -7
  35. openstackclient/identity/v2_0/role.py +1 -1
  36. openstackclient/identity/v2_0/role_assignment.py +3 -3
  37. openstackclient/identity/v2_0/service.py +1 -1
  38. openstackclient/identity/v2_0/token.py +1 -1
  39. openstackclient/identity/v2_0/user.py +2 -2
  40. openstackclient/identity/v3/access_rule.py +16 -4
  41. openstackclient/identity/v3/application_credential.py +30 -10
  42. openstackclient/identity/v3/catalog.py +3 -3
  43. openstackclient/identity/v3/consumer.py +1 -1
  44. openstackclient/identity/v3/credential.py +1 -1
  45. openstackclient/identity/v3/domain.py +10 -4
  46. openstackclient/identity/v3/ec2creds.py +1 -1
  47. openstackclient/identity/v3/endpoint.py +33 -12
  48. openstackclient/identity/v3/endpoint_group.py +1 -1
  49. openstackclient/identity/v3/federation_protocol.py +1 -1
  50. openstackclient/identity/v3/group.py +11 -5
  51. openstackclient/identity/v3/identity_provider.py +12 -10
  52. openstackclient/identity/v3/implied_role.py +1 -1
  53. openstackclient/identity/v3/limit.py +1 -1
  54. openstackclient/identity/v3/mapping.py +1 -1
  55. openstackclient/identity/v3/policy.py +1 -1
  56. openstackclient/identity/v3/project.py +10 -3
  57. openstackclient/identity/v3/region.py +1 -1
  58. openstackclient/identity/v3/registered_limit.py +16 -11
  59. openstackclient/identity/v3/role.py +20 -39
  60. openstackclient/identity/v3/role_assignment.py +12 -23
  61. openstackclient/identity/v3/service.py +1 -1
  62. openstackclient/identity/v3/service_provider.py +1 -1
  63. openstackclient/identity/v3/tag.py +3 -2
  64. openstackclient/identity/v3/token.py +3 -2
  65. openstackclient/identity/v3/trust.py +4 -2
  66. openstackclient/identity/v3/unscoped_saml.py +1 -1
  67. openstackclient/identity/v3/user.py +22 -13
  68. openstackclient/image/v1/image.py +19 -16
  69. openstackclient/image/v2/cache.py +1 -1
  70. openstackclient/image/v2/image.py +14 -11
  71. openstackclient/image/v2/info.py +1 -1
  72. openstackclient/image/v2/metadef_namespaces.py +1 -1
  73. openstackclient/image/v2/metadef_objects.py +1 -1
  74. openstackclient/image/v2/metadef_properties.py +3 -2
  75. openstackclient/image/v2/metadef_resource_type_association.py +1 -1
  76. openstackclient/image/v2/metadef_resource_types.py +1 -1
  77. openstackclient/image/v2/task.py +1 -1
  78. openstackclient/network/common.py +10 -9
  79. openstackclient/network/v2/address_group.py +4 -3
  80. openstackclient/network/v2/address_scope.py +8 -6
  81. openstackclient/network/v2/default_security_group_rule.py +9 -8
  82. openstackclient/network/v2/floating_ip.py +16 -9
  83. openstackclient/network/v2/floating_ip_port_forwarding.py +9 -6
  84. openstackclient/network/v2/ip_availability.py +7 -4
  85. openstackclient/network/v2/l3_conntrack_helper.py +11 -4
  86. openstackclient/network/v2/local_ip.py +13 -7
  87. openstackclient/network/v2/local_ip_association.py +7 -4
  88. openstackclient/network/v2/ndp_proxy.py +13 -6
  89. openstackclient/network/v2/network.py +33 -16
  90. openstackclient/network/v2/network_agent.py +5 -5
  91. openstackclient/network/v2/network_auto_allocated_topology.py +1 -1
  92. openstackclient/network/v2/network_flavor.py +1 -1
  93. openstackclient/network/v2/network_flavor_profile.py +1 -1
  94. openstackclient/network/v2/network_meter.py +1 -1
  95. openstackclient/network/v2/network_meter_rule.py +1 -1
  96. openstackclient/network/v2/network_qos_policy.py +7 -5
  97. openstackclient/network/v2/network_qos_rule.py +1 -1
  98. openstackclient/network/v2/network_qos_rule_type.py +1 -1
  99. openstackclient/network/v2/network_rbac.py +8 -5
  100. openstackclient/network/v2/network_segment.py +2 -2
  101. openstackclient/network/v2/network_segment_range.py +13 -6
  102. openstackclient/network/v2/network_service_provider.py +1 -1
  103. openstackclient/network/v2/network_trunk.py +65 -42
  104. openstackclient/network/v2/port.py +22 -20
  105. openstackclient/network/v2/router.py +19 -8
  106. openstackclient/network/v2/security_group.py +10 -6
  107. openstackclient/network/v2/security_group_rule.py +11 -5
  108. openstackclient/network/v2/subnet.py +17 -18
  109. openstackclient/network/v2/subnet_pool.py +11 -9
  110. openstackclient/network/v2/taas/__init__.py +0 -0
  111. openstackclient/network/v2/taas/tap_flow.py +245 -0
  112. openstackclient/network/v2/taas/tap_mirror.py +237 -0
  113. openstackclient/network/v2/taas/tap_service.py +211 -0
  114. openstackclient/object/v1/account.py +1 -1
  115. openstackclient/object/v1/container.py +1 -1
  116. openstackclient/object/v1/object.py +1 -1
  117. openstackclient/shell.py +18 -8
  118. openstackclient/tests/functional/identity/v3/test_catalog.py +42 -23
  119. openstackclient/tests/functional/identity/v3/test_role_assignment.py +174 -0
  120. openstackclient/tests/functional/image/v2/test_cache.py +54 -0
  121. openstackclient/tests/functional/image/v2/test_metadef_resource_type.py +55 -0
  122. openstackclient/tests/unit/common/test_command.py +1 -1
  123. openstackclient/tests/unit/common/test_extension.py +2 -3
  124. openstackclient/tests/unit/common/test_module.py +14 -7
  125. openstackclient/tests/unit/common/test_quota.py +20 -0
  126. openstackclient/tests/unit/compute/v2/test_aggregate.py +5 -3
  127. openstackclient/tests/unit/compute/v2/test_console.py +1 -4
  128. openstackclient/tests/unit/compute/v2/test_flavor.py +1 -3
  129. openstackclient/tests/unit/compute/v2/test_hypervisor_stats.py +1 -9
  130. openstackclient/tests/unit/compute/v2/test_server.py +364 -30
  131. openstackclient/tests/unit/compute/v2/test_server_backup.py +1 -3
  132. openstackclient/tests/unit/compute/v2/test_service.py +1 -3
  133. openstackclient/tests/unit/fakes.py +35 -134
  134. openstackclient/tests/unit/identity/test_common.py +100 -0
  135. openstackclient/tests/unit/identity/v2_0/test_project.py +4 -4
  136. openstackclient/tests/unit/identity/v3/fakes.py +10 -2
  137. openstackclient/tests/unit/identity/v3/test_application_credential.py +3 -3
  138. openstackclient/tests/unit/identity/v3/test_domain.py +1 -1
  139. openstackclient/tests/unit/identity/v3/test_endpoint.py +1 -1
  140. openstackclient/tests/unit/identity/v3/test_group.py +4 -2
  141. openstackclient/tests/unit/identity/v3/test_identity_provider.py +10 -10
  142. openstackclient/tests/unit/identity/v3/test_oauth.py +1 -1
  143. openstackclient/tests/unit/identity/v3/test_project.py +1 -1
  144. openstackclient/tests/unit/identity/v3/test_registered_limit.py +2 -2
  145. openstackclient/tests/unit/identity/v3/test_role.py +1 -82
  146. openstackclient/tests/unit/identity/v3/test_user.py +7 -51
  147. openstackclient/tests/unit/image/v2/test_image.py +111 -0
  148. openstackclient/tests/unit/network/test_common.py +9 -13
  149. openstackclient/tests/unit/network/v2/taas/__init__.py +0 -0
  150. openstackclient/tests/unit/network/v2/taas/test_osc_tap_flow.py +276 -0
  151. openstackclient/tests/unit/network/v2/taas/test_osc_tap_mirror.py +288 -0
  152. openstackclient/tests/unit/network/v2/taas/test_osc_tap_service.py +271 -0
  153. openstackclient/tests/unit/network/v2/test_address_group.py +19 -22
  154. openstackclient/tests/unit/network/v2/test_address_scope.py +10 -15
  155. openstackclient/tests/unit/network/v2/test_default_security_group_rule.py +38 -49
  156. openstackclient/tests/unit/network/v2/test_floating_ip_network.py +21 -27
  157. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +21 -18
  158. openstackclient/tests/unit/network/v2/test_ip_availability.py +6 -8
  159. openstackclient/tests/unit/network/v2/test_l3_conntrack_helper.py +6 -15
  160. openstackclient/tests/unit/network/v2/test_local_ip.py +12 -23
  161. openstackclient/tests/unit/network/v2/test_local_ip_association.py +13 -18
  162. openstackclient/tests/unit/network/v2/test_ndp_proxy.py +11 -21
  163. openstackclient/tests/unit/network/v2/test_network.py +41 -37
  164. openstackclient/tests/unit/network/v2/test_network_agent.py +13 -20
  165. openstackclient/tests/unit/network/v2/test_network_auto_allocated_topology.py +5 -8
  166. openstackclient/tests/unit/network/v2/test_network_flavor.py +14 -26
  167. openstackclient/tests/unit/network/v2/test_network_flavor_profile.py +14 -17
  168. openstackclient/tests/unit/network/v2/test_network_meter.py +7 -17
  169. openstackclient/tests/unit/network/v2/test_network_meter_rule.py +10 -20
  170. openstackclient/tests/unit/network/v2/test_network_qos_policy.py +7 -13
  171. openstackclient/tests/unit/network/v2/test_network_qos_rule.py +44 -54
  172. openstackclient/tests/unit/network/v2/test_network_qos_rule_type.py +2 -7
  173. openstackclient/tests/unit/network/v2/test_network_rbac.py +21 -36
  174. openstackclient/tests/unit/network/v2/test_network_segment.py +13 -29
  175. openstackclient/tests/unit/network/v2/test_network_segment_range.py +20 -19
  176. openstackclient/tests/unit/network/v2/test_network_service_provider.py +1 -4
  177. openstackclient/tests/unit/network/v2/test_network_trunk.py +52 -47
  178. openstackclient/tests/unit/network/v2/test_port.py +75 -86
  179. openstackclient/tests/unit/network/v2/test_router.py +104 -126
  180. openstackclient/tests/unit/network/v2/test_security_group_network.py +19 -26
  181. openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +17 -18
  182. openstackclient/tests/unit/network/v2/test_subnet.py +35 -46
  183. openstackclient/tests/unit/network/v2/test_subnet_pool.py +21 -33
  184. openstackclient/tests/unit/volume/test_find_resource.py +4 -13
  185. openstackclient/tests/unit/volume/v2/test_volume_backup.py +3 -1
  186. openstackclient/tests/unit/volume/v3/test_volume.py +4 -0
  187. openstackclient/tests/unit/volume/v3/test_volume_backup.py +9 -0
  188. openstackclient/volume/client.py +7 -17
  189. openstackclient/volume/v2/backup_record.py +1 -1
  190. openstackclient/volume/v2/consistency_group.py +1 -1
  191. openstackclient/volume/v2/consistency_group_snapshot.py +1 -1
  192. openstackclient/volume/v2/qos_specs.py +1 -1
  193. openstackclient/volume/v2/service.py +1 -1
  194. openstackclient/volume/v2/volume.py +2 -2
  195. openstackclient/volume/v2/volume_backend.py +1 -1
  196. openstackclient/volume/v2/volume_backup.py +5 -3
  197. openstackclient/volume/v2/volume_host.py +1 -2
  198. openstackclient/volume/v2/volume_snapshot.py +2 -2
  199. openstackclient/volume/v2/volume_transfer_request.py +1 -1
  200. openstackclient/volume/v2/volume_type.py +11 -6
  201. openstackclient/volume/v3/block_storage_cleanup.py +1 -1
  202. openstackclient/volume/v3/block_storage_cluster.py +1 -1
  203. openstackclient/volume/v3/block_storage_log_level.py +1 -1
  204. openstackclient/volume/v3/block_storage_manage.py +1 -1
  205. openstackclient/volume/v3/block_storage_resource_filter.py +1 -1
  206. openstackclient/volume/v3/service.py +1 -1
  207. openstackclient/volume/v3/volume.py +2 -2
  208. openstackclient/volume/v3/volume_attachment.py +6 -5
  209. openstackclient/volume/v3/volume_backup.py +18 -3
  210. openstackclient/volume/v3/volume_group.py +1 -1
  211. openstackclient/volume/v3/volume_group_snapshot.py +1 -1
  212. openstackclient/volume/v3/volume_group_type.py +1 -1
  213. openstackclient/volume/v3/volume_message.py +1 -1
  214. openstackclient/volume/v3/volume_snapshot.py +2 -2
  215. openstackclient/volume/v3/volume_transfer_request.py +1 -1
  216. openstackclient/volume/v3/volume_type.py +15 -9
  217. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/METADATA +15 -13
  218. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/RECORD +224 -213
  219. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/WHEEL +1 -1
  220. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/entry_points.txt +15 -0
  221. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/AUTHORS +10 -0
  222. python_openstackclient-8.3.0.dist-info/pbr.json +1 -0
  223. openstackclient/tests/unit/common/test_logs.py +0 -221
  224. python_openstackclient-8.2.0.dist-info/pbr.json +0 -1
  225. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info/licenses}/LICENSE +0 -0
  226. {python_openstackclient-8.2.0.dist-info → python_openstackclient-8.3.0.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,6 @@
13
13
  # under the License.
14
14
 
15
15
  import base64
16
- import collections
17
16
  import getpass
18
17
  import json
19
18
  import tempfile
@@ -21,9 +20,11 @@ from unittest import mock
21
20
  import uuid
22
21
 
23
22
  import iso8601
23
+ from openstack.compute.v2 import flavor as _flavor
24
24
  from openstack.compute.v2 import server as _server
25
25
  from openstack.compute.v2 import server_group as _server_group
26
26
  from openstack import exceptions as sdk_exceptions
27
+ from openstack.image.v2 import image as _image
27
28
  from openstack.test import fakes as sdk_fakes
28
29
  from osc_lib.cli import format_columns
29
30
  from osc_lib import exceptions
@@ -1212,7 +1213,6 @@ class TestServerCreate(TestServer):
1212
1213
  'locked',
1213
1214
  'locked_reason',
1214
1215
  'name',
1215
- 'pinned_availability_zone',
1216
1216
  'progress',
1217
1217
  'project_id',
1218
1218
  'properties',
@@ -1261,7 +1261,6 @@ class TestServerCreate(TestServer):
1261
1261
  None, # locked
1262
1262
  None, # locked_reason
1263
1263
  self.server.name,
1264
- None, # pinned_availability_zone
1265
1264
  None, # progress
1266
1265
  None, # project_id
1267
1266
  format_columns.DictColumn({}), # properties
@@ -4450,6 +4449,55 @@ class TestServerDelete(compute_fakes.TestComputev2):
4450
4449
  )
4451
4450
  self.assertIsNone(result)
4452
4451
 
4452
+ def test_server_delete_multi_servers_with_exceptions(self):
4453
+ servers = compute_fakes.create_servers(count=2)
4454
+ self.compute_client.find_server.side_effect = [
4455
+ servers[0],
4456
+ sdk_exceptions.ResourceNotFound(),
4457
+ servers[1],
4458
+ ]
4459
+
4460
+ arglist = [servers[0].id, 'unexist_server', servers[1].id]
4461
+
4462
+ verifylist = [
4463
+ ('force', False),
4464
+ ('all_projects', False),
4465
+ ('wait', False),
4466
+ (
4467
+ 'server',
4468
+ [servers[0].id, 'unexist_server', servers[1].id],
4469
+ ),
4470
+ ]
4471
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
4472
+
4473
+ exc = self.assertRaises(
4474
+ exceptions.CommandError,
4475
+ self.cmd.take_action,
4476
+ parsed_args,
4477
+ )
4478
+ self.assertEqual('1 of 3 servers failed to delete.', str(exc))
4479
+
4480
+ self.compute_client.find_server.assert_has_calls(
4481
+ [
4482
+ mock.call(
4483
+ servers[0].id, ignore_missing=False, all_projects=False
4484
+ ),
4485
+ mock.call(
4486
+ 'unexist_server', ignore_missing=False, all_projects=False
4487
+ ),
4488
+ mock.call(
4489
+ servers[1].id, ignore_missing=False, all_projects=False
4490
+ ),
4491
+ ]
4492
+ )
4493
+
4494
+ self.compute_client.delete_server.assert_has_calls(
4495
+ [
4496
+ mock.call(servers[0], force=False),
4497
+ mock.call(servers[1], force=False),
4498
+ ]
4499
+ )
4500
+
4453
4501
  def test_server_delete_with_all_projects(self):
4454
4502
  arglist = [
4455
4503
  self.server.id,
@@ -4583,10 +4631,8 @@ class _TestServerList(TestServer):
4583
4631
  'Flavor Name',
4584
4632
  'Flavor ID',
4585
4633
  'Availability Zone',
4586
- 'Pinned Availability Zone',
4587
4634
  'Host',
4588
4635
  'Properties',
4589
- 'Scheduler Hints',
4590
4636
  )
4591
4637
  columns_all_projects = (
4592
4638
  'ID',
@@ -4653,17 +4699,19 @@ class TestServerList(_TestServerList):
4653
4699
  def setUp(self):
4654
4700
  super().setUp()
4655
4701
 
4656
- Image = collections.namedtuple('Image', 'id name')
4657
4702
  self.image_client.images.return_value = [
4658
- Image(id=s.image['id'], name=self.image.name)
4703
+ sdk_fakes.generate_fake_resource(
4704
+ _image.Image, id=s.image['id'], name=self.image.name
4705
+ )
4659
4706
  # Image will be an empty string if boot-from-volume
4660
4707
  for s in self.servers
4661
4708
  if s.image
4662
4709
  ]
4663
4710
 
4664
- Flavor = collections.namedtuple('Flavor', 'id name')
4665
4711
  self.compute_client.flavors.return_value = [
4666
- Flavor(id=s.flavor['id'], name=self.flavor.name)
4712
+ sdk_fakes.generate_fake_resource(
4713
+ _flavor.Flavor, id=s.flavor['id'], name=self.flavor.name
4714
+ )
4667
4715
  for s in self.servers
4668
4716
  ]
4669
4717
 
@@ -4732,10 +4780,8 @@ class TestServerList(_TestServerList):
4732
4780
  self.flavor.name,
4733
4781
  s.flavor['id'],
4734
4782
  getattr(s, 'availability_zone'),
4735
- getattr(s, 'pinned_availability_zone', ''),
4736
4783
  server.HostColumn(getattr(s, 'hypervisor_hostname')),
4737
4784
  format_columns.DictColumn(s.metadata),
4738
- format_columns.DictListColumn(None),
4739
4785
  )
4740
4786
  for s in self.servers
4741
4787
  )
@@ -4809,13 +4855,9 @@ class TestServerList(_TestServerList):
4809
4855
  '-c',
4810
4856
  'Availability Zone',
4811
4857
  '-c',
4812
- 'Pinned Availability Zone',
4813
- '-c',
4814
4858
  'Host',
4815
4859
  '-c',
4816
4860
  'Properties',
4817
- '-c',
4818
- 'Scheduler Hints',
4819
4861
  '--long',
4820
4862
  ]
4821
4863
  verifylist = [
@@ -4835,10 +4877,8 @@ class TestServerList(_TestServerList):
4835
4877
  self.assertIn('Image ID', columns)
4836
4878
  self.assertIn('Flavor ID', columns)
4837
4879
  self.assertIn('Availability Zone', columns)
4838
- self.assertIn('Pinned Availability Zone', columns)
4839
4880
  self.assertIn('Host', columns)
4840
4881
  self.assertIn('Properties', columns)
4841
- self.assertIn('Scheduler Hints', columns)
4842
4882
  self.assertCountEqual(columns, set(columns))
4843
4883
 
4844
4884
  def test_server_list_no_name_lookup_option(self):
@@ -5249,10 +5289,8 @@ class TestServerList(_TestServerList):
5249
5289
  self.flavor.name,
5250
5290
  s.flavor['id'],
5251
5291
  getattr(s, 'availability_zone'),
5252
- getattr(s, 'pinned_availability_zone', ''),
5253
5292
  server.HostColumn(getattr(s, 'hypervisor_hostname')),
5254
5293
  format_columns.DictColumn(s.metadata),
5255
- format_columns.DictListColumn(s.scheduler_hints),
5256
5294
  )
5257
5295
  for s in self.servers
5258
5296
  )
@@ -5281,9 +5319,10 @@ class TestServerList(_TestServerList):
5281
5319
  self.compute_client.servers.return_value = servers
5282
5320
 
5283
5321
  # Make sure the returned image and flavor IDs match the servers.
5284
- Image = collections.namedtuple('Image', 'id name')
5285
5322
  self.image_client.images.return_value = [
5286
- Image(id=s.image['id'], name=self.image.name)
5323
+ sdk_fakes.generate_fake_resource(
5324
+ _image.Image, id=s.image['id'], name=self.image.name
5325
+ )
5287
5326
  # Image will be an empty string if boot-from-volume
5288
5327
  for s in servers
5289
5328
  if s.image
@@ -5305,10 +5344,8 @@ class TestServerList(_TestServerList):
5305
5344
  self.flavor.name,
5306
5345
  s.flavor['id'],
5307
5346
  getattr(s, 'availability_zone'),
5308
- getattr(s, 'pinned_availability_zone', ''),
5309
5347
  server.HostColumn(getattr(s, 'hypervisor_hostname')),
5310
5348
  format_columns.DictColumn(s.metadata),
5311
- format_columns.DictListColumn(s.scheduler_hints),
5312
5349
  s.host_status,
5313
5350
  )
5314
5351
  for s in servers
@@ -5343,7 +5380,6 @@ class TestServerListV273(_TestServerList):
5343
5380
  'Image ID',
5344
5381
  'Flavor',
5345
5382
  'Availability Zone',
5346
- 'Pinned Availability Zone',
5347
5383
  'Host',
5348
5384
  'Properties',
5349
5385
  'Scheduler Hints',
@@ -5368,9 +5404,10 @@ class TestServerListV273(_TestServerList):
5368
5404
  self.servers = self.setup_sdk_servers_mock(3)
5369
5405
  self.compute_client.servers.return_value = self.servers
5370
5406
 
5371
- Image = collections.namedtuple('Image', 'id name')
5372
5407
  self.image_client.images.return_value = [
5373
- Image(id=s.image['id'], name=self.image.name)
5408
+ sdk_fakes.generate_fake_resource(
5409
+ _image.Image, id=s.image['id'], name=self.image.name
5410
+ )
5374
5411
  # Image will be an empty string if boot-from-volume
5375
5412
  for s in self.servers
5376
5413
  if s.image
@@ -5541,6 +5578,307 @@ class TestServerListV273(_TestServerList):
5541
5578
  self.assertEqual(expected_row, partial_server)
5542
5579
 
5543
5580
 
5581
+ class TestServerListV296(_TestServerList):
5582
+ columns = (
5583
+ 'ID',
5584
+ 'Name',
5585
+ 'Status',
5586
+ 'Networks',
5587
+ 'Image',
5588
+ 'Flavor',
5589
+ )
5590
+ columns_long = (
5591
+ 'ID',
5592
+ 'Name',
5593
+ 'Status',
5594
+ 'Task State',
5595
+ 'Power State',
5596
+ 'Networks',
5597
+ 'Image Name',
5598
+ 'Image ID',
5599
+ 'Flavor',
5600
+ 'Availability Zone',
5601
+ 'Host',
5602
+ 'Properties',
5603
+ 'Pinned Availability Zone',
5604
+ )
5605
+
5606
+ def setUp(self):
5607
+ super().setUp()
5608
+ self.set_compute_api_version('2.96')
5609
+
5610
+ self.image_client.images.return_value = [
5611
+ sdk_fakes.generate_fake_resource(
5612
+ _image.Image, id=s.image['id'], name=self.image.name
5613
+ )
5614
+ # Image will be an empty string if boot-from-volume
5615
+ for s in self.servers
5616
+ if s.image
5617
+ ]
5618
+
5619
+ self.compute_client.flavors.return_value = [
5620
+ sdk_fakes.generate_fake_resource(
5621
+ _flavor.Flavor, id=s.flavor['id'], name=self.flavor.name
5622
+ )
5623
+ for s in self.servers
5624
+ ]
5625
+
5626
+ self.data = tuple(
5627
+ (
5628
+ s.id,
5629
+ s.name,
5630
+ s.status,
5631
+ server.AddressesColumn(s.addresses),
5632
+ # Image will be an empty string if boot-from-volume
5633
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
5634
+ self.flavor.name,
5635
+ )
5636
+ for s in self.servers
5637
+ )
5638
+
5639
+ def test_server_list_long_option(self):
5640
+ self.data = tuple(
5641
+ (
5642
+ s.id,
5643
+ s.name,
5644
+ s.status,
5645
+ getattr(s, 'task_state'),
5646
+ server.PowerStateColumn(getattr(s, 'power_state')),
5647
+ server.AddressesColumn(s.addresses),
5648
+ # Image will be an empty string if boot-from-volume
5649
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
5650
+ s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
5651
+ self.flavor.name,
5652
+ getattr(s, 'availability_zone'),
5653
+ server.HostColumn(getattr(s, 'hypervisor_hostname')),
5654
+ format_columns.DictColumn(s.metadata),
5655
+ getattr(s, 'pinned_availability_zone', ''),
5656
+ )
5657
+ for s in self.servers
5658
+ )
5659
+ arglist = [
5660
+ '--long',
5661
+ ]
5662
+ verifylist = [
5663
+ ('all_projects', False),
5664
+ ('long', True),
5665
+ ]
5666
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
5667
+
5668
+ columns, data = self.cmd.take_action(parsed_args)
5669
+ self.compute_client.servers.assert_called_with(**self.kwargs)
5670
+ image_ids = {s.image['id'] for s in self.servers if s.image}
5671
+ self.image_client.images.assert_called_once_with(
5672
+ id=f'in:{",".join(image_ids)}',
5673
+ )
5674
+ self.compute_client.flavors.assert_called_once_with(is_public=None)
5675
+ self.assertEqual(self.columns_long, columns)
5676
+ self.assertEqual(self.data, tuple(data))
5677
+
5678
+ def test_server_list_column_option(self):
5679
+ arglist = [
5680
+ '-c',
5681
+ 'Project ID',
5682
+ '-c',
5683
+ 'User ID',
5684
+ '-c',
5685
+ 'Created At',
5686
+ '-c',
5687
+ 'Security Groups',
5688
+ '-c',
5689
+ 'Task State',
5690
+ '-c',
5691
+ 'Power State',
5692
+ '-c',
5693
+ 'Image ID',
5694
+ '-c',
5695
+ 'Flavor ID',
5696
+ '-c',
5697
+ 'Availability Zone',
5698
+ '-c',
5699
+ 'Host',
5700
+ '-c',
5701
+ 'Properties',
5702
+ '-c',
5703
+ 'Pinned Availability Zone',
5704
+ '--long',
5705
+ ]
5706
+ verifylist = [
5707
+ ('long', True),
5708
+ ]
5709
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
5710
+
5711
+ columns, data = self.cmd.take_action(parsed_args)
5712
+
5713
+ self.compute_client.servers.assert_called_with(**self.kwargs)
5714
+ self.assertIn('Project ID', columns)
5715
+ self.assertIn('User ID', columns)
5716
+ self.assertIn('Created At', columns)
5717
+ self.assertIn('Security Groups', columns)
5718
+ self.assertIn('Task State', columns)
5719
+ self.assertIn('Power State', columns)
5720
+ self.assertIn('Image ID', columns)
5721
+ self.assertIn('Flavor ID', columns)
5722
+ self.assertIn('Availability Zone', columns)
5723
+ self.assertIn('Pinned Availability Zone', columns)
5724
+ self.assertIn('Host', columns)
5725
+ self.assertIn('Properties', columns)
5726
+ self.assertCountEqual(columns, set(columns))
5727
+
5728
+
5729
+ class TestServerListV2100(_TestServerList):
5730
+ columns = (
5731
+ 'ID',
5732
+ 'Name',
5733
+ 'Status',
5734
+ 'Networks',
5735
+ 'Image',
5736
+ 'Flavor',
5737
+ )
5738
+ columns_long = (
5739
+ 'ID',
5740
+ 'Name',
5741
+ 'Status',
5742
+ 'Task State',
5743
+ 'Power State',
5744
+ 'Networks',
5745
+ 'Image Name',
5746
+ 'Image ID',
5747
+ 'Flavor',
5748
+ 'Availability Zone',
5749
+ 'Host',
5750
+ 'Properties',
5751
+ 'Pinned Availability Zone',
5752
+ 'Scheduler Hints',
5753
+ )
5754
+
5755
+ def setUp(self):
5756
+ super().setUp()
5757
+ self.set_compute_api_version('2.100')
5758
+
5759
+ self.image_client.images.return_value = [
5760
+ sdk_fakes.generate_fake_resource(
5761
+ _image.Image, id=s.image['id'], name=self.image.name
5762
+ )
5763
+ # Image will be an empty string if boot-from-volume
5764
+ for s in self.servers
5765
+ if s.image
5766
+ ]
5767
+
5768
+ self.compute_client.flavors.return_value = [
5769
+ sdk_fakes.generate_fake_resource(
5770
+ _flavor.Flavor, id=s.flavor['id'], name=self.flavor.name
5771
+ )
5772
+ for s in self.servers
5773
+ ]
5774
+
5775
+ self.data = tuple(
5776
+ (
5777
+ s.id,
5778
+ s.name,
5779
+ s.status,
5780
+ server.AddressesColumn(s.addresses),
5781
+ # Image will be an empty string if boot-from-volume
5782
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
5783
+ self.flavor.name,
5784
+ )
5785
+ for s in self.servers
5786
+ )
5787
+
5788
+ def test_server_list_long_option(self):
5789
+ self.data = tuple(
5790
+ (
5791
+ s.id,
5792
+ s.name,
5793
+ s.status,
5794
+ getattr(s, 'task_state'),
5795
+ server.PowerStateColumn(getattr(s, 'power_state')),
5796
+ server.AddressesColumn(s.addresses),
5797
+ # Image will be an empty string if boot-from-volume
5798
+ self.image.name if s.image else server.IMAGE_STRING_FOR_BFV,
5799
+ s.image['id'] if s.image else server.IMAGE_STRING_FOR_BFV,
5800
+ self.flavor.name,
5801
+ getattr(s, 'availability_zone'),
5802
+ server.HostColumn(getattr(s, 'hypervisor_hostname')),
5803
+ format_columns.DictColumn(s.metadata),
5804
+ getattr(s, 'pinned_availability_zone', ''),
5805
+ format_columns.DictListColumn(None),
5806
+ )
5807
+ for s in self.servers
5808
+ )
5809
+ arglist = [
5810
+ '--long',
5811
+ ]
5812
+ verifylist = [
5813
+ ('all_projects', False),
5814
+ ('long', True),
5815
+ ]
5816
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
5817
+
5818
+ columns, data = self.cmd.take_action(parsed_args)
5819
+ self.compute_client.servers.assert_called_with(**self.kwargs)
5820
+ image_ids = {s.image['id'] for s in self.servers if s.image}
5821
+ self.image_client.images.assert_called_once_with(
5822
+ id=f'in:{",".join(image_ids)}',
5823
+ )
5824
+ self.compute_client.flavors.assert_called_once_with(is_public=None)
5825
+ self.assertEqual(self.columns_long, columns)
5826
+ self.assertEqual(self.data, tuple(data))
5827
+
5828
+ def test_server_list_column_option(self):
5829
+ arglist = [
5830
+ '-c',
5831
+ 'Project ID',
5832
+ '-c',
5833
+ 'User ID',
5834
+ '-c',
5835
+ 'Created At',
5836
+ '-c',
5837
+ 'Security Groups',
5838
+ '-c',
5839
+ 'Task State',
5840
+ '-c',
5841
+ 'Power State',
5842
+ '-c',
5843
+ 'Image ID',
5844
+ '-c',
5845
+ 'Flavor ID',
5846
+ '-c',
5847
+ 'Availability Zone',
5848
+ '-c',
5849
+ 'Host',
5850
+ '-c',
5851
+ 'Properties',
5852
+ '-c',
5853
+ 'Pinned Availability Zone',
5854
+ '-c',
5855
+ 'Scheduler Hints',
5856
+ '--long',
5857
+ ]
5858
+ verifylist = [
5859
+ ('long', True),
5860
+ ]
5861
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
5862
+
5863
+ columns, data = self.cmd.take_action(parsed_args)
5864
+
5865
+ self.compute_client.servers.assert_called_with(**self.kwargs)
5866
+ self.assertIn('Project ID', columns)
5867
+ self.assertIn('User ID', columns)
5868
+ self.assertIn('Created At', columns)
5869
+ self.assertIn('Security Groups', columns)
5870
+ self.assertIn('Task State', columns)
5871
+ self.assertIn('Power State', columns)
5872
+ self.assertIn('Image ID', columns)
5873
+ self.assertIn('Flavor ID', columns)
5874
+ self.assertIn('Availability Zone', columns)
5875
+ self.assertIn('Pinned Availability Zone', columns)
5876
+ self.assertIn('Host', columns)
5877
+ self.assertIn('Properties', columns)
5878
+ self.assertIn('Scheduler Hints', columns)
5879
+ self.assertCountEqual(columns, set(columns))
5880
+
5881
+
5544
5882
  class TestServerAction(compute_fakes.TestComputev2):
5545
5883
  def run_method_with_sdk_servers(self, method_name, server_count):
5546
5884
  servers = compute_fakes.create_servers(count=server_count)
@@ -8533,7 +8871,6 @@ class TestServerShow(TestServer):
8533
8871
  'locked',
8534
8872
  'locked_reason',
8535
8873
  'name',
8536
- 'pinned_availability_zone',
8537
8874
  'progress',
8538
8875
  'project_id',
8539
8876
  'properties',
@@ -8583,7 +8920,6 @@ class TestServerShow(TestServer):
8583
8920
  None, # locked
8584
8921
  None, # locked_reason
8585
8922
  self.server.name,
8586
- None, # pinned_availability_zone
8587
8923
  None, # progress
8588
8924
  'tenant-id-xxx', # project_id
8589
8925
  format_columns.DictColumn({}), # properties
@@ -9522,7 +9858,6 @@ class TestServerGeneral(TestServer):
9522
9858
  'locked': None,
9523
9859
  'locked_reason': None,
9524
9860
  'name': _server.name,
9525
- 'pinned_availability_zone': None,
9526
9861
  'progress': None,
9527
9862
  'project_id': 'tenant-id-xxx',
9528
9863
  'properties': format_columns.DictColumn({}),
@@ -9609,7 +9944,6 @@ class TestServerGeneral(TestServer):
9609
9944
  'locked': None,
9610
9945
  'locked_reason': None,
9611
9946
  'name': _server.name,
9612
- 'pinned_availability_zone': None,
9613
9947
  'progress': None,
9614
9948
  'project_id': 'tenant-id-xxx',
9615
9949
  'properties': format_columns.DictColumn({}),
@@ -161,9 +161,7 @@ class TestServerBackupCreate(compute_fakes.TestComputev2):
161
161
 
162
162
  @mock.patch.object(common_utils, 'wait_for_status', return_value=True)
163
163
  def test_server_backup_wait_ok(self, mock_wait_for_status):
164
- self.image_client.get_image = mock.Mock(
165
- side_effect=self.image,
166
- )
164
+ self.image_client.get_image.side_effect = (self.image,)
167
165
 
168
166
  arglist = [
169
167
  '--name',
@@ -77,9 +77,7 @@ class TestServiceDelete(compute_fakes.TestComputev2):
77
77
  parsed_args = self.check_parser(self.cmd, arglist, verifylist)
78
78
 
79
79
  delete_mock_result = [None, exceptions.CommandError]
80
- self.compute_client.delete_service = mock.Mock(
81
- side_effect=delete_mock_result
82
- )
80
+ self.compute_client.delete_service.side_effect = delete_mock_result
83
81
 
84
82
  try:
85
83
  self.cmd.take_action(parsed_args)