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.
- openstackclient/common/project_cleanup.py +3 -5
- openstackclient/common/quota.py +4 -6
- openstackclient/compute/v2/host.py +44 -16
- openstackclient/compute/v2/server.py +18 -24
- openstackclient/compute/v2/server_migration.py +53 -29
- openstackclient/compute/v2/server_volume.py +35 -38
- openstackclient/compute/v2/service.py +5 -5
- openstackclient/identity/common.py +12 -0
- openstackclient/identity/v3/access_rule.py +8 -6
- openstackclient/image/v2/image.py +8 -2
- openstackclient/network/v2/floating_ip_port_forwarding.py +70 -32
- openstackclient/network/v2/network_service_provider.py +16 -10
- openstackclient/tests/functional/compute/v2/test_server.py +0 -3
- openstackclient/tests/unit/compute/v2/fakes.py +122 -207
- openstackclient/tests/unit/compute/v2/test_host.py +63 -42
- openstackclient/tests/unit/compute/v2/test_server.py +1 -2
- openstackclient/tests/unit/compute/v2/test_server_migration.py +92 -95
- openstackclient/tests/unit/compute/v2/test_server_volume.py +103 -83
- openstackclient/tests/unit/identity/v3/test_access_rule.py +11 -11
- openstackclient/tests/unit/network/v2/fakes.py +31 -7
- openstackclient/tests/unit/network/v2/test_floating_ip_port_forwarding.py +213 -18
- openstackclient/tests/unit/volume/v1/test_volume.py +48 -3
- openstackclient/tests/unit/volume/v2/test_consistency_group.py +2 -2
- openstackclient/tests/unit/volume/v2/test_volume.py +50 -3
- openstackclient/tests/unit/volume/v3/test_volume_group.py +47 -8
- openstackclient/volume/v1/volume.py +33 -4
- openstackclient/volume/v2/backup_record.py +8 -6
- openstackclient/volume/v2/consistency_group.py +32 -13
- openstackclient/volume/v2/volume.py +33 -4
- openstackclient/volume/v3/volume_group.py +91 -36
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/AUTHORS +5 -0
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/METADATA +1 -1
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/RECORD +38 -38
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/entry_points.txt +1 -0
- python_openstackclient-6.2.1.dist-info/pbr.json +1 -0
- python_openstackclient-6.1.0.dist-info/pbr.json +0 -1
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/LICENSE +0 -0
- {python_openstackclient-6.1.0.dist-info → python_openstackclient-6.2.1.dist-info}/WHEEL +0 -0
- {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 = _(
|
|
30
|
-
|
|
31
|
-
|
|
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 = _(
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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=_(
|
|
120
|
-
|
|
121
|
-
|
|
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.
|
|
162
|
+
if parsed_args.source:
|
|
146
163
|
consistency_group_id = utils.find_resource(
|
|
147
164
|
volume_client.consistencygroups,
|
|
148
|
-
parsed_args.
|
|
149
|
-
|
|
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.
|
|
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
|
-
|
|
261
|
-
|
|
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
|
-
|
|
281
|
+
if utils.wait_for_status(
|
|
282
|
+
volume_client.volumes.get,
|
|
267
283
|
volume.id,
|
|
268
|
-
|
|
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
|
|
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
|
-
'
|
|
103
|
+
'volume_group_type_legacy',
|
|
88
104
|
metavar='<volume_group_type>',
|
|
89
105
|
nargs='?',
|
|
90
|
-
help=
|
|
106
|
+
help=argparse.SUPPRESS,
|
|
91
107
|
)
|
|
92
|
-
parser.
|
|
93
|
-
|
|
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=
|
|
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=_(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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.
|
|
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
|
|
193
|
+
if not volume_types:
|
|
140
194
|
msg = _(
|
|
141
|
-
"
|
|
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
|
-
|
|
200
|
+
volume_group_type_id = utils.find_resource(
|
|
147
201
|
volume_client.group_types,
|
|
148
|
-
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
for volume_type in
|
|
152
|
-
|
|
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
|
-
|
|
161
|
-
','.join(
|
|
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
|
-
|
|
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>
|