def login(self, username, password): """ Login to the Traffic Ops API. :param username: Traffic Ops User Name :type username: Text :param password: Traffic Ops User Password :type password: Text :return: None :rtype: None :raises: trafficops.restapi.LoginError """ if not self.is_open: self.create() self._logged_in = False try: # Try to login to Traffic Ops self.post(u'user/login', data={u'u': username, u'p': password}) self._logged_in = True except rex.SSLError as e: self.close() msg = (u'{0}. This system may have a self-signed certificate. Try creating this TOSession ' u'object passing verify_cert=False. e.g. TOSession(..., verify_cert=False). ' u'WARNING: disabling certificate verification is not recommended.') msg = msg.format(e) utils.log_with_debug_info(logging.ERROR, msg) raise restapi.LoginError(msg) except restapi.OperationError as e: msg = u'Logging in to Traffic Ops has failed. Reason: {0}' msg = msg.format(e) self.close() utils.log_with_debug_info(logging.ERROR, msg) raise restapi.OperationError(msg)
def __init__(self, host_ip, host_port=443, api_version=u'1.3', ssl=True, headers=default_headers, verify_cert=True): """ The class initializer. :param host_ip: The dns name or ip address of the Traffic Ops host to use to talk to the API :type host_ip: Text :param host_port: The port to use when contacting the Traffic Ops API :type host_port: int :param api_version: The version of the API to use when calling end-points on the Traffic Ops API :type api_version: Text :param ssl: Should ssl be used? http vs. https :type ssl: bool :param headers: The http headers to use when contacting the Traffic Ops API :type headers: Dict[Text, Text] :param verify_cert: Should the ssl certificates be verified when contacting the Traffic Ops API. You may want to set this to False for systems with self-signed certificates. :type verify_cert: bool """ super(TOSession, self).__init__(host_ip=host_ip, api_version=api_version, api_base_path=u'api/{api_version}/', host_port=host_port, ssl=ssl, headers=headers, verify_cert=verify_cert) self._logged_in = False msg = u'TOSession instance {0:#0x} initialized: Details: {1}' utils.log_with_debug_info(logging.DEBUG, msg.format(id(self), self.__dict__))
def close(self): """ Close and cleanup the requests Session object. :return: None :rtype: None """ if self._session: sid = id(self._session) self._session.close() del self._session self._session = None if logging: msg = u'Internal requests Session instance 0x{0:x} closed and cleaned up' utils.log_with_debug_info(logging.DEBUG, msg.format(sid))
def method_wrapper(self, *args, **kwargs): # Positional arguments, e.g. *args, are not being used. Keyword arguments are the # preferred way to pass the parameters needed by the helper functions if (self.api_version is None) or (self.api_version in supported_versions): msg = (u'Calling method [{0}] with keyword arguments [{1}] ' u'via API endpoint method [{2}]') # type: Text utils.log_with_debug_info(logging.DEBUG, msg.format(method_name, kwargs, func.__name__)) return getattr(self, method_name)(api_path, **kwargs) else: # Client API version is not supported by the method being called msg = (u"Method [{0}] is not supported by this client's API version [{1}]; " u'Supported versions: {2}') # type: Text msg = msg.format(func.__name__, self.api_version, supported_versions) utils.log_with_debug_info(logging.DEBUG, msg) raise OperationError(msg)
def create(self): """ Create the requests.Session to communicate with the RESTful API. :return: None :rtype: None """ if self._session: self.close() if not self._session: self._session = requests.Session() self._session.mount('http://', ra.HTTPAdapter(max_retries=self._max_retries)) self._session.mount('https://', ra.HTTPAdapter(max_retries=self._max_retries)) msg = u'Created internal requests Session instance {0:#0x}' utils.log_with_debug_info(logging.DEBUG, msg.format(id(self._session)))
def method_wrapper(self, *args, **kwargs): # Positional arguments, e.g. *args, are not being used. Keyword arguments are the # preferred way to pass the parameters needed by the helper functions if (self.api_version is None) or (self.api_version in supported_versions): msg = (u'Calling method [{0}] with keyword arguments [{1}] ' u'via API endpoint method [{2}]') # type: Text utils.log_with_debug_info( logging.DEBUG, msg.format(method_name, kwargs, func.__name__)) return getattr(self, method_name)(api_path, **kwargs) else: # Client API version is not supported by the method being called msg = ( u"Method [{0}] is not supported by this client's API version [{1}]; " u'Supported versions: {2}') # type: Text msg = msg.format(func.__name__, self.api_version, supported_versions) utils.log_with_debug_info(logging.DEBUG, msg) raise OperationError(msg)
def login(self, username, password): """ Login to the Traffic Ops API. :param username: Traffic Ops User Name :type username: Text :param password: Traffic Ops User Password :type password: Text :return: None :rtype: None :raises: trafficops.restapi.LoginError """ if not self.is_open: self.create() self._logged_in = False try: # Try to login to Traffic Ops self.post(u'user/login', data={u'u': username, u'p': password}) self._logged_in = True except rex.SSLError as e: self.close() msg = ( u'{0}. This system may have a self-signed certificate. Try creating this TOSession ' u'object passing verify_cert=False. e.g. TOSession(..., verify_cert=False). ' u'WARNING: disabling certificate verification is not recommended.' ) msg = msg.format(e) utils.log_with_debug_info(logging.ERROR, msg) raise restapi.LoginError(msg) except restapi.OperationError as e: msg = u'Logging in to Traffic Ops has failed. Reason: {0}' msg = msg.format(e) self.close() utils.log_with_debug_info(logging.ERROR, msg) raise restapi.OperationError(msg)
def __init__(self, host_ip, host_port=443, api_version=u'1.2', ssl=True, headers=default_headers, verify_cert=True): """ The class initializer. :param host_ip: The dns name or ip address of the Traffic Ops host to use to talk to the API :type host_ip: Text :param host_port: The port to use when contacting the Traffic Ops API :type host_port: int :param api_version: The version of the API to use when calling end-points on the Traffic Ops API :type api_version: Text :param ssl: Should ssl be used? http vs. https :type ssl: bool :param headers: The http headers to use when contacting the Traffic Ops API :type headers: Dict[Text, Text] :param verify_cert: Should the ssl certificates be verified when contacting the Traffic Ops API. You may want to set this to False for systems with self-signed certificates. :type verify_cert: bool """ super(TOSession, self).__init__(host_ip=host_ip, api_version=api_version, api_base_path=u'api/{api_version}/', host_port=host_port, ssl=ssl, headers=headers, verify_cert=verify_cert) self._logged_in = False msg = u'TOSession instance {0:#0x} initialized: Details: {1}' utils.log_with_debug_info(logging.DEBUG, msg.format(id(self), self.__dict__))
def _do_operation(self, operation, api_path, query_params=None, munchify=True, debug_response=False, expected_status_codes=( 200, 204, ), *args, **kwargs): """ Helper method to perform http operation requests - This is a boilerplate process for http operations :param operation: Name of method to call on the self._session object to perform the http request :type operation: Text :param api_path: The path to the API end-point that you want to call which does not include the base url. e.g. 'user/login', 'servers', etc. This string can contain substitution parameters as denoted by a valid field_name replacement field specification as per str.format(). E.g. 'cachegroups/{id}' or 'cachegroups/{id:d}' :type api_path: Text :param: query_params: URL query params to provide to the end-point. E.g. { 'sort': 'asc', 'maxresults': 200 } which translates to something like '?sort=asc&maxresults=200' which is appended to the request URL :type query_params: Union[Dict[Text, Any], None] :param: munchify: If True encapsulate data to be returned in a munch.Munch object which allows keys in a Python dictionary to additionally have attribute access. E.g. a_dict['a_key'] with munch becomes a_dict['a_key'] or a_dict.a_key :type munchify: bool :param kwargs: Passed Keyword Parameters. If you need to send JSON data to the endpoint pass the keyword parameter 'data' with the python data structure e.g. a dict. This method will convert it to JSON before sending it to the API endpoint. :type kwargs: Dict[Text, Any] :param debug_response: If True, the actual response data text will be added to the log if a JSON decoding exception is encountered. :type debug_response: bool :type expected_status_codes: Tuple[int] :param: expected_status_codes: expected success http status codes. If the user needs to override the defaults this parameter can be passed. E.g. (200, 204,) :type munchify: bool :return: Python data structure distilled from JSON from the API request. :rtype: Tuple[Union[Dict[Text, Any], List[Dict[Text, Any]], munch.Munch, List[munch.Munch]], requests.Response] :raises: miscellaneous.exceptions.OperationError """ if not self._session: msg = u'No session has been created for the API. Have you called create() yet?' utils.log_with_debug_info(logging.ERROR, msg) raise OperationError(msg) response = None retdata = None endpoint = self._build_endpoint(api_path, params=kwargs, query_params=query_params) params = { u'headers': self._headers, u'verify': self._verify_cert, } if u'data' in kwargs: params[u'data'] = json.dumps(kwargs[u'data']) utils.log_with_debug_info(logging.DEBUG, u'Call parameters: {0}'.format(params)) # Call the API endpoint response = getattr(self._session, operation)(endpoint, **params) utils.log_with_debug_info( logging.DEBUG, u'Response status: {0} {1}'.format(response.status_code, response.reason)) if response.status_code not in expected_status_codes: try: retdata = response.json() except Exception as e: # Invalid JSON payload. msg = ( u'HTTP Status Code: [{0}]; API response data for end-point [{1}] does not ' u'appear to be valid JSON. Cause: {2}.') msg = msg.format(response.status_code, endpoint, e) if debug_response: utils.log_with_debug_info( logging.ERROR, msg + u' Data: [' + str(response.text) + u']') raise InvalidJSONError(msg) msg = u'{0} request to RESTful API at [{1}] expected status(s) {2}; failed: {3} {4}; Response: {5}' msg = msg.format(operation.upper(), endpoint, expected_status_codes, response.status_code, response.reason, retdata) utils.log_with_debug_info(logging.ERROR, msg) raise OperationError(msg) try: if response.status_code in ('204', ): # "204 No Content" retdata = {} else: # Decode the expected JSON retdata = response.json() except Exception as e: # Invalid JSON payload. msg = ( u'HTTP Status Code: [{0}]; API response data for end-point [{1}] does not ' u'appear to be valid JSON. Cause: {2}.') msg = msg.format(response.status_code, endpoint, e) if debug_response: utils.log_with_debug_info( logging.ERROR, msg + u' Data: [' + str(response.text) + u']') raise InvalidJSONError(msg) retdata = munch.munchify(retdata) if munchify else retdata return (retdata[u'response'] if u'response' in retdata else retdata), response
def _build_endpoint(self, api_path, params=None, query_params=None): """ Helper function to form API URL. The base url is '<protocol>://<hostname>[:<port>]/<api base url>' E.g. 'https://to.somedomain.net/api/0.1/' :param api_path: The path to the API end-point that you want to call which does not include the base url. e.g. 'user/login', 'servers', etc. This string can contain substitution parameters as denoted by a valid field_name replacement field specification as per str.format(). E.g. 'cachegroups/{id}' or 'cachegroups/{id:d}' :type api_path: Text :param params: If str.format() field_name replacement field specifications exists in the api_path use this dictionary to perform replacements of the specifications with the value(s) in the dictionary that match the parameter name(s). E.g. '{param_id}' or '{param_id:d}' in api_string is replaced by value in params['param_id']. :type params: Union[Dict[Text, Any], None] :param: query_params: URL query params to provide to the end-point. E.g. { 'sort': 'asc', 'maxresults': 200 } which translates to something like '?sort=asc&maxresults=200' which is appended to the request URL :type query_params: Union[Dict[Text, Any], None] :return: The base url plus the passed and possibly substituted api_path to form a complete URL to the API resource to request :rtype: Text :raises: ValueError """ new_api_path = api_path # Replace all parameters in the new_api_path path, if required try: # Make the parameters values safe for adding to URLs url_params = { k: compat.quote(str(v)) if isinstance(v, str) else v for k, v in iteritems(params) } utils.log_with_debug_info( logging.DEBUG, u'URL parameters are: [{0}]'.format(url_params)) qparams = u'' if query_params: # Process the URL query parameters qparams = u'?{0}'.format(compat.urlencode(query_params)) utils.log_with_debug_info( logging.DEBUG, u'URL query parameters are: [{0}]'.format(qparams)) new_api_path = api_path.format(**url_params) + qparams except KeyError as e: msg = ( u'Expecting a value for keyword argument [{0}] for format field ' u'specification [{1!r}]') msg = msg.format(e, api_path) utils.log_with_debug_info(logging.ERROR, msg) raise ValueError(msg) except ValueError as e: msg = ( u'One or more values do not match the format field specification ' u'[{0!r}]; Supplied values: {1!r} ') msg = msg.format(api_path, params) utils.log_with_debug_info(logging.ERROR, msg) raise ValueError(msg) retval = compat.urljoin(self.api_base_url, new_api_path) utils.log_with_debug_info( logging.DEBUG, u'Built end-point to return: {0}'.format(retval)) return retval
def __init__(self, host_ip, api_version=None, api_base_path=u'api/', host_port=443, ssl=True, headers=default_headers, verify_cert=True, create_session=False, max_retries=5): """ The class initializer. :param host_ip: The dns name or ip address of the RESTful API host to use to talk to the API :type host_ip: Text :param host_port: The port to use when contacting the RESTful API :type host_port: int :param api_version: The version of the API to make calls against. If supplied, end-point version validation will be performed. If supplied as None, no version validation will be performed. None is allowed so that non-versioned REST APIs can be implemented. E.g. '1.2', None, etc. :type api_version: Union[Text, None] :param api_base_path: The part of the url that is the base path, from the web server root (which may include a api version), for all api end-points without the server url portion. E.g. 'api/', 'api/1.2/', etc. NOTE: To specify the base path with the passed 'api_version' you can specify api_base_path as 'api/{api_version}/' and the API version will be substituted. If api_version is None and '{api_version}' is specified in the api_base_path string then an exception will be thrown. e.g. api_version=u'1.2' -> 'api/{api_version}/' -> 'api/1.2/' api_version=None -> 'api/{api_version}/' -> Throws Exception :type api_base_path: Text :param ssl: Should ssl be used? http vs. https :type ssl: bool :param headers: The http headers to use when contacting the RESTful API :type headers: Dict[Text, Text] :param verify_cert: Should the ssl certificates be verified when contacting the RESTful API. You may want to set this to False for systems with self-signed certificates. :type verify_cert: bool :param create_session: Should a session be created automatically? :type create_session: bool """ self._session = None self._host_ip = host_ip self._host_port = host_port self._api_version = api_version self._api_base_path = api_base_path self._ssl = ssl self._headers = headers self._verify_cert = verify_cert self._create_session = create_session self._max_retries = max_retries # Setup API End-point Version validation, if enabled self.__api_version_format_name = u'api_version' self.__api_version_format_value = u'{{{0}}}'.format( self.__api_version_format_name) if self._api_version: # if api_base_path is supplied as 'api/{api_version}/' or some string # containing '{api_version}' then try to substitute the api_version supplied # by the user. version_params = { self.__api_version_format_name: self._api_version } self._api_base_path = self._api_base_path.format(**version_params) if not self._api_version and self.__api_version_format_value in self._api_base_path: msg = ( u'{0} was specified in the API Base Path [{1}] ' u'but the replacement did not occur because the API Version ' u'was not supplied.') # type: Text msg = msg.format(self.__api_version_format_value, self._api_base_path) utils.log_with_debug_info(logging.ERROR, msg) raise OperationError(msg) # Setup some common URLs self._server_url = u'{0}://{1}{2}/'.format( u'https' if ssl else u'http', host_ip, u':{0}'.format(host_port) if host_port else u'') self._api_base_url = compat.urljoin(self._server_url, self._api_base_path) self._api_base_url = self._api_base_url.rstrip(u'/') + u'/' utils.log_with_debug_info(logging.DEBUG, u'Server URL: {0}'.format(self._server_url)) utils.log_with_debug_info( logging.DEBUG, u'API Base Path: {0}'.format(self._api_base_path)) utils.log_with_debug_info( logging.DEBUG, u'API Version: {0}'.format(self._api_version)) utils.log_with_debug_info( logging.DEBUG, u'API Base URL: {0}'.format(self._api_base_url)) if not self._verify_cert: # Not verifying certs so let's disable the warning import requests.packages.urllib3 as u3l import requests.packages.urllib3.exceptions as u3e u3l.disable_warnings(u3e.InsecureRequestWarning) utils.log_with_debug_info( logging.WARNING, u'Certificate verification warnings are disabled.') msg = u'RestApiSession instance {0:#0x} initialized: Details: {1}' utils.log_with_debug_info(logging.DEBUG, msg.format(id(self), self.__dict__)) if self._create_session: self.create()
def _do_operation(self, operation, api_path, query_params=None, munchify=True, debug_response=False, expected_status_codes=(200, 204,), *args, **kwargs): """ Helper method to perform http operation requests - This is a boilerplate process for http operations :param operation: Name of method to call on the self._session object to perform the http request :type operation: Text :param api_path: The path to the API end-point that you want to call which does not include the base url. e.g. 'user/login', 'servers', etc. This string can contain substitution parameters as denoted by a valid field_name replacement field specification as per str.format(). E.g. 'cachegroups/{id}' or 'cachegroups/{id:d}' :type api_path: Text :param: query_params: URL query params to provide to the end-point. E.g. { 'sort': 'asc', 'maxresults': 200 } which translates to something like '?sort=asc&maxresults=200' which is appended to the request URL :type query_params: Union[Dict[Text, Any], None] :param: munchify: If True encapsulate data to be returned in a munch.Munch object which allows keys in a Python dictionary to additionally have attribute access. E.g. a_dict['a_key'] with munch becomes a_dict['a_key'] or a_dict.a_key :type munchify: bool :param kwargs: Passed Keyword Parameters. If you need to send JSON data to the endpoint pass the keyword parameter 'data' with the python data structure e.g. a dict. This method will convert it to JSON before sending it to the API endpoint. :type kwargs: Dict[Text, Any] :param debug_response: If True, the actual response data text will be added to the log if a JSON decoding exception is encountered. :type debug_response: bool :type expected_status_codes: Tuple[int] :param: expected_status_codes: expected success http status codes. If the user needs to override the defaults this parameter can be passed. E.g. (200, 204,) :type munchify: bool :return: Python data structure distilled from JSON from the API request. :rtype: Tuple[Union[Dict[Text, Any], List[Dict[Text, Any]], munch.Munch, List[munch.Munch]], requests.Response] :raises: miscellaneous.exceptions.OperationError """ if not self._session: msg = u'No session has been created for the API. Have you called create() yet?' utils.log_with_debug_info(logging.ERROR, msg) raise OperationError(msg) response = None retdata = None endpoint = self._build_endpoint(api_path, params=kwargs, query_params=query_params) params = { u'headers': self._headers, u'verify': self._verify_cert, } if u'data' in kwargs: params[u'data'] = json.dumps(kwargs[u'data']) utils.log_with_debug_info(logging.DEBUG, u'Call parameters: {0}'.format(params)) # Call the API endpoint response = getattr(self._session, operation)(endpoint, **params) utils.log_with_debug_info(logging.DEBUG, u'Response status: {0} {1}'.format(response.status_code, response.reason)) if response.status_code not in expected_status_codes: try: retdata = response.json() except Exception as e: # Invalid JSON payload. msg = (u'HTTP Status Code: [{0}]; API response data for end-point [{1}] does not ' u'appear to be valid JSON. Cause: {2}.') msg = msg.format(response.status_code, endpoint, e) if debug_response: utils.log_with_debug_info(logging.ERROR, msg + u' Data: [' + str(response.text) + u']') raise InvalidJSONError(msg) msg = u'{0} request to RESTful API at [{1}] expected status(s) {2}; failed: {3} {4}; Response: {5}' msg = msg.format(operation.upper(), endpoint, expected_status_codes, response.status_code, response.reason, retdata) utils.log_with_debug_info(logging.ERROR, msg) raise OperationError(msg) try: if response.status_code in ('204',): # "204 No Content" retdata = {} else: # Decode the expected JSON retdata = response.json() except Exception as e: # Invalid JSON payload. msg = (u'HTTP Status Code: [{0}]; API response data for end-point [{1}] does not ' u'appear to be valid JSON. Cause: {2}.') msg = msg.format(response.status_code, endpoint, e) if debug_response: utils.log_with_debug_info(logging.ERROR, msg + u' Data: [' + str(response.text) + u']') raise InvalidJSONError(msg) retdata = munch.munchify(retdata) if munchify else retdata return (retdata[u'response'] if u'response' in retdata else retdata), response
def _build_endpoint(self, api_path, params=None, query_params=None): """ Helper function to form API URL. The base url is '<protocol>://<hostname>[:<port>]/<api base url>' E.g. 'https://to.somedomain.net/api/0.1/' :param api_path: The path to the API end-point that you want to call which does not include the base url. e.g. 'user/login', 'servers', etc. This string can contain substitution parameters as denoted by a valid field_name replacement field specification as per str.format(). E.g. 'cachegroups/{id}' or 'cachegroups/{id:d}' :type api_path: Text :param params: If str.format() field_name replacement field specifications exists in the api_path use this dictionary to perform replacements of the specifications with the value(s) in the dictionary that match the parameter name(s). E.g. '{param_id}' or '{param_id:d}' in api_string is replaced by value in params['param_id']. :type params: Union[Dict[Text, Any], None] :param: query_params: URL query params to provide to the end-point. E.g. { 'sort': 'asc', 'maxresults': 200 } which translates to something like '?sort=asc&maxresults=200' which is appended to the request URL :type query_params: Union[Dict[Text, Any], None] :return: The base url plus the passed and possibly substituted api_path to form a complete URL to the API resource to request :rtype: Text :raises: ValueError """ new_api_path = api_path # Replace all parameters in the new_api_path path, if required try: # Make the parameters values safe for adding to URLs url_params = {k: compat.quote(str(v)) if isinstance(v, str) else v for k, v in iteritems(params)} utils.log_with_debug_info(logging.DEBUG, u'URL parameters are: [{0}]'.format(url_params)) qparams = u'' if query_params: # Process the URL query parameters qparams = u'?{0}'.format(compat.urlencode(query_params)) utils.log_with_debug_info(logging.DEBUG, u'URL query parameters are: [{0}]'.format(qparams)) new_api_path = api_path.format(**url_params) + qparams except KeyError as e: msg = (u'Expecting a value for keyword argument [{0}] for format field ' u'specification [{1!r}]') msg = msg.format(e, api_path) utils.log_with_debug_info(logging.ERROR, msg) raise ValueError(msg) except ValueError as e: msg = (u'One or more values do not match the format field specification ' u'[{0!r}]; Supplied values: {1!r} ') msg = msg.format(api_path, params) utils.log_with_debug_info(logging.ERROR, msg) raise ValueError(msg) retval = compat.urljoin(self.api_base_url, new_api_path) utils.log_with_debug_info(logging.DEBUG, u'Built end-point to return: {0}'.format(retval)) return retval
def __init__(self, host_ip, api_version=None, api_base_path=u'api/', host_port=443, ssl=True, headers=default_headers, verify_cert=True, create_session=False, max_retries=5): """ The class initializer. :param host_ip: The dns name or ip address of the RESTful API host to use to talk to the API :type host_ip: Text :param host_port: The port to use when contacting the RESTful API :type host_port: int :param api_version: The version of the API to make calls against. If supplied, end-point version validation will be performed. If supplied as None, no version validation will be performed. None is allowed so that non-versioned REST APIs can be implemented. E.g. '1.2', None, etc. :type api_version: Union[Text, None] :param api_base_path: The part of the url that is the base path, from the web server root (which may include a api version), for all api end-points without the server url portion. E.g. 'api/', 'api/1.2/', etc. NOTE: To specify the base path with the passed 'api_version' you can specify api_base_path as 'api/{api_version}/' and the API version will be substituted. If api_version is None and '{api_version}' is specified in the api_base_path string then an exception will be thrown. e.g. api_version=u'1.2' -> 'api/{api_version}/' -> 'api/1.2/' api_version=None -> 'api/{api_version}/' -> Throws Exception :type api_base_path: Text :param ssl: Should ssl be used? http vs. https :type ssl: bool :param headers: The http headers to use when contacting the RESTful API :type headers: Dict[Text, Text] :param verify_cert: Should the ssl certificates be verified when contacting the RESTful API. You may want to set this to False for systems with self-signed certificates. :type verify_cert: bool :param create_session: Should a session be created automatically? :type create_session: bool """ self._session = None self._host_ip = host_ip self._host_port = host_port self._api_version = api_version self._api_base_path = api_base_path self._ssl = ssl self._headers = headers self._verify_cert = verify_cert self._create_session = create_session self._max_retries = max_retries # Setup API End-point Version validation, if enabled self.__api_version_format_name = u'api_version' self.__api_version_format_value = u'{{{0}}}'.format(self.__api_version_format_name) if self._api_version: # if api_base_path is supplied as 'api/{api_version}/' or some string # containing '{api_version}' then try to substitute the api_version supplied # by the user. version_params = { self.__api_version_format_name: self._api_version } self._api_base_path = self._api_base_path.format(**version_params) if not self._api_version and self.__api_version_format_value in self._api_base_path: msg = (u'{0} was specified in the API Base Path [{1}] ' u'but the replacement did not occur because the API Version ' u'was not supplied.') # type: Text msg = msg.format(self.__api_version_format_value, self._api_base_path) utils.log_with_debug_info(logging.ERROR, msg) raise OperationError(msg) # Setup some common URLs self._server_url = u'{0}://{1}{2}/'.format(u'https' if ssl else u'http', host_ip, u':{0}'.format(host_port) if host_port else u'') self._api_base_url = compat.urljoin(self._server_url, self._api_base_path) self._api_base_url = self._api_base_url.rstrip(u'/') + u'/' utils.log_with_debug_info(logging.DEBUG, u'Server URL: {0}'.format(self._server_url)) utils.log_with_debug_info(logging.DEBUG, u'API Base Path: {0}'.format(self._api_base_path)) utils.log_with_debug_info(logging.DEBUG, u'API Version: {0}'.format(self._api_version)) utils.log_with_debug_info(logging.DEBUG, u'API Base URL: {0}'.format(self._api_base_url)) if not self._verify_cert: # Not verifying certs so let's disable the warning import requests.packages.urllib3 as u3l import requests.packages.urllib3.exceptions as u3e u3l.disable_warnings(u3e.InsecureRequestWarning) utils.log_with_debug_info(logging.WARNING, u'Certificate verification warnings are disabled.') msg = u'RestApiSession instance {0:#0x} initialized: Details: {1}' utils.log_with_debug_info(logging.DEBUG, msg.format(id(self), self.__dict__)) if self._create_session: self.create()