def test_mock(self):
        # It's likely that clean will be called with a mock during testing.
        # It shouldn't blow up

        m = mock.MagicMock()
        str(m)
        target.clean(m)
Beispiel #2
0
    def test_mock(self):
        # It's likely that clean will be called with a mock during testing.
        # It shouldn't blow up

        m = mock.MagicMock()
        str(m)
        target.clean(m)
Beispiel #3
0
    def _http(self, method, api_url, payload):
        self.protocol = 'http'
        self.port = 80
        if self.protocol == 'https':
            http = httplib.HTTPSConnection(self.host,
                                           self.port,
                                           timeout=self.timeout)
            http.connect = lambda: force_tlsv1_connect(http)
        else:
            http = httplib.HTTPConnection(self.host,
                                          self.port,
                                          timeout=self.timeout)

        LOG.debug("axapi_http: url:     %s", api_url)
        LOG.debug("axapi_http: method:  %s", method)
        LOG.debug("axapi_http: headers: %s", logutils.clean(self.HEADERS))
        LOG.debug("axapi_http: payload: %s", logutils.clean(payload))

        http.request(method, api_url, body=payload, headers=self.headers)

        r = http.getresponse()
        r_data = r.read()

        # Workaround for zero length response
        def handle_empty_response(data):
            if not data:
                raise EmptyHttpResponse(r)

            return data

        http.close()

        return handle_empty_response(r_data)
 def test_list_dict(self):
     actual = target.clean(
         [{'credentials': {
             'username': '******',
             'password': '******'}}])
     expected = [{'credentials': {
         'username': target.REPLACEMENT,
         'password': target.REPLACEMENT}
         }]
     self.assertEqual(expected, actual)
 def test_tuple_dict(self):
     actual = target.clean(
         (1, {'credentials': {
             'username': '******',
             'password': '******'}
         }))
     expected = (1, {'credentials': {
         'username': target.REPLACEMENT,
         'password': target.REPLACEMENT}
         })
     self.assertEqual(expected, actual)
Beispiel #6
0
 def test_tuple_dict(self):
     actual = target.clean((1, {
         'credentials': {
             'username': '******',
             'password': '******'
         }
     }))
     expected = (1, {
         'credentials': {
             'username': target.REPLACEMENT,
             'password': target.REPLACEMENT
         }
     })
     self.assertEqual(expected, actual)
Beispiel #7
0
 def test_list_dict(self):
     actual = target.clean([{
         'credentials': {
             'username': '******',
             'password': '******'
         }
     }])
     expected = [{
         'credentials': {
             'username': target.REPLACEMENT,
             'password': target.REPLACEMENT
         }
     }]
     self.assertEqual(expected, actual)
Beispiel #8
0
    def _http(self, method, api_url, payload):
        if self.protocol == 'https':
            http = httplib.HTTPSConnection(self.host, self.port, timeout=self.timeout)
            http.connect = lambda: force_tlsv1_connect(http)
        else:
            http = httplib.HTTPConnection(self.host, self.port, timeout=self.timeout)

        LOG.debug("axapi_http: url:     %s", api_url)
        LOG.debug("axapi_http: method:  %s", method)
        LOG.debug("axapi_http: headers: %s", logutils.clean(self.HEADERS))
        LOG.debug("axapi_http: payload: %s", logutils.clean(payload))

        http.request(method, api_url, body=payload, headers=self.headers)

        r = http.getresponse()

        # Workaround for zero length response
        def handle_empty_response(data):
            if not data:
                raise EmptyHttpResponse(r)

            return data

        return handle_empty_response(r.read())
Beispiel #9
0
 def test_obj_flat(self):
     actual = target.clean(self.obj_flat)
     self.assertEqual(target.REPLACEMENT, actual.username)
     self.assertEqual(target.REPLACEMENT, actual.password)
