150 lines
5.6 KiB
Python
150 lines
5.6 KiB
Python
# 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(session, action='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, processed=True):
|
|
"""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`
|
|
:param processed: Whether to fetch the final processed data (the
|
|
default) or the raw unprocessed data as received from the ramdisk.
|
|
:type processed: bool
|
|
:returns: introspection data from the most recent successful run.
|
|
:rtype: dict
|
|
"""
|
|
session = self._get_session(session)
|
|
|
|
version = (
|
|
self._get_microversion(session, action='fetch')
|
|
if processed
|
|
else '1.17'
|
|
)
|
|
request = self._prepare_request(requires_id=True)
|
|
request.url = utils.urljoin(request.url, 'data')
|
|
if not processed:
|
|
request.url = utils.urljoin(request.url, 'unprocessed')
|
|
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.
|
|
:raises: :class:`~openstack.exceptions.ResourceFailure` if
|
|
introspection fails and ``ignore_error`` is ``False``.
|
|
:raises: :class:`~openstack.exceptions.ResourceTimeout` on timeout.
|
|
"""
|
|
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.ResourceFailure(
|
|
"Introspection of node %(node)s failed: %(error)s"
|
|
% {'node': self.id, 'error': self.error}
|
|
)
|
|
else:
|
|
return self.is_finished
|