web_app.py 6.81 KB
Newer Older
carignani's avatar
carignani committed
#!/bin/python3
carignani's avatar
carignani committed
'''
Web app to offer a frontend to the doc2tosca and tosca2doc tools

'''
carignani's avatar
carignani committed

import os
carignani's avatar
carignani committed
import shutil
import tempfile
from zipfile import ZipFile
carignani's avatar
carignani committed

carignani's avatar
carignani committed
from flask import Flask, flash, request, redirect, send_file, render_template, g
carignani's avatar
carignani committed
from werkzeug.utils import secure_filename
import docx
carignani's avatar
carignani committed

import config
carignani's avatar
carignani committed
import tosca2doc
carignani's avatar
carignani committed
import doc2tosca
carignani's avatar
carignani committed

class ReverseProxied(object):

carignani's avatar
carignani committed
    def __init__(self, the_app, script_name=None, scheme=None, server=None):
        self.app = the_app
        self.script_name = script_name
        self.scheme = scheme
        self.server = server

    def __call__(self, environ, start_response):
        script_name = environ.get('HTTP_X_SCRIPT_NAME', '') or self.script_name
        if script_name:
            environ['SCRIPT_NAME'] = script_name
            path_info = environ['PATH_INFO']
            if path_info.startswith(script_name):
                environ['PATH_INFO'] = path_info[len(script_name):]
        scheme = environ.get('HTTP_X_SCHEME', '') or self.scheme
        if scheme:
            environ['wsgi.url_scheme'] = scheme
        server = environ.get('HTTP_X_FORWARDED_HOST', '') or self.server
        if server:
            environ['HTTP_HOST'] = server
        return self.app(environ, start_response)

app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app, script_name='/tosca-ie')
carignani's avatar
carignani committed
UPLOAD_FOLDER = '/tmp/upload'

ALLOWED_EXTENSIONS = set(['txt', 'yaml', 'docx'])

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
carignani's avatar
carignani committed
app.secret_key = config.SECRET
carignani's avatar
carignani committed
app.config['SESSION_TYPE'] = 'filesystem'

carignani's avatar
carignani committed
TOSCA_DEFS = ['VNFD', 'NSD', 'PNFD']
carignani's avatar
carignani committed

carignani's avatar
carignani committed
MISSING_MODULE_ERR_MSG = \
    'Error: some TOSCA module missing. Make sure to \
    upload definitions for NSD, VNFD, PNFD.'

carignani's avatar
carignani committed
def allowed_file(filename):
    '''
    Check filename is in the list of allowed extensions
    '''
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route("/")
def hello():
carignani's avatar
carignani committed
    '''
    Render home page
    '''
    if config.LAST_COMMIT is not False:
        link = config.REPO_URL+config.LAST_COMMIT.split(" ")[0]
    else:
        link = "#"

carignani's avatar
carignani committed
    return render_template(
        "./home.html", 
        VERSION=config.VERSION, 
        doc_allowed_versions=doc2tosca.allowed_versions,
        default_tosca_version=doc2tosca.DEFAULT_TOSCA_VERSION,
        last_rev=config.LAST_COMMIT,
        rev_link=link
carignani's avatar
carignani committed
    )
carignani's avatar
carignani committed

carignani's avatar
carignani committed
@app.route("/doc2tosca-info")
def doc2tosca_info():
    '''
    Render home page
    '''
    return render_template("./doc2tosca-details.html", VERSION=config.VERSION)

@app.route("/tosca2doc-info")
def tosca2doc_info():
    '''
    Render home page
    '''
    return render_template("./tosca2doc-details.html", VERSION=config.VERSION)

carignani's avatar
carignani committed
@app.route("/tosca2doc", methods=['POST'])
def mk_tosca2doc():
carignani's avatar
carignani committed
    '''
    Execute tosca2doc on the uploaded files
    '''
carignani's avatar
carignani committed

    if 'file' not in request.files:
        flash('Error: No file uploaded.')
        return redirect("/tosca-ie")
carignani's avatar
carignani committed

    ufiles=request.files.getlist("file")

    for tosca_def in TOSCA_DEFS:
        found=False
        for uploaded_file in ufiles:
            if tosca_def in uploaded_file.filename or \
                tosca_def.lower() in uploaded_file.filename:
                found=True
        if not found:
carignani's avatar
carignani committed
            flash(MISSING_MODULE_ERR_MSG)
            print('Error: TOSCA module missing.')
            return redirect("/tosca-ie")
