0

I am creating a site using OpenShift with Tornado and I need to use persistent storage for images and other files. Documentation says, what persistent storage path stored in $OPENSHIFT_DATA_DIR. Here is app file system overview:

 |-- app-root
 |   -- data # <--$OPENSHIFT_DATA_DIR
 |   -- repo # 
 |      -- wsgi
 |         -- static
 |            -- img
 |         -- templates
 |         -- ...
 |   -- runtime
 |       -- data
 |       -- repo
 |           -- ...deployed application code

And here I have a problem: I tried to serve images and other files from $OPENSHIFT_DATA_DIR, but it's doesn't work, I always get 404 because $OPENSHIFT_DATA_DIR placed outside of wsgi path. I founded what I'm not alone and Django/Java/Flask developers using OpenShift having same problems.

I tried to serve files from /static folder, but that was bad idea: making git push will delete all new files founded here.

I tried to do something like this, but it doesn't work too for me. Maybe I doing something wrong and it need to rewrite something else to use this trick for Tornado?

Can someone help me? Thanks!

EDIT

Tried to use tornado.web.StaticFileHandler, add it to handlers like this:

__UPLOADS__ = str(os.environ.get('OPENSHIFT_DATA_DIR'))+"/uploads" ... 

handlers =     [(r'/',MainHandler,), 
               (r'/media/(.*)', tornado.web.StaticFileHandler, {'path': __UPLOADS__}), 
               ...,]

Find what this way Tornado replace __UPLOADS__+/media/img.jpg to wsgi/static/img.jpg

Here is application file, maybe it can make something clear:

 #!/usr/bin/env python
 import os
 import sys

 if 'OPENSHIFT_REPO_DIR' in os.environ:
      sys.path.append(os.path.join(os.environ['OPENSHIFT_REPO_DIR'], 'wsgi',))
      virtenv = os.environ['OPENSHIFT_PYTHON_DIR'] + '/virtenv/venv'
      os.environ['PYTHON_EGG_CACHE'] = os.path.join(virtenv, 'lib/python3.3/site-packages')
      virtualenv = os.path.join(virtenv, 'bin/activate_this.py')
      try:
           exec(compile(open(virtualenv).read(), virtualenv, 'exec'),dict(__file__ = virtualenv))
           except IOError:
                pass

 import tornado.wsgi
 from openshift import handlers

 if 'OPENSHIFT_REPO_DIR' in os.environ:
      settings = {
           'cookie_secret': 'TOP_SECRET',
           'template_path' : os.path.join(os.environ['OPENSHIFT_REPO_DIR'], 'wsgi/templates'),
           'xsrf_cookies': True,
           'debug': True,
           'login_url': '/login',
      }
 else:
      settings = {
           'cookie_secret': 'TOP_SECRET',
           'template_path' : os.path.join(os.getcwd(), 'wsgi/templates'),
           'xsrf_cookies': True,
           'debug': True,
           'login_url': '/login',
 }

 application = tornado.wsgi.WSGIApplication(handlers, **settings)
Community
  • 1
  • 1
ashchuk
  • 331
  • 5
  • 19
  • If you are using Tornado it implies you have provided an app.py file. This disables the use of Apache/mod_wsgi so the static directory isn't used. You will need to find some code specifically for the TornadoWeb framework that can serve up static files via your Python code. Such as http://stackoverflow.com/questions/10165665/using-tornado-how-do-i-serve-static-files-and-serve-a-favicon-ico-from-a-differ – Graham Dumpleton Mar 23 '16 at 10:22
  • I have edit handlers like this: `__UPLOADS__ = str(os.environ.get('OPENSHIFT_DATA_DIR'))+"/uploads" ... handlers = [(r'/',MainHandler,), (r'/media/(.*)', tornado.web.StaticFileHandler, {'path': __UPLOADS__}), ...` Now tornado redirect it to `/static/2431aa15-61b2-4de6-9d71-6009bbcc4bf3.jpg`, but not `/uploads`. And 404 again – ashchuk Mar 23 '16 at 11:39
  • Did you create the ``uploads`` directory first? – Graham Dumpleton Mar 24 '16 at 20:34
  • Yep, it's placed into `__UPLOADS__` – ashchuk Mar 25 '16 at 11:17
  • So you are saying files are uploaded okay, but your code you are using doesn't find them to download? – Graham Dumpleton Mar 26 '16 at 05:31
  • It's all right with uploading and saving into `__UPLOADS__`. I don't know how to add images from `__UPLOADS__` into my templates. The simplest solution I temporarily made: copy files from `__UPLOADS__` to `wsgi/static`. The second solution, I think: first upload image into `__UPLOADS__` dir, second step - create variable via python that will contain image binary, saved into `__UPLOADS__`, and at last - send this python var to template as argument. The right way - use images from `__UPLOADS__` directly, from path to template, but I do not get it. – ashchuk Mar 27 '16 at 10:03
  • Could you show us your templates? It sounds like you're using `static_url()` there, which returns a path for the default `StaticFileHandler` (and not the custom one you created for the `/media` path). Try constructing the path by hand. – Ben Darnell Mar 31 '16 at 11:47

1 Answers1

-1

You definitely should add media to data directory out of your project root. Basicly you use MEDIA variable to set this. In settings.py:

MEDIA_ROOT = os.environ.get('OPENSHIFT_DATA_DIR', '')
MEDIA_URL = '/media/'

In your model then use:

logo = models.ImageField(upload_to="logo")

If this does not help, may be you can create symlink from static folder to your media root. For example in deploy action hook .openshift/action_hooks/deploy:

#!/bin/bash

source ${OPENSHIFT_HOMEDIR}python/virtenv/bin/activate
export PYTHON_EGG_CACHE=${OPENSHIFT_HOME_DIR}python/virtenv/lib/python-2.7/site-packages

echo "Executing 'python ${OPENSHIFT_REPO_DIR}wsgi/APP_NAME/manage.py migrate --noinput'"
python "$OPENSHIFT_REPO_DIR"wsgi/APP_NAME/manage.py migrate --noinput

echo "Executing 'python ${OPENSHIFT_REPO_DIR}wsgi/APP_NAME/manage.py collectstatic --noinput -v0'"
python "$OPENSHIFT_REPO_DIR"wsgi/APP_NAME/manage.py collectstatic --noinput -v0

if [ ! -d $OPENSHIFT_REPO_DIR/wsgi/static/ ]; then mkdir $OPENSHIFT_REPO_DIR/wsgi/static/; fi
if [ ! -d $OPENSHIFT_DATA_DIR/media ]; then mkdir $OPENSHIFT_DATA_DIR/media; fi
ln -sf $OPENSHIFT_DATA_DIR/media $OPENSHIFT_REPO_DIR/wsgi/static/media

Basicly check logs for any errors, wrong path settings and you will get there eventually. Good luck!

Lucas03
  • 2,267
  • 2
  • 32
  • 60
  • This answer is correct for Django, but not Tornado. I said it in question, what I tried it and it doesn't work – ashchuk Mar 23 '16 at 10:49