Target WSGI script '/opt/graphite/conf/graphite.wsgi' cannot be loaded as Python module

Asked by jgoldsmithuo on 2017-12-30

I have an installation in /opt/graphite, followed the instructions on https://graphite.readthedocs.io/en/latest/install-pip.html, so used pip, already had httpd installed and the mod_wsgi.so is working and loading fine. Instructions are terrible to be honest. I had to look at these instruction and many searches. According it the instructions for pip if you are not doing a cutoms location install, you run the three pip commands and it's suppose to magically work! well it doesn't. I sometimes wonder if the developers of the product actually want people to seriously use it, there's about there's so many pieces version of dependancies, it really needs a boiler plate/cook book style install instructions. It appears to be easier for Ubuntu, but a nightmare for centos/redhat OS's. Getting a yum repo together would have been nice. The files were non modified, except for the secret in local.settings.py. Any other files are on these git repos, this is being installed on centos7

export PYTHONPATH="/opt/graphite/lib/:/opt/graphite/webapp/"
pip install --no-binary=:all: https://github.com/graphite-project/whisper/tarball/master
pip install --no-binary=:all: https://github.com/graphite-project/carbon/tarball/master
pip install --no-binary=:all: https://github.com/graphite-project/graphite-web/tarball/master

This is 3days of debugging, before sending this, sorry if I sound frustrated, I am annoyed there's no proper documentation. if any one has a clue please help.

Question information

Language:
English Edit question
Status:
Solved
For:
Graphite Edit question
Assignee:
No assignee Edit question
Solved by:
jgoldsmithuo
Solved:
2018-01-15
Last query:
2018-01-15
Last reply:
2017-12-30
Denis Zhdanov (deniszhdanov) said : #1

Hello,

Sorry for a frustrating experience, but yes - python based software is not easiest to install, especially on centos/rhel, because of outdated dependencies. That's one of the reasons why we're not producing deb/rpms - on current distributions, it will require so many efforts to maintain all dependencies - it will be around 10 custom packages.
We also have Synthesize project (Graphite on vagrant) and Docker image - but both are based on Ubuntu and will work – but not will help you to install Graphite on redhat-based distro.
Let me test it in VM. Do you have centos 7, I hope?

Denis Zhdanov (deniszhdanov) said : #2

BTW, the error above is not Graphite specific. It looks like mismatched python version in system and wsgi module. Did you use 3rd party repos?
Try this solution also - https://stackoverflow.com/a/10313354/1139639

Piotr Popieluch (piotr1212) said : #3

Sorry to hear.
As Denis said, Python software can be hard to install, especially software which uses large frameworks like Django. Resources for improving Graphite are limited and priorities are usually not in making installation easier and improving docs. eg. My customers pay me for making Graphite run better on their systems, fixing bugs which affect them, developing custom features but not for writing documentation for others. If you have any suggestions in improving please let it know. I'm sure Denis is quite happy to merge pull requests on the docs.

Graphite 0.9.16 is available in the EPEL repository. Installation on CentOS should be not much more than:
yum install -y epel-release &&
yum install -y graphite-web python-carbon
then run the commands from /usr/share/doc/graphite-web*/fedora.readme.

Running graphite 1.x on CentOS/RHEL is a bit harder due to RHEL's conservative update policies. But if you want to run latest versions you probably wouldn't be using RHEL anyway.

My personal experience with the docs is quite good actually. Make sure you read the docs for the version of graphite you are installing.

> According it the instructions for pip if you are not doing a cutoms location install, you run the three pip commands and it's suppose to magically work! well it doesn't

I think you missed the "initial configuration" part. The three pip commands are enough for installation, but not for actually starting/running it.

Denis Zhdanov (deniszhdanov) said : #4

Yes, agreed with Piotr here - maybe 0.9.16 is better to use with CentOS/Rhel now.
And maybe we should amend documentation, mention e.g. EPEL and installation of Development Tools. And agreed with TS - documentation can be better, it's currently not very simple and require some external knowlege, e.g. how to setup and run Django apps.
But yes - documentation is on Github, PRs are very welcoming! If someone want to include any distro specific installation - it's possible, of course.

Anyway, I manage to run graphite-web with fresh CentOS with something like