carignani's avatar
carignani committed

    for file in ufiles:
        if file.filename == '':
            print('Error: No selected file')
            flash('Error: No file uploaded or wrong name.')
            return redirect("/tosca-ie")
carignani's avatar
carignani committed

carignani's avatar
carignani committed
    tmp_dir = tempfile.mkdtemp()
    g.tmp_dir = tmp_dir

carignani's avatar
carignani committed
    doc = docx.Document()    

    for tosca_def in TOSCA_DEFS:
        for file in ufiles:
            if tosca_def in uploaded_file.filename or \
                tosca_def.lower() in uploaded_file.filename:
                filename = secure_filename(file.filename)
                filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
                file.save(filepath)
                file.close()

                tosca2doc.generate_from_file(tosca_def, doc, filepath)

carignani's avatar
carignani committed
    outfilename = os.path.join(tmp_dir, 'myfile.docx')

    doc.save(outfilename)
    return send_file(outfilename)
carignani's avatar
carignani committed

carignani's avatar
carignani committed
    #return ("No content found")

def get_all_yaml_file_paths(directory): 
carignani's avatar
carignani committed
    '''
    Finds yaml files within a directory and sub directories and
    returns the list of paths
    '''
carignani's avatar
carignani committed

    file_paths = []

carignani's avatar
carignani committed
    for root, _, files in os.walk(directory):
carignani's avatar
carignani committed
        for filename in files:
            if ".yaml" in filename:
                filepath = os.path.join(root, filename)
                file_paths.append(filepath)

    return file_paths

carignani's avatar
carignani committed
@app.after_request
def after_request(response):
carignani's avatar
carignani committed
    '''
    Clean up files created by doc2tosca
    '''
carignani's avatar
carignani committed
    if request.path != '/doc2tosca':
        return response
carignani's avatar
carignani committed
    if g.get('tmp_dir') is None:
        return response
carignani's avatar
carignani committed
    shutil.rmtree(g.tmp_dir, ignore_errors=True)
    print("Deleted {}\n\n".format(g.tmp_dir))
    return response

carignani's avatar
carignani committed
@app.route("/doc2tosca", methods=['POST'])
def mk_doc2tosca():
carignani's avatar
carignani committed
    '''
    Executes doc2tosca on the uploaded file
    '''
carignani's avatar
carignani committed

    zip_fn = "tosca_defs.zip"

    if 'file' not in request.files:
        flash('No file uploaded')
        return redirect("/tosca-ie")
carignani's avatar
carignani committed

    ufiles = request.files.getlist("file")

    try:
        print(request.form)
        doc_version = request.form.get('doc-version')
        custom_doc_version = request.form.get('custom-doc-version')
        custom_tosca_version = request.form.get('custom-tosca-version')
carignani's avatar
carignani committed
        yaml_root_path = request.form.get('yaml-root-path')
    except:
        flash("Something went wrong :/")
        return redirect("/tosca-ie")

    if doc_version not in doc2tosca.allowed_versions:
        flash('Incorrect doc version selected')
        return redirect("/tosca-ie")

carignani's avatar
carignani committed
    sol001_file = ufiles[0]

    tosca_version = doc2tosca.DEFAULT_TOSCA_VERSION

    if custom_doc_version != "":
        doc_version = custom_doc_version

    if custom_tosca_version != "":
        tosca_version = custom_tosca_version

        doc2tosca.generate_templates(sol001_file, doc_version, yaml_root_path, tosca_version)
    except ValueError as e:
        flash(str(e))
        return redirect("/tosca-ie")
    except BaseException as e:
        flash(str(e))
        flash("Unknown error in the generation of the files. Please contact the support.")
        return redirect("/tosca-ie")
carignani's avatar
carignani committed

    tmp_dir = tempfile.mkdtemp()
    print("TMP DIR: " + tmp_dir)
    doc2tosca.print_to_files(tmp_dir)

    file_paths = get_all_yaml_file_paths(tmp_dir)

    zip_path = os.path.join(tmp_dir, zip_fn)

    with ZipFile( zip_path, 'w') as archive:
        for myfile in file_paths:
            archive.write(myfile, arcname=os.path.basename(myfile))

carignani's avatar
carignani committed
    g.tmp_dir = tmp_dir
carignani's avatar
carignani committed
    return send_file(zip_path, as_attachment=True)
carignani's avatar
carignani committed

if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0')