Beispiel #10
0
 def test_obj_onelevel(self):
     actual = target.clean(self.obj_onelevel).credentials
     self.assertEqual(target.REPLACEMENT, actual.username)
     self.assertEqual(target.REPLACEMENT, actual.password)
Beispiel #11
0
 def test_none(self):
     actual = target.clean(None)
     self.assertEqual(None, actual)
Beispiel #12
0
    def test_clean_twolevel_dict(self):
        actual = target.clean(self.dict_twolevel).get("credentials").get("inside_secret")

        self.assertEqual(target.REPLACEMENT, actual["username"])
        self.assertEqual(target.REPLACEMENT, actual["password"])
Beispiel #13
0
 def test_clean_flat_dict(self):
     actual = target.clean(self.flat_dict)
     self.assertEqual(target.REPLACEMENT, actual["username"])
     self.assertEqual(target.REPLACEMENT, actual["password"])
     self.assertEqual(self.flat_dict["a"], actual["a"])
Beispiel #14
0
    def test_clean_twolevel_dict(self):
        actual = target.clean(
            self.dict_twolevel).get("credentials").get("inside_secret")

        self.assertEqual(target.REPLACEMENT, actual["username"])
        self.assertEqual(target.REPLACEMENT, actual["password"])
Beispiel #15
0
 def test_obj_onelevel(self):
     actual = target.clean(self.obj_onelevel).credentials
     self.assertEqual(target.REPLACEMENT, actual.username)
     self.assertEqual(target.REPLACEMENT, actual.password)
Beispiel #16
0
 def test_float(self):
     actual = target.clean(3.7)
     self.assertEqual(3.7, actual)
Beispiel #17
0
 def test_ustring(self):
     actual = target.clean('sometext')
     self.assertEqual('sometext', actual)
    def request(self, method, api_url, params={}, headers=None,
                file_name=None, file_content=None, axapi_args=None, **kwargs):
        LOG.debug("axapi_http: full url = %s", self.url_base + api_url)
        LOG.debug("axapi_http: %s url = %s", method, api_url)
        LOG.debug("axapi_http: params = %s", json.dumps(logutils.clean(params), indent=4))

        valid_http_codes = [200, 204]

        # Update params with axapi_args for currently unsupported configuration of objects
        if axapi_args is not None:
            formatted_axapi_args = dict(
                [(k.replace('_', '-'), v) for k, v in six.iteritems(axapi_args)]
            )
            params = acos_client.v21.axapi_http.merge_dicts(params, formatted_axapi_args)

        # Set data" variable for the request
        if params:
            params_copy = params.copy()
            LOG.debug("axapi_http: params_all = %s", logutils.clean(params_copy))
            payload = json.dumps(params_copy)
        else:
            payload = None

        if (file_name is None and file_content is not None) or \
           (file_name is not None and file_content is None):
            raise ValueError("file_name and file_content must both be populated if one is")

        max_retries = kwargs.get('max_retries', self.max_retries)
        timeout = kwargs.get('timeout', self.timeout)

        # Set "headers" variable for the request
        request_headers = self.HEADERS.copy()
        if headers:
            request_headers.update(headers)
        LOG.debug("axapi_http: headers = %s", json.dumps(logutils.clean(request_headers), indent=4))

        # Process files if passed as a parameter
        if file_name is not None:
            files = {
                'file': (file_name, file_content, "application/octet-stream"),
                'json': ('blob', payload, "application/json")
            }
            request_headers.pop("Content-type", None)
            request_headers.pop("Content-Type", None)

        # Create session to set HTTPAdapter or SSLAdapter and set max_retries
        session = Session()
        if self.port == 443:
            session.mount('https://', HTTPAdapter(max_retries=max_retries))
        else:
            session.mount('http://', HTTPAdapter(max_retries=max_retries))
        session_request = getattr(session, method.lower())

        # Make actual request and handle any errors
        try:
            if file_name is not None:
                device_response = session_request(
                    self.url_base + api_url, verify=False, files=files, headers=request_headers, timeout=timeout
                )
            else:
                device_response = session_request(
                    self.url_base + api_url, verify=False, data=payload, headers=request_headers, timeout=timeout
                )
        except (Exception) as e:
            LOG.error("acos_client failing with error %s after %s retries", e.__class__.__name__, max_retries)
            raise e
        finally:
            session.close()

        # Validate json response
        try:
            json_response = device_response.json()
            LOG.debug("axapi_http: data = %s", json.dumps(logutils.clean(json_response), indent=4))
        except ValueError as e:
            # The response is not JSON but it still succeeded.
            if device_response.status_code in valid_http_codes:
                return device_response.text
            else:
                raise e

        # Handle "fail" responses returned by AXAPI
        if 'response' in json_response and 'status' in json_response['response']:
            if json_response['response']['status'] == 'fail':
                    acos_responses.raise_axapi_ex(json_response, method, api_url)

        # Handle "authorizationschema" responses returned by AXAPI
        if 'authorizationschema' in json_response:
            acos_responses.raise_axapi_auth_error(json_response, method, api_url, headers)

        return json_response
