8

Objective: Connect to a MS SQL Server in AWS Lambda

Error From AWS Lambda:

START RequestId: 37951004-404b-11e7-98fd-5177b3a46ec6 Version: $LATEST
module initialization error: ('01000', "[01000] [unixODBC][Driver Manager]Can't open lib 'ODBC Driver 13 for SQL Server' : file not found (0) (SQLDriverConnect)")
END RequestId: 37951004-404b-11e7-98fd-5177b3a46ec6

My Approach:

refering to Tesseract OCR on AWS Lambda via virtualenv

  1. Installed unixODBC and ODBC Driver 13 for SQL Server in an aws ec2 instance
  2. Created a deployment package (i.e. pip install -t pyodbc /home/ec2-user/lambda and copied the relevant files to zip root)
  3. mkdir lib and copied all shared libraries by looking up ldd pyodbc.so * ldd libmsodbcsql-13.0.so.1.0
  4. change LD_LIBRARY_PATH to lib in lambda.py and upload the zip to Lambda

Zip File Structure:

.
+-- lambda.py
+-- pyodbc.so
+-- pyodbc-4.0.16-py2.7.egg-info
+-- lib
|   +-- libodbc*.so etc.

My Guess:

From the response it looks like everything is running OK except for the unixODBC manager cannot find the driver on AWS Lambda Instance

Question:

How do I bundle the driver with my package for AWS Lambda to use? Or Is there a way to tell ODBC driver manager to look for libmsodbcsql-13.0.so.1.0?

I have tried offline installation of unixODBC and set ./configure --prefix=/home/ec2-user/lambda --libdir=.. and manually changing odbcinst.ini but no hope.


(sorry I am not so familiar with anything outside python environment so I am not sure about all the shared libraries stuff and couldn't solve my problem by just googling for a few days)

nujhong
  • 81
  • 2
  • 5
  • Did you ever figure this out? – Nonnib Oct 22 '17 at 20:20
  • [This might help](https://gist.github.com/diriver63/b72a954fa0da4851d89e5086aa13c6e8#file-pyodbc-unixodbc-lambda-layer-L40), although I still get errors with it, but I think it gets us closer to a solution. – falsePockets Jan 12 '21 at 01:36

2 Answers2

1

Is there a way to tell ODBC driver manager to look for libmsodbcsql-13.0.so.1.0?

You can run odbcinst -j and check where the driver ini file is located (odbcinst.ini) so you can set the path there. Otherwise create the new one at ~/.odbcinst.ini which can define the path to SQL ODBC driver library.

Example INI config file:

[ODBC Driver 13 for SQL Server]
Description=Microsoft ODBC Driver 13 for SQL Server
Driver=/path/to/libmsodbcsql-13.0.so.1.0

Here is the example command to create the config file (~/.odbcinst.ini):

printf "[ODBC Driver 13 for SQL Server]\nDescription=Microsoft ODBC Driver 13 for SQL Server\nDriver=/path/to/libmsodbcsql-13.0.so.1.0\n" >> ~/.odbcinst.ini

Anaconda

If the driver file exists, but still you got file not found, run: conda update libgcc.

See: PyODBC : can't open the driver even if it exists.

kenorb
  • 155,785
  • 88
  • 678
  • 743
  • Note that the question was about AWS Lambda. In Lambda you upload a zip at build time which gets extracted to `/opt`. At run time, you get python, not bash, and you can only modify `/tmp`. e.g. I don't think it's possible to modify `~` or `/etc` inside a Lambda function. – falsePockets Jan 12 '21 at 00:04
0

Compilation Approach

By default unixODBC looks for odbc.ini inside /etc/. In a Lambda function, you can't modify that. (Well, perhaps you can from the python script at runtime, but that's not ideal.)

If you're compiling unixODBC yourself, you can try adding an extra argument to ./configure, --sysconfdir, as well as --prefix. See here for more detail.

Personally I was putting odbc inside a lambda layer, which goes to /opt. I think the lambda itself is unzipped to /var/task. This means that when you compile on EC2, you should point to /var/task. (You might have to manually create this directory if it doesn't yet exist.)

./configure --sysconfdir=/var/task --prefix=/var/task

Simple Yum Approach

Personally I found that it's easier to just yum install unixODBC, and then /usr/lib64/libodbc* to /lib/ inside the zip, and /opt to / inside the zip, and /usr/bin/odbc* to /bin/ inside the zip. Then the only extra trick was to set environment variables in the lambda.

ODBCINI=/var/task/odbc.ini
ODBCSYSINI=/var/task/
falsePockets
  • 3,826
  • 4
  • 18
  • 37