Wednesday, July 13, 2016

Exposing a Python App via Django using Vagrant

Introduction


I have a python application.  It's inner workings are complex, but the I/O is simple.  Text input (application/text) comes in, and a JSON structure (application/json) comes out.

I want to expose the python application via a REST interface.  Django is a popular web framework for Python that requires minimal "plumbing" and requires minimal up-front decisions about application infrastructure.  In other words, ideal for my needs.

At the time of this article, I am using OS X 10.11.5.

Initialize Directory


Create a directory (name is not relevant).  Place the Vagrantfile (below) into this directory.  Create a sub-directory called "scripts" and place the following shell scrips (setup_python.sh, git repo cloning) into this folder.

Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.network "public_network", bridge: [ 'en0', 'en1', 'en2', 'bridge0' ]
  
  config.vm.synced_folder("scripts", "/home/vagrant/scripts")

  config.vm.provider "virtualbox" do |v|
    v.gui = false
    v.memory = "4096"
    v.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
    v.customize ["modifyvm", :id, "--natdnsproxy1", "on"]
  end

  config.vm.define "cnc" do |cnc|
    cnc.vm.hostname = "cnc"
    cnc.vm.network "private_network", ip: "192.168.36.99"
  end 
 
  config.vm.provision "shell", path: "scripts/init_env.sh"
 
end
Note: you may wish to change the elements highlighted in red bold. The italicized provisioning line is optional; the scripts shown below can be placed here.

setup_python.sh
sudo apt-get update -y
sudo apt-get install -y build-essential git libopenblas-dev python-dev python-scipy python-pip
sudo apt-get update -y

Run these commands to drop into an SSH session:
$ vagrant up 
$ vagrant ssh

Once in the SSH session, run the shell scripts from the "scripts" directory. I haven't included the code to clone my git repos.  Assumption is that this also happens at this point and is scripted; the installation works and is tested.

One of my projects contains a requirements.txt file.  The contents list "Django".

The file is installed using
$ pip install -r requirements.txt

This will install the latest version of Django.

I was using version 1.10b at the time of this article.
vagrant@cnc:~$ python -m django --version
1.10b1


Do not proceed any further if Django is not installed.

Also, type this command to ensure django is set correctly on the path:
~/workspaces/public/vagrant/cnc_tst_1 $ django-admin --help

Type 'django-admin help <subcommand>' for help on a specific subcommand.

Available subcommands:

[django]
    check
    compilemessages
    createcachetable
    dbshell
    diffsettings
    dumpdata
    flush
    inspectdb
    loaddata
    makemessages
    makemigrations
    migrate
    runserver
    sendtestemail
    shell
    showmigrations
    sqlflush
    sqlmigrate
    sqlsequencereset
    squashmigrations
    startapp
    startproject
    test
    testserver
Note that only Django core commands are listed as settings are not properly configured (error: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.).
~/workspaces/public/vagrant/cnc_tst_1 $ 
If you don't see a list of available subcommands, something is wrong.

Django Setup

Once in the VM, run this command
$ django-admin startproject mysite
$ cd mysite
$ python manage.py runserver 0.0.0.0:8000

Outside the VM, on your host machine, you should be able to view the default Django app here:
http://192.168.36.99:8000/
The default page looks something like this:
Passing in 0.0.0.0:8000 as a parameter to the runserver will cause Django to listen on all public IPs.  This makes the web server accessible from other computers on our network.

Wiring in the Existing App

In Django parlance, an app is a Web application that does something.  A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.

References

  1. [AirPair] Django vs Flask vs Pyramid
    1. Django's "batteries included" approach makes it easy for developers who know Python already to dive in to web applications quickly without needing to make a lot of decisions about their application's infrastructure ahead of time. 
    2. Django has for templating, forms, routing, authentication, basic database administration, and more built in. 
    3. In contrast, Pyramid includes routing and authentication, but templating and database administration require external libraries.
  2. [Official] Writing your first Django app