Beispiel #19
0
    def request(self,
                method,
                api_url,
                params={},
                headers=None,
                file_name=None,
                file_content=None,
                axapi_args=None,
                **kwargs):
        LOG.debug("axapi_http: full url = %s", self.url_base + api_url)
        LOG.debug("axapi_http: %s url = %s", method, api_url)
        LOG.debug("axapi_http: params = %s",
                  json.dumps(logutils.clean(params), indent=4))

        # Update params with axapi_args for currently unsupported configuration of objects
        if axapi_args is not None:
            formatted_axapi_args = dict([(k.replace('_', '-'), v)
                                         for k, v in axapi_args.iteritems()])
            params = acos_client.v21.axapi_http.merge_dicts(
                params, formatted_axapi_args)

        if (file_name is None and file_content is not None) or \
           (file_name is not None and file_content is None):
            raise ValueError("file_name and file_content must both be "
                             "populated if one is")

        hdrs = self.HEADERS.copy()
        if headers:
            hdrs.update(headers)

        if params:
            params_copy = params.copy()
            # params_copy.update(extra_params)
            LOG.debug("axapi_http: params_all = %s",
                      logutils.clean(params_copy))

            payload = json.dumps(params_copy, encoding='utf-8')
        else:
            payload = None

        LOG.debug("axapi_http: headers = %s",
                  json.dumps(logutils.clean(hdrs), indent=4))

        if file_name is not None:
            files = {
                'file': (file_name, file_content, "application/octet-stream"),
                'json': ('blob', payload, "application/json")
            }

            hdrs.pop("Content-type", None)
            hdrs.pop("Content-Type", None)

        last_e = None

        for i in xrange(0, 1500):
            try:
                last_e = None
                if file_name is not None:
                    z = requests.request(method,
                                         self.url_base + api_url,
                                         verify=False,
                                         files=files,
                                         headers=hdrs)
                else:
                    #requests.packages.urllib3.disable_warnings()
                    z = requests.request(method,
                                         self.url_base + api_url,
                                         verify=False,
                                         data=payload,
                                         headers=hdrs)

                break
            except (socket.error, requests.exceptions.ConnectionError) as e:
                # Workaround some bogosity in the API
                if e.errno in self.retry_errnos or \
                   any(s in str(e) for s in self.retry_err_strings):
                    time.sleep(0.1)
                    last_e = e
                    continue
                raise e

        LOG.debug("acos_client retried %s %s times", self.url_base + api_url,
                  i)

        if last_e is not None:
            LOG.error(
                "acos_client failing with error %s after %s retries ignoring %s",
                last_e, i, self.retry_err_strings)
            raise e

        if z.status_code == 204:
            return None

        try:
            r = z.json()
        except ValueError as e:
            # The response is not JSON but it still succeeded.
            if z.status_code == 200:
                return {}
            else:
                raise e

        LOG.debug("axapi_http: data = %s",
                  json.dumps(logutils.clean(r), indent=4))

        if 'response' in r and 'status' in r['response']:
            if r['response']['status'] == 'fail':
                acos_responses.raise_axapi_ex(r, method, api_url)

        if 'authorizationschema' in r:
            acos_responses.raise_axapi_auth_error(r, method, api_url, headers)

        return r
