def _check_depends_on_nova_network(cls): # Since nova-network APIs were removed from Nova in the Rocky release, # determine, based on the max version from the version document, if # the compute API is >Queens and if so, skip tests that rely on # nova-network. if not getattr(cls, 'depends_on_nova_network', False): return versions = cls.versions_client.list_versions()['versions'] # Find the v2.1 version which will tell us our max version for the # compute API we're testing against. for version in versions: if version['id'] == 'v2.1': max_version = api_version_request.APIVersionRequest( version['version']) break else: LOG.warning('Unable to determine max v2.1 compute API version: %s', versions) return # The max compute API version in Queens is 2.60 so we cap # at that version. queens = api_version_request.APIVersionRequest('2.60') if max_version > queens: raise cls.skipException('nova-network is gone')
def is_requested_microversion_compatible(cls, max_version): """Check the compatibility of selected request microversion This method will check if selected request microversion (cls.request_microversion) for test is compatible with respect to 'max_version'. Compatible means if selected request microversion is in the range(<=) of 'max_version'. :param max_version: maximum microversion to compare for compatibility. Example: '2.30' :returns: True if selected request microversion is compatible with 'max_version'. False in other case. """ try: req_version_obj = api_version_request.APIVersionRequest( cls.request_microversion) # NOTE(gmann): This is case where this method is used before calling # resource_setup(), where cls.request_microversion is set. There may # not be any such case but still we can handle this case. except AttributeError: request_microversion = ( api_version_utils.select_request_microversion( cls.min_microversion, CONF.compute.min_microversion)) req_version_obj = api_version_request.APIVersionRequest( request_microversion) max_version_obj = api_version_request.APIVersionRequest(max_version) return req_version_obj <= max_version_obj
def create_test_server(cls, validatable=False, volume_backed=False, **kwargs): """Wrapper utility that returns a test server. This wrapper utility calls the common create test server and returns a test server. The purpose of this wrapper is to minimize the impact on the code of the tests already using this function. :param validatable: Whether the server will be pingable or sshable. :param volume_backed: Whether the instance is volume backed or not. """ if 'name' not in kwargs: kwargs['name'] = data_utils.rand_name(cls.__name__ + "-server") request_version = api_version_request.APIVersionRequest( cls.request_microversion) v2_37_version = api_version_request.APIVersionRequest('2.37') # NOTE(snikitin): since microversion v2.37 'networks' field is required if request_version >= v2_37_version and 'networks' not in kwargs: kwargs['networks'] = 'none' tenant_network = cls.get_tenant_network() body, servers = compute.create_test_server( cls.os_primary, validatable, validation_resources=cls.validation_resources, tenant_network=tenant_network, volume_backed=volume_backed, **kwargs) cls.servers.extend(servers) return body
def get_schema(self, schema_versions_info): """Get JSON schema This method provides the matching schema for requested microversion. :param schema_versions_info: List of dict which provides schema information with range of valid versions. Example:: schema_versions_info = [ {'min': None, 'max': '2.1', 'schema': schemav21}, {'min': '2.2', 'max': '2.9', 'schema': schemav22}, {'min': '2.10', 'max': None, 'schema': schemav210}] """ schema = None version = api_version_request.APIVersionRequest(COMPUTE_MICROVERSION) for items in schema_versions_info: min_version = api_version_request.APIVersionRequest(items['min']) max_version = api_version_request.APIVersionRequest(items['max']) # This is case where COMPUTE_MICROVERSION is None, which means # request without microversion So select base v2.1 schema. if version.is_null() and items['min'] is None: schema = items['schema'] break # else select appropriate schema as per COMPUTE_MICROVERSION elif version.matches(min_version, max_version): schema = items['schema'] break if schema is None: raise exceptions.JSONSchemaNotFound( version=version.get_string(), schema_versions_info=schema_versions_info) return schema
def test_get_string(self): vers_string = ["3.23", "latest"] for ver in vers_string: ver_obj = api_version_request.APIVersionRequest(ver) self.assertEqual(ver, ver_obj.get_string()) self.assertIsNotNone( api_version_request.APIVersionRequest().get_string)
def _is_version_supported(version): """Return whether an API microversion is supported.""" min_version = api_version_request.APIVersionRequest( CONF.baremetal.min_microversion) max_version = api_version_request.APIVersionRequest( CONF.baremetal.max_microversion) version = api_version_request.APIVersionRequest(version) return min_version <= version <= max_version
def create_test_server(cls, validatable=False, volume_backed=False, validation_resources=None, clients=None, **kwargs): """Wrapper utility that returns a test server. This wrapper utility calls the common create test server and returns a test server. The purpose of this wrapper is to minimize the impact on the code of the tests already using this function. :param validatable: Whether the server will be pingable or sshable. :param volume_backed: Whether the instance is volume backed or not. :param validation_resources: Dictionary of validation resources as returned by `get_class_validation_resources`. :param clients: Client manager, defaults to os_primary. :param kwargs: Extra arguments are passed down to the `compute.create_test_server` call. """ if 'name' not in kwargs: kwargs['name'] = data_utils.rand_name(cls.__name__ + "-server") request_version = api_version_request.APIVersionRequest( cls.request_microversion) v2_37_version = api_version_request.APIVersionRequest('2.37') tenant_network = cls.get_tenant_network() # NOTE(snikitin): since microversion v2.37 'networks' field is required if (request_version >= v2_37_version and 'networks' not in kwargs and not tenant_network): kwargs['networks'] = 'none' if clients is None: clients = cls.os_primary body, servers = compute.create_test_server( clients, validatable, validation_resources=validation_resources, tenant_network=tenant_network, volume_backed=volume_backed, **kwargs) # For each server schedule wait and delete, so we first delete all # and then wait for all for server in servers: cls.addClassResourceCleanup(waiters.wait_for_server_termination, clients.servers_client, server['id']) for server in servers: cls.addClassResourceCleanup( test_utils.call_and_ignore_notfound_exc, clients.servers_client.delete_server, server['id']) return body
def compare_version_header_to_response(api_microversion_header_name, api_microversion, response_header, operation='eq'): """Compares API microversion in response header to ``api_microversion``. Compare the ``api_microversion`` value in response header if microversion header is present in response, otherwise return false. To make this function work for APIs which do not return microversion header in response (example compute v2.0), this function does *not* raise InvalidHTTPResponseHeader. :param api_microversion_header_name: Microversion header name. Example: 'Openstack-Api-Version'. :param api_microversion: Microversion number. Example: * '2.10' for the old-style header name, 'X-OpenStack-Nova-API-Version' * 'Compute 2.10' for the new-style header name, 'Openstack-Api-Version' :param response_header: Response header where microversion is expected to be present. :param operation: The boolean operation to use to compare the ``api_microversion`` to the microversion in ``response_header``. Can be 'lt', 'eq', 'gt', 'le', 'ne', 'ge'. Default is 'eq'. The operation type should be based on the order of the arguments: ``api_microversion`` <operation> ``response_header`` microversion. :returns: True if the comparison is logically true, else False if the comparison is logically false or if ``api_microversion_header_name`` is missing in the ``response_header``. :raises InvalidParam: If the operation is not lt, eq, gt, le, ne or ge. """ api_microversion_header_name = api_microversion_header_name.lower() if api_microversion_header_name not in response_header: return False op = getattr(api_version_request.APIVersionRequest, '__%s__' % operation, None) if op is None: msg = ("Operation %s is invalid. Valid options include: lt, eq, gt, " "le, ne, ge." % operation) LOG.debug(msg) raise exceptions.InvalidParam(invalid_param=msg) # Remove "volume" from "volume <microversion>", for example, so that the # microversion can be converted to `APIVersionRequest`. api_version = api_microversion.split(' ')[-1] resp_version = response_header[api_microversion_header_name].split(' ')[-1] if not op(api_version_request.APIVersionRequest(api_version), api_version_request.APIVersionRequest(resp_version)): return False return True
def select_request_microversion(test_min_version, cfg_min_version): """Select microversion from test and configuration min version. Compare requested microversion and return the maximum microversion out of those. :param test_min_version: Test Minimum Microversion :param cfg_min_version: Configured Minimum Microversion :returns: Selected microversion string """ test_version = api_version_request.APIVersionRequest(test_min_version) cfg_version = api_version_request.APIVersionRequest(cfg_min_version) max_version = cfg_version if cfg_version >= test_version else test_version return max_version.get_string()
def check_skip_with_microversion(test_min_version, test_max_version, cfg_min_version, cfg_max_version): """Checks API microversions range and returns whether test needs to be skip Compare the test and configured microversion range and returns whether test microversion range is out of configured one. This method can be used to skip the test based on configured and test microversion range. :param test_min_version: Test Minimum Microversion :param test_max_version: Test Maximum Microversion :param cfg_min_version: Configured Minimum Microversion :param cfg_max_version: Configured Maximum Microversion :returns: boolean """ min_version = api_version_request.APIVersionRequest(test_min_version) max_version = api_version_request.APIVersionRequest(test_max_version) config_min_version = api_version_request.APIVersionRequest(cfg_min_version) config_max_version = api_version_request.APIVersionRequest(cfg_max_version) if ((min_version > max_version) or (config_min_version > config_max_version)): msg = ( "Test Class versions [%s - %s]. " "Configuration versions [%s - %s]." % (min_version.get_string(), max_version.get_string(), config_min_version.get_string(), config_max_version.get_string())) raise exceptions.InvalidAPIVersionRange(msg) # NOTE: Select tests which are in range of configuration like # config min config max # ----------------+--------------------------+---------------- # ...don't-select| # ...select... ...select... ...select... # |don't-select... # ......................select............................ if (max_version < config_min_version or config_max_version < min_version): msg = ( "The microversion range[%s - %s] of this test is out of the " "configuration range[%s - %s]." % (min_version.get_string(), max_version.get_string(), config_min_version.get_string(), config_max_version.get_string())) raise testtools.TestCase.skipException(msg)
def test_version_comparisons(self): vers2_0 = api_version_request.APIVersionRequest("2.0") vers2_5 = api_version_request.APIVersionRequest("2.5") vers5_23 = api_version_request.APIVersionRequest("5.23") v_null = api_version_request.APIVersionRequest() v_latest = api_version_request.APIVersionRequest('latest') self.assertTrue(v_null < vers2_5) self.assertTrue(vers2_0 < vers2_5) self.assertTrue(vers2_0 <= vers2_5) self.assertTrue(vers2_0 <= vers2_0) self.assertTrue(vers2_5 > v_null) self.assertTrue(vers5_23 > vers2_5) self.assertTrue(vers2_0 >= vers2_0) self.assertTrue(vers5_23 >= vers2_5) self.assertTrue(vers2_0 != vers2_5) self.assertTrue(vers2_0 == vers2_0) self.assertTrue(vers2_0 != v_null) self.assertTrue(v_null == v_null) self.assertTrue(vers2_0 <= v_latest) self.assertTrue(vers2_0 != v_latest) self.assertTrue(v_latest == v_latest) self.assertRaises(TypeError, vers2_0.__lt__, "2.1")
def validate_ports(self): node_uuid = self.node['uuid'] vifs = [] # TODO(vsaienko) switch to get_node_vifs() when all stable releases # supports Ironic API 1.28 if (api_version_request.APIVersionRequest( CONF.baremetal.max_microversion) >= api_version_request.APIVersionRequest('1.28')): vifs = self.get_node_vifs(node_uuid) else: for port in self.get_ports(self.node['uuid']): vif = port['extra'].get('vif_port_id') if vif: vifs.append({'id': vif}) ir_ports = self.get_ports(node_uuid) ir_ports_addresses = [x['address'] for x in ir_ports] for vif in vifs: n_port_id = vif['id'] body = self.ports_client.show_port(n_port_id) n_port = body['port'] self.assertEqual(n_port['device_id'], self.instance['id']) self.assertIn(n_port['mac_address'], ir_ports_addresses)
def test_version_matches(self): vers2_0 = api_version_request.APIVersionRequest("2.0") vers2_5 = api_version_request.APIVersionRequest("2.5") vers2_45 = api_version_request.APIVersionRequest("2.45") vers3_3 = api_version_request.APIVersionRequest("3.3") vers3_23 = api_version_request.APIVersionRequest("3.23") vers4_0 = api_version_request.APIVersionRequest("4.0") v_null = api_version_request.APIVersionRequest() v_latest = api_version_request.APIVersionRequest('latest') def _check_version_matches(version, version1, version2, check=True): if check: msg = "Version %s does not matches with [%s - %s] range" self.assertTrue( version.matches(version1, version2), msg % (version.get_string(), version1.get_string(), version2.get_string())) else: msg = "Version %s matches with [%s - %s] range" self.assertFalse( version.matches(version1, version2), msg % (version.get_string(), version1.get_string(), version2.get_string())) _check_version_matches(vers2_5, vers2_0, vers2_45) _check_version_matches(vers2_5, vers2_0, v_null) _check_version_matches(vers2_0, vers2_0, vers2_5) _check_version_matches(vers3_3, vers2_5, vers3_3) _check_version_matches(vers3_3, v_null, vers3_3) _check_version_matches(vers3_3, v_null, vers4_0) _check_version_matches(vers2_0, vers2_5, vers2_45, False) _check_version_matches(vers3_23, vers2_5, vers3_3, False) _check_version_matches(vers2_5, vers2_45, vers2_0, False) _check_version_matches(vers2_5, vers2_0, v_latest) _check_version_matches(v_latest, v_latest, v_latest) _check_version_matches(vers2_5, v_latest, v_latest, False) _check_version_matches(v_latest, vers2_0, vers4_0, False) self.assertRaises(ValueError, v_null.matches, vers2_0, vers2_45)
def test_null_version(self): v = api_version_request.APIVersionRequest() self.assertTrue(v.is_null())
def _test_string(version, exp_major, exp_minor): v = api_version_request.APIVersionRequest(version) self.assertEqual(v.ver_major, exp_major) self.assertEqual(v.ver_minor, exp_minor)