cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
1356
Views
5
Helpful
2
Replies

Django application with zeep on IIS Web Server

Evgeny Udaltsov
Level 1
Level 1

Hi Everyone. I have written a simple web application based on Django for work with UCM API. While it works in Django Development Server Mode (`python manange.py runserver`) everything is ok, I can connect to UCM without any issue.
But when I deployed an application on MS IIS it stopped work at all and I have got an Server Error (500). If I set `DEBUG = True` the server will raise an error:

Request Method: POST
Request URL: https://youwillneverguess.com/cucm/device_search

Django Version: 3.0.8
Python Version: 3.7.8

Traceback (most recent call last):
  File "c:\python37\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "c:\python37\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "c:\python37\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "c:\python37\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\inetpub\wwwroot\xxxxxxxxxx\app_cucm\views.py", line 80, in cucm_device_search
    resp = cucm_script_sql_device_search(cucm_request.lower(), cucm_object)
  File "C:\inetpub\wwwroot\xxxxxxxxxx\cucm\cucm_device\cucm_device_sql.py", line 53, in cucm_script_sql_device_search
    resp = cucm_script_sql_executor(sql)
  File "C:\inetpub\wwwroot\xxxxxxxxxx\cucm\cucm_connector.py", line 166, in cucm_script_sql_executor
    cucm, cucm_history = cucm_connector()
  File "C:\inetpub\wwwroot\xxxxxxxxxx\cucm\cucm_connector.py", line 82, in cucm_connector
    transport = Transport(cache=SqliteCache(), session=session, timeout=20)
  File "c:\python37\lib\site-packages\zeep\cache.py", line 80, in __init__
    self._db_path = path if path else _get_default_cache_path()
  File "c:\python37\lib\site-packages\zeep\cache.py", line 160, in _get_default_cache_path
    os.makedirs(path)
  File "c:\python37\lib\os.py", line 213, in makedirs
    makedirs(head, exist_ok=exist_ok)
  File "c:\python37\lib\os.py", line 223, in makedirs
    mkdir(name, mode)

Exception Type: PermissionError at /cucm/device_search
Exception Value: [WinError 5] Access is denied: '.\\zeep'

Debug from Django:

C:\inetpub\wwwroot\xxxxxxxxxxxx\cucm\cucm_connector.py in cucm_connector
    transport = Transport(cache=SqliteCache(), session=session, timeout=20)
▼ Local vars
Variable 	Value
BASE_DIR 	'C:\\inetpub\\wwwroot\\XXXXXXXXXXX'
binding 	'{http://www.cisco.com/AXLAPIService/}AXLAPIBinding'
cluster 	{'cucm_default': True,
	         'cucm_description': 'Production Cluster',
		 'cucm_ip': 'XXX.XXX.XXX.XXX',
		 'cucm_login': 'login',
		 'cucm_password': 'password',
		 'cucm_publisher': 'cucm.youwillneverguess.com'}
location 	'https://xxx.xxx.xxx.xxx:8443/axl/'
session 	<requests.sessions.Session object at 0x000001E6E832FF48>
wsdl 		'C:\\inetpub\\wwwroot\\xxxxxxxxxxx\\cucm/axlsqltoolkit/schema/11.5/AXLAPI.wsdl'
wsdl_ris 	'https://xxx.xxx.xxx.xxx:8443/realtimeservice2/services/RISService70?wsdl'

c:\python37\lib\site-packages\zeep\cache.py in __init__
            self._db_path = path if path else _get_default_cache_path()
▼ Local vars
Variable 	Value
path 		None
self		<zeep.cache.SqliteCache object at 0x000001E6E8349BC8>
timeout 	3600

c:\python37\lib\site-packages\zeep\cache.py in _get_default_cache_path
            os.makedirs(path)
▼ Local vars
Variable 	Value
path 		'.\\zeep\\Cache'

c:\python37\lib\os.py in makedirs
            makedirs(head, exist_ok=exist_ok)
▼ Local vars
Variable 	Value
exist_ok 	False
head 		'.\\zeep'
mode 		511
name		'.\\zeep\\Cache'
tail		'Cache'

c:\python37\lib\os.py in makedirs
        mkdir(name, mode)