Beispiel #20
0
 def test_int(self):
     actual = target.clean(1)
     self.assertEqual(1, actual)
Beispiel #21
0
 def test_ustring(self):
     actual = target.clean(u'sometext')
     self.assertEqual(u'sometext', actual)
Beispiel #22
0
 def test_obj_twolevel(self):
     actual = target.clean(self.obj_twolevel).credentials.inside_secret
     self.assertEqual(target.REPLACEMENT, actual.username)
     self.assertEqual(target.REPLACEMENT, actual.password)
Beispiel #23
0
    def request(self, method, api_url, params={}, headers=None,
                file_name=None, file_content=None, axapi_args=None, **kwargs):
        LOG.debug("axapi_http: full url = %s", self.url_base + api_url)
        LOG.debug("axapi_http: %s url = %s", method, api_url)
        LOG.debug("axapi_http: params = %s", json.dumps(logutils.clean(params), indent=4))

        # Update params with axapi_args for currently unsupported configuration of objects
        if axapi_args is not None:
            formatted_axapi_args = dict([(k.replace('_', '-'), v) for k, v in
                                        axapi_args.iteritems()])
            params = acos_client.v21.axapi_http.merge_dicts(params, formatted_axapi_args)

        if (file_name is None and file_content is not None) or \
           (file_name is not None and file_content is None):
            raise ValueError("file_name and file_content must both be "
                             "populated if one is")

        hdrs = self.HEADERS.copy()
        if headers:
            hdrs.update(headers)

        if params:
            params_copy = params.copy()
            # params_copy.update(extra_params)
            LOG.debug("axapi_http: params_all = %s", logutils.clean(params_copy))

            payload = json.dumps(params_copy, encoding='utf-8')
        else:
            payload = None

        LOG.debug("axapi_http: headers = %s", json.dumps(logutils.clean(hdrs), indent=4))

        if file_name is not None:
            files = {
                'file': (file_name, file_content, "application/octet-stream"),
                'json': ('blob', payload, "application/json")
            }

            hdrs.pop("Content-type", None)
            hdrs.pop("Content-Type", None)
            z = requests.request(method, self.url_base + api_url, verify=False,
                                 files=files, headers=hdrs)
        else:
            z = requests.request(method, self.url_base + api_url, verify=False,
                                 data=payload, headers=hdrs)

        if z.status_code == 204:
            return None

        try:
            r = z.json()
        except ValueError as e:
            # The response is not JSON but it still succeeded.
            if z.status_code == 200:
                return {}
            else:
                raise e

        LOG.debug("axapi_http: data = %s", json.dumps(logutils.clean(r), indent=4))

        if 'response' in r and 'status' in r['response']:
            if r['response']['status'] == 'fail':
                    acos_responses.raise_axapi_ex(r, method, api_url)

        if 'authorizationschema' in r:
            acos_responses.raise_axapi_auth_error(
                r, method, api_url, headers)

        return r
Beispiel #24
0
 def test_none(self):
     actual = target.clean(None)
     self.assertEqual(None, actual)
