blob: 7625460d2c423bc406cdef00377833515604092f [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 +020021import six
22from tempest import config
23import testtools
24
25CONF = config.CONF
Douglas Viroelb7e27e72019-08-06 19:40:37 -030026SHARE_NETWORK_SUBNETS_MICROVERSION = '2.51'
silvacarlossca4dd9f2020-03-11 13:57:18 +000027SHARE_REPLICA_QUOTAS_MICROVERSION = "2.53"
silvacarloss6e575682020-02-18 19:52:35 -030028EXPERIMENTAL = {'X-OpenStack-Manila-API-Experimental': 'True'}
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020029
30
Luigi Toscanod91870b2020-10-03 15:17:23 +020031def deduplicate(items):
32 """De-duplicate a list of items while preserving the order.
33
34 It is useful when passing a list of items to ddt.data, in order
35 to remove duplicated elements which may be specified as constants.
36 """
37 return list(OrderedDict.fromkeys(items))
38
39
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +020040def get_microversion_as_tuple(microversion_str):
41 """Transforms string-like microversion to two-value tuple of integers.
42
43 Tuple of integers useful for microversion comparisons.
44 """
45 regex = r"^([1-9]\d*)\.([1-9]\d*|0)$"
46 match = re.match(regex, microversion_str)
47 if not match:
48 raise ValueError(
49 "Microversion does not fit template 'x.y' - %s" % microversion_str)
50 return int(match.group(1)), int(match.group(2))
51
52
53def is_microversion_gt(left, right):
54 """Is microversion for left is greater than the right one."""
55 return get_microversion_as_tuple(left) > get_microversion_as_tuple(right)
56
57
58def is_microversion_ge(left, right):
59 """Is microversion for left is greater than or equal to the right one."""
60 return get_microversion_as_tuple(left) >= get_microversion_as_tuple(right)
61
62
63def is_microversion_eq(left, right):
64 """Is microversion for left is equal to the right one."""
65 return get_microversion_as_tuple(left) == get_microversion_as_tuple(right)
66
67
68def is_microversion_ne(left, right):
69 """Is microversion for left is not equal to the right one."""
70 return get_microversion_as_tuple(left) != get_microversion_as_tuple(right)
71
72
73def is_microversion_le(left, right):
74 """Is microversion for left is less than or equal to the right one."""
75 return get_microversion_as_tuple(left) <= get_microversion_as_tuple(right)
76
77
78def is_microversion_lt(left, right):
79 """Is microversion for left is less than the right one."""
80 return get_microversion_as_tuple(left) < get_microversion_as_tuple(right)
81
82
83def is_microversion_supported(microversion):
84 bottom = get_microversion_as_tuple(CONF.share.min_api_microversion)
85 microversion = get_microversion_as_tuple(microversion)
86 top = get_microversion_as_tuple(CONF.share.max_api_microversion)
87 return bottom <= microversion <= top
88
89
90def skip_if_microversion_not_supported(microversion):
91 """Decorator for tests that are microversion-specific."""
92 if not is_microversion_supported(microversion):
93 reason = ("Skipped. Test requires microversion '%s'." % microversion)
94 return testtools.skip(reason)
95 return lambda f: f
96
97
lkuchlana3b6f7a2020-01-07 10:45:45 +020098def check_skip_if_microversion_not_supported(microversion):
Goutham Pacha Ravia0acf252021-05-27 19:57:55 -070099 """Callable method for tests that are microversion-specific."""
lkuchlana3b6f7a2020-01-07 10:45:45 +0200100 if not is_microversion_supported(microversion):
101 reason = ("Skipped. Test requires microversion '%s'." % microversion)
102 raise testtools.TestCase.skipException(reason)
103
104
zhongjun72974ff2016-05-04 11:47:03 +0800105def rand_ip(network=False):
Valeriy Ponomaryovfcde7712015-12-14 18:06:13 +0200106 """This uses the TEST-NET-3 range of reserved IP addresses.
107
108 Using this range, which are reserved solely for use in
109 documentation and example source code, should avoid any potential
110 conflicts in real-world testing.
111 """
zhongjun72974ff2016-05-04 11:47:03 +0800112 test_net_3 = '203.0.113.'
113 address = test_net_3 + six.text_type(random.randint(0, 255))
114 if network:
115 mask_length = six.text_type(random.randint(24, 32))
116 address = '/'.join((address, mask_length))
117 ip_network = ip.IPNetwork(address)
118 return '/'.join((six.text_type(ip_network.network), mask_length))
119 return address
120
121
122def rand_ipv6_ip(network=False):
123 """This uses the IPv6 documentation range of 2001:DB8::/32"""
Raissa Sarmento80f5fbf2017-10-16 14:38:36 +0100124 ran_add = ["%x" % random.randrange(0, 16 ** 4) for i in range(6)]
zhongjun72974ff2016-05-04 11:47:03 +0800125 address = "2001:0DB8:" + ":".join(ran_add)
126 if network:
127 mask_length = six.text_type(random.randint(32, 128))
128 address = '/'.join((address, mask_length))
129 ip_network = ip.IPNetwork(address)
130 return '/'.join((six.text_type(ip_network.network), mask_length))
131 return address
Rodrigo Barbieric9abf282016-08-24 22:01:31 -0300132
133
134def choose_matching_backend(share, pools, share_type):
135 extra_specs = {}
136 # fix extra specs with string values instead of boolean
137 for k, v in share_type['extra_specs'].items():
138 extra_specs[k] = (True if six.text_type(v).lower() == 'true'
139 else False if six.text_type(v).lower() == 'false'
140 else v)
141 selected_pool = next(
142 (x for x in pools if (x['name'] != share['host'] and all(
143 y in x['capabilities'].items() for y in extra_specs.items()))),
144 None)
145
146 return selected_pool
Rodrigo Barbieri58d9de32016-09-06 13:16:47 -0300147
148
149def get_configured_extra_specs(variation=None):
150 """Retrieve essential extra specs according to configuration in tempest.
151
152 :param variation: can assume possible values: None to be as configured in
153 tempest; 'opposite_driver_modes' for as configured in tempest but
154 inverse driver mode; 'invalid' for inverse as configured in tempest,
155 ideal for negative tests.
156 :return: dict containing essential extra specs.
157 """
158
159 extra_specs = {'storage_protocol': CONF.share.capability_storage_protocol}
160
161 if variation == 'invalid':
162 extra_specs['driver_handles_share_servers'] = (
163 not CONF.share.multitenancy_enabled)
164 extra_specs['snapshot_support'] = (
165 not CONF.share.capability_snapshot_support)
166
167 elif variation == 'opposite_driver_modes':
168 extra_specs['driver_handles_share_servers'] = (
169 not CONF.share.multitenancy_enabled)
170 extra_specs['snapshot_support'] = (
171 CONF.share.capability_snapshot_support)
172
173 else:
174 extra_specs['driver_handles_share_servers'] = (
175 CONF.share.multitenancy_enabled)
176 extra_specs['snapshot_support'] = (
177 CONF.share.capability_snapshot_support)
Victoria Martinez de la Cruzf6bc6fa2018-02-01 11:27:00 -0500178 extra_specs['create_share_from_snapshot_support'] = (
179 CONF.share.capability_create_share_from_snapshot_support)
Rodrigo Barbieri58d9de32016-09-06 13:16:47 -0300180
181 return extra_specs
Lucio Seki37056942019-01-24 15:40:20 -0200182
183
Douglas Viroelbd4e78c2019-09-02 17:16:30 -0300184def replication_with_multitenancy_support():
185 return (share_network_subnets_are_supported() and
186 CONF.share.multitenancy_enabled)
187
188
Lucio Seki37056942019-01-24 15:40:20 -0200189def skip_if_manage_not_supported_for_version(
190 version=CONF.share.max_api_microversion):
191 if (is_microversion_lt(version, "2.49")
192 and CONF.share.multitenancy_enabled):
193 raise testtools.TestCase.skipException(
194 "Share manage tests with multitenancy are disabled for "
195 "microversion < 2.49")
Douglas Viroelb7e27e72019-08-06 19:40:37 -0300196
197
198def share_network_subnets_are_supported():
199 return is_microversion_supported(SHARE_NETWORK_SUBNETS_MICROVERSION)
200
201
silvacarlossca4dd9f2020-03-11 13:57:18 +0000202def share_replica_quotas_are_supported():
203 return is_microversion_supported(SHARE_REPLICA_QUOTAS_MICROVERSION)
204
205
Douglas Viroelb7e27e72019-08-06 19:40:37 -0300206def share_network_get_default_subnet(share_network):
207 return next((
208 subnet for subnet in share_network.get('share_network_subnets', [])
209 if subnet['availability_zone'] is None), None)
silvacarloss6e575682020-02-18 19:52:35 -0300210
211
212def get_extra_headers(request_version, graduation_version):
213 headers = None
214 extra_headers = False
215 if is_microversion_lt(request_version, graduation_version):
216 headers = EXPERIMENTAL
217 extra_headers = True
218 return headers, extra_headers