This document will illustrate installation of all the dependencies required for setting up the application.
Here we use the setuptools
module from the standard lib, to make a
setup.py
file, which will install all the python library dependencies.
from setuptools import setup
requires = [
'Flask',
'Flask-SQLAlchemy',
'oursql',
'Flask-cors',
'Flask-testing',
'requests',
'pyyaml'
]
setup(
name='feedback',
version='2.0.0',
install_requires=requires
)
This is used to run the service in developer’s environment. Otherwise, mostly the database on production is updated from a dump of previous instance.
from runtime.rest.app import create_app
from runtime.config import flask_app_config as config
from runtime.utils.class_persistence_template import db
from runtime.system.system import System
def populate():
q_type = "radio"
question_cls = System.delegate.entities['question']
question1 = question_cls(name="Did you attempt the experiment?",
question_type=q_type)
question2 = question_cls(name="Did the experiment work?",
question_type=q_type)
question3 = question_cls(name="Did you find any bugs in the experiment?",
question_type=q_type)
question4 = question_cls(name="How much did you know about the experiment before doing it in Virtual Labs?",
question_type=q_type)
question5 = question_cls(name="Is this experiment part of your curriculum?",
question_type=q_type)
question6 = question_cls(name="Did this experiment help you understand the concept better?",
question_type=q_type)
question7 = question_cls(name="Will you recommend this experiment to others?",
question_type=q_type)
q_type = "textarea"
question8 = question_cls(name="Please provide any other feedback about this experiment",
question_type=q_type)
question9 = question_cls(name="feedback_about_experiment",
question_type=q_type)
question10 = question_cls(name="feedback_about_lab",
question_type=q_type)
question11 = question_cls(name="how_useful_are_labs",
question_type=q_type)
question12 = question_cls(name="suggestions_about_experiment",
question_type=q_type)
question13 = question_cls(name="suggestions_about_lab",
question_type=q_type)
question14 = question_cls(name="suggestions_in_general",
question_type=q_type)
q_type = "radio"
question15 = question_cls(name="How much did you know about the lab?",
question_type=q_type)
question16 = question_cls(name="Is this lab part of your curriculum?",
question_type=q_type)
question17 = question_cls(name="Did this lab help you understand the concept better?",
question_type=q_type)
question19 = question_cls(name="Will you recommend this lab to others?",
question_type=q_type)
question20 = question_cls(name="Did you find any bugs in the lab?",
question_type=q_type)
q_type = "textarea"
question21 = question_cls(name="Please provide any other feedback about this lab",
question_type=q_type)
question22 = question_cls(name="Please provide any other feedback about Virtual Labs",
question_type=q_type)
q_type = "radio"
question23 = question_cls(name="Designation",
question_type=q_type)
question24 = question_cls(name="Did you attempt any experiments ?",
question_type=q_type)
question25 = question_cls(name="Please rate your experience",
question_type=q_type)
question1.save()
question2.save()
question3.save()
question4.save()
question5.save()
question6.save()
question7.save()
question8.save()
question9.save()
question10.save()
question11.save()
question12.save()
question13.save()
question14.save()
question15.save()
question16.save()
question17.save()
question19.save()
question20.save()
question21.save()
question22.save()
question23.save()
question24.save()
question25.save()
if __name__ == "__main__":
db.create_all(app=create_app(config))
populate()
import requests
import json
import yaml
data_url = "http://data.vlabs.ac.in/feedback"
data_by_id = data_url+"/"
fb_url = "http://localhost:5000/feedback"
fbs = requests.get(data_url).json()
questions = ['feedback_about_experiment', 'feedback_about_lab',
'how_useful_are_labs', 'suggestions_about_experiment',
'suggestions_about_lab', 'suggestions_in_general']
for index in range(1, len(fbs)):
a_url = data_by_id + str(index)
fb = requests.get(a_url).json()
fb_x = yaml.safe_load(json.dumps(fb))
gateway_ip = fb_x['ip']
user_id = fb_x['user_name']
print index
if fb_x['lab'] is None:
lab_name = "Null"
else:
lab_name = fb_x['lab']['name']
if fb_x['experiment'] is None:
exp_name = "Null"
else:
exp_name = fb_x['experiment']['name']
print exp_name
responses = []
for question in questions:
if fb_x[question] is None or\
fb_x[question] is '':
answer = "Null"
response = {'name': question,
'answers':[answer] }
responses.append(response)
else:
answer = fb_x[question]
response = {'name': question,
'answers':[answer] }
responses.append(response)
version = "virtual-labs-feedback-v1.0"
payload = {'lab_name': lab_name,
'exp_name': exp_name,
'key' : 'defaultkey',
'responses': responses,
'gateway_ip': gateway_ip,
'user_id': user_id,
'version': version
}
print payload
headers = {'Content-Type': 'application/json'}
response = requests.post(fb_url, data=json.dumps(payload),
headers=headers)
print response.status_code
Install pre-requsite dependencies: python-dev, libmysqld-dev, python-setuptools, apache2, libapache2-mod-wsgi
echo "Updating package cache.."
apt-get -y update
if [ $? -ne 0 ]; then
echo "Updating package cache failed!"
exit 1;
fi
echo "Installing pre-requisite dependencies.."
apt-get install -y python-dev libmysqld-dev python-setuptools apache2 libapache2-mod-wsgi python-mysqldb
if [ $? -ne 0 ]; then
echo "FATAL: Installing os-related packages failed!"
exit 1;
fi
WSGI mode is needed for one web server to talk to another. In our case, Flask and Apache2 need to communicate. To make this happen, wsgi is enabled.
echo "Enabling the mod WSGI on apache"
a2enmod wsgi
if [ $? -ne 0 ]; then
echo "FATAL: Unable to enable mod wsgi!"
exit 1;
fi
Install mysql db. The idea to generate a random password
while installaing the mysql. This same password that is
stored in a file is used by the application to connect to
the database. Currently, this is not implemented,
instead the password is set to root
. The database can
only be installed by a super user.
DB_PASS_FILE="db_pass.txt"
if [ `id -u` -ne 0 ]; then
echo "You have to execute this script as super user!"
exit 1;
fi
echo "Installing MySQL database.."
DBPASS="root"
# Install MySQL Server in a Non-Interactive mode.
echo "mysql-server mysql-server/root_password password $DBPASS" | debconf-set-selections
echo "mysql-server mysql-server/root_password_again password $DBPASS" | debconf-set-selections
apt-get install -y mysql-server
if [ $? -ne 0 ]; then
echo "FATAL: MySQL installation failed!"
exit 1;
fi
echo $DBPASS > $DB_PASS_FILE
pip is python package insaller.
echo "Installing PIP"
apt-get remove -y python-pip
apt-get purge python-pip
mkdir -p build/pip
cd build/pip
wget https://pypi.python.org/packages/11/b6/abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/pip-9.0.1.tar.gz
tar xvf pip-9.0.1.tar.gz
cd pip-9.0.1
python setup.py install
if [ $? -ne 0 ]; then
echo "FATAL: PIP installation failed!"
exit 1;
fi
The flask application needs the following python
packages. oursql
package is installed from sources.
Others are installed using pip package manager.
echo "Installing dependencies.."
mkdir -p build/oursql
cd build/oursql
wget https://pypi.python.org/packages/8c/88/9f53a314a2af6f56c0a1249c5673ee384b85dc791bac5c1228772ced3502/oursql-0.9.3.2.tar.gz#md5=ade5959a6571b1626966d47f3ab2d315
tar xvf oursql-0.9.3.2.tar.gz
cd oursql-0.9.3.2
python setup.py install
pip install Flask Flask-SQLAlchemy Flask-cors Flask-testing oursql requests pyyaml
if [ $? -ne 0 ]; then
echo "FATAL: Python package installation failed!"
exit 1;
fi
#!/bin/bash
<<os-pack>>
<<enable-mod-wsgi>>
<<install-mysql>>
<<install-pip>>
<<py-pack>>
exit 0
Provide one end of the flask application to the apache server for it to route the traffic to flask application.
import sys, os
BASE_DIR = BASE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)))
#sys.path.insert(0, BASE_DIR)
sys.path.insert(0, "/var/www")
from runtime.rest.app import create_app
from runtime.config import flask_app_config as config
application = create_app(config)
Configuring the application involves:
- set up the configuration parameters of the
application. These include:
- Database parameters
- database userId, Password, dbname, dbhost
- Cross origin pameters
- Whitelist IPs, allowed origins. These parameters are not set currently.
if [ `id -u` -ne 0 ]; then
echo "You have to execute this script as super user!"
exit 1;
fi
ABS_PATH_DS=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
update_app_config () {
CONFIG_FILE="../runtime/config/flask_app_config.py"
DB_USER="root"
DB_PASS=$(cat db_pass.txt)
DB_NAME="feedback"
DB_SERVER="localhost"
# the list of white-listed IPs for POST/PUT requests to data service
WHITELIST_IPS="['127.0.0.1']"
# the list of allowed domains for CORS
ALLOWED_ORIGINS="['*']"
echo "Updating config.py.."
# Update parts of the DB URI
sed -i "s/<userid>/$DB_USER/" $ABS_PATH_DS/$CONFIG_FILE
sed -i "s/<password>/$DB_PASS/" $ABS_PATH_DS/$CONFIG_FILE
sed -i "s/<servername>/$DB_SERVER/" $ABS_PATH_DS/$CONFIG_FILE
sed -i "s/<db_name>/$DB_NAME/" $ABS_PATH_DS/$CONFIG_FILE
# update SQLALCHEMY_ECHO
sed -i "s/^SQLALCHEMY_ECHO.*$/SQLALCHEMY_ECHO = False/" $ABS_PATH_DS/$CONFIG_FILE
# update WHITELIST_IPS
#sed -i "s/^WHITELIST_IPS.*$/WHITELIST_IPS = $WHITELIST_IPS/" $CONFIG_FILE
# update ALLOWED_ORIGINS
#sed -i "s/^ALLOWED_ORIGINS.*$/ALLOWED_ORIGINS = $ALLOWED_ORIGINS/" $CONFIG_FILE
# NOTE: this is hardcoded now..somehow the log file when dynamically created
# is owned by root. then the app fails to run.. hence the following is
# necessary
}
The wsgi conduit is configured with the apache. This is
necessary since apache web server has to forward the
traffic on the /
to the feedback application that uses flask
web server.
update_apache_config() {
PROC_NAME="feedback"
WSGI_SCRIPT="feedback.wsgi"
APACHE_VHOST_FILE="/etc/apache2/sites-available/000-default.conf"
sed -i "/<\/VirtualHost>/i \
WSGIScriptAlias / $ABS_PATH_DS/$WSGI_SCRIPT
" $APACHE_VHOST_FILE
}
An empty database is created for the application to use.
setup_db() {
echo "Creating database: $DB_NAME"
mysql -u $DB_USER -p$DB_PASS -Bse "create database $DB_NAME;"
if [ $? -ne 0 ]; then
echo "Failed to create database $DB_NAME"
exit 1;
fi
}
#!/bin/bash
<<configure-app>>
<<configure-wserver>>
<<create-db>>
update_app_config
if [ $? -ne 0 ]; then
echo "FATAL: Failed to update application flask_app_config.py"
exit 1;
fi
update_apache_config
if [ $? -ne 0 ]; then
echo "FATAL: Failed to update apache config"
exit 1;
fi
service apache2 restart
export PYTHONPATH="/var/www"
if [ $? -ne 0 ]; then
echo "FATAL: Failed to restart apache2 webserver"
exit 1;
fi
setup_db
if [ $? -ne 0 ]; then
echo "FATAL: Failed to create database"
exit 1;
fi
exit 0
print "deployment package"