Beispiel #25
0
    def request(self, method, api_url, params={}, **kwargs):
        LOG.debug("axapi_http: url = %s", api_url)
        LOG.debug("axapi_http: params = %s", logutils.clean(params))

        self.headers = self.HEADERS

        if params:
            extra_params = kwargs.get('axapi_args', {})
            params_copy = merge_dicts(params, extra_params)
            LOG.debug("axapi_http: params_all = %s", logutils.clean(params_copy))

            payload = json.dumps(params_copy, encoding='utf-8')
        else:
            try:
                payload = kwargs.pop('payload', None)
                self.headers = dict(self.headers, **kwargs.pop('headers', {}))
                LOG.debug("axapi_http: headers_all = %s", logutils.clean(self.headers))
            except KeyError:
                payload = None

        last_e = None

        for i in xrange(0, 600):
            try:
                last_e = None
                data = self._http(method, api_url, payload)
                break
            except socket.error as e:
                # Workaround some bogosity in the API
                if (e.errno == errno.ECONNRESET or
                   e.errno == errno.ECONNREFUSED):
                    time.sleep(0.1)
                    last_e = e
                    continue
                raise e
            except httplib.BadStatusLine as e:
                time.sleep(0.1)
                last_e = e
                continue
            except EmptyHttpResponse as e:
                if e.response.status != httplib.OK:
                    msg = dict(e.response.msg.items())
                    data = json.dumps({"response": {'status': 'fail', 'err':
                                      {'code': e.response.status,
                                       'msg': msg}}})
                else:
                    data = json.dumps({"response": {"status": "OK"}})
                break

        if last_e is not None:
            raise e

        LOG.debug("axapi_http: data = %s", logutils.clean(data))

        # Fixup some broken stuff in an earlier version of the axapi
        # xmlok = ('<?xml version="1.0" encoding="utf-8" ?>'
        #          '<response status="ok"></response>')
        # if data == xmlok:
        #     return {'response': {'status': 'OK'}}
        # TODO()
        if data in broken_replies:
            data = broken_replies[data]
            LOG.debug("axapi_http: broken reply, new response: %s",
                      logutils.clean(data))

        try:
            r = json.loads(data, encoding='utf-8')
        except ValueError as e:
            # Handle non json response
            LOG.debug("axapi_http: json = %s", e)
            return data

        if 'response' in r and 'status' in r['response']:
            if r['response']['status'] == 'fail':
                    acos_responses.raise_axapi_ex(
                        r, action=extract_method(api_url))

        return r
Beispiel #26
0
 def test_int(self):
     actual = target.clean(1)
     self.assertEqual(1, actual)
Beispiel #27
0
 def test_clean_flat_dict(self):
     actual = target.clean(self.flat_dict)
     self.assertEqual(target.REPLACEMENT, actual["username"])
     self.assertEqual(target.REPLACEMENT, actual["password"])
     self.assertEqual(self.flat_dict["a"], actual["a"])
Beispiel #28
0
    def test_clean_onelevel_dict(self):
        actual = target.clean(self.dict_onelevel).get("credentials")

        self.assertEqual(target.REPLACEMENT, actual["username"])
        self.assertEqual(target.REPLACEMENT, actual["password"])
        self.assertEqual(1, self.dict_onelevel["a"])
Beispiel #29
0
    def test_clean_onelevel_dict(self):
        actual = target.clean(self.dict_onelevel).get("credentials")

        self.assertEqual(target.REPLACEMENT, actual["username"])
        self.assertEqual(target.REPLACEMENT, actual["password"])
        self.assertEqual(1, self.dict_onelevel["a"])
Beispiel #30
0
 def test_obj_flat(self):
     actual = target.clean(self.obj_flat)
     self.assertEqual(target.REPLACEMENT, actual.username)
     self.assertEqual(target.REPLACEMENT, actual.password)
Beispiel #31
0
 def test_float(self):
     actual = target.clean(3.7)
     self.assertEqual(3.7, actual)
Beispiel #32
0
 def test_obj_twolevel(self):
     actual = target.clean(self.obj_twolevel).credentials.inside_secret
     self.assertEqual(target.REPLACEMENT, actual.username)
     self.assertEqual(target.REPLACEMENT, actual.password)
