blob: d7d86f1605f31cfa0de930a449574935c533e2cc [file] [log] [blame]
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +02001# Copyright 2015 Mirantis Inc.
2# All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License"); you may
5# not use this file except in compliance with the License. You may obtain
6# a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13# License for the specific language governing permissions and limitations
14# under the License.
15
Luigi Toscanod91870b2020-10-03 15:17:23 +020016from collections import OrderedDict
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020017import random
18import re
19
lkuchlan1d1461d2020-08-04 11:19:11 +030020from netaddr import ip
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020021from tempest import config
lkuchlan4a803162022-11-16 11:34:33 +020022from tempest.lib.common.utils import data_utils
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020023import testtools
24
lkuchlan7b63ec72022-12-11 11:57:59 +020025from manila_tempest_tests import utils
26
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020027CONF = config.CONF
Douglas Viroelb7e27e72019-08-06 19:40:37 -030028SHARE_NETWORK_SUBNETS_MICROVERSION = '2.51'
silvacarlossca4dd9f2020-03-11 13:57:18 +000029SHARE_REPLICA_QUOTAS_MICROVERSION = "2.53"
silvacarloss6e575682020-02-18 19:52:35 -030030EXPERIMENTAL = {'X-OpenStack-Manila-API-Experimental': 'True'}
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020031
32
Luigi Toscanod91870b2020-10-03 15:17:23 +020033def deduplicate(items):
34 """De-duplicate a list of items while preserving the order.
35
36 It is useful when passing a list of items to ddt.data, in order
37 to remove duplicated elements which may be specified as constants.
38 """
39 return list(OrderedDict.fromkeys(items))
40
41
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020042def get_microversion_as_tuple(microversion_str):
43 """Transforms string-like microversion to two-value tuple of integers.
44
45 Tuple of integers useful for microversion comparisons.
46 """
47 regex = r"^([1-9]\d*)\.([1-9]\d*|0)$"
48 match = re.match(regex, microversion_str)
49 if not match:
50 raise ValueError(
51 "Microversion does not fit template 'x.y' - %s" % microversion_str)
52 return int(match.group(1)), int(match.group(2))
53
54
55def is_microversion_gt(left, right):
56 """Is microversion for left is greater than the right one."""
57 return get_microversion_as_tuple(left) > get_microversion_as_tuple(right)
58
59
60def is_microversion_ge(left, right):
61 """Is microversion for left is greater than or equal to the right one."""
62 return get_microversion_as_tuple(left) >= get_microversion_as_tuple(right)
63
64
65def is_microversion_eq(left, right):
66 """Is microversion for left is equal to the right one."""
67 return get_microversion_as_tuple(left) == get_microversion_as_tuple(right)
68
69
70def is_microversion_ne(left, right):
71 """Is microversion for left is not equal to the right one."""
72 return get_microversion_as_tuple(left) != get_microversion_as_tuple(right)
73
74
75def is_microversion_le(left, right):
76 """Is microversion for left is less than or equal to the right one."""
77 return get_microversion_as_tuple(left) <= get_microversion_as_tuple(right)
78
79
80def is_microversion_lt(left, right):
81 """Is microversion for left is less than the right one."""
82 return get_microversion_as_tuple(left) < get_microversion_as_tuple(right)
83
84
85def is_microversion_supported(microversion):
86 bottom = get_microversion_as_tuple(CONF.share.min_api_microversion)
87 microversion = get_microversion_as_tuple(microversion)
88 top = get_microversion_as_tuple(CONF.share.max_api_microversion)
89 return bottom <= microversion <= top
90
91
92def skip_if_microversion_not_supported(microversion):
93 """Decorator for tests that are microversion-specific."""
94 if not is_microversion_supported(microversion):
95 reason = ("Skipped. Test requires microversion '%s'." % microversion)
96 return testtools.skip(reason)
97 return lambda f: f
98
99
Andrec1a3c0e2022-01-29 14:46:53 +0000100def skip_if_is_microversion_ge(left, right):
101 """Skip if version for left is greater than or equal to the right one."""
102
103 if is_microversion_ge(left, right):
104 reason = ("Skipped. Test requires microversion "
105 "< than '%s'." % right)
106 return testtools.skip(reason)
107 return lambda f: f
108
109
lkuchlana3b6f7a2020-01-07 10:45:45 +0200110def check_skip_if_microversion_not_supported(microversion):
Goutham Pacha Ravia0acf252021-05-27 19:57:55 -0700111 """Callable method for tests that are microversion-specific."""
lkuchlana3b6f7a2020-01-07 10:45:45 +0200112 if not is_microversion_supported(microversion):
113 reason = ("Skipped. Test requires microversion '%s'." % microversion)
114 raise testtools.TestCase.skipException(reason)
115
116
zhongjun72974ff2016-05-04 11:47:03 +0800117def rand_ip(network=False):
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +0200118 """This uses the TEST-NET-3 range of reserved IP addresses.
119
120 Using this range, which are reserved solely for use in
121 documentation and example source code, should avoid any potential
122 conflicts in real-world testing.
123 """
zhongjun72974ff2016-05-04 11:47:03 +0800124 test_net_3 = '203.0.113.'
haixin48895812020-09-30 13:50:37 +0800125 address = test_net_3 + str(random.randint(0, 255))
zhongjun72974ff2016-05-04 11:47:03 +0800126 if network:
haixin48895812020-09-30 13:50:37 +0800127 mask_length = str(random.randint(24, 32))
zhongjun72974ff2016-05-04 11:47:03 +0800128 address = '/'.join((address, mask_length))
129 ip_network = ip.IPNetwork(address)
haixin48895812020-09-30 13:50:37 +0800130 return '/'.join((str(ip_network.network), mask_length))
zhongjun72974ff2016-05-04 11:47:03 +0800131 return address
132
133
134def rand_ipv6_ip(network=False):
135 """This uses the IPv6 documentation range of 2001:DB8::/32"""
Raissa Sarmento80f5fbf2017-10-16 14:38:36 +0100136 ran_add = ["%x" % random.randrange(0, 16 ** 4) for i in range(6)]
zhongjun72974ff2016-05-04 11:47:03 +0800137 address = "2001:0DB8:" + ":".join(ran_add)
138 if network:
haixin48895812020-09-30 13:50:37 +0800139 mask_length = str(random.randint(32, 128))
zhongjun72974ff2016-05-04 11:47:03 +0800140 address = '/'.join((address, mask_length))
141 ip_network = ip.IPNetwork(address)
haixin48895812020-09-30 13:50:37 +0800142 return '/'.join((str(ip_network.network), mask_length))
zhongjun72974ff2016-05-04 11:47:03 +0800143 return address
Rodrigo Barbieric9abf282016-08-24 22:01:31 -0300144
145
lkuchlan7b63ec72022-12-11 11:57:59 +0200146def generate_share_network_data():
147 data = {
148 "name": data_utils.rand_name("sn-name"),
149 "description": data_utils.rand_name("sn-desc"),
150 "neutron_net_id": data_utils.rand_name("net-id"),
151 "neutron_subnet_id": data_utils.rand_name("subnet-id"),
152 }
153 return data
154
155
156def generate_subnet_data():
157 data = {
158 "neutron_net_id": data_utils.rand_name("net-id"),
159 "neutron_subnet_id": data_utils.rand_name("subnet-id"),
160 }
161 return data
162
163
164def generate_security_service_data(set_ou=False):
165 data = {
166 "name": data_utils.rand_name("ss-name"),
167 "description": data_utils.rand_name("ss-desc"),
168 "dns_ip": utils.rand_ip(),
169 "server": utils.rand_ip(),
170 "domain": data_utils.rand_name("ss-domain"),
171 "user": data_utils.rand_name("ss-user"),
172 "password": data_utils.rand_name("ss-password"),
173 }
174 if set_ou:
175 data["ou"] = data_utils.rand_name("ss-ou")
176
177 return data
178
179
Rodrigo Barbieric9abf282016-08-24 22:01:31 -0300180def choose_matching_backend(share, pools, share_type):
181 extra_specs = {}
182 # fix extra specs with string values instead of boolean
183 for k, v in share_type['extra_specs'].items():
haixin48895812020-09-30 13:50:37 +0800184 extra_specs[k] = (True if str(v).lower() == 'true'
185 else False if str(v).lower() == 'false'
Rodrigo Barbieric9abf282016-08-24 22:01:31 -0300186 else v)
187 selected_pool = next(
188 (x for x in pools if (x['name'] != share['host'] and all(
189 y in x['capabilities'].items() for y in extra_specs.items()))),
190 None)
191
192 return selected_pool
Rodrigo Barbieri58d9de32016-09-06 13:16:47 -0300193
194
195def get_configured_extra_specs(variation=None):
196 """Retrieve essential extra specs according to configuration in tempest.
197
198 :param variation: can assume possible values: None to be as configured in
199 tempest; 'opposite_driver_modes' for as configured in tempest but
200 inverse driver mode; 'invalid' for inverse as configured in tempest,
201 ideal for negative tests.
202 :return: dict containing essential extra specs.
203 """
204
205 extra_specs = {'storage_protocol': CONF.share.capability_storage_protocol}
206
207 if variation == 'invalid':
208 extra_specs['driver_handles_share_servers'] = (
209 not CONF.share.multitenancy_enabled)
210 extra_specs['snapshot_support'] = (
211 not CONF.share.capability_snapshot_support)
212
213 elif variation == 'opposite_driver_modes':
214 extra_specs['driver_handles_share_servers'] = (
215 not CONF.share.multitenancy_enabled)
216 extra_specs['snapshot_support'] = (
217 CONF.share.capability_snapshot_support)
218
219 else:
220 extra_specs['driver_handles_share_servers'] = (
221 CONF.share.multitenancy_enabled)
222 extra_specs['snapshot_support'] = (
223 CONF.share.capability_snapshot_support)
Victoria Martinez de la Cruzf6bc6fa2018-02-01 11:27:00 -0500224 extra_specs['create_share_from_snapshot_support'] = (
225 CONF.share.capability_create_share_from_snapshot_support)
Rodrigo Barbieri58d9de32016-09-06 13:16:47 -0300226
227 return extra_specs
Lucio Seki37056942019-01-24 15:40:20 -0200228
229
lkuchlan4a803162022-11-16 11:34:33 +0200230def get_access_rule_data_from_config(protocol):
231 """Get the first available access type/to combination from config.
232
233 This method opportunistically picks the first configured protocol
234 to create the share. Do not use this method in tests where you need
235 to test depth and breadth in the access types and access recipients.
236 """
237
238 if protocol in CONF.share.enable_ip_rules_for_protocols:
239 access_type = "ip"
240 access_to = rand_ip()
241 elif protocol in CONF.share.enable_user_rules_for_protocols:
242 access_type = "user"
243 access_to = CONF.share.username_for_user_rules
244 elif protocol in CONF.share.enable_cert_rules_for_protocols:
245 access_type = "cert"
246 access_to = "client3.com"
247 elif protocol in CONF.share.enable_cephx_rules_for_protocols:
248 access_type = "cephx"
249 access_to = data_utils.rand_name("cephx-id")
250 else:
251 message = "Unrecognized protocol and access rules configuration."
252 raise testtools.TestCase.skipException(message)
253
254 return access_type, access_to
255
256
Douglas Viroelbd4e78c2019-09-02 17:16:30 -0300257def replication_with_multitenancy_support():
258 return (share_network_subnets_are_supported() and
259 CONF.share.multitenancy_enabled)
260
261
Lucio Seki37056942019-01-24 15:40:20 -0200262def skip_if_manage_not_supported_for_version(
263 version=CONF.share.max_api_microversion):
264 if (is_microversion_lt(version, "2.49")
265 and CONF.share.multitenancy_enabled):
266 raise testtools.TestCase.skipException(
267 "Share manage tests with multitenancy are disabled for "
268 "microversion < 2.49")
Douglas Viroelb7e27e72019-08-06 19:40:37 -0300269
270
271def share_network_subnets_are_supported():
272 return is_microversion_supported(SHARE_NETWORK_SUBNETS_MICROVERSION)
273
274
silvacarlossca4dd9f2020-03-11 13:57:18 +0000275def share_replica_quotas_are_supported():
276 return is_microversion_supported(SHARE_REPLICA_QUOTAS_MICROVERSION)
277
278
Douglas Viroelb7e27e72019-08-06 19:40:37 -0300279def share_network_get_default_subnet(share_network):
280 return next((
281 subnet for subnet in share_network.get('share_network_subnets', [])
282 if subnet['availability_zone'] is None), None)
silvacarloss6e575682020-02-18 19:52:35 -0300283
284
285def get_extra_headers(request_version, graduation_version):
286 headers = None
287 extra_headers = False
288 if is_microversion_lt(request_version, graduation_version):
289 headers = EXPERIMENTAL
290 extra_headers = True
291 return headers, extra_headers