python-openstackclient 6.1.0__py3-none-any.whl → 6.2.1__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 (39) hide show
  1. openstackclient/common/project_cleanup.py +3 -5
  2. openstackclient/common/quota.py +4 -6
  3. openstackclient/compute/v2/host.py +44 -16
  4. openstackclient/compute/v2/server.py +18 -24
  5. openstackclient/compute/v2/server_migration.py +53 -29
  6. openstackclient/compute/v2/server_volume.py +35 -38
  7. openstackclient/compute/v2/service.py +5 -5
  8. openstackclient/identity/common.py +12 -0
  9. openstackclient/identity/v3/access_rule.py +8 -6
  10. openstackclient/image/v2/image.py +8 -2
  11. openstackclient/network/v2/floating_ip_port_forwarding.py +70 -32
  12. openstackclient/network/v2/network_service_provider.py +16 -10
  13. openstackclient/tests/functional/compute/v2/test_server.py +0 -3
  14. openstackclient/tests/unit/compute/v2/fakes.py +122 -207
  15. openstackclient/tests/unit/compute/v2/test_host.py +63 -42
  16. openstackclient/tests/unit/compute/v2/test_server.py +1 -2
  17. openstackclient/tests/unit/compute/v2/test_server_migration.py +92 -95
  18. openstackclient/tests/unit/compute/v2/test_server_volume.py +103 -83
  19. openstackclient/tests/unit/identity/v3/test_access_rule.py +11 -11
  20. openstackclient/tests/unit/network/v2/fakes.py +31 -7
  21. openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +213 -18
  22. openstackclient/tests/unit/volume/v1/test_volume.py +48 -3
  23. openstackclient/tests/unit/volume/v2/test_consistency_group.py +2 -2
  24. openstackclient/tests/unit/volume/v2/test_volume.py +50 -3
  25. openstackclient/tests/unit/volume/v3/test_volume_group.py +47 -8
  26. openstackclient/volume/v1/volume.py +33 -4
  27. openstackclient/volume/v2/backup_record.py +8 -6
  28. openstackclient/volume/v2/consistency_group.py +32 -13
  29. openstackclient/volume/v2/volume.py +33 -4
  30. openstackclient/volume/v3/volume_group.py +91 -36
  31. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/AUTHORS +5 -0
  32. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/METADATA +1 -1
  33. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/RECORD +38 -38
  34. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/entry_points.txt +1 -0
  35. python_openstackclient-6.2.1.dist-info/pbr.json +1 -0
  36. python_openstackclient-6.1.0.dist-info/pbr.json +0 -1
  37. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/LICENSE +0 -0
  38. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/WHEEL +0 -0
  39. {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/top_level.txt +0 -0
@@ -26,9 +26,10 @@ LOG = logging.getLogger(__name__)
26
26
 
27
27
 
28
28
  class ExportBackupRecord(command.ShowOne):
29
- _description = _('Export volume backup details. Backup information can be '
30
- 'imported into a new service instance to be able to '
31
- 'restore.')
29
+ _description = _("""Export volume backup details.
30
+
31
+ Backup information can be imported into a new service instance to be able to
32
+ restore.""")
32
33
 
33
34
  def get_parser(self, prog_name):
34
35
  parser = super(ExportBackupRecord, self).get_parser(prog_name)
@@ -54,9 +55,10 @@ class ExportBackupRecord(command.ShowOne):
54
55
 
55
56
 
56
57
  class ImportBackupRecord(command.ShowOne):
57
- _description = _('Import volume backup details. Exported backup details '
58
- 'contain the metadata necessary to restore to a new or '
59
- 'rebuilt service instance')
58
+ _description = _("""Import volume backup details.
59
+
60
+ Exported backup details contain the metadata necessary to restore to a new or
61
+ rebuilt service instance""")
60
62
 
61
63
  def get_parser(self, prog_name):
62
64
  parser = super(ImportBackupRecord, self).get_parser(prog_name)
@@ -14,6 +14,7 @@
14
14
 
15
15
  """Volume v2 consistency group action implementations"""
16
16
 
17
+ import argparse
17
18
  import logging
18
19
 
19
20
  from osc_lib.cli import format_columns
@@ -90,35 +91,51 @@ class CreateConsistencyGroup(command.ShowOne):
90
91
  "name",
91
92
  metavar="<name>",
92
93
  nargs="?",
93
- help=_("Name of new consistency group (default to None)")
94
+ help=_("Name of new consistency group (default to None)"),
94
95
  )