▼ Local vars
Variable 	Value
exist_ok 	False
head 		'.'
mode		511
name		'.\\zeep'
tail		'zeep'

Do you have any idea?

1 Accepted Solution

Accepted Solutions

Evgeny Udaltsov
Level 1
Level 1

I found the solution. Yes, it possible to disable the cache, however in my opinion the better way relocate the cache db file to the project directory.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

disable_warnings(InsecureRequestWarning)

wsdl = os.path.join(BASE_DIR, "cucm/axlsqltoolkit/schema/11.5/AXLAPI.wsdl")
wsdl_ris = "https://{host}:8443/realtimeservice2/services/RISService70?wsdl".format(host=cluster["cucm_publisher"])
location = "https://{host}:8443/axl/".format(host=cluster["cucm_publisher"])
binding = "{http://www.cisco.com/AXLAPIService/}AXLAPIBinding"

session = requests.Session()

if settings.DEBUG:
	# DEBUG = True - Development mode
	session.verify = False
else:
	# DEBUG = False - Production mode
	cert = os.path.join(BASE_DIR, "cucm/{}.pem".format(cucm_cluster))
	if os.path.isfile(cert):
		session.verify = cert
		session.auth = HTTPBasicAuth(cluster["cucm_login"], cluster["cucm_password"])

		transport = Transport(cache=SqliteCache(os.path.join(BASE_DIR, "cucm/cache.db")), session=session, timeout=20)
		history = HistoryPlugin()

		# For Cisco UCM AXL Request
		client = Client(wsdl=wsdl, transport=transport, plugins=[history])
		service = client.create_service(binding, location)

		# For Cisco UCM RIS Request
		client_ris = Client(wsdl=wsdl_ris, transport=transport, plugins=[history])
                factory = client_ris.type_factory("ns0")
	else:
		log_message = "'{}.pem' Tomcat Certificate not found!".format(cluster["cucm_publisher"])
		logger.error(log_message, extra={"username": "cucm_script"})

 

View solution in original post

2 Replies 2

dstaudt
Cisco Employee
Cisco Employee

Not being super familiar with IIS/Django, my initial guess from the stack trace would be that there is a permission problem when Zeep attempts to cache its interim WSDL representation stuff on disk...maybe at ./zeep/cache?

You should be able to disable this caching (see the Zeep docs) though maybe just to help in pinning down the issue, as that may impact performance quite a bit due to the very large AXL WSDL size and overhead of compiling it.

Evgeny Udaltsov
Level 1
Level 1

I found the solution. Yes, it possible to disable the cache, however in my opinion the better way relocate the cache db file to the project directory.

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

disable_warnings(InsecureRequestWarning)

wsdl = os.path.join(BASE_DIR, "cucm/axlsqltoolkit/schema/11.5/AXLAPI.wsdl")
wsdl_ris = "https://{host}:8443/realtimeservice2/services/RISService70?wsdl".format(host=cluster["cucm_publisher"])
location = "https://{host}:8443/axl/".format(host=cluster["cucm_publisher"])
binding = "{http://www.cisco.com/AXLAPIService/}AXLAPIBinding"

session = requests.Session()

if settings.DEBUG:
	# DEBUG = True - Development mode
	session.verify = False
else:
	# DEBUG = False - Production mode
	cert = os.path.join(BASE_DIR, "cucm/{}.pem".format(cucm_cluster))
	if os.path.isfile(cert):
		session.verify = cert
		session.auth = HTTPBasicAuth(cluster["cucm_login"], cluster["cucm_password"])

		transport = Transport(cache=SqliteCache(os.path.join(BASE_DIR, "cucm/cache.db")), session=session, timeout=20)
		history = HistoryPlugin()

		# For Cisco UCM AXL Request
		client = Client(wsdl=wsdl, transport=transport, plugins=[history])
		service = client.create_service(binding, location)

		# For Cisco UCM RIS Request
		client_ris = Client(wsdl=wsdl_ris, transport=transport, plugins=[history])
                factory = client_ris.type_factory("ns0")
	else:
		log_message = "'{}.pem' Tomcat Certificate not found!".format(cluster["cucm_publisher"])
		logger.error(log_message, extra={"username": "cucm_script"})