예제 #1
0
    def test_nova(self, nova):
        reload(clients)

        # test normal flow
        context = mock.Mock(
            auth_token='fake_token',
            service_catalog=[{'type': 'computev21',
                              'endpoints': [{'publicURL': 'novav21_url'}]}])
        with fixtures.LoggerFixture() as logs:
            res = clients.nova(context)
        self.assertEqual(nova.return_value, res)
        nova.assert_called_with(
            '2.3', bypass_url='novav21_url', cacert=None, insecure=False,
            auth_url='keystone_url', auth_token='fake_token',
            username=None, api_key=None, project_id=None)
        self.assertEqual(0, len(logs.output))

        # test switching to v2 client
        nova.side_effect = [nova_exception.UnsupportedVersion(), 'v2_client']
        with fixtures.LoggerFixture() as logs:
            res = clients.nova(context)
        self.assertEqual('v2_client', res)
        nova.assert_called_with(
            '2', bypass_url='novav21_url', cacert=None, insecure=False,
            auth_url='keystone_url', auth_token='fake_token',
            username=None, api_key=None, project_id=None)
        self.assertNotEqual(0, len(logs.output))

        # test raising of an exception if v2 client is not supported as well
        nova.side_effect = nova_exception.UnsupportedVersion()
        self.assertRaises(nova_exception.UnsupportedVersion,
                          clients.nova, context)

        nova.side_effect = None
        reload(clients)

        # test switching to 'compute' service type
        context.service_catalog = [{'type': 'compute',
                                    'endpoints': [{'publicURL': 'nova_url'}]}]
        with fixtures.LoggerFixture() as logs:
            res = clients.nova(context)
        nova.assert_called_with(
            '2.3', bypass_url='nova_url', cacert=None, insecure=False,
            auth_url='keystone_url', auth_token='fake_token',
            username=None, api_key=None, project_id=None)
        self.assertNotEqual(0, len(logs.output))

        # test behavior if 'compute' service type is not found as well
        context.service_catalog = [{'type': 'fake'}]
        clients.nova(context)
        nova.assert_called_with(
            '2.3', bypass_url=None, cacert=None, insecure=False,
            auth_url='keystone_url', auth_token='fake_token',
            username=None, api_key=None, project_id=None)