Troubleshooting

  1. Warning: Remote connection disconnect. Retrying... 
    1. Solution 1: Patience, grasshopper. 
      The session shown here took 10 minutes:
      ~/workspaces/public/vagrant/cnc_tst_1 $ vagrant halt && vagrant up && vagrant ssh
      ==> cnc: Attempting graceful shutdown of VM...
      Bringing machine 'cnc' up with 'virtualbox' provider...
      ==> cnc: Checking if box 'ubuntu/trusty64' is up to date...
      ==> cnc: A newer version of the box 'ubuntu/trusty64' is available! You currently
      ==> cnc: have version '20160323.0.0'. The latest is version '20160708.1.0'. Run
      ==> cnc: `vagrant box update` to update.
      ==> cnc: Clearing any previously set forwarded ports...
      ==> cnc: Clearing any previously set network interfaces...
      ==> cnc: Preparing network interfaces based on configuration...
          cnc: Adapter 1: nat
          cnc: Adapter 2: bridged
          cnc: Adapter 3: hostonly
      ==> cnc: Forwarding ports...
          cnc: 8000 (guest) => 8000 (host) (adapter 1)
          cnc: 22 (guest) => 2222 (host) (adapter 1)
      ==> cnc: Running 'pre-boot' VM customizations...
      ==> cnc: Booting VM...
      ==> cnc: Waiting for machine to boot. This may take a few minutes...
          cnc: SSH address: 127.0.0.1:2222
          cnc: SSH username: vagrant
          cnc: SSH auth method: private key
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
          cnc: Warning: Remote connection disconnect. Retrying...
      ==> cnc: Machine booted and ready!
      ==> cnc: Checking for guest additions in VM...
          cnc: The guest additions on this VM do not match the installed version of
          cnc: VirtualBox! In most cases this is fine, but in rare cases it can
          cnc: prevent things such as shared folders from working properly. If you see
          cnc: shared folder errors, please make sure the guest additions within the
          cnc: virtual machine match the version of VirtualBox you have installed on
          cnc: your host and reload your VM.
          cnc: 
          cnc: Guest Additions Version: 4.3.36
          cnc: VirtualBox Version: 5.0
      ==> cnc: Setting hostname...
      ==> cnc: Configuring and enabling network interfaces...
      ==> cnc: Mounting shared folders...
          cnc: /vagrant => /Users/craigtrim/workspaces/public/vagrant/cnc_tst_1
          cnc: /home/vagrant/scripts => /Users/craigtrim/workspaces/public/vagrant/cnc_tst_1/scripts
      ==> cnc: Machine already provisioned. Run `vagrant provision` or use the `--provision`
      ==> cnc: flag to force provisioning. Provisioners marked to run always will still run.
      Welcome to Ubuntu 14.04.4 LTS (GNU/Linux 3.13.0-83-generic x86_64)
      
       * Documentation:  https://help.ubuntu.com/
      
        System information as of Wed Jul 13 19:24:50 UTC 2016
      
        System load:  0.0               Processes:           86
        Usage of /:   4.6% of 39.34GB   Users logged in:     0
        Memory usage: 2%                IP address for eth0: 10.0.2.15
        Swap usage:   0%                IP address for eth2: 192.168.36.99
      
        Graph this data and manage this system at:
          https://landscape.canonical.com/
      
        Get cloud support with Ubuntu Advantage Cloud Guest:
          http://www.ubuntu.com/business/services/cloud
      
      
      Last login: Wed Jul 13 19:10:40 2016 from 10.0.2.2
      vagrant@cnc:~$ 
      
    2. Solution 2: If the Virtualbox was not shut down properly, vagrant destroy may be the most effective answer.  This will remove all the files and require going through the setup again.

2 comments:


  1. nice post! Thanks for delivering a good stuff related to DevOps, Explination is good, nice Article
    anyone want to learn advance devops tools or devops online training
    DevOps Online Training
    DevOps Online Training hyderabad

    ReplyDelete