def create(self, conditions, actions, uuid=None, description=None):
        """Create a new introspection rule.

        :param conditions: list of rule conditions
        :param actions: list of rule actions
        :param uuid: rule UUID, will be generated if not specified
        :param description: optional rule description
        :returns: rule representation
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        """
        if uuid is not None and not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        for name, arg in [('conditions', conditions), ('actions', actions)]:
            if not isinstance(arg, list) or not all(isinstance(x, dict)
                                                    for x in arg):
                raise TypeError(_("Expected list of dicts for %(arg)s "
                                  "argument, got %(real)r"),
                                {'arg': name, 'real': arg})

        body = {'uuid': uuid, 'conditions': conditions, 'actions': actions,
                'description': description}
        return self.from_json(body)
Exemplo n.º 2
0
    def introspect(self, uuid, new_ipmi_password=None, new_ipmi_username=None):
        """Start introspection for a node.

        :param uuid: node UUID or name
        :param new_ipmi_password: if set, *Ironic Inspector* will update IPMI
                                  password to this value. DEPRECATED.
        :param new_ipmi_username: if new_ipmi_password is set, this values sets
                                  new IPMI user name. Defaults to one in
                                  driver_info. DEPRECATED.
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        :raises: *requests* library exception on connection problems.
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        if new_ipmi_username and not new_ipmi_password:
            raise ValueError(
                _("Setting IPMI user name requires a new password"))

        if new_ipmi_password:
            LOG.warning(
                _LW('Setting IPMI credentials via ironic-inspector '
                    'is deprecated, this feature will be removed '
                    'in the Pike release'))

        params = {
            'new_ipmi_username': new_ipmi_username,
            'new_ipmi_password': new_ipmi_password
        }
        self.request('post', '/introspection/%s' % uuid, params=params)
Exemplo n.º 3
0
    def create(self, conditions, actions, uuid=None, description=None):
        """Create a new introspection rule.

        :param conditions: list of rule conditions
        :param actions: list of rule actions
        :param uuid: rule UUID, will be generated if not specified
        :param description: optional rule description
        :returns: rule representation
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        """
        if uuid is not None and not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        for name, arg in [('conditions', conditions), ('actions', actions)]:
            if not isinstance(arg, list) or not all(
                    isinstance(x, dict) for x in arg):
                raise TypeError(
                    _("Expected list of dicts for %(arg)s "
                      "argument, got %(real)r"), {
                          'arg': name,
                          'real': arg
                      })

        body = {
            'uuid': uuid,
            'conditions': conditions,
            'actions': actions,
            'description': description
        }
        return self.from_json(body)
    def take_action(self, parsed_args):
        if parsed_args.check_errors and not parsed_args.wait:
            raise RuntimeError(
                _("--check-errors can only be used with --wait"))

        client = self.app.client_manager.baremetal_introspection
        for uuid in parsed_args.node:
            client.introspect(uuid)

        if parsed_args.wait:
            print('Waiting for introspection to finish...', file=sys.stderr)
            result = client.wait_for_finish(parsed_args.node)
            result = [(uuid, s.get('error'))
                      for uuid, s in result.items()]
            if parsed_args.check_errors:
                uuids_errors = "\n".join("%s (%s)" % node_info
                                         for node_info in result
                                         if node_info[1] is not None)
                if uuids_errors:
                    raise Exception(
                        _("Introspection failed for some nodes: %s")
                        % uuids_errors)
        else:
            result = []

        return self.COLUMNS, result
Exemplo n.º 5
0
def _parse_version(api_version):
    try:
        return tuple(int(x) for x in api_version.split('.'))
    except (ValueError, TypeError):
        raise ValueError(
            _("Malformed API version: expect tuple, string "
              "in form of X.Y or integer"))
Exemplo n.º 6
0
    def wait_for_finish(self,
                        node_ids=None,
                        retry_interval=DEFAULT_RETRY_INTERVAL,
                        max_retries=DEFAULT_MAX_RETRIES,
                        sleep_function=time.sleep,
                        uuids=None):
        """Wait for introspection finishing for given nodes.

        :param uuids: collection of node UUIDs or names, deprecated
        :param node_ids: collection of node node_ids or names
        :param retry_interval: sleep interval between retries.
        :param max_retries: maximum number of retries.
        :param sleep_function: function used for sleeping between retries.
        :raises: :py:class:`ironic_inspector_client.WaitTimeoutError` on
            timeout
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        :return: dictionary UUID -> status (the same as in get_status).
        """
        result = {}
        node_ids = node_ids or uuids
        if uuids:
            warnings.warn(
                "Parameter uuid is deprecated and will be "
                "removed in future releases, please use "
                "node_id instead.", DeprecationWarning)
        elif not node_ids:
            raise TypeError("The node_ids argument is required")

        # Number of attempts = number of retries + first attempt
        for attempt in range(max_retries + 1):
            new_active_node_ids = []
            for node_id in node_ids:
                status = self.get_status(node_id)
                if status.get('finished'):
                    result[node_id] = status
                else:
                    new_active_node_ids.append(node_id)

            if new_active_node_ids:
                if attempt != max_retries:
                    node_ids = new_active_node_ids
                    LOG.debug(
                        'Still waiting for introspection results for '
                        '%(count)d nodes, attempt %(attempt)d of '
                        '%(total)d', {
                            'count': len(new_active_node_ids),
                            'attempt': attempt + 1,
                            'total': max_retries + 1
                        })
                    sleep_function(retry_interval)
            else:
                return result

        raise WaitTimeoutError(
            _("Timeout while waiting for introspection "
              "of nodes %s") % new_active_node_ids)
 def __init__(self, expected, supported):
     msg = (_('Version %(expected)s is not supported by the server, '
              'supported range is %(supported)s') %
            {'expected': expected,
             'supported': ' to '.join(str(x) for x in supported)})
     self.expected_version = expected
     self.supported_versions = supported
     super(Exception, self).__init__(msg)
Exemplo n.º 8
0
 def __init__(self, expected, supported):
     msg = (_('Version %(expected)s is not supported by the server, '
              'supported range is %(supported)s') % {
                  'expected': expected,
                  'supported': ' to '.join(str(x) for x in supported)
              })
     self.expected_version = expected
     self.supported_versions = supported
     super(Exception, self).__init__(msg)
    def _check_api_version(self, api_version):
        if isinstance(api_version, int):
            api_version = (api_version, 0)
        if isinstance(api_version, six.string_types):
            api_version = _parse_version(api_version)
        api_version = tuple(api_version)
        if not all(isinstance(x, int) for x in api_version):
            raise TypeError(_("All API version components should be integers"))
        if len(api_version) == 1:
            api_version += (0,)
        elif len(api_version) > 2:
            raise ValueError(_("API version should be of length 1 or 2"))

        minv, maxv = self.server_api_versions()
        if api_version < minv or api_version > maxv:
            raise VersionNotSupported(api_version, (minv, maxv))

        return api_version
Exemplo n.º 10
0
    def delete(self, uuid):
        """Delete an introspection rule.

        :param uuid: rule UUID
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        self._request('delete', '/rules/%s' % uuid)
Exemplo n.º 11
0
    def _check_api_version(self, api_version):
        if isinstance(api_version, int):
            api_version = (api_version, 0)
        if isinstance(api_version, six.string_types):
            api_version = _parse_version(api_version)
        api_version = tuple(api_version)
        if not all(isinstance(x, int) for x in api_version):
            raise TypeError(_("All API version components should be integers"))
        if len(api_version) == 1:
            api_version += (0, )
        elif len(api_version) > 2:
            raise ValueError(_("API version should be of length 1 or 2"))

        minv, maxv = self.server_api_versions()
        if api_version < minv or api_version > maxv:
            raise VersionNotSupported(api_version, (minv, maxv))

        return api_version
