Esempio n. 1
0
 def test_task_not_in_progress(self):
     self.conn.post.return_value.status_code = 202
     self.conn.post.return_value.headers = self.res_headers1.copy()
     self.conn.get.return_value.status_code = 201
     self.conn.get.return_value.json.return_value = self.data.copy()
     res = self.conn.post(path='fake/path', data=self.data.copy(),
                          headers=self.req_headers.copy())
     tm = TaskMonitor(self.conn, res.headers.get('location'))\
         .set_retry_after(res.headers.get('retry-after'))
     self.assertIsNotNone(tm)
     self.assertFalse(tm.in_progress)
Esempio n. 2
0
 def test_retry_after_http_date(self):
     self.conn.post.return_value.status_code = 202
     self.conn.post.return_value.headers = self.res_headers1.copy()
     self.conn.get.return_value.status_code = 202
     self.conn.get.return_value.headers = self.res_headers1.copy()
     self.conn.get.return_value.json.return_value = {}
     res = self.conn.post(path='fake/path', data=self.data.copy(),
                          headers=self.req_headers.copy())
     tm = TaskMonitor(self.conn, res.headers.get('location')) \
         .set_retry_after(res.headers.get('retry-after'))
     self.assertIsNotNone(tm)
     self.assertEqual(self.datetime, tm.retry_after)
Esempio n. 3
0
 def test_retry_after_seconds(self):
     self.conn.post.return_value.status_code = 202
     self.conn.post.return_value.headers = self.res_headers2.copy()
     self.conn.get.return_value.status_code = 202
     self.conn.get.return_value.headers = self.res_headers2.copy()
     self.conn.get.return_value.json.return_value = {}
     start = datetime.now() + timedelta(seconds=self.seconds)
     res = self.conn.post(path='fake/path', data=self.data.copy(),
                          headers=self.req_headers.copy())
     tm = TaskMonitor(self.conn, res.headers.get('location')) \
         .set_retry_after(res.headers.get('retry-after'))
     end = datetime.now() + timedelta(seconds=self.seconds)
     self.assertIsNotNone(tm)
     self.assertTrue(start <= tm.retry_after <= end)
Esempio n. 4
0
 def test_init_deprecation_warning(self, mock_log):
     self.conn.post.return_value.status_code = 202
     self.conn.post.return_value.headers = self.res_headers1.copy()
     self.conn.get.return_value.status_code = 202
     self.conn.get.return_value.headers = self.res_headers1.copy()
     self.conn.get.return_value.json.return_value = {}
     res = self.conn.post(path='fake/path',
                          data=self.data.copy(),
                          headers=self.req_headers.copy())
     TaskMonitor(self.conn, res.headers.get('location'))\
         .set_retry_after(res.headers.get('retry-after'))
     mock_log.assert_called_once_with(
         'sushy.resources.task_monitor.TaskMonitor is deprecated. '
         'Use sushy.taskmonitor.TaskMonitor')
Esempio n. 5
0
 def test_sleep_for(self):
     self.conn.post.return_value.status_code = 202
     self.conn.post.return_value.headers = self.res_headers2.copy()
     self.conn.get.return_value.status_code = 202
     self.conn.get.return_value.headers = self.res_headers2.copy()
     self.conn.get.return_value.json.return_value = {}
     start = datetime.now()
     res = self.conn.post(path='fake/path', data=self.data.copy(),
                          headers=self.req_headers.copy())
     tm = TaskMonitor(self.conn, res.headers.get('location')) \
         .set_retry_after(res.headers.get('retry-after'))
     self.assertIsNotNone(tm)
     sleep_for = tm.sleep_for
     elapsed = (datetime.now() - start).total_seconds()
     self.assertTrue(self.seconds - elapsed <= sleep_for <= self.seconds)
Esempio n. 6
0
    def _op(self, method, path='', data=None, headers=None, blocking=False,
            timeout=60, **extra_session_req_kwargs):
        """Generic RESTful request handler.

        :param method: The HTTP method to be used, e.g: GET, POST,
            PUT, PATCH, etc...
        :param path: The sub-URI or absolute URL path to the resource.
        :param data: Optional JSON data.
        :param headers: Optional dictionary of headers.
        :param blocking: Whether to block for asynchronous operations.
        :param timeout: Max time in seconds to wait for blocking async call.
        :param extra_session_req_kwargs: Optional keyword argument to pass
         requests library arguments which would pass on to requests session
         object.
        :returns: The response object from the requests library.
        :raises: ConnectionError
        :raises: HTTPError
        """
        url = path if urlparse.urlparse(path).netloc else urlparse.urljoin(
            self._url, path)
        headers = headers or {}
        if not any(k.lower() == 'odata-version' for k in headers):
            headers['OData-Version'] = '4.0'
        # TODO(lucasagomes): We should mask the data to remove sensitive
        # information
        LOG.debug('HTTP request: %(method)s %(url)s; headers: %(headers)s; '
                  'body: %(data)s; blocking: %(blocking)s; timeout: '
                  '%(timeout)s; session arguments: %(session)s;',
                  {'method': method, 'url': url, 'headers': headers,
                   'data': data, 'blocking': blocking, 'timeout': timeout,
                   'session': extra_session_req_kwargs})
        try:
            response = self._session.request(method, url, json=data,
                                             headers=headers,
                                             **extra_session_req_kwargs)
        except requests.ConnectionError as e:
            raise exceptions.ConnectionError(url=url, error=e)

        if self._response_callback:
            self._response_callback(response)

        # If we received an AccessError, and we
        # previously established a redfish session
        # there is a chance that the session has timed-out.
        # Attempt to re-establish a session.
        try:
            exceptions.raise_for_response(method, url, response)
        except exceptions.AccessError:
            if self._auth.can_refresh_session():
                self._auth.refresh_session()
                LOG.debug("Authentication refreshed successfully, "
                          "retrying the call.")
                response = self._session.request(method, url, json=data,
                                                 headers=headers,
                                                 **extra_session_req_kwargs)
            else:
                raise

        if blocking and response.status_code == 202:
            if not response.headers.get('location'):
                m = ('HTTP response for %(method)s request to %(url)s '
                     'returned status 202, but no Location header'
                     % {'method': method, 'url': url})
                raise exceptions.ConnectionError(url=url, error=m)
            timeout_at = time.time() + timeout
            mon = (TaskMonitor(self, response.headers.get('location'))
                   .set_retry_after(response.headers.get('retry-after')))
            while mon.in_progress:
                LOG.debug('Blocking for in-progress %(method)s call to '
                          '%(url)s; sleeping for %(sleep)s seconds',
                          {'method': method, 'url': url,
                           'sleep': mon.sleep_for})
                time.sleep(mon.sleep_for)
                if time.time() >= timeout_at and mon.in_progress:
                    m = ('Timeout waiting for blocking %(method)s '
                         'request to %(url)s (timeout = %(timeout)s)'
                         % {'method': method, 'url': url,
                            'timeout': timeout})
                    raise exceptions.ConnectionError(url=url, error=m)
            response = mon.response

        LOG.debug('HTTP response for %(method)s %(url)s: '
                  'status code: %(code)s',
                  {'method': method, 'url': url,
                   'code': response.status_code})

        return response