예제 #2
0
    def __init__(self, version_str=None):
        """Create an API version object.

        :param version_string: 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)
예제 #3
0
def get_client_class(version):
    version = str(version)
    if version in DEPRECATED_VERSIONS:
        warnings.warn(
            _LW("Version %(deprecated_version)s is deprecated, using "
                "alternative version %(alternative)s instead.") % {
                    "deprecated_version": version,
                    "alternative": DEPRECATED_VERSIONS[version]
                })
        version = DEPRECATED_VERSIONS[version]
    try:
        return importutils.import_class("novaclient.v%s.client.Client" %
                                        version)
    except ImportError:
        # NOTE(andreykurilin): available clients version should not be
        # hardcoded, so let's discover them.
        matcher = re.compile(r"v[0-9_]*$")
        submodules = pkgutil.iter_modules(['novaclient'])
        available_versions = [
            name[1:].replace("_", ".") for loader, name, ispkg in submodules
            if matcher.search(name)
        ]
        msg = _("Invalid client version '%(version)s'. must be one of: "
                "%(keys)s") % {
                    'version': version,
                    'keys': ', '.join(available_versions)
                }
        raise exceptions.UnsupportedVersion(msg)
    def search(self, hypervisor_match, servers=False, detailed=False):
        """
        Get a list of matching hypervisors.

        :param hypervisor_match: The hypervisor host name or a portion of it.
            The hypervisor hosts are selected with the host name matching
            this pattern.
        :param servers: If True, server information is also retrieved.
        :param detailed: If True, detailed hypervisor information is returned.
            This requires API version 2.53 or greater.
        """
        # Starting with microversion 2.53, the /servers and /search routes are
        # deprecated and we get the same results using GET /os-hypervisors
        # using query parameters for the hostname pattern and servers.
        if self.api_version >= api_versions.APIVersion('2.53'):
            url = ('/os-hypervisors%s?hypervisor_hostname_pattern=%s' %
                   ('/detail' if detailed else '',
                    parse.quote(hypervisor_match, safe='')))
            if servers:
                url += '&with_servers=True'
        else:
            if detailed:
                raise exceptions.UnsupportedVersion(
                    _('Parameter "detailed" requires API version 2.53 or '
                      'greater.'))
            target = 'servers' if servers else 'search'
            url = ('/os-hypervisors/%s/%s' %
                   (parse.quote(hypervisor_match, safe=''), target))
        return self._list(url, 'hypervisors')
예제 #5
0
def _get_client_class_and_version(version):
    if not isinstance(version, api_versions.APIVersion):
        version = api_versions.get_api_version(version)
    else:
        api_versions.check_major_version(version)
    if version.is_latest():
        raise exceptions.UnsupportedVersion(
            _("The version should be explicit, not latest."))
    return version, importutils.import_class(
        "novaclient.v%s.client.Client" % version.ver_major)
예제 #6
0
def get_client_class(version):
    try:
        version = str(version)
        client_path = {
            '1.1': 'novaclient.v1_1.client.Client',
            '2': 'novaclient.v1_1.client.Client',
        }[version]
    except (KeyError, ValueError):
        raise exceptions.UnsupportedVersion()

    return utils.import_class(client_path)
예제 #7
0
def get_client_class(version):
    version_map = {
        '1.1': 'novaclient.v1_1.client.Client',
        '2': 'novaclient.v1_1.client.Client',
    }
    try:
        client_path = version_map[str(version)]
    except (KeyError, ValueError):
        msg = "Invalid client version '%s'. must be one of: %s" % (
            (version, ', '.join(version_map.keys())))
        raise exceptions.UnsupportedVersion(msg)

    return utils.import_class(client_path)
예제 #8
0
def get_client_class(version):
    version_map = {
        '1.1': 'novaclient.v1_1.client.Client',
        '2': 'novaclient.v1_1.client.Client',
        '3': 'novaclient.v3.client.Client',
    }
    try:
        client_path = version_map[str(version)]
    except (KeyError, ValueError):
        msg = _("Invalid client version '%(version)s'. must be one of: "
                "%(keys)s") % {'version': version,
                               'keys': ', '.join(version_map.keys())}
        raise exceptions.UnsupportedVersion(msg)

    return utils.import_class(client_path)
예제 #9
0
 def _init_nova(self):
     if self.nova:
         return  # Already initialised
     for version in NOVA_API_VERSIONS:
         try:
             self.nova = nova_client.Client(version,
                                            self.params['username'],
                                            self.params['password'],
                                            self.params['tenant_name'],
                                            self.params['auth_url'])
         except nova_exceptions.ClientException as exc:
             self.logger.debug(
                 "Failed to instantiate Nova client" +
                 " for API version '%s': %s", version, exc)
     if self.nova is None:
         raise nova_exceptions.UnsupportedVersion()
예제 #10
0
    def test_check_nova_api_version(self, mock_glance, mock_cinder,
                                    mock_neutron, mock_nova):
        nova_util = nova_helper.NovaHelper()

        # verify that the method will return True when the version of nova_api
        # is supported.
        api_versions.APIVersion = mock.MagicMock()
        result = nova_util._check_nova_api_version(nova_util.nova, "2.56")
        self.assertTrue(result)

        # verify that the method will return False when the version of nova_api
        # is not supported.
        side_effect = nvexceptions.UnsupportedVersion()
        api_versions.discover_version = mock.MagicMock(side_effect=side_effect)
        result = nova_util._check_nova_api_version(nova_util.nova, "2.56")
        self.assertFalse(result)
예제 #11
0
def check_major_version(api_version):
    """Checks major part of ``APIVersion`` obj is supported.

    :raises novaclient.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)
