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
|
@@ -49,6 +49,18 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
49
49
|
}
|
|
50
50
|
)
|
|
51
51
|
)
|
|
52
|
+
|
|
53
|
+
self.new_port_forwarding_with_ranges = (
|
|
54
|
+
network_fakes.FakeFloatingIPPortForwarding.
|
|
55
|
+
create_one_port_forwarding(
|
|
56
|
+
use_range=True,
|
|
57
|
+
attrs={
|
|
58
|
+
'internal_port_id': self.port.id,
|
|
59
|
+
'floatingip_id': self.floating_ip.id,
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
)
|
|
63
|
+
|
|
52
64
|
self.network.create_floating_ip_port_forwarding = mock.Mock(
|
|
53
65
|
return_value=self.new_port_forwarding)
|
|
54
66
|
|
|
@@ -63,22 +75,26 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
63
75
|
self.columns = (
|
|
64
76
|
'description',
|
|
65
77
|
'external_port',
|
|
78
|
+
'external_port_range',
|
|
66
79
|
'floatingip_id',
|
|
67
80
|
'id',
|
|
68
81
|
'internal_ip_address',
|
|
69
82
|
'internal_port',
|
|
70
83
|
'internal_port_id',
|
|
84
|
+
'internal_port_range',
|
|
71
85
|
'protocol'
|
|
72
86
|
)
|
|
73
87
|
|
|
74
88
|
self.data = (
|
|
75
89
|
self.new_port_forwarding.description,
|
|
76
90
|
self.new_port_forwarding.external_port,
|
|
91
|
+
self.new_port_forwarding.external_port_range,
|
|
77
92
|
self.new_port_forwarding.floatingip_id,
|
|
78
93
|
self.new_port_forwarding.id,
|
|
79
94
|
self.new_port_forwarding.internal_ip_address,
|
|
80
95
|
self.new_port_forwarding.internal_port,
|
|
81
96
|
self.new_port_forwarding.internal_port_id,
|
|
97
|
+
self.new_port_forwarding.internal_port_range,
|
|
82
98
|
self.new_port_forwarding.protocol,
|
|
83
99
|
)
|
|
84
100
|
|
|
@@ -90,6 +106,160 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
90
106
|
self.assertRaises(tests_utils.ParserException, self.check_parser,
|
|
91
107
|
self.cmd, arglist, verifylist)
|
|
92
108
|
|
|
109
|
+
def test_create_all_options_with_range(self):
|
|
110
|
+
arglist = [
|
|
111
|
+
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
|
|
112
|
+
'--internal-protocol-port',
|
|
113
|
+
self.new_port_forwarding_with_ranges.internal_port_range,
|
|
114
|
+
'--external-protocol-port',
|
|
115
|
+
self.new_port_forwarding_with_ranges.external_port_range,
|
|
116
|
+
'--protocol', self.new_port_forwarding_with_ranges.protocol,
|
|
117
|
+
self.new_port_forwarding_with_ranges.floatingip_id,
|
|
118
|
+
'--internal-ip-address',
|
|
119
|
+
self.new_port_forwarding_with_ranges.internal_ip_address,
|
|
120
|
+
'--description',
|
|
121
|
+
self.new_port_forwarding_with_ranges.description,
|
|
122
|
+
]
|
|
123
|
+
verifylist = [
|
|
124
|
+
('port', self.new_port_forwarding_with_ranges.internal_port_id),
|
|
125
|
+
('internal_protocol_port',
|
|
126
|
+
self.new_port_forwarding_with_ranges.internal_port_range),
|
|
127
|
+
('external_protocol_port',
|
|
128
|
+
self.new_port_forwarding_with_ranges.external_port_range),
|
|
129
|
+
('protocol', self.new_port_forwarding_with_ranges.protocol),
|
|
130
|
+
('floating_ip',
|
|
131
|
+
self.new_port_forwarding_with_ranges.floatingip_id),
|
|
132
|
+
('internal_ip_address', self.new_port_forwarding_with_ranges.
|
|
133
|
+
internal_ip_address),
|
|
134
|
+
('description', self.new_port_forwarding_with_ranges.description),
|
|
135
|
+
]
|
|
136
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
137
|
+
columns, data = self.cmd.take_action(parsed_args)
|
|
138
|
+
|
|
139
|
+
self.network.create_floating_ip_port_forwarding.\
|
|
140
|
+
assert_called_once_with(
|
|
141
|
+
self.new_port_forwarding.floatingip_id,
|
|
142
|
+
**{
|
|
143
|
+
'external_port_range':
|
|
144
|
+
self.new_port_forwarding_with_ranges.
|
|
145
|
+
external_port_range,
|
|
146
|
+
'internal_ip_address':
|
|
147
|
+
self.new_port_forwarding_with_ranges.
|
|
148
|
+
internal_ip_address,
|
|
149
|
+
'internal_port_range':
|
|
150
|
+
self.new_port_forwarding_with_ranges.
|
|
151
|
+
internal_port_range,
|
|
152
|
+
'internal_port_id':
|
|
153
|
+
self.new_port_forwarding_with_ranges.internal_port_id,
|
|
154
|
+
'protocol': self.new_port_forwarding_with_ranges.protocol,
|
|
155
|
+
'description':
|
|
156
|
+
self.new_port_forwarding_with_ranges.description,
|
|
157
|
+
})
|
|
158
|
+
self.assertEqual(self.columns, columns)
|
|
159
|
+
self.assertEqual(self.data, data)
|
|
160
|
+
|
|
161
|
+
def test_create_all_options_with_range_invalid_port_exception(self):
|
|
162
|
+
invalid_port_range = '999999:999999'
|
|
163
|
+
arglist = [
|
|
164
|
+
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
|
|
165
|
+
'--internal-protocol-port', invalid_port_range,
|
|
166
|
+
'--external-protocol-port', invalid_port_range,
|
|
167
|
+
'--protocol', self.new_port_forwarding_with_ranges.protocol,
|
|
168
|
+
self.new_port_forwarding_with_ranges.floatingip_id,
|
|
169
|
+
'--internal-ip-address',
|
|
170
|
+
self.new_port_forwarding_with_ranges.internal_ip_address,
|
|
171
|
+
'--description',
|
|
172
|
+
self.new_port_forwarding_with_ranges.description,
|
|
173
|
+
]
|
|
174
|
+
verifylist = [
|
|
175
|
+
('port', self.new_port_forwarding_with_ranges.internal_port_id),
|
|
176
|
+
('internal_protocol_port', invalid_port_range),
|
|
177
|
+
('external_protocol_port', invalid_port_range),
|
|
178
|
+
('protocol', self.new_port_forwarding_with_ranges.protocol),
|
|
179
|
+
('floating_ip',
|
|
180
|
+
self.new_port_forwarding_with_ranges.floatingip_id),
|
|
181
|
+
('internal_ip_address', self.new_port_forwarding_with_ranges.
|
|
182
|
+
internal_ip_address),
|
|
183
|
+
('description', self.new_port_forwarding_with_ranges.description),
|
|
184
|
+
]
|
|
185
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
186
|
+
msg = 'The port number range is <1-65535>'
|
|
187
|
+
try:
|
|
188
|
+
self.cmd.take_action(parsed_args)
|
|
189
|
+
self.fail('CommandError should be raised.')
|
|
190
|
+
except exceptions.CommandError as e:
|
|
191
|
+
self.assertEqual(msg, str(e))
|
|
192
|
+
self.network.create_floating_ip_port_forwarding.assert_not_called()
|
|
193
|
+
|
|
194
|
+
def test_create_all_options_with_invalid_range_exception(self):
|
|
195
|
+
invalid_port_range = '80:70'
|
|
196
|
+
arglist = [
|
|
197
|
+
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
|
|
198
|
+
'--internal-protocol-port', invalid_port_range,
|
|
199
|
+
'--external-protocol-port', invalid_port_range,
|
|
200
|
+
'--protocol', self.new_port_forwarding_with_ranges.protocol,
|
|
201
|
+
self.new_port_forwarding_with_ranges.floatingip_id,
|
|
202
|
+
'--internal-ip-address',
|
|
203
|
+
self.new_port_forwarding_with_ranges.internal_ip_address,
|
|
204
|
+
'--description',
|
|
205
|
+
self.new_port_forwarding_with_ranges.description,
|
|
206
|
+
]
|
|
207
|
+
verifylist = [
|
|
208
|
+
('port', self.new_port_forwarding_with_ranges.internal_port_id),
|
|
209
|
+
('internal_protocol_port', invalid_port_range),
|
|
210
|
+
('external_protocol_port', invalid_port_range),
|
|
211
|
+
('protocol', self.new_port_forwarding_with_ranges.protocol),
|
|
212
|
+
('floating_ip',
|
|
213
|
+
self.new_port_forwarding_with_ranges.floatingip_id),
|
|
214
|
+
('internal_ip_address', self.new_port_forwarding_with_ranges.
|
|
215
|
+
internal_ip_address),
|
|
216
|
+
('description', self.new_port_forwarding_with_ranges.description),
|
|
217
|
+
]
|
|
218
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
219
|
+
msg = 'The last number in port range must be greater or equal to ' \
|
|
220
|
+
'the first'
|
|
221
|
+
try:
|
|
222
|
+
self.cmd.take_action(parsed_args)
|
|
223
|
+
self.fail('CommandError should be raised.')
|
|
224
|
+
except exceptions.CommandError as e:
|
|
225
|
+
self.assertEqual(msg, str(e))
|
|
226
|
+
self.network.create_floating_ip_port_forwarding.assert_not_called()
|
|
227
|
+
|
|
228
|
+
def test_create_all_options_with_unmatch_ranges_exception(self):
|
|
229
|
+
internal_range = '80:90'
|
|
230
|
+
external_range = '8080:8100'
|
|
231
|
+
arglist = [
|
|
232
|
+
'--port', self.new_port_forwarding_with_ranges.internal_port_id,
|
|
233
|
+
'--internal-protocol-port', internal_range,
|
|
234
|
+
'--external-protocol-port', external_range,
|
|
235
|
+
'--protocol', self.new_port_forwarding_with_ranges.protocol,
|
|
236
|
+
self.new_port_forwarding_with_ranges.floatingip_id,
|
|
237
|
+
'--internal-ip-address',
|
|
238
|
+
self.new_port_forwarding_with_ranges.internal_ip_address,
|
|
239
|
+
'--description',
|
|
240
|
+
self.new_port_forwarding_with_ranges.description,
|
|
241
|
+
]
|
|
242
|
+
verifylist = [
|
|
243
|
+
('port', self.new_port_forwarding_with_ranges.internal_port_id),
|
|
244
|
+
('internal_protocol_port', internal_range),
|
|
245
|
+
('external_protocol_port', external_range),
|
|
246
|
+
('protocol', self.new_port_forwarding_with_ranges.protocol),
|
|
247
|
+
('floating_ip',
|
|
248
|
+
self.new_port_forwarding_with_ranges.floatingip_id),
|
|
249
|
+
('internal_ip_address', self.new_port_forwarding_with_ranges.
|
|
250
|
+
internal_ip_address),
|
|
251
|
+
('description', self.new_port_forwarding_with_ranges.description),
|
|
252
|
+
]
|
|
253
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
254
|
+
msg = "The relation between internal and external ports does not " \
|
|
255
|
+
"match the pattern 1:N and N:N"
|
|
256
|
+
try:
|
|
257
|
+
self.cmd.take_action(parsed_args)
|
|
258
|
+
self.fail('CommandError should be raised.')
|
|
259
|
+
except exceptions.CommandError as e:
|
|
260
|
+
self.assertEqual(msg, str(e))
|
|
261
|
+
self.network.create_floating_ip_port_forwarding.assert_not_called()
|
|
262
|
+
|
|
93
263
|
def test_create_all_options(self):
|
|
94
264
|
arglist = [
|
|
95
265
|
'--port', self.new_port_forwarding.internal_port_id,
|
|
@@ -106,8 +276,10 @@ class TestCreateFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
106
276
|
]
|
|
107
277
|
verifylist = [
|
|
108
278
|
('port', self.new_port_forwarding.internal_port_id),
|
|
109
|
-
('internal_protocol_port',
|
|
110
|
-
|
|
279
|
+
('internal_protocol_port',
|
|
280
|
+
str(self.new_port_forwarding.internal_port)),
|
|
281
|
+
('external_protocol_port',
|
|
282
|
+
str(self.new_port_forwarding.external_port)),
|
|
111
283
|
('protocol', self.new_port_forwarding.protocol),
|
|
112
284
|
('floating_ip', self.new_port_forwarding.floatingip_id),
|
|
113
285
|
('internal_ip_address', self.new_port_forwarding.
|
|
@@ -253,7 +425,9 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
253
425
|
'Internal Port ID',
|
|
254
426
|
'Internal IP Address',
|
|
255
427
|
'Internal Port',
|
|
428
|
+
'Internal Port Range',
|
|
256
429
|
'External Port',
|
|
430
|
+
'External Port Range',
|
|
257
431
|
'Protocol',
|
|
258
432
|
'Description',
|
|
259
433
|
)
|
|
@@ -275,7 +449,9 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
275
449
|
port_forwarding.internal_port_id,
|
|
276
450
|
port_forwarding.internal_ip_address,
|
|
277
451
|
port_forwarding.internal_port,
|
|
452
|
+
port_forwarding.internal_port_range,
|
|
278
453
|
port_forwarding.external_port,
|
|
454
|
+
port_forwarding.external_port_range,
|
|
279
455
|
port_forwarding.protocol,
|
|
280
456
|
port_forwarding.description,
|
|
281
457
|
))
|
|
@@ -330,7 +506,7 @@ class TestListFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
330
506
|
|
|
331
507
|
query = {
|
|
332
508
|
'internal_port_id': self.port_forwardings[0].internal_port_id,
|
|
333
|
-
'external_port':
|
|
509
|
+
'external_port': self.port_forwardings[0].external_port,
|
|
334
510
|
'protocol': self.port_forwardings[0].protocol,
|
|
335
511
|
}
|
|
336
512
|
|
|
@@ -392,7 +568,7 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
392
568
|
self.assertIsNone(result)
|
|
393
569
|
|
|
394
570
|
def test_set_all_thing(self):
|
|
395
|
-
|
|
571
|
+
arglist_single = [
|
|
396
572
|
'--port', self.port.id,
|
|
397
573
|
'--internal-ip-address', 'new_internal_ip_address',
|
|
398
574
|
'--internal-protocol-port', '100',
|
|
@@ -402,21 +578,23 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
402
578
|
self._port_forwarding.floatingip_id,
|
|
403
579
|
self._port_forwarding.id,
|
|
404
580
|
]
|
|
405
|
-
|
|
581
|
+
arglist_range = list(arglist_single)
|
|
582
|
+
arglist_range[5] = '100:110'
|
|
583
|
+
arglist_range[7] = '200:210'
|
|
584
|
+
verifylist_single = [
|
|
406
585
|
('port', self.port.id),
|
|
407
586
|
('internal_ip_address', 'new_internal_ip_address'),
|
|
408
|
-
('internal_protocol_port', 100),
|
|
409
|
-
('external_protocol_port', 200),
|
|
587
|
+
('internal_protocol_port', '100'),
|
|
588
|
+
('external_protocol_port', '200'),
|
|
410
589
|
('protocol', 'tcp'),
|
|
411
590
|
('description', 'some description'),
|
|
412
591
|
('floating_ip', self._port_forwarding.floatingip_id),
|
|
413
592
|
('port_forwarding_id', self._port_forwarding.id),
|
|
414
593
|
]
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
attrs = {
|
|
594
|
+
verifylist_range = list(verifylist_single)
|
|
595
|
+
verifylist_range[2] = ('internal_protocol_port', '100:110')
|
|
596
|
+
verifylist_range[3] = ('external_protocol_port', '200:210')
|
|
597
|
+
attrs_single = {
|
|
420
598
|
'internal_port_id': self.port.id,
|
|
421
599
|
'internal_ip_address': 'new_internal_ip_address',
|
|
422
600
|
'internal_port': 100,
|
|
@@ -424,12 +602,25 @@ class TestSetFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
424
602
|
'protocol': 'tcp',
|
|
425
603
|
'description': 'some description',
|
|
426
604
|
}
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
605
|
+
attrs_range = dict(attrs_single, internal_port_range='100:110',
|
|
606
|
+
external_port_range='200:210')
|
|
607
|
+
attrs_range.pop('internal_port')
|
|
608
|
+
attrs_range.pop('external_port')
|
|
609
|
+
|
|
610
|
+
def run_and_validate(arglist, verifylist, attrs):
|
|
611
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
612
|
+
|
|
613
|
+
result = self.cmd.take_action(parsed_args)
|
|
614
|
+
|
|
615
|
+
self.network.update_floating_ip_port_forwarding.assert_called_with(
|
|
616
|
+
self._port_forwarding.floatingip_id,
|
|
617
|
+
self._port_forwarding.id,
|
|
618
|
+
**attrs
|
|
619
|
+
)
|
|
620
|
+
self.assertIsNone(result)
|
|
621
|
+
|
|
622
|
+
run_and_validate(arglist_single, verifylist_single, attrs_single)
|
|
623
|
+
run_and_validate(arglist_range, verifylist_range, attrs_range)
|
|
433
624
|
|
|
434
625
|
|
|
435
626
|
class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
@@ -438,11 +629,13 @@ class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
438
629
|
columns = (
|
|
439
630
|
'description',
|
|
440
631
|
'external_port',
|
|
632
|
+
'external_port_range',
|
|
441
633
|
'floatingip_id',
|
|
442
634
|
'id',
|
|
443
635
|
'internal_ip_address',
|
|
444
636
|
'internal_port',
|
|
445
637
|
'internal_port_id',
|
|
638
|
+
'internal_port_range',
|
|
446
639
|
'protocol',
|
|
447
640
|
)
|
|
448
641
|
|
|
@@ -459,11 +652,13 @@ class TestShowFloatingIPPortForwarding(TestFloatingIPPortForwarding):
|
|
|
459
652
|
self.data = (
|
|
460
653
|
self._port_forwarding.description,
|
|
461
654
|
self._port_forwarding.external_port,
|
|
655
|
+
self._port_forwarding.external_port_range,
|
|
462
656
|
self._port_forwarding.floatingip_id,
|
|
463
657
|
self._port_forwarding.id,
|
|
464
658
|
self._port_forwarding.internal_ip_address,
|
|
465
659
|
self._port_forwarding.internal_port,
|
|
466
660
|
self._port_forwarding.internal_port_id,
|
|
661
|
+
self._port_forwarding.internal_port_range,
|
|
467
662
|
self._port_forwarding.protocol,
|
|
468
663
|
)
|
|
469
664
|
self.network.find_floating_ip_port_forwarding = mock.Mock(
|
|
@@ -430,7 +430,8 @@ class TestVolumeCreate(TestVolume):
|
|
|
430
430
|
self.assertEqual(self.columns, columns)
|
|
431
431
|
self.assertCountEqual(self.datalist, data)
|
|
432
432
|
|
|
433
|
-
|
|
433
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=True)
|
|
434
|
+
def test_volume_create_with_bootable_and_readonly(self, mock_wait):
|
|
434
435
|
arglist = [
|
|
435
436
|
'--bootable',
|
|
436
437
|
'--read-only',
|
|
@@ -472,7 +473,8 @@ class TestVolumeCreate(TestVolume):
|
|
|
472
473
|
self.volumes_mock.update_readonly_flag.assert_called_with(
|
|
473
474
|
self.new_volume.id, True)
|
|
474
475
|
|
|
475
|
-
|
|
476
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=True)
|
|
477
|
+
def test_volume_create_with_nonbootable_and_readwrite(self, mock_wait):
|
|
476
478
|
arglist = [
|
|
477
479
|
'--non-bootable',
|
|
478
480
|
'--read-write',
|
|
@@ -515,8 +517,9 @@ class TestVolumeCreate(TestVolume):
|
|
|
515
517
|
self.new_volume.id, False)
|
|
516
518
|
|
|
517
519
|
@mock.patch.object(volume.LOG, 'error')
|
|
520
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=True)
|
|
518
521
|
def test_volume_create_with_bootable_and_readonly_fail(
|
|
519
|
-
self, mock_error):
|
|
522
|
+
self, mock_wait, mock_error):
|
|
520
523
|
|
|
521
524
|
self.volumes_mock.set_bootable.side_effect = (
|
|
522
525
|
exceptions.CommandError())
|
|
@@ -566,6 +569,48 @@ class TestVolumeCreate(TestVolume):
|
|
|
566
569
|
self.volumes_mock.update_readonly_flag.assert_called_with(
|
|
567
570
|
self.new_volume.id, True)
|
|
568
571
|
|
|
572
|
+
@mock.patch.object(volume.LOG, 'error')
|
|
573
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=False)
|
|
574
|
+
def test_volume_create_non_available_with_readonly(
|
|
575
|
+
self, mock_wait, mock_error):
|
|
576
|
+
arglist = [
|
|
577
|
+
'--non-bootable',
|
|
578
|
+
'--read-only',
|
|
579
|
+
'--size', str(self.new_volume.size),
|
|
580
|
+
self.new_volume.display_name,
|
|
581
|
+
]
|
|
582
|
+
verifylist = [
|
|
583
|
+
('bootable', False),
|
|
584
|
+
('non_bootable', True),
|
|
585
|
+
('read_only', True),
|
|
586
|
+
('read_write', False),
|
|
587
|
+
('size', self.new_volume.size),
|
|
588
|
+
('name', self.new_volume.display_name),
|
|
589
|
+
]
|
|
590
|
+
|
|
591
|
+
parsed_args = self.check_parser(
|
|
592
|
+
self.cmd, arglist, verifylist)
|
|
593
|
+
|
|
594
|
+
columns, data = self.cmd.take_action(parsed_args)
|
|
595
|
+
|
|
596
|
+
self.volumes_mock.create.assert_called_with(
|
|
597
|
+
self.new_volume.size,
|
|
598
|
+
None,
|
|
599
|
+
None,
|
|
600
|
+
self.new_volume.display_name,
|
|
601
|
+
None,
|
|
602
|
+
None,
|
|
603
|
+
None,
|
|
604
|
+
None,
|
|
605
|
+
None,
|
|
606
|
+
None,
|
|
607
|
+
None,
|
|
608
|
+
)
|
|
609
|
+
|
|
610
|
+
self.assertEqual(2, mock_error.call_count)
|
|
611
|
+
self.assertEqual(self.columns, columns)
|
|
612
|
+
self.assertCountEqual(self.datalist, data)
|
|
613
|
+
|
|
569
614
|
def test_volume_create_without_size(self):
|
|
570
615
|
arglist = [
|
|
571
616
|
self.new_volume.display_name,
|
|
@@ -257,7 +257,7 @@ class TestConsistencyGroupCreate(TestConsistencyGroup):
|
|
|
257
257
|
self.new_consistency_group.name,
|
|
258
258
|
]
|
|
259
259
|
verifylist = [
|
|
260
|
-
('
|
|
260
|
+
('source', self.new_consistency_group.id),
|
|
261
261
|
('description', self.new_consistency_group.description),
|
|
262
262
|
('name', self.new_consistency_group.name),
|
|
263
263
|
]
|
|
@@ -285,7 +285,7 @@ class TestConsistencyGroupCreate(TestConsistencyGroup):
|
|
|
285
285
|
self.new_consistency_group.name,
|
|
286
286
|
]
|
|
287
287
|
verifylist = [
|
|
288
|
-
('
|
|
288
|
+
('snapshot', self.consistency_group_snapshot.id),
|
|
289
289
|
('description', self.new_consistency_group.description),
|
|
290
290
|
('name', self.new_consistency_group.name),
|
|
291
291
|
]
|
|
@@ -435,7 +435,8 @@ class TestVolumeCreate(TestVolume):
|
|
|
435
435
|
self.assertEqual(self.columns, columns)
|
|
436
436
|
self.assertCountEqual(self.datalist, data)
|
|
437
437
|
|
|
438
|
-
|
|
438
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=True)
|
|
439
|
+
def test_volume_create_with_bootable_and_readonly(self, mock_wait):
|
|
439
440
|
arglist = [
|
|
440
441
|
'--bootable',
|
|
441
442
|
'--read-only',
|
|
@@ -478,7 +479,8 @@ class TestVolumeCreate(TestVolume):
|
|
|
478
479
|
self.volumes_mock.update_readonly_flag.assert_called_with(
|
|
479
480
|
self.new_volume.id, True)
|
|
480
481
|
|
|
481
|
-
|
|
482
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=True)
|
|
483
|
+
def test_volume_create_with_nonbootable_and_readwrite(self, mock_wait):
|
|
482
484
|
arglist = [
|
|
483
485
|
'--non-bootable',
|
|
484
486
|
'--read-write',
|
|
@@ -522,8 +524,9 @@ class TestVolumeCreate(TestVolume):
|
|
|
522
524
|
self.new_volume.id, False)
|
|
523
525
|
|
|
524
526
|
@mock.patch.object(volume.LOG, 'error')
|
|
527
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=True)
|
|
525
528
|
def test_volume_create_with_bootable_and_readonly_fail(
|
|
526
|
-
self, mock_error):
|
|
529
|
+
self, mock_wait, mock_error):
|
|
527
530
|
|
|
528
531
|
self.volumes_mock.set_bootable.side_effect = (
|
|
529
532
|
exceptions.CommandError())
|
|
@@ -574,6 +577,50 @@ class TestVolumeCreate(TestVolume):
|
|
|
574
577
|
self.volumes_mock.update_readonly_flag.assert_called_with(
|
|
575
578
|
self.new_volume.id, True)
|
|
576
579
|
|
|
580
|
+
@mock.patch.object(volume.LOG, 'error')
|
|
581
|
+
@mock.patch.object(utils, 'wait_for_status', return_value=False)
|
|
582
|
+
def test_volume_create_non_available_with_readonly(
|
|
583
|
+
self, mock_wait, mock_error,
|
|
584
|
+
):
|
|
585
|
+
arglist = [
|
|
586
|
+
'--non-bootable',
|
|
587
|
+
'--read-only',
|
|
588
|
+
'--size', str(self.new_volume.size),
|
|
589
|
+
self.new_volume.name,
|
|
590
|
+
]
|
|
591
|
+
verifylist = [
|
|
592
|
+
('bootable', False),
|
|
593
|
+
('non_bootable', True),
|
|
594
|
+
('read_only', True),
|
|
595
|
+
('read_write', False),
|
|
596
|
+
('size', self.new_volume.size),
|
|
597
|
+
('name', self.new_volume.name),
|
|
598
|
+
]
|
|
599
|
+
|
|
600
|
+
parsed_args = self.check_parser(
|
|
601
|
+
self.cmd, arglist, verifylist)
|
|
602
|
+
|
|
603
|
+
columns, data = self.cmd.take_action(parsed_args)
|
|
604
|
+
|
|
605
|
+
self.volumes_mock.create.assert_called_with(
|
|
606
|
+
size=self.new_volume.size,
|
|
607
|
+
snapshot_id=None,
|
|
608
|
+
name=self.new_volume.name,
|
|
609
|
+
description=None,
|
|
610
|
+
volume_type=None,
|
|
611
|
+
availability_zone=None,
|
|
612
|
+
metadata=None,
|
|
613
|
+
imageRef=None,
|
|
614
|
+
source_volid=None,
|
|
615
|
+
consistencygroup_id=None,
|
|
616
|
+
scheduler_hints=None,
|
|
617
|
+
backup_id=None,
|
|
618
|
+
)
|
|
619
|
+
|
|
620
|
+
self.assertEqual(2, mock_error.call_count)
|
|
621
|
+
self.assertEqual(self.columns, columns)
|
|
622
|
+
self.assertCountEqual(self.datalist, data)
|
|
623
|
+
|
|
577
624
|
def test_volume_create_without_size(self):
|
|
578
625
|
arglist = [
|
|
579
626
|
self.new_volume.name,
|
|
@@ -100,8 +100,8 @@ class TestVolumeGroupCreate(TestVolumeGroup):
|
|
|
100
100
|
api_versions.APIVersion('3.13')
|
|
101
101
|
|
|
102
102
|
arglist = [
|
|
103
|
-
self.fake_volume_group_type.id,
|
|
104
|
-
self.fake_volume_type.id,
|
|
103
|
+
'--volume-group-type', self.fake_volume_group_type.id,
|
|
104
|
+
'--volume-type', self.fake_volume_type.id,
|
|
105
105
|
]
|
|
106
106
|
verifylist = [
|
|
107
107
|
('volume_group_type', self.fake_volume_group_type.id),
|
|
@@ -128,12 +128,51 @@ class TestVolumeGroupCreate(TestVolumeGroup):
|
|
|
128
128
|
self.assertEqual(self.columns, columns)
|
|
129
129
|
self.assertCountEqual(self.data, data)
|
|
130
130
|
|
|
131
|
+
def test_volume_group_create__legacy(self):
|
|
132
|
+
self.app.client_manager.volume.api_version = \
|
|
133
|
+
api_versions.APIVersion('3.13')
|
|
134
|
+
|
|
135
|
+
arglist = [
|
|
136
|
+
self.fake_volume_group_type.id,
|
|
137
|
+
self.fake_volume_type.id,
|
|
138
|
+
]
|
|
139
|
+
verifylist = [
|
|
140
|
+
('volume_group_type_legacy', self.fake_volume_group_type.id),
|
|
141
|
+
('volume_types_legacy', [self.fake_volume_type.id]),
|
|
142
|
+
('name', None),
|
|
143
|
+
('description', None),
|
|
144
|
+
('availability_zone', None),
|
|
145
|
+
]
|
|
146
|
+
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
|
147
|
+
|
|
148
|
+
with mock.patch.object(self.cmd.log, 'warning') as mock_warning:
|
|
149
|
+
columns, data = self.cmd.take_action(parsed_args)
|
|
150
|
+
|
|
151
|
+
self.volume_group_types_mock.get.assert_called_once_with(
|
|
152
|
+
self.fake_volume_group_type.id)
|
|
153
|
+
self.volume_types_mock.get.assert_called_once_with(
|
|
154
|
+
self.fake_volume_type.id)
|
|
155
|
+
self.volume_groups_mock.create.assert_called_once_with(
|
|
156
|
+
self.fake_volume_group_type.id,
|
|
157
|
+
self.fake_volume_type.id,
|
|
158
|
+
None,
|
|
159
|
+
None,
|
|
160
|
+
availability_zone=None,
|
|
161
|
+
)
|
|
162
|
+
self.assertEqual(self.columns, columns)
|
|
163
|
+
self.assertCountEqual(self.data, data)
|
|
164
|
+
mock_warning.assert_called_once()
|
|
165
|
+
self.assertIn(
|
|
166
|
+
'Passing volume group type and volume types as positional ',
|
|
167
|
+
str(mock_warning.call_args[0][0]),
|
|
168
|
+
)
|
|
169
|
+
|
|
131
170
|
def test_volume_group_create_no_volume_type(self):
|
|
132
171
|
self.app.client_manager.volume.api_version = \
|
|
133
172
|
api_versions.APIVersion('3.13')
|
|
134
173
|
|
|
135
174
|
arglist = [
|
|
136
|
-
self.fake_volume_group_type.id
|
|
175
|
+
'--volume-group-type', self.fake_volume_group_type.id,
|
|
137
176
|
]
|
|
138
177
|
verifylist = [
|
|
139
178
|
('volume_group_type', self.fake_volume_group_type.id),
|
|
@@ -148,7 +187,7 @@ class TestVolumeGroupCreate(TestVolumeGroup):
|
|
|
148
187
|
self.cmd.take_action,
|
|
149
188
|
parsed_args)
|
|
150
189
|
self.assertIn(
|
|
151
|
-
'
|
|
190
|
+
'--volume-types is a required argument when creating ',
|
|
152
191
|
str(exc))
|
|
153
192
|
|
|
154
193
|
def test_volume_group_create_with_options(self):
|
|
@@ -156,8 +195,8 @@ class TestVolumeGroupCreate(TestVolumeGroup):
|
|
|
156
195
|
api_versions.APIVersion('3.13')
|
|
157
196
|
|
|
158
197
|
arglist = [
|
|
159
|
-
self.fake_volume_group_type.id,
|
|
160
|
-
self.fake_volume_type.id,
|
|
198
|
+
'--volume-group-type', self.fake_volume_group_type.id,
|
|
199
|
+
'--volume-type', self.fake_volume_type.id,
|
|
161
200
|
'--name', 'foo',
|
|
162
201
|
'--description', 'hello, world',
|
|
163
202
|
'--availability-zone', 'bar',
|
|
@@ -192,8 +231,8 @@ class TestVolumeGroupCreate(TestVolumeGroup):
|
|
|
192
231
|
api_versions.APIVersion('3.12')
|
|
193
232
|
|
|
194
233
|
arglist = [
|
|
195
|
-
self.fake_volume_group_type.id,
|
|
196
|
-
self.fake_volume_type.id,
|
|
234
|
+
'--volume-group-type', self.fake_volume_group_type.id,
|
|
235
|
+
'--volume-type', self.fake_volume_type.id,
|
|
197
236
|
]
|
|
198
237
|
verifylist = [
|
|
199
238
|
('volume_group_type', self.fake_volume_group_type.id),
|
|
@@ -224,15 +224,44 @@ class CreateVolume(command.ShowOne):
|
|
|
224
224
|
|
|
225
225
|
if parsed_args.bootable or parsed_args.non_bootable:
|
|
226
226
|
try:
|
|
227
|
-
|
|
228
|
-
|
|
227
|
+
if utils.wait_for_status(
|
|
228
|
+
volume_client.volumes.get,
|
|
229
|
+
volume.id,
|
|
230
|
+
success_status=['available'],
|
|
231
|
+
error_status=['error'],
|
|
232
|
+
sleep_time=1
|
|
233
|
+
):
|
|
234
|
+
volume_client.volumes.set_bootable(
|
|
235
|
+
volume.id,
|
|
236
|
+
parsed_args.bootable
|
|
237
|
+
)
|
|
238
|
+
else:
|
|
239
|
+
msg = _(
|
|
240
|
+
"Volume status is not available for setting boot "
|
|
241
|
+
"state"
|
|
242
|
+
)
|
|
243
|
+
raise exceptions.CommandError(msg)
|
|
229
244
|
except Exception as e:
|
|
230
245
|
LOG.error(_("Failed to set volume bootable property: %s"), e)
|
|
231
246
|
if parsed_args.read_only or parsed_args.read_write:
|
|
232
247
|
try:
|
|
233
|
-
|
|
248
|
+
if utils.wait_for_status(
|
|
249
|
+
volume_client.volumes.get,
|
|
234
250
|
volume.id,
|
|
235
|
-
|
|
251
|
+
success_status=['available'],
|
|
252
|
+
error_status=['error'],
|
|
253
|
+
sleep_time=1
|
|
254
|
+
):
|
|
255
|
+
volume_client.volumes.update_readonly_flag(
|
|
256
|
+
volume.id,
|
|
257
|
+
parsed_args.read_only
|
|
258
|
+
)
|
|
259
|
+
else:
|
|
260
|
+
msg = _(
|
|
261
|
+
"Volume status is not available for setting it"
|
|
262
|
+
"read only."
|
|
263
|
+
)
|
|
264
|
+
raise exceptions.CommandError(msg)
|
|
236
265
|
except Exception as e:
|
|
237
266
|
LOG.error(_("Failed to set volume read-only access "
|
|
238
267
|
"mode flag: %s"), e)
|