```
yum install epel-release
yum groupinstall 'Development Tools'
yum install python-pip httpd mod_wsgi
yum install python-devel cairo-devel libffi-devel

disable SELINUX, reboot

export PYTHONPATH="/opt/graphite/lib/:/opt/graphite/webapp/"
pip install --no-binary=:all: https://github.com/graphite-project/whisper/tarball/master
pip install --no-binary=:all: https://github.com/graphite-project/carbon/tarball/master
pip install --no-binary=:all: https://github.com/graphite-project/graphite-web/tarball/master

chown -R apache:apache /opt/graphite/storage
cp /opt/graphite/webapp/graphite/local_settings.py.example /opt/graphite/webapp/graphite/local_settings.py

copying https://github.com/graphite-project/graphite-web/blob/master/examples/example-graphite-vhost.conf to /etc/httpd/conf.d/

PYTHONPATH=/opt/graphite/webapp django-admin.py migrate \
      --noinput --settings=graphite.settings --run-syncdb

PYTHONPATH=/opt/graphite/webapp django-admin.py collect-static \
      --noinput --settings=graphite.settings

service httpd restart
```

So, I think your problem lies somewhere in different versions of python/wsgi. I saw that before e.g. when wsgi script was running on python 2.7 and apache wsgi was built against python 2.6

jgoldsmithuo (zoureclipse) said : #5

Hi @Denis @Piotr, thank you for the responses to this, much appreciated. I take onboard both your comments and agree. I'm from a sysadmin background, more than dev, and been through so many installs over time as I'm sure we all have. @Denis, yes you're right some additional info on Centos/Redhat type installs would definitely benefit many admin guys. They are the type of guys who normally get asked to setup PoC environments to demo, and my experience is many companies as far as linux platforms go, mainly use Centos or Redhat. Ubuntu is what I would use at home to try our stuff. I understand your views on rpm/repos for centos/redhat, I agree with you it definitely is a minefield.

The good news it's working now, the bad news is I don't really know what fixed it. @Denis I followed yor series of steps and it was still coming up with the same error, but you're both right it's some kind of mismatch in versions, and also both right again, this is where the bulk of many install issues arise. One thing I did not do from your steps the first time around is this command:

PYTHONPATH=/opt/graphite/webapp django-admin.py collect-static \ (no minus in collectstatic)
      --noinput --settings=graphite.settings

I rebooted.

I remove the mod_wsgi and installed it again, yum erase, then install, I also installed a pip install mod_wsgi

I tried the apachectl start, it gave me this error: [Sun Dec 31 08:14:31.748199 2017] [so:warn] [pid 5801] AH01574: module wsgi_module is already loaded, skipping

so I commented out this in the vhosts file.
#<IfModule !wsgi_module.c>
# LoadModule wsgi_module modules/mod_wsgi.so
#</IfModule>

I also had to change the vhosts file to allow /opt/graphite/ permissions from that level, otherwise it was coming up with client permission for various files.
AH01630: client denied by server configuration: /opt/graphite/static/js/composer_widgets.js, referer: http://x/composer? this was even tho all files under /opt/graphite were chown -R apache:apache, the default setting in vhosts example file /opt/graphite/conf/ does not seem to be enough permissions

@Piotr, I have not used readthedocs format docs many times, from the main graphiteapp site there's a install link on the top right, if you click that I assumed that was generic install procedure for all versions, then right at the bottom, I saw the little drop down, where you can pick your version. I'll know for next time. I think also your 0.9.16 would have worked fine, for some reason it's in built thing that I must get on the latest version, which is why I went down the pip install route.

@Piotr, @Denis, thank you for the assistance. When I build this out for prod, I will definitely look at making any needed mods via PR's.

Piotr Popieluch (piotr1212) said : #6

I really can't recommend installing with pip (without virtualenv). The issue is that pip installs libraries in the same paths as yum/dnf. There is no support for installing multiple versions of a library at the same time (neither in yum or pip), which means pip can update installed system libraries. Obviously this can make a mess of your system Python and mess up your rpmdb (other versions are installed than yum thinks). Many system tools on Fedora/RHEL are Python based, for example yum/dnf itself. Using pip to install libraries can potentially break your system. Also when you run a "yum update/install someotherpythonapp" later, this can break you Graphite installation as yum might downgrade your Python libraries.

