def _send(self, request, url, data=None, refreshed=None, accepted=None, sleep_offset=0): """Send a request and process the response.""" curr_call = time.time() try: time.sleep((self.sleep + sleep_offset) - (curr_call - self.last_call)) except IOError: # Negative sleep value pass if data is None: response = self._do_request(request, url, cookies=self.cookie) else: response = self._do_request(request, url, data=data, cookies=self.cookie) self.last_call = time.time() if response is None: raise cexc.ApicHostNoResponse(url=url) # Every request refreshes the timeout self.session_deadline = time.time() + self.session_timeout if data is None: request_str = url else: request_str = '%s, data=%s' % (url, data) LOG.debug(("data = %s"), data) # imdata is where the APIC returns the useful information imdata = response.json().get('imdata') LOG.debug(("Response: %s"), imdata) if response.status_code != requests.codes.ok: try: err_code = imdata[0]['error']['attributes']['code'] err_text = imdata[0]['error']['attributes']['text'] except (IndexError, KeyError): err_code = '[code for APIC error not found]' err_text = '[text for APIC error not found]' # If invalid token then re-login and retry once if (not refreshed and (err_code in REFRESH_CODES) and not self._is_cert_auth()): self.login() return self._send(request, url, data=data, refreshed=True) if not accepted and response.status_code == 202: # The APIC queue is full, slow down significantly return self._send(request, url, data=data, accepted=True, sleep_offset=SLEEP_ON_FULL_QUEUE) raise cexc.ApicResponseNotOk(request=request_str, status=response.status_code, reason=response.reason, err_text=err_text, err_code=err_code) return imdata
def set_private_key(self, usr, cert_name, private_key_file, sign_algo=None, sign_hash=None): """Set the X.509 private key used for session-less REST calls""" url = self._api_url('mo/%s' % self._get_cert_dn(usr, cert_name)) try: with open(private_key_file) as key_file: private_key = crypto.load_privatekey(crypto.FILETYPE_PEM, key_file.read()) except Exception as e: LOG.error("Failed to load private key from file %s: %s" % (private_key_file, e)) raise self.username = usr self.cert_name = cert_name self.private_key = private_key self.sign_algo = sign_algo and sign_algo or 'v1.0' self.sign_hash = sign_hash and sign_hash or 'sha256' # Verify that the cert-name and key are ok try: response = self._do_request(self.session.get, url) except rexc.Timeout: raise cexc.ApicHostNoResponse(url=url) if response.status_code != requests.codes.ok: attr = response.json().get('imdata')[0]['error']['attributes'] raise cexc.ApicResponseNotOk(request=url, status=response.status_code, reason=response.reason, err_text=attr['text'], err_code=attr['code'])
def login(self, usr=None, pwd=None): """Log in to controller. Save user name and authentication.""" usr = usr or self.username pwd = pwd or self.password name_pwd = self._make_data('aaaUser', name=usr, pwd=pwd) url = self._api_url('aaaLogin') self.cookie = {} try: response = self._do_request(self.session.post, url, data=name_pwd) except rexc.Timeout: raise cexc.ApicHostNoResponse(url=url) attributes = self._save_cookie('aaaLogin', response) if response.status_code == requests.codes.ok: self.username = usr self.password = pwd self.authentication = attributes else: self.authentication = None raise cexc.ApicResponseNotOk(request=url, status=response.status_code, reason=response.reason, err_text=attributes['text'], err_code=attributes['code'])
def test_analyze_exception_no_response(self): self.assertEqual( errors.SYSTEM_TRANSIENT, self.apic_handler.analyze_exception( exceptions.ApicHostNoResponse(url='')))