turbodbc icon indicating copy to clipboard operation
turbodbc copied to clipboard

Connection Fails when run as part of Apache2/WSGI application.

Open jayhub42 opened this issue 7 years ago • 2 comments

I am working on a Django site that uses TURBODBC to execute SQL commands against a legacy DB. Everything works when using the Django test server and when I run code from the terminal. BUT errors when run from Apache2 with mod_wsgi.

below is a simple program that reproduces the error/issue.

/srcPython3/wsgi_test/hello_world.py

from turbodbc import connect


def application(environ, start_response):
    status = '200 OK'
    output = b'TURBODBC ROCKS!!!'
    connect_to_db()
    response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))]
    start_response(status, response_headers)

    return [output]


def connect_to_db():
    connection = connect(dsn="odbc-dev", uid='foo', pwd='bar')
    cursor = connection.cursor()

Apache2 config

WSGIScriptAlias / /srcPython3/wsgi_test/hello_world.py

WSGIPythonPath /srcPython3/wsgi_test/

<VirtualHost *:80>
    <Directory  /srcPython3/wsgi_test>
        <Files hello_world.py>
            Require all granted
        </Files>
    </Directory>
</VirtualHost>

error.log

mod_wsgi (pid=11944): Exception occurred processing WSGI script '/srcPython3/wsgi_test/hello_world.py'.
[wsgi:error]  Traceback (most recent call last):
[wsgi:error]  File "/usr/local/lib/python3.5/dist-packages/turbodbc/exceptions.py", line 50, in wrapper
[wsgi:error]     return f(*args, **kwds)
[wsgi:error]   File "/usr/local/lib/python3.5/dist-packages/turbodbc/connect.py", line 44, in connect
[wsgi:error]     turbodbc_options))
[wsgi:error] turbodbc_intern.Error: ODBC error
[wsgi:error] state: 60
[wsgi:error]
[wsgi:error] During handling of the above exception, another exception occurred:
[wsgi:error]
[wsgi:error] Traceback (most recent call last):
[wsgi:error]  File "/srcPython3/wsgi_test/hello_world.py", line 7, in application
[wsgi:error]     connect_to_db()
[wsgi:error]   File "/srcPython3/wsgi_test/hello_world.py", line 15, in connect_to_db
[wsgi:error]     connection = connect(dsn="odbc-dev", uid='foo', pwd='bar')
[wsgi:error]   File "/usr/local/lib/python3.5/dist-packages/turbodbc/exceptions.py", line 52, in wrapper
[wsgi:error]     raise DatabaseError(str(e))
[wsgi:error] turbodbc.exceptions.DatabaseError: ODBC error
[wsgi:error] state: 60

If you comment out the line: connect_to_db(), the program should print "TURBODBC ROCKS!!!" in the web browser.

jayhub42 avatar Apr 10 '18 17:04 jayhub42

Hi! First of all, congratulations on using such flattering debug output; I feel compelled to assist ;-). Given your description I suspect that the problem has something to do with your execution environment that seems to be different in situations where it works (console, Django test server) and when it does not (Apache2).

A guess could be that the path to your odbc.ini is not correctly configured; in this case, turbodbc may have difficulties in identifying what the DSN odbc-dev is supposed to be. The error message is not great, but other people have reported SQL states of 60 before (see here or there, and they seemingly could resolve it by fixing their environment.

Suggestions for debugging:

  • Log the values of environment variables ODBCINI, ODBCSYSINI, ODBCINSTINI using os.environ`. That should help with checking whether the environment is setup up in a hugely different way.
  • Try to connect with the database without using a DSN. You do that by specifying all parameters that you have in your odbc.ini in the connect() call, including driver="/path/to/your/driver.so". When that works when called from the terminal, it should also work from Apache. If not, files (ODBC drivers and their dependencies) might not be accessible.
  • Enable ODBC tracing with the appropriate setting for your ODBC driver. That might provide additional pointers as to what goes wrong.

For the record, it would be great to know what kind of legacy database you are connecting to, using which turbodbc version on which operating system.

MathMagique avatar Apr 10 '18 18:04 MathMagique

First off thanks for your help. You were spot on with your assumption that the environment var for odbc.ini was not set.

I am connecting to a Progress OpenEdge 10.1c database, using turbodbc version 2.5.0 from a Debian 9 64bit machine.

Per your first bullet point I updated my testing program to print the environment variables to the error.log file.

from turbodbc import connect
import os

def application(environ, start_response):
    status = '200 OK'
    output = b'TURBODBC ROCKS!!!'
    #connect_to_db()
    print(os.environ)
    response_headers = [('Content-type', 'text/plain'), ('Content-Length', str(len(output)))]
    start_response(status, response_headers)

    return [output]


def connect_to_db():
    connection = connect(dsn="odbc-dev", uid='root', pwd='password')
    cursor = connection.cursor()

this generated the output

error.log

[wsgi:error] environ({'PATH': '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', 'PWD': '/', 'APACHE_RUN_DIR': '/var/run/apache2', 'APACHE_RUN_USER': 'www-data', 'LANG': 'C', 'APACHE_LOCK_DIR': '/var/lock/apache2', 'APACHE_LOG_DIR': '/var/log/apache2', 'APACHE_PID_FILE': '/var/run/apache2/apache2.pid', 'INVOCATION_ID': '728c2ddf582d4fa4ae9b4db4e22ff61b', 'APACHE_RUN_GROUP': 'www-data', 'JOURNAL_STREAM': '8:6676540'}) 

So then the question became how do we set the env variable. That turned out to be simple enough.

I added the line. export ODBCINI=/etc/odbc.ini to end of /etc/apache2/envvars

restarted Apache and ran my test. That worked so I tried the Django site and that worked too. So now I am golden.

I had asked a question on stackoverflow about this, if you would like to post an answer I will happily mark it as correct. Thanks again for your help.

jayhub42 avatar Apr 11 '18 00:04 jayhub42