Example #1
0
    def _load(self) -> UnindexedData:
        logger.debug('loading from %s', self._file_path)

        try:
            # If the file is accessible but empty, consider data loaded and return empty dictionary
            if os.stat(self._file_path).st_size == 0:
                logger.debug('file %s is empty', self._file_path)
                return {}

        except FileNotFoundError:
            # If the file does not exist, consider data loaded and return empty dictionary
            logger.debug('file %s does not exist', self._file_path)
            return {}

        try:
            with open(self._file_path, 'rb') as f:
                data = f.read()
                return json_utils.loads(data, allow_extended_types=True)

        except Exception as e:
            if not self._use_backup:
                raise

            # Upon failure, if using a backup, simply log the error and attempt to load from backup file
            logger.error('failed to load from %s: %s', self._file_path, e, exc_info=True)

            backup_file_path = self._get_backup_file_path()
            logger.warning('loading from backup %s', backup_file_path)

            with open(backup_file_path, 'rb') as f:
                return json_utils.loads(f.read(), allow_extended_types=True)
Example #2
0
    async def request(self,
                      method: str,
                      path: str,
                      body: Any = None,
                      admin_password: Optional[str] = None,
                      no_log: bool = False) -> Any:

        http_client = httpclient.AsyncHTTPClient()
        if admin_password:
            password_hash = hashlib.sha256(admin_password.encode()).hexdigest()

        else:
            password_hash = core_api_auth.EMPTY_PASSWORD_HASH

        headers = {
            'Content-Type':
            json_utils.JSON_CONTENT_TYPE,
            'Authorization':
            core_api_auth.make_auth_header(core_api_auth.ORIGIN_CONSUMER,
                                           username='******',
                                           password_hash=password_hash)
        }

        # TODO: this only tries standard port 80; ideally it should try connecting on a list of known ports

        timeout = settings.slaves.discover.request_timeout
        url = f'http://{self.ip_address}:80{path}'

        body_str = None
        if body is not None:
            body_str = json_utils.dumps(body)

        request = httpclient.HTTPRequest(url=url,
                                         method=method,
                                         headers=headers,
                                         body=body_str,
                                         connect_timeout=timeout,
                                         request_timeout=timeout)

        if not no_log:
            self.debug('requesting %s %s', method, path)

        try:
            response = await http_client.fetch(request, raise_error=True)

        except Exception as e:
            if not no_log:
                self.error('request %s %s failed: %s',
                           method,
                           path,
                           e,
                           exc_info=True)
            raise

        if response.body:
            return json_utils.loads(response.body)
Example #3
0
    def get_request_json(self) -> Any:
        if self._json is self._UNDEFINED:
            try:
                self._json = json_utils.loads(self.request.body)

            except ValueError as e:
                logger.error('could not decode json from request body: %s', e)

                raise core_api.APIError(400, 'malformed-body') from e

        return self._json
Example #4
0
def parse(response: HTTPResponse,
          decode_json: bool = True,
          resolve_refs: bool = True) -> Any:
    if 100 <= response.code < 599:
        if response.code == 204:
            return  # Happy case - no content

        if decode_json and response.body:
            try:
                body = json_utils.loads(response.body,
                                        resolve_refs=resolve_refs)

            except Exception as e:
                raise InvalidJson() from e

        else:
            body = response.body

        if response.code == 200:
            return body  # Happy case with content

        if response.code == 202:
            raise Accepted(body)

        if response.code == 301:
            raise MovedPermanently(response.headers.get('Location', ''))

        if response.code in [302, 303]:
            raise Redirect(response.headers.get('Location', ''))

        if decode_json:
            raise HTTPError(response.code, body.pop('error', ''), **body)

        raise HTTPError(response.code, response.reason)

    elif response.error or response.code == 599:
        if str(response.error).lower().count('timeout'):
            raise Timeout()

        eno = getattr(response.error, 'errno', None)
        if eno:
            raise _response_error_errno(eno)

        raise OtherError(str(response.error))

    raise OtherError(
        f'Unknown HTTP error ({response.code}: {str(response.error)})')
Example #5
0
 def _value_from_db(value: str) -> Any:
     return json_utils.loads(value, allow_extended_types=True)
Example #6
0
 def _value_from_db(value: str) -> Any:
     return json_utils.loads(value)