Exemplo n.º 12
0
    def get(self, uuid):
        """Get detailed information about an introspection rule.

        :param uuid: rule UUID
        :returns: rule representation
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        return self._request('get', '/rules/%s' % uuid).json()
Exemplo n.º 13
0
    def delete(self, uuid):
        """Delete an introspection rule.

        :param uuid: rule UUID
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        self._request('delete', '/rules/%s' % uuid)
Exemplo n.º 14
0
    def get_status(self, uuid):
        """Get introspection status for a node.

        :param uuid: node uuid.
        :raises: ClientError on error reported from a server
        :raises: VersionNotSupported if requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)

        return self.request('get', '/introspection/%s' % uuid).json()
Exemplo n.º 15
0
    def get(self, uuid):
        """Get detailed information about an introspection rule.

        :param uuid: rule UUID
        :returns: rule representation
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        return self._request('get', '/rules/%s' % uuid).json()
Exemplo n.º 16
0
    def delete(self, uuid):
        """Delete an introspection rule.

        :param uuid: rule UUID
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        self._request('delete', '/rules/%s' % uuid)
Exemplo n.º 17
0
    def create(self, conditions, actions, uuid=None, description=None):
        """Create a new introspection rule.

        :conditions: list of rule conditions
        :actions: list of rule actions
        :uuid: rule UUID, will be generated if not specified
        :description: optional rule description
        :returns: rule representation
        """
        if uuid is not None and not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        for name, arg in [('conditions', conditions), ('actions', actions)]:
            if not isinstance(arg, list) or not all(isinstance(x, dict)
                                                    for x in arg):
                raise TypeError(_("Expected list of dicts for %(arg)s "
                                  "argument, got %(real)r"),
                                {'arg': name, 'real': arg})

        body = {'uuid': uuid, 'conditions': conditions, 'actions': actions,
                'description': description}
        return self.from_json(body)
Exemplo n.º 18
0
    def wait_for_finish(self, node_ids, retry_interval=DEFAULT_RETRY_INTERVAL,
                        max_retries=DEFAULT_MAX_RETRIES,
                        sleep_function=time.sleep, uuids=None):
        """Wait for introspection finishing for given nodes.

        :param uuids: collection of node UUIDs or names, deprecated
        :param node_ids: collection of node node_ids or names
        :param retry_interval: sleep interval between retries.
        :param max_retries: maximum number of retries.
        :param sleep_function: function used for sleeping between retries.
        :raises: :py:class:`ironic_inspector_client.WaitTimeoutError` on
            timeout
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        :return: dictionary UUID -> status (the same as in get_status).
        """
        result = {}
        node_ids = node_ids or uuids
        if uuids:
            warnings.warn("Parameter uuid is deprecated and will be "
                          "removed in future releases, please use "
                          "node_id instead.", DeprecationWarning)

        # Number of attempts = number of retries + first attempt
        for attempt in range(max_retries + 1):
            new_active_node_ids = []
            for node_id in node_ids:
                status = self.get_status(node_id)
                if status.get('finished'):
                    result[node_id] = status
                else:
                    new_active_node_ids.append(node_id)

            if new_active_node_ids:
                if attempt != max_retries:
                    node_ids = new_active_node_ids
                    LOG.debug('Still waiting for introspection results for '
                              '%(count)d nodes, attempt %(attempt)d of '
                              '%(total)d',
                              {'count': len(new_active_node_ids),
                               'attempt': attempt + 1,
                               'total': max_retries + 1})
                    sleep_function(retry_interval)
            else:
                return result

        raise WaitTimeoutError(_("Timeout while waiting for introspection "
                                 "of nodes %s") % new_active_node_ids)
Exemplo n.º 19
0
    def list_statuses(self, marker=None, limit=None):
        """List introspection statuses.

        Supports pagination via the marker and limit params. The items are
        sorted by the server according to the `started_at` attribute, newer
        items first.

        :param marker: pagination maker, UUID or None
        :param limit: pagination limit, int or None
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        :return: a list of status dictionaries with the keys:

            * `error` an error string or None,
            * `finished` whether introspection was finished,
            * `finished_at` an ISO8601 timestamp or None,
            * `links` with a self-link URL,
            * `started_at` an ISO8601 timestamp,
            * `uuid` the node UUID
        """
        if not (marker is None or isinstance(marker, six.string_types)):
            raise TypeError(
                _('Expected a string value of the marker, got '
                  '%s instead') % marker)
        if not (limit is None or isinstance(limit, int)):
            raise TypeError(
                _('Expected an integer value of the limit, got '
                  '%s instead') % limit)

        params = {
            'marker': marker,
            'limit': limit,
        }
        response = self.request('get', '/introspection', params=params)
        return response.json()['introspection']
Exemplo n.º 20
0
    def introspect(self, uuid):
        """Start introspection for a node.

        :param uuid: node UUID or name
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        :raises: *requests* library exception on connection problems.
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)

        self.request('post', '/introspection/%s' % uuid)