There have been some attempts to split into a system python and a user python in separate directories, a bit comparable to how Perl does this with system_perl, site_pers, user_perl. But afaik these attempts have all failed (don't know the specifics).

I'm a Fedora/RHEL guy, no clue how other distros handle this but I guess they also use the Ostrich algorithm :)

Anyway, if you want to run latest Graphite on RHEL based systems I would recommend to install it in virtualenv or Docker. This installs it completely isolated so it cannot mess up your system.

Denis Zhdanov (deniszhdanov) said : #7

Hello @jgoldsmithuo,

Yes, collectstatic should be without '-'.
I also faced `AH01630: client denied by server configuration` but I thought it was about my system - but looks like it's some RH-specific thing.
You need to add something like

        <Directory /opt/graphite/static/>
                <IfVersion < 2.4>
                        Order allow,deny
                        Allow from all
                </IfVersion>
                <IfVersion >= 2.4>
                        Require all granted
                </IfVersion>
        </Directory>

to apache config. You can include that in your PR it will not hurt for Ubuntu too.

+1 for @Piotr advice about virtualenv also.
Sysadmin here BTW. :hi:
And we're using Ubuntu at prod, quite successfully. RHEL is too conservative for us.

jgoldsmithuo (zoureclipse) said : #8

Hi @Piotr & @Denis, Appreciate your help with. I will take note for a production installation. Good to get info from fellow sysadmins, the company has gone with RHEL/Centos mainly and cloud space also RHEL. I'd like to use Ubuntu for easy of many things, but can't at work. Where I'm at now. I have working graphite install, but I'm trying to configure a collector, having an issue I'm going to start a new thread on this. Thanks.

Aurimas Plunge (aurimas88) said : #9

Hi,
I am complacently reen to graphite and django and I am also trying to install POC environment wih newest graphite version on RHEL7 and to add to the challenge my server is in out of band network so no Internet connection and no public repositories only very limited local repos.

But I managed to collect all packages with dependencies ( I think). It seems that I managed to launch graphite successfully but when trying to access it I get an same error you got:

mod_wsgi (pid=8031): Target WSGI script '/opt/graphite/conf/graphite.wsgi' cannot be loaded as Python module.
mod_wsgi (pid=8031): Exception occurred processing WSGI script '/opt/graphite/conf/graphite.wsgi'.
Traceback (most recent call last):
  File "/opt/graphite/conf/graphite.wsgi", line 4, in <module>
    from graphite.wsgi import application
  File "/opt/graphite/webapp/graphite/wsgi.py", line 11, in <module>
    from django.conf import settings
ImportError: No module named django.conf

@jgoldsmithuo, as I understand you have managed to solve your issue but from your post I am not sure how you done it. Could you share a bit more detailed steps? Or perhaps from my log someone can see some other problem?

Denis Zhdanov (deniszhdanov) said : #10

@aurimas88: you need to install django 1.8 or newer, IIRC it's not included as package to RHEL7. Even EPEL repo contains 1.6.x, which is too old for latest Graphite. Usually, people installing it to RHEL using `pip` but that's will not work w/o Internet connection.
You can also build all required packages using `fpm` tool (https://fpm.readthedocs.io/en/latest/source/python.html) on RHEL server which have internet connection, but you need to resolve all dependencies manually, which require some work.

Aurimas Plunge (aurimas88) said : #11

Hi Denis,
I downloaded all the newest packages. Here is the list I used:
argparse-1.4.0.tar.gz
Django-1.11.9.tar.gz
django-tagging-0.4.6.tar.gz
pip-9.0.1.tar.gz
pyparsing-2.2.0.tar.gz
wheel-0.30.0.tar.gz
zope.interface-4.4.3.tar.gz
incremental-17.5.0.tar.gz
six-1.11.0.tar.gz
idna-2.5.tar.gz
Automat-0.6.0.tar.gz
docutils-0.14.tar.gz
mistune-0.8.2.tar.gz
m2r-0.1.9.tar.gz
setuptools_scm-1.15.6.tar.gz
attrs-17.4.0.tar.gz
Automat-0.6.0.tar.gz
constantly-15.1.0.tar.gz
setuptools-38.4.0.zip
hyperlink-master.zip
Twisted-17.9.0.tar.bz2
urllib3-1.22.tar.gz

And by IIRC you mean irc-16.2?

Denis Zhdanov (deniszhdanov) said : #12

BY IIRC I mean "If I Remember Correctly". How do you install packages above?

Aurimas Plunge (aurimas88) said : #13

I installed them in two ways:
pip install -e Django-1.11.9/
or
python setup.py install --record INSTALLATION-FILES.txt

Aurimas Plunge (aurimas88) said : #14

And to add to the picture apache, mod_wsgi and python versions used from httpd log:
[mpm_prefork:notice] [pid 3106] AH00163: Apache/2.4.6 (Red Hat Enterprise Linux) mod_wsgi/3.4 Python/2.7.5 configured -- resuming normal operations

Denis Zhdanov (deniszhdanov) said : #15

Sorry for asking stupid questions, just want to check most obvious reasons. If module is installed but not visible for mod_uwsgi then try to correct WSGIPythonPath variable. Sorry, but I do not know why default setting is not working for you and it's a not really directly related with Graphite per se...

Aurimas Plunge (aurimas88) said : #16

With my limited knowledge there is no stupid questions :)

Where do I set this WSGIPythonPath variable?

I think its definitely issue with paths, but no idea there

For example then I do this I can successfully load django.conf :

PYTHONPATH=/opt/graphite/webapp django-admin.py shell --settings=graphite.settings

Python 2.7.5 (default, May 3 2017, 07:55:04)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-14)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.conf import settings
>>>