95
96
  exclusive_group = parser.add_mutually_exclusive_group(required=True)
96
97
  exclusive_group.add_argument(
97
98
  "--volume-type",
98
99
  metavar="<volume-type>",
99
- help=_("Volume type of this consistency group (name or ID)")
100
+ help=_("Volume type of this consistency group (name or ID)"),
100
101
  )
102
+ exclusive_group.add_argument(
103
+ "--source",
104
+ metavar="<consistency-group>",
105
+ help=_("Existing consistency group (name or ID)"),
106
+ )
107
+ # NOTE(stephenfin): Legacy alias
101
108
  exclusive_group.add_argument(
102
109
  "--consistency-group-source",
103
110
  metavar="<consistency-group>",
104
- help=_("Existing consistency group (name or ID)")
111
+ dest='source',
112
+ help=argparse.SUPPRESS,
113
+ )
114
+ exclusive_group.add_argument(
115
+ "--snapshot",
116
+ metavar="<consistency-group-snapshot>",
117
+ help=_("Existing consistency group snapshot (name or ID)"),
105
118
  )
119
+ # NOTE(stephenfin): Legacy alias
106
120
  exclusive_group.add_argument(
107
121
  "--consistency-group-snapshot",
108
122
  metavar="<consistency-group-snapshot>",
109
- help=_("Existing consistency group snapshot (name or ID)")
123
+ dest='snapshot',
124
+ help=argparse.SUPPRESS,
110
125
  )
111
126
  parser.add_argument(
112
127
  "--description",
113
128
  metavar="<description>",
114
- help=_("Description of this consistency group")
129
+ help=_("Description of this consistency group"),
115
130
  )
116
131
  parser.add_argument(
117
132
  "--availability-zone",
118
133
  metavar="<availability-zone>",
119
- help=_("Availability zone for this consistency group "
120
- "(not available if creating consistency group "
121
- "from source)"),
134
+ help=_(
135
+ "Availability zone for this consistency group "
136
+ "(not available if creating consistency group "
137
+ "from source)"
138
+ ),
122
139
  )
123
140
  return parser
124
141
 
@@ -142,21 +159,23 @@ class CreateConsistencyGroup(command.ShowOne):
142
159
 
143
160
  consistency_group_id = None
144
161
  consistency_group_snapshot = None
145
- if parsed_args.consistency_group_source:
162
+ if parsed_args.source:
146
163
  consistency_group_id = utils.find_resource(
147
164
  volume_client.consistencygroups,
148
- parsed_args.consistency_group_source).id
149
- elif parsed_args.consistency_group_snapshot:
165
+ parsed_args.source,
166
+ ).id
167
+ elif parsed_args.snapshot:
150
168
  consistency_group_snapshot = utils.find_resource(
151
169
  volume_client.cgsnapshots,
152
- parsed_args.consistency_group_snapshot).id
170
+ parsed_args.snapshot,
171
+ ).id
153
172
 
154
173
  consistency_group = (
155
174
  volume_client.consistencygroups.create_from_src(
156
175
  consistency_group_snapshot,
157
176
  consistency_group_id,
158
177
  name=parsed_args.name,
159
- description=parsed_args.description
178
+ description=parsed_args.description,
160
179
  )
161
180
  )
162
181
 
@@ -257,15 +257,44 @@ class CreateVolume(command.ShowOne):
257
257
 
258
258
  if parsed_args.bootable or parsed_args.non_bootable:
259
259
  try:
