From a3b34632bc535328ce7ed479c8e89eaf82ac9cf6 Mon Sep 17 00:00:00 2001 From: Maxim Kulkin Date: Wed, 25 Sep 2013 11:51:56 +0400 Subject: [PATCH] Added webui and celery background jobs --- Procfile | 4 ++ Vagrantfile | 15 ++++++ ostack_validator/celery.py | 22 ++++++++ .../templates/validation_form.html | 13 +++++ ostack_validator/webui.py | 53 +++++++++++++++++++ requirements.txt | 8 +++ .../openstack-validator/recipes/default.rb | 8 +++ 7 files changed, 123 insertions(+) create mode 100644 Procfile create mode 100644 Vagrantfile create mode 100644 ostack_validator/celery.py create mode 100644 ostack_validator/templates/validation_form.html create mode 100644 ostack_validator/webui.py create mode 100644 requirements.txt create mode 100644 vagrant/cookbooks/openstack-validator/recipes/default.rb diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..e256fa4 --- /dev/null +++ b/Procfile @@ -0,0 +1,4 @@ +webui: gunicorn --error-logfile - --log-level info ostack_validator.webui:app +redis: redis-server +worker: celery worker --app=ostack_validator.celery:app + diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 0000000..2e203d4 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,15 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +Vagrant::Config.run do |config| + config.vm.box = "ubuntu12.04-server-amd64" + # config.vm.box_url = "http://domain.com/path/to/above.box" + + # config.vm.forward_port 80, 8080 + config.vm.forward_port 5000, 5000 + + config.vm.provision :chef_solo do |chef| + chef.cookbooks_path = ["vagrant/cookbooks"] + chef.add_recipe "openstack-validator" + end +end diff --git a/ostack_validator/celery.py b/ostack_validator/celery.py new file mode 100644 index 0000000..2a44172 --- /dev/null +++ b/ostack_validator/celery.py @@ -0,0 +1,22 @@ +from __future__ import absolute_import +import os +import time + +from celery import Celery + +broker_url = os.getenv('CELERY_BROKER_URL', 'redis://localhost:6379/0') +backend_url = os.getenv('CELERY_RESULT_BACKEND', broker_url) + +app = Celery('ostack_validator', broker=broker_url, backend=backend_url) +app.conf.update( + CELERY_TRACK_STARTED=True +) + +@app.task +def ostack_inspect_task(nodes, username, password=None, private_key=None): + time.sleep(10) + return username[::-1] + +if __name__ == '__main__': + app.start() + diff --git a/ostack_validator/templates/validation_form.html b/ostack_validator/templates/validation_form.html new file mode 100644 index 0000000..4bfc417 --- /dev/null +++ b/ostack_validator/templates/validation_form.html @@ -0,0 +1,13 @@ +{% extends "bootstrap/base.html" %} +{% import "bootstrap/wtf.html" as wtf %} + +{% block title %}OpenStack Validator{% endblock %} + +{% block content %} +
+

OpenStack Validator

+ {{ wtf.quick_form(form, action='/validation', method='POST', button_map={'launch': 'primary'}) }} +
+ +{% endblock %} + diff --git a/ostack_validator/webui.py b/ostack_validator/webui.py new file mode 100644 index 0000000..c16779e --- /dev/null +++ b/ostack_validator/webui.py @@ -0,0 +1,53 @@ +from flask import Flask, request, redirect, render_template, json +from flask_bootstrap import Bootstrap +from flask_wtf import Form +from wtforms import StringField, TextAreaField, SubmitField +from wtforms.validators import DataRequired + +from ostack_validator.celery import app as celery, ostack_inspect_task + +app = Flask(__name__) +Bootstrap(app) +app.debug = True +app.config.update( + WTF_CSRF_SECRET_KEY = 'foo bar baz' +) +app.secret_key = 'A0Zr98j/3fooN]LWX/,?RT' + + +class ValidationLaunchForm(Form): + nodes = StringField('Nodes', validators=[DataRequired()]) + username = StringField('Username', default='root', validators=[DataRequired()]) + private_key = TextAreaField('Private Key', validators=[DataRequired()]) + + launch = SubmitField('Launch validation') + +@app.route('/') +def index(): + return redirect('/validation') + +@app.route('/validation', methods=['GET', 'POST']) +def launch_validation(): + form = ValidationLaunchForm() + if form.validate_on_submit(): + nodes = form.nodes.data.split(' ') + username = form.username.data + private_key = form.private_key.data + + job = ostack_inspect_task.delay(nodes=nodes, username=username, private_key=private_key) + + return redirect('/validation/%s' % job.id) + else: + return render_template('validation_form.html', form=form) + +@app.route('/validation/') +def job(id): + job = celery.AsyncResult(id) + if job.ready(): + return 'Result is %s' % job.result + else: + return 'State is %s' % job.state + +if __name__ == '__main__': + app.run(host='0.0.0.0', debug=True) + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..bb837a4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,8 @@ +spur==0.3.5 +Flask==0.10.1 +Flask-Bootstrap>=3.0.0 +Flask-WTF==0.9.2 +gunicorn==18.0 +celery-with-redis>=3.0 +# Jinja2==2.7.1 + diff --git a/vagrant/cookbooks/openstack-validator/recipes/default.rb b/vagrant/cookbooks/openstack-validator/recipes/default.rb new file mode 100644 index 0000000..cedff4d --- /dev/null +++ b/vagrant/cookbooks/openstack-validator/recipes/default.rb @@ -0,0 +1,8 @@ +package 'redis-server' +package 'python-pip' + +bash 'Install python dependencies' do + code 'pip install -r requirements.txt' + cwd '/vagrant' +end +