Beispiel #33
0
    def request(self, method, api_url, params={}, **kwargs):
        LOG.debug("axapi_http: url = %s", api_url)
        LOG.debug("axapi_http: params = %s", logutils.clean(params))

        self.headers = self.HEADERS

        if params:
            extra_params = kwargs.get('axapi_args', {})
            params_copy = merge_dicts(params, extra_params)
            LOG.debug("axapi_http: params_all = %s",
                      logutils.clean(params_copy))

            payload = json.dumps(params_copy, encoding='utf-8')
        else:
            try:
                payload = kwargs.pop('payload', None)
                self.headers = dict(self.headers, **kwargs.pop('headers', {}))
                LOG.debug("axapi_http: headers_all = %s",
                          logutils.clean(self.headers))
            except KeyError:
                payload = None

        last_e = None

        for i in xrange(0, 10):
            try:
                last_e = None
                data = self._http(method, api_url, payload)
                break
            except socket.error as e:
                # Workaround some bogosity in the API
                if e.errno in self.retry_errnos:
                    time.sleep(0.01)
                    last_e = e
                    continue
                raise e
            except httplib.BadStatusLine as e:
                time.sleep(0.01)
                last_e = e
                continue
            except EmptyHttpResponse as e:
                if e.response.status != httplib.OK:
                    msg = dict(e.response.msg.items())
                    data = json.dumps({
                        "response": {
                            'status': 'fail',
                            'err': {
                                'code': e.response.status,
                                'msg': msg
                            }
                        }
                    })
                else:
                    data = json.dumps({"response": {"status": "OK"}})
                break

        if last_e is not None:
            raise e

        LOG.debug("axapi_http: data = %s", logutils.clean(data))

        # Fixup some broken stuff in an earlier version of the axapi
        # xmlok = ('<?xml version="1.0" encoding="utf-8" ?>'
        #          '<response status="ok"></response>')
        # if data == xmlok:
        #     return {'response': {'status': 'OK'}}
        # TODO()
        if data in broken_replies:
            data = broken_replies[data]
            LOG.debug("axapi_http: broken reply, new response: %s",
                      logutils.clean(data))

        try:
            r = json.loads(data, encoding='utf-8')
        except ValueError as e:
            # Handle non json response
            LOG.debug("axapi_http: json = %s", e)
            return data

        if 'response' in r and 'status' in r['response']:
            if r['response']['status'] == 'fail':
                acos_responses.raise_axapi_ex(r,
                                              action=extract_method(api_url))

        return r
Beispiel #34
0
    def request(self, method, api_url, params={}, **kwargs):
        """Generate the API call to the device."""

        LOG.debug("axapi_http: full url = %s", self.url_base + api_url)
        LOG.debug("axapi_http: %s url = %s", method, api_url)
        LOG.debug("axapi_http: params = %s",
                  json.dumps(logutils.clean(params), indent=4))

        # Set "data" variable for the request
        if params:
            extra_params = kwargs.get('axapi_args', {})
            params_copy = merge_dicts(params, extra_params)
            LOG.debug("axapi_http: params_all = %s",
                      logutils.clean(params_copy))

            payload = json.dumps(params_copy)
        else:
            try:
                payload = kwargs.pop('payload', None)
                self.headers = dict(self.HEADERS, **kwargs.pop('headers', {}))
                LOG.debug("axapi_http: headers_all = %s",
                          logutils.clean(self.headers))
            except KeyError:
                payload = None

        max_retries = kwargs.get('max_retries', self.max_retries)
        timeout = kwargs.get('timeout', self.timeout)

        # Create session to set HTTPAdapter or SSLAdapter
        session = Session()
        if self.port == 443:
            # Add adapter for any https session to force TLS1_0 connection for v21 of AXAPI
            session.mount('https://', SSLAdapter(max_retries=max_retries))
        else:
            session.mount('http://', HTTPAdapter(max_retries=max_retries))
        session_request = getattr(session, method.lower())

        # Make actual request and handle any errors
        try:
            device_response = session_request(self.url_base + api_url,
                                              verify=False,
                                              data=payload,
                                              headers=self.HEADERS,
                                              timeout=timeout)
        except (Exception) as e:
            LOG.error("acos_client failing with error %s after %s retries",
                      e.__class__.__name__, max_retries)
            raise e
        finally:
            session.close()

        # Log if the reponse is one of the known broken response
        if device_response in broken_replies:
            device_response = broken_replies[device_response]
            LOG.debug("axapi_http: broken reply, new response: %s",
                      logutils.clean(device_response))

        # Validate json response
        try:
            json_response = device_response.json()
            LOG.debug("axapi_http: data = %s",
                      json.dumps(logutils.clean(json_response), indent=4))
        except ValueError as e:
            # The response is not JSON but it still succeeded.
            LOG.debug("axapi_http: json = %s", e)
            return device_response

        # Handle "fail" responses returned by AXAPI
        if 'response' in json_response and 'status' in json_response[
                'response']:
            if json_response['response']['status'] == 'fail':
                acos_responses.raise_axapi_ex(json_response,
                                              action=extract_method(api_url))

        # Return json portion of response
        return json_response