260
- volume_client.volumes.set_bootable(
261
- volume.id, parsed_args.bootable)
260
+ if utils.wait_for_status(
261
+ volume_client.volumes.get,
262
+ volume.id,
263
+ success_status=['available'],
264
+ error_status=['error'],
265
+ sleep_time=1
266
+ ):
267
+ volume_client.volumes.set_bootable(
268
+ volume.id,
269
+ parsed_args.bootable
270
+ )
271
+ else:
272
+ msg = _(
273
+ "Volume status is not available for setting boot "
274
+ "state"
275
+ )
276
+ raise exceptions.CommandError(msg)
262
277
  except Exception as e:
263
278
  LOG.error(_("Failed to set volume bootable property: %s"), e)
264
279
  if parsed_args.read_only or parsed_args.read_write:
265
280
  try:
266
- volume_client.volumes.update_readonly_flag(
281
+ if utils.wait_for_status(
282
+ volume_client.volumes.get,
267
283
  volume.id,
268
- parsed_args.read_only)
284
+ success_status=['available'],
285
+ error_status=['error'],
286
+ sleep_time=1
287
+ ):
288
+ volume_client.volumes.update_readonly_flag(
289
+ volume.id,
290
+ parsed_args.read_only
291
+ )
292
+ else:
293
+ msg = _(
294
+ "Volume status is not available for setting it"
295
+ "read only."
296
+ )
297
+ raise exceptions.CommandError(msg)
269
298
  except Exception as e:
270
299
  LOG.error(_("Failed to set volume read-only access "
271
300
  "mode flag: %s"), e)
@@ -10,7 +10,7 @@
10
10
  # License for the specific language governing permissions and limitations
11
11
  # under the License.
12
12
 
13
- import logging
13
+ import argparse
14
14
 
15
15
  from cinderclient import api_versions
16
16
  from osc_lib.command import command
@@ -19,8 +19,6 @@ from osc_lib import utils
19
19
 
20
20
  from openstackclient.i18n import _
21
21
 
22
- LOG = logging.getLogger(__name__)
23
-
24
22
 
25
23
  def _format_group(group):