Aurimas Plunge (aurimas88) said : #18

No I didn't follow this doc, because these files was created automatically and seemed to be OK, exept for directory part which I needed to expand because static files was not allowed.

##### cat /opt/graphite/conf/graphite.wsgi

import sys
sys.path.append('/opt/graphite/webapp')

from graphite.wsgi import application

======================================================================================================================

##### cat /etc/httpd/conf.d/graphite.conf

# Enable virtualhosts, perhaps by adding this to your server's config somewhere,
# probably the main httpd.conf
# NameVirtualHost *:80

# This line also needs to be in your server's config.
# LoadModule wsgi_module modules/mod_wsgi.so

# You need to manually edit this file to fit your needs.
# This configuration assumes the default installation prefix
# of /opt/graphite/, if you installed graphite somewhere else
# you will need to change all the occurrences of /opt/graphite/
# in this file to your chosen install location.

#<IfModule !wsgi_module.c>
# LoadModule wsgi_module modules/mod_wsgi.so
#</IfModule>

# XXX You need to set this up!
# Read http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGISocketPrefix
# For example, create a directory /var/run/wsgi and use that.
WSGISocketPrefix run/wsgi

<VirtualHost *:80>
        ServerName graphite
        DocumentRoot "/opt/graphite/webapp"
        ErrorLog /opt/graphite/storage/log/webapp/error.log
        CustomLog /opt/graphite/storage/log/webapp/access.log common

        # I've found that an equal number of processes & threads tends
        # to show the best performance for Graphite (ymmv).
        WSGIDaemonProcess graphite processes=5 threads=5 display-name='%{GROUP}' inactivity-timeout=120
        WSGIProcessGroup graphite
        WSGIApplicationGroup %{GLOBAL}
        WSGIImportScript /opt/graphite/conf/graphite.wsgi process-group=graphite application-group=%{GLOBAL}

        # XXX You will need to create this file! There is a graphite.wsgi.example
        # file in this directory that you can safely use, just copy it to graphite.wgsi
        WSGIScriptAlias / /opt/graphite/conf/graphite.wsgi

        # XXX To serve static files, either:
        # * Install the whitenoise Python package (pip install whitenoise)
        # * Collect static files in a directory by running:
        # django-admin.py collectstatic --noinput --settings=graphite.settings
        # And set an alias to serve static files with Apache:
        Alias /static/ /opt/graphite/static/

        ########################
        # URL-prefixed install #
        ########################
        # If using URL_PREFIX in local_settings for URL-prefixed install (that is not located at "/"))
        # your WSGIScriptAlias line should look like the following (e.g. URL_PREFX="/graphite"

        # WSGIScriptAlias /graphite /srv/graphite-web/conf/graphite.wsgi/graphite
        # Alias /graphite/static /opt/graphite/webapp/content
        # <Location "/graphite/static/">
        # SetHandler None
        # </Location>

        # XXX In order for the django admin site media to work you
        # must change @DJANGO_ROOT@ to be the path to your django
        # installation, which is probably something like:
        # /usr/lib/python2.6/site-packages/django
        Alias /media/ "@DJANGO_ROOT@/contrib/admin/media/"

        # The graphite.wsgi file has to be accessible by apache. It won't
        # be visible to clients because of the DocumentRoot though.
        <Directory /opt/graphite/>
                <IfVersion < 2.4>
                        Order deny,allow
                        Allow from all
                </IfVersion>
                <IfVersion >= 2.4>
                        Require all granted
                </IfVersion>
        </Directory>

</VirtualHost>

Steven Pine (spine) said : #19

I wanted to respond and say that the current documentation should be much more forceful to explain that essentially the community and developers are not really supporting centos 7, or at least the documentation you have for installing your software is inadequate, untested, and doesn't work -- it would of saved at least me several hours instead of finding this comment log well after the fact.

If you're going to have installation documentation, *PLEASE* be more forceful and say, don;t use centos 7 because we don't actually test our documentation for this build, or if you're using centos 7, you must use our docker container configuration (which again i doubt anyone has tested recently).

Thanks for hearing me.

Piotr Popieluch (piotr1212) said : #20

But the documentation does work for RHEL7 like systems.
If you find problems with the documentation, please create a PR, docs are found here: https://github.com/graphite-project/graphite-web/tree/master/docs