Exemplo n.º 21
0
    def get(self, uuid):
        """Get detailed information about an introspection rule.

        :param uuid: rule UUID
        :returns: rule representation
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        return self._request('get', '/rules/%s' % uuid).json()
Exemplo n.º 22
0
    def introspect(self, uuid, new_ipmi_password=None, new_ipmi_username=None):
        """Start introspection for a node.

        :param uuid: node uuid
        :param new_ipmi_password: if set, *Ironic Inspector* will update IPMI
                                  password to this value.
        :param new_ipmi_username: if new_ipmi_password is set, this values sets
                                  new IPMI user name. Defaults to one in
                                  driver_info.
        :raises: ClientError on error reported from a server
        :raises: VersionNotSupported if requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)
        if new_ipmi_username and not new_ipmi_password:
            raise ValueError(
                _("Setting IPMI user name requires a new password"))

        params = {'new_ipmi_username': new_ipmi_username,
                  'new_ipmi_password': new_ipmi_password}
        self.request('post', '/introspection/%s' % uuid, params=params)
Exemplo n.º 23
0
    def list_statuses(self, marker=None, limit=None):
        """List introspection statuses.

        Supports pagination via the marker and limit params. The items are
        sorted by the server according to the `started_at` attribute, newer
        items first.

        :param marker: pagination maker, UUID or None
        :param limit: pagination limit, int or None
        :raises: :py:class:`ironic_inspector_client.ClientError` on error
            reported from a server
        :raises: :py:class:`ironic_inspector_client.VersionNotSupported` if
            requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        :return: a list of status dictionaries with the keys:

            * `error` an error string or None,
            * `finished` whether introspection was finished,
            * `finished_at` an ISO8601 timestamp or None,
            * `links` with a self-link URL,
            * `started_at` an ISO8601 timestamp,
            * `uuid` the node UUID
        """
        if not (marker is None or isinstance(marker, six.string_types)):
            raise TypeError(_('Expected a string value of the marker, got '
                              '%s instead') % marker)
        if not (limit is None or isinstance(limit, int)):
            raise TypeError(_('Expected an integer value of the limit, got '
                              '%s instead') % limit)

        params = {
            'marker': marker,
            'limit': limit,
        }
        response = self.request('get', '/introspection', params=params)
        return response.json()['introspection']
