def negotiate_version(self, conn, resp): """Negotiate the server version Assumption: Called after receiving a 406 error when doing a request. param conn: A connection object param resp: The response object from http request """ if self.api_version_select_state not in API_VERSION_SELECTED_STATES: raise RuntimeError( _('Error: self.api_version_select_state should be one of the ' 'values in: "%(valid)s" but had the value: "%(value)s"') % { 'valid': ', '.join(API_VERSION_SELECTED_STATES), 'value': self.api_version_select_state }) min_ver, max_ver = self._parse_version_headers(resp) # If the user requested an explicit version or we have negotiated a # version and still failing then error now. The server could # support the version requested but the requested operation may not # be supported by the requested version. if self.api_version_select_state == 'user': raise exceptions.UnsupportedVersion( textwrap.fill( _("Requested API version %(req)s is not supported by the " "server or the requested operation is not supported by the " "requested version. Supported version range is %(min)s to " "%(max)s") % { 'req': self.os_infra_optim_api_version, 'min': min_ver, 'max': max_ver })) if self.api_version_select_state == 'negotiated': raise exceptions.UnsupportedVersion( textwrap.fill( _("No API version was specified and the requested operation " "was not supported by the client's negotiated API version " "%(req)s. Supported version range is: %(min)s to %(max)s" ) % { 'req': self.os_infra_optim_api_version, 'min': min_ver, 'max': max_ver })) negotiated_ver = str( min(version.StrictVersion(self.os_infra_optim_api_version), version.StrictVersion(max_ver))) if negotiated_ver < min_ver: negotiated_ver = min_ver # server handles microversions, but doesn't support # the requested version, so try a negotiated version self.api_version_select_state = 'negotiated' self.os_infra_optim_api_version = negotiated_ver LOG.debug('Negotiated API version is %s', negotiated_ver) return negotiated_ver
def __init__(self, version_str=None): """Create an API version object. :param version_str: String representation of APIVersionRequest. Correct format is 'X.Y', where 'X' and 'Y' are int values. None value should be used to create Null APIVersionRequest, which is equal to 0.0 """ self.ver_major = 0 self.ver_minor = 0 if version_str is not None: match = re.match(r"^([1-9]\d*)\.([1-9]\d*|0|latest)$", version_str) if match: self.ver_major = int(match.group(1)) if match.group(2) == "latest": # NOTE(andreykurilin): Infinity allows to easily determine # latest version and doesn't require any additional checks # in comparison methods. self.ver_minor = float("inf") else: self.ver_minor = int(match.group(2)) else: msg = _("Invalid format of client version '%s'. " "Expected format 'X.Y', where X is a major part and Y " "is a minor part of version.") % version_str raise exceptions.UnsupportedVersion(msg)
def check_major_version(api_version): """Checks major part of ``APIVersion`` obj is supported. :raises watcherclient.exceptions.UnsupportedVersion: if major part is not supported """ available_versions = get_available_major_versions() if (not api_version.is_null() and str(api_version.ver_major) not in available_versions): if len(available_versions) == 1: msg = _("Invalid client version '%(version)s'. " "Major part should be '%(major)s'") % { "version": api_version.get_string(), "major": available_versions[0]} else: msg = _("Invalid client version '%(version)s'. " "Major part must be one of: '%(major)s'") % { "version": api_version.get_string(), "major": ", ".join(available_versions)} raise exceptions.UnsupportedVersion(msg)