26
24
  columns = (
@@ -82,19 +80,72 @@ class CreateVolumeGroup(command.ShowOne):
82
80
 
83
81
  def get_parser(self, prog_name):
84
82
  parser = super().get_parser(prog_name)
83
+ # This is a bit complicated. We accept two patterns: a legacy pattern
84
+ #
85
+ # volume group create \
86
+ # <volume-group-type> <volume-type> [<volume-type>...]
87
+ #
88
+ # and the modern approach
89
+ #
90
+ # volume group create \
91
+ # --volume-group-type <volume-group-type>
92
+ # --volume-type <volume-type>
93
+ # [--volume-type <volume-type> ...]
94
+ #
95
+ # Because argparse doesn't properly support nested exclusive groups, we
96
+ # use two groups: one to ensure users don't pass <volume-group-type> as
97
+ # both a positional and an option argument and another to ensure users
98
+ # don't pass <volume-type> this way. It's a bit weird but it catches
99
+ # everything we care about.
85
100
  source_parser = parser.add_mutually_exclusive_group()
101
+ # we use a different name purely so we can issue a deprecation warning
86
102
  source_parser.add_argument(
87
- 'volume_group_type',
103
+ 'volume_group_type_legacy',
88
104
  metavar='<volume_group_type>',
89
105
  nargs='?',
90
- help=_('Name or ID of volume group type to use.'),
106
+ help=argparse.SUPPRESS,
91
107
  )
92
- parser.add_argument(
93
- 'volume_types',
108
+ volume_types_parser = parser.add_mutually_exclusive_group()
109
+ # We need to use a separate dest
110
+ # https://github.com/python/cpython/issues/101990
111
+ volume_types_parser.add_argument(
112
+ 'volume_types_legacy',
94
113
  metavar='<volume_type>',
95
114
  nargs='*',
96
115
  default=[],
97
- help=_('Name or ID of volume type(s) to use.'),
116
+ help=argparse.SUPPRESS,
117
+ )
118
+ source_parser.add_argument(
119
+ '--volume-group-type',
120
+ metavar='<volume_group_type>',
121
+ help=_('Volume group type to use (name or ID)'),
122
+ )
123
+ volume_types_parser.add_argument(
124
+ '--volume-type',
125
+ metavar='<volume_type>',
126
+ dest='volume_types',
127
+ action='append',
128
+ default=[],
129
+ help=_(
130
+ 'Volume type(s) to use (name or ID) '
131
+ '(required with --volume-group-type)'
132
+ ),
133
+ )
134
+ source_parser.add_argument(
135
+ '--source-group',
136
+ metavar='<source-group>',
137
+ help=_(
138
+ 'Existing volume group to use (name or ID) '
139
+ '(supported by --os-volume-api-version 3.14 or later)'
140
+ ),
141
+ )
142
+ source_parser.add_argument(
143
+ '--group-snapshot',
144
+ metavar='<group-snapshot>',
145
+ help=_(
146
+ 'Existing group snapshot to use (name or ID) '
147
+ '(supported by --os-volume-api-version 3.14 or later)'
148
+ ),
98
149
  )
99
150
  parser.add_argument(
100
151
  '--name',
@@ -109,59 +160,63 @@ class CreateVolumeGroup(command.ShowOne):
109
160
  parser.add_argument(
110
161
  '--availability-zone',
111
162
  metavar='<availability-zone>',
112
- help=_('Availability zone for volume group. '
113
- '(not available if creating group from source)'),
114
- )
115
- source_parser.add_argument(
116
- '--source-group',
117
- metavar='<source-group>',
118
- help=_('Existing volume group (name or ID) '
119
- '(supported by --os-volume-api-version 3.14 or later)'),
120
- )
121
- source_parser.add_argument(
122
- '--group-snapshot',
123
- metavar='<group-snapshot>',
124
- help=_('Existing group snapshot (name or ID) '
125
- '(supported by --os-volume-api-version 3.14 or later)'),
163
+ help=_(
164
+ 'Availability zone for volume group. '
165
+ '(not available if creating group from source)'
166
+ ),
126
167
  )
127
168
  return parser
128
169
 
129
170
  def take_action(self, parsed_args):
130
171
  volume_client = self.app.client_manager.volume
131
172
 
132
- if parsed_args.volume_group_type:
173
+ if parsed_args.volume_group_type_legacy:
174
+ msg = _(
175
+ "Passing volume group type and volume types as positional "
176
+ "arguments is deprecated. Use the --volume-group-type and "
177
+ "--volume-type option arguments instead."
178
+ )
179
+ self.log.warning(msg)
180
+
181
+ volume_group_type = parsed_args.volume_group_type or \
182
+ parsed_args.volume_group_type_legacy
183
+ volume_types = parsed_args.volume_types[:]
184
+ volume_types.extend(parsed_args.volume_types_legacy)
185
+
186
+ if volume_group_type:
133
187
  if volume_client.api_version < api_versions.APIVersion('3.13'):
134
188
  msg = _(
135
189
  "--os-volume-api-version 3.13 or greater is required to "
136
190
  "support the 'volume group create' command"
137
191
  )
138
192
  raise exceptions.CommandError(msg)
139
- if not parsed_args.volume_types:
193
+ if not volume_types:
140
194
  msg = _(
141
- "<volume_types> is a required argument when creating a "
195
+ "--volume-types is a required argument when creating a "
142
196
  "group from group type."
143
197
  )
144
198
  raise exceptions.CommandError(msg)
145
199
 
146
- volume_group_type = utils.find_resource(
200
+ volume_group_type_id = utils.find_resource(
147
201
  volume_client.group_types,
148
- parsed_args.volume_group_type,
149
- )
150
- volume_types = []
151
- for volume_type in parsed_args.volume_types:
152
- volume_types.append(
202
+ volume_group_type,
203
+ ).id
204
+ volume_types_ids = []
205
+ for volume_type in volume_types:
206
+ volume_types_ids.append(
153
207
  utils.find_resource(
154
208
  volume_client.volume_types,
155
209
  volume_type,
156
- )
210
+ ).id
157
211
  )
158
212
 
159
213
  group = volume_client.groups.create(
160
- volume_group_type.id,
161
- ','.join(x.id for x in volume_types),
214
+ volume_group_type_id,
215
+ ','.join(volume_types_ids),
162
216
  parsed_args.name,
163
217
  parsed_args.description,
164
- availability_zone=parsed_args.availability_zone)
218
+ availability_zone=parsed_args.availability_zone,
219
+ )
165
220
 
166
221
  group = volume_client.groups.get(group.id)
167
222
  return _format_group(group)
@@ -186,7 +241,7 @@ class CreateVolumeGroup(command.ShowOne):
186
241
  if parsed_args.availability_zone:
187
242
  msg = _("'--availability-zone' option will not work "
188
243
  "if creating group from source.")
189
- LOG.warning(msg)
244
+ self.log.warning(msg)
190
245
 
191
246
  source_group = None
192
247
  if parsed_args.source_group:
@@ -110,6 +110,7 @@ Doug Hellmann <doug.hellmann@dreamhost.com>
110
110
  Doug Hellmann <doug@doughellmann.com>
111
111
  Doug Wiegley <dwiegley@salesforce.com>
112
112
  Dougal Matthews <dougal@redhat.com>
113
+ Douglas Mendizábal <dmendiza@redhat.com>
113
114
  Dr. Jens Harbott <harbott@osism.tech>
114
115
  Einst Crazy <yu.changcai@99cloud.net>
115
116
  Elena Ezhova <eezhova@mirantis.com>
@@ -142,6 +143,7 @@ Hang Yang <hangyang@verizonmedia.com>
142
143
  Hangdong Zhang <hdzhang@fiberhome.com>
143
144
  Harald Jensas <hjensas@redhat.com>
144
145
  Harry Rybacki <hrybacki@redhat.com>
146
+ Harsh Mutha <hmutha31@bu.edu>
145
147
  He Jie Xu <hejie.xu@intel.com>
146
148
  Henry Nash <henryn@linux.vnet.ibm.com>
147
149
  Hidekazu Nakamura <hid-nakamura@vf.jp.nec.com>
@@ -166,6 +168,7 @@ Imtiaz Chowdhury <imtiaz.chowdhury@workday.com>
166
168
  Inessa Vasilevskaya <ivasilevskaya@mirantis.com>
167
169
  Iswarya_Vakati <v.iswarya@nectechnologies.in>
168
170
  Ivan Kolodyazhny <e0ne@e0ne.info>
171
+ JAE YONG LEE <jaeljy135@gmail.com>
169
172
  JIHOJU <jihoju96@gmail.com>
170
173
  JP Parkin <jpparkin@ca.ibm.com>
171
174
  Jackie Yuan <yj2311@126.com>
@@ -291,6 +294,7 @@ OpenStack Release Bot <infra-root@openstack.org>
291
294
  Paul Belanger <paul.belanger@polybeacon.com>
292
295
  Paul Bourke <paul.bourke@oracle.com>
293
296
  Pavlo Shchelokovskyy <shchelokovskyy@gmail.com>
297
+ Pedro Martins <phpm13@gmail.com>
294
298
  Pedro Navarro <pednape@gmail.com>
295
299
  Pete Zaitcev <zaitcev@kotori.zaitcev.us>
296
300
  Petr Blaho <pblaho@redhat.com>
@@ -466,6 +470,7 @@ lsmman <lsmman07@gmail.com>
466
470
  lvjiawei <lvjiawei@cmss.chinamobile.com>
467
471
  lvxianguo <lvxianguo@inspur.com>
468
472
  maaoyu <maaoyu@inspur.com>
473
+ matbu <mat.bultel@gmail.com>
469
474
  mb711d <mb711d@att.com>
470
475
  melanie witt <melwittt@gmail.com>
471
476
  melissaml <ma.lei@99cloud.net>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-openstackclient
3
- Version: 6.1.0
3
+ Version: 6.2.1
4
4
  Summary: OpenStack Command-line Client
5
5
  Home-page: https://docs.openstack.org/python-openstackclient/latest/
6
6
  Author: OpenStack