Exemplo n.º 24
0
    def wait_for_finish(self,
                        uuids,
                        retry_interval=DEFAULT_RETRY_INTERVAL,
                        max_retries=DEFAULT_MAX_RETRIES,
                        sleep_function=time.sleep):
        """Wait for introspection finishing for given nodes.

        :param uuids: collection of node UUIDs or names.
        :param retry_interval: sleep interval between retries.
        :param max_retries: maximum number of retries.
        :param sleep_function: function used for sleeping between retries.
        :raises: :py:class:`.WaitTimeoutError` on timeout
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        :raises: *requests* library exception on connection problems.
        :return: dictionary UUID -> status (the same as in get_status).
        """
        result = {}

        # Number of attempts = number of retries + first attempt
        for attempt in range(max_retries + 1):
            new_active_uuids = []
            for uuid in uuids:
                status = self.get_status(uuid)
                if status.get('finished'):
                    result[uuid] = status
                else:
                    new_active_uuids.append(uuid)

            if new_active_uuids:
                if attempt != max_retries:
                    uuids = new_active_uuids
                    LOG.debug(
                        'Still waiting for introspection results for '
                        '%(count)d nodes, attempt %(attempt)d of '
                        '%(total)d', {
                            'count': len(new_active_uuids),
                            'attempt': attempt + 1,
                            'total': max_retries + 1
                        })
                    sleep_function(retry_interval)
            else:
                return result

        raise WaitTimeoutError(
            _("Timeout while waiting for introspection "
              "of nodes %s") % new_active_uuids)