Beispiel #35
0
    def request(self, method, api_url, params={}, **kwargs):
        """Generate the API call to the device."""

        LOG.debug("axapi_http: full url = %s", self.url_base + api_url)
        LOG.debug("axapi_http: %s url = %s", method, api_url)
        LOG.debug("axapi_http: params = %s", json.dumps(logutils.clean(params), indent=4))

        # Set "data" variable for the request
        if params:
            extra_params = kwargs.get('axapi_args', {})
            params_copy = merge_dicts(params, extra_params)
            LOG.debug("axapi_http: params_all = %s", logutils.clean(params_copy))

            payload = json.dumps(params_copy)
        else:
            try:
                payload = kwargs.pop('payload', None)
                self.headers = dict(self.HEADERS, **kwargs.pop('headers', {}))
                LOG.debug("axapi_http: headers_all = %s", logutils.clean(self.headers))
            except KeyError:
                payload = None

        max_retries = kwargs.get('max_retries', self.max_retries)
        timeout = kwargs.get('timeout', self.timeout)

        # Create session to set HTTPAdapter or SSLAdapter
        session = Session()
        if self.port == 443:
            # Add adapter for any https session to force TLS1_0 connection for v21 of AXAPI
            session.mount('https://', SSLAdapter(max_retries=max_retries))
        else:
            session.mount('http://', HTTPAdapter(max_retries=max_retries))
        session_request = getattr(session, method.lower())

        # Make actual request and handle any errors
        try:
            device_response = session_request(
                self.url_base + api_url, verify=False, data=payload, headers=self.HEADERS, timeout=timeout
            )
        except (Exception) as e:
            LOG.error("acos_client failing with error %s after %s retries", e.__class__.__name__, max_retries)
            raise e
        finally:
            session.close()

        # Log if the reponse is one of the known broken response
        if device_response in broken_replies:
            device_response = broken_replies[device_response]
            LOG.debug("axapi_http: broken reply, new response: %s", logutils.clean(device_response))

        # Validate json response
        try:
            json_response = device_response.json()
            LOG.debug("axapi_http: data = %s", json.dumps(logutils.clean(json_response), indent=4))
        except ValueError as e:
            # The response is not JSON but it still succeeded.
            LOG.debug("axapi_http: json = %s", e)
            return device_response

        # Handle "fail" responses returned by AXAPI
        if 'response' in json_response and 'status' in json_response['response']:
            if json_response['response']['status'] == 'fail':
                    acos_responses.raise_axapi_ex(json_response, action=extract_method(api_url))

        # Return json portion of response
        return json_response