예제 #12
0
    def __init__(self, version_str=None):
        """Create an API version object."""
        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)
예제 #13
0
def get_client_class(version):
    version = str(version)
    if version in DEPRECATED_VERSIONS:
        warnings.warn(
            _LW("Version %(deprecated_version)s is deprecated, using "
                "alternative version %(alternative)s instead.") % {
                    "deprecated_version": version,
                    "alternative": DEPRECATED_VERSIONS[version]
                })
        version = DEPRECATED_VERSIONS[version]
    try:
        return importutils.import_class("novaclient.v%s.client.Client" %
                                        version)
    except ImportError:
        available_versions = _get_available_client_versions()
        msg = _("Invalid client version '%(version)s'. must be one of: "
                "%(keys)s") % {
                    'version': version,
                    'keys': ', '.join(available_versions)
                }
        raise exceptions.UnsupportedVersion(msg)
예제 #14
0
def discover_version(client, requested_version):
    """Discover most recent version supported by API and client.

    Checks ``requested_version`` and returns the most recent version
    supported by both the API and the client.

    :param client: client object
    :param requested_version: requested version represented by APIVersion obj
    :returns: APIVersion
    """
    server_start_version, server_end_version = _get_server_version_range(
        client)

    if (not requested_version.is_latest() and
            requested_version != APIVersion('2.0')):
        if server_start_version.is_null() and server_end_version.is_null():
            raise exceptions.UnsupportedVersion(
                _("Server doesn't support microversions"))
        if not requested_version.matches(server_start_version,
                                         server_end_version):
            raise exceptions.UnsupportedVersion(
                _("The specified version isn't supported by server. The valid "
                  "version range is '%(min)s' to '%(max)s'") % {
                    "min": server_start_version.get_string(),
                    "max": server_end_version.get_string()})
        return requested_version

    if requested_version == APIVersion('2.0'):
        if (server_start_version == APIVersion('2.1') or
                (server_start_version.is_null() and
                 server_end_version.is_null())):
            return APIVersion('2.0')
        else:
            raise exceptions.UnsupportedVersion(
                _("The server isn't backward compatible with Nova V2 REST "
                  "API"))

    if server_start_version.is_null() and server_end_version.is_null():
        return APIVersion('2.0')
    elif novaclient.API_MIN_VERSION > server_end_version:
        raise exceptions.UnsupportedVersion(
            _("Server version is too old. The client valid version range is "
              "'%(client_min)s' to '%(client_max)s'. The server valid version "
              "range is '%(server_min)s' to '%(server_max)s'.") % {
                  'client_min': novaclient.API_MIN_VERSION.get_string(),
                  'client_max': novaclient.API_MAX_VERSION.get_string(),
                  'server_min': server_start_version.get_string(),
                  'server_max': server_end_version.get_string()})
    elif novaclient.API_MAX_VERSION < server_start_version:
        raise exceptions.UnsupportedVersion(
            _("Server version is too new. The client valid version range is "
              "'%(client_min)s' to '%(client_max)s'. The server valid version "
              "range is '%(server_min)s' to '%(server_max)s'.") % {
                  'client_min': novaclient.API_MIN_VERSION.get_string(),
                  'client_max': novaclient.API_MAX_VERSION.get_string(),
                  'server_min': server_start_version.get_string(),
                  'server_max': server_end_version.get_string()})
    elif novaclient.API_MAX_VERSION <= server_end_version:
        return novaclient.API_MAX_VERSION
    elif server_end_version < novaclient.API_MAX_VERSION:
        return server_end_version
예제 #15
0
 def statistics(self):
     raise exceptions.UnsupportedVersion(
         _("The 'statistics' API is removed in API version 2.88 or later.")
     )