Exemplo n.º 25
0
    def _check_parameters(self, node_id, uuid):
        """Deprecate uuid parameters.

        Check the parameters and return a deprecation warning
        if the uuid parameter is present.
        """

        node_id = node_id or uuid
        if not isinstance(node_id, six.string_types):
            raise TypeError(
                _("Expected string for node_id argument, got %r") % node_id)
        if uuid:
            warnings.warn("Parameter uuid is deprecated and will be "
                          "removed in future releases, please use "
                          "node_id instead.", DeprecationWarning)
        return node_id
Exemplo n.º 26
0
    def reprocess(self, uuid):
        """Reprocess stored introspection data.

        :param uuid: node UUID or name.
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        :raises: *requests* library exception on connection problems.
        :raises: TypeError if uuid is not a string.
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got"
                  " %r instead") % uuid)

        return self.request('post',
                            '/introspection/%s/data/unprocessed' % uuid)
Exemplo n.º 27
0
    def _check_parameters(self, node_id, uuid):
        """Deprecate uuid parameters.

        Check the parameters and return a deprecation warning
        if the uuid parameter is present.
        """

        node_id = node_id or uuid
        if not isinstance(node_id, six.string_types):
            raise TypeError(
                _("Expected string for node_id argument, got %r") % node_id)
        if uuid:
            warnings.warn(
                "Parameter uuid is deprecated and will be "
                "removed in future releases, please use "
                "node_id instead.", DeprecationWarning)
        return node_id
Exemplo n.º 28
0
    def get_interface_data(self, node_ident, interface, field_sel):
        """Get interface data for the input node and interface

        To get LLDP data, collection must be enabled by the kernel parameter
        ``ipa-collect-lldp=1``, and the inspector plugin ``basic_lldp`` must
        be enabled.

        :param node_ident: node UUID or name
        :param interface: interface name
        :param field_sel: list of all fields for which to get data
        :returns: interface data in OrderedDict
        :raises: ValueError if interface is not found.
        """
        # Use OrderedDict to maintain order of user-entered fields
        iface_data = collections.OrderedDict()

        data = self.get_data(node_ident)
        all_interfaces = data.get('all_interfaces', [])

        # Make sure interface name is valid
        if interface not in all_interfaces:
            raise ValueError(
                _("Interface %s was not found on this node") % interface)

        # If lldp data not available this will still return interface,
        # mac, node_ident etc.
        lldp_proc = all_interfaces[interface].get('lldp_processed', {})

        for f in field_sel:
            if f == 'node_ident':
                iface_data[f] = node_ident
            elif f == 'interface':
                iface_data[f] = interface
            elif f == 'mac':
                iface_data[f] = all_interfaces[interface].get(f)
            elif f == 'switch_port_vlan_ids':
                iface_data[f] = [
                    item['id']
                    for item in lldp_proc.get('switch_port_vlans', [])
                ]
            else:
                iface_data[f] = lldp_proc.get(f)

        return iface_data
Exemplo n.º 29
0
    def get_interface_data(self, node_ident, interface, field_sel):
        """Get interface data for the input node and interface

        To get LLDP data, collection must be enabled by the kernel parameter
        ``ipa-collect-lldp=1``, and the inspector plugin ``basic_lldp`` must
        be enabled.

        :param node_ident: node UUID or name
        :param interface: interface name
        :param field_sel: list of all fields for which to get data
        :returns: interface data in OrderedDict
        :raises: ValueError if interface is not found.
        """
        # Use OrderedDict to maintain order of user-entered fields
        iface_data = collections.OrderedDict()

        data = self.get_data(node_ident)
        all_interfaces = data.get('all_interfaces', [])

        # Make sure interface name is valid
        if interface not in all_interfaces:
            raise ValueError(
                _("Interface %s was not found on this node")
                % interface)

        # If lldp data not available this will still return interface,
        # mac, node_ident etc.
        lldp_proc = all_interfaces[interface].get('lldp_processed', {})

        for f in field_sel:
            if f == 'node_ident':
                iface_data[f] = node_ident
            elif f == 'interface':
                iface_data[f] = interface
            elif f == 'mac':
                iface_data[f] = all_interfaces[interface].get(f)
            elif f == 'switch_port_vlan_ids':
                iface_data[f] = [item['id'] for item in
                                 lldp_proc.get('switch_port_vlans', [])]
            else:
                iface_data[f] = lldp_proc.get(f)

        return iface_data
Exemplo n.º 30
0
    def get_data(self, uuid, raw=False):
        """Get introspection data from the last introspection of a node.

        :param uuid: node UUID.
        :param raw: whether to return raw binary data or parsed JSON data
        :returns: bytes or a dict depending on the 'raw' argument
        :raises: ClientError on error reported from a server
        :raises: VersionNotSupported if requested api_version is not supported
        :raises: *requests* library exception on connection problems.
        :raises: TypeError if uuid is not a string
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)

        resp = self.request('get', '/introspection/%s/data' % uuid)
        if raw:
            return resp.content
        else:
            return resp.json()
