# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from openstack import _log from openstack.baremetal.v1 import _common from openstack import exceptions from openstack import resource from openstack import utils _logger = _log.setup_logging('openstack') class Introspection(resource.Resource): resources_key = 'introspection' base_path = '/introspection' # capabilities allow_create = True allow_fetch = True allow_commit = False allow_delete = True allow_list = True # created via POST with ID create_method = 'POST' create_requires_id = True create_returns_body = False #: Timestamp at which the introspection was finished. finished_at = resource.Body('finished_at') #: The last error message (if any). error = resource.Body('error') #: The UUID of the introspection (matches the node UUID). id = resource.Body('uuid', alternate_id=True) #: Whether introspection is finished. is_finished = resource.Body('finished', type=bool) #: A list of relative links, including the self and bookmark links. links = resource.Body('links', type=list) #: Timestamp at which the introspection was started. started_at = resource.Body('started_at') #: The current introspection state. state = resource.Body('state') def abort(self, session): """Abort introspection. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` """ if self.is_finished: return session = self._get_session(session) version = self._get_microversion_for(session, 'delete') request = self._prepare_request(requires_id=True) request.url = utils.urljoin(request.url, 'abort') response = session.post( request.url, headers=request.headers, microversion=version, retriable_status_codes=_common.RETRIABLE_STATUS_CODES) msg = ("Failed to abort introspection for node {id}" .format(id=self.id)) exceptions.raise_from_response(response, error_message=msg) def get_data(self, session): """Get introspection data. Note that the introspection data format is not stable and can vary from environment to environment. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :returns: introspection data from the most recent successful run. :rtype: dict """ session = self._get_session(session) version = self._get_microversion_for(session, 'fetch') request = self._prepare_request(requires_id=True) request.url = utils.urljoin(request.url, 'data') response = session.get( request.url, headers=request.headers, microversion=version) msg = ("Failed to fetch introspection data for node {id}" .format(id=self.id)) exceptions.raise_from_response(response, error_message=msg) return response.json() def wait(self, session, timeout=None, ignore_error=False): """Wait for the node to reach the expected state. :param session: The session to use for making this request. :type session: :class:`~keystoneauth1.adapter.Adapter` :param timeout: How much (in seconds) to wait for the introspection. The value of ``None`` (the default) means no client-side timeout. :param ignore_error: If ``True``, this call will raise an exception if the introspection reaches the ``error`` state. Otherwise the error state is considered successful and the call returns. :return: This :class:`Introspection` instance. """ if self._check_state(ignore_error): return self for count in utils.iterate_timeout( timeout, "Timeout waiting for introspection on node %s" % self.id): self.fetch(session) if self._check_state(ignore_error): return self _logger.debug('Still waiting for introspection of node %(node)s, ' 'the current state is "%(state)s"', {'node': self.id, 'state': self.state}) def _check_state(self, ignore_error): if self.state == 'error' and not ignore_error: raise exceptions.SDKException( "Introspection of node %(node)s failed: %(error)s" % {'node': self.id, 'error': self.error}) else: return self.is_finished