Exemplo n.º 31
0
    def get_status(self, uuid):
        """Get introspection status for a node.

        :param uuid: node UUID or name.
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        :raises: *requests* library exception on connection problems.
        :return: dictionary with the keys:
                 `error` an error string or None,
                 `finished` True/False,
                 `finished_at` an ISO8601 timestamp or None,
                 `links` with a self-link URL,
                 `started_at` an ISO8601 timestamp,
                 `uuid` the node UUID
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)

        return self.request('get', '/introspection/%s' % uuid).json()
Exemplo n.º 32
0
    def get_data(self, uuid, raw=False):
        """Get introspection data from the last introspection of a node.

        :param uuid: node UUID or name.
        :param raw: whether to return raw binary data or parsed JSON data
        :returns: bytes or a dict depending on the 'raw' argument
        :raises: :py:class:`.ClientError` on error reported from a server
        :raises: :py:class:`.VersionNotSupported` if requested api_version
            is not supported
        :raises: *requests* library exception on connection problems.
        :raises: TypeError if uuid is not a string
        """
        if not isinstance(uuid, six.string_types):
            raise TypeError(
                _("Expected string for uuid argument, got %r") % uuid)

        resp = self.request('get', '/introspection/%s/data' % uuid)
        if raw:
            return resp.content
        else:
            return resp.json()
    def __init__(self, response):
        # inspector returns error message in body
        msg = response.content.decode(_ERROR_ENCODING)
        try:
            msg = json.loads(msg)
        except ValueError:
            LOG.debug('Old style error response returned, assuming '
                      'ironic-discoverd')
        except TypeError:
            LOG.exception('Bad error response from Ironic Inspector')
        else:
            try:
                msg = msg['error']['message']
            except KeyError as exc:
                LOG.error(
                    'Invalid error response from Ironic Inspector: '
                    '%(msg)s (missing key %(key)s)', {
                        'msg': msg,
                        'key': exc
                    })
                # It's surprisingly common to try accessing ironic URL with
                # ironic-inspector-client, handle this case
                try:
                    msg = msg['error_message']
                except KeyError:
                    pass
                else:
                    msg = _('Received Ironic-style response %s. Are you '
                            'trying to access Ironic URL instead of Ironic '
                            'Inspector?') % msg
            except TypeError:
                LOG.exception('Bad error response from Ironic Inspector')

        LOG.debug('Inspector returned error "%(msg)s" (HTTP %(code)s)', {
            'msg': msg,
            'code': response.status_code
        })
        super(ClientError, self).__init__(msg, response=response)
 def __init__(self, service_type):
     self.service_type = service_type
     msg = _('Endpoint of type %s was not found in the service catalog '
             'and was not provided explicitly') % service_type
     super(Exception, self).__init__(msg)
Exemplo n.º 35
0
 def __init__(self, service_type):
     self.service_type = service_type
     msg = _('Endpoint of type %s was not found in the service catalog '
             'and was not provided explicitly') % service_type
     super(Exception, self).__init__(msg)
def _parse_version(api_version):
    try:
        return tuple(int(x) for x in api_version.split('.'))
    except (ValueError, TypeError):
        raise ValueError(_("Malformed API version: expect tuple, string "
                           "in form of X.Y or integer"))