Using the Simple module


Note

You can download the full source code for this tutorial


Project File

Create the project using:

mkdir -p ~/Projects/webapp_simple
echo -e "com.nasos.webapp_simple\n1.0\norg.debian.wheezy-lamp-1.2,com.nasos.unicorn_api-7.0.0" | sudo rainbow --init ~/Projects/webapp_simple/
sudo chown -R rainbow:rainbow ~/Projects/webapp_simple

Edit ~/Projects/webapp_simple/package.json so it contains:

{
    "type": "application", 
    "id": "com.nasos.webapp_simple", 
    "version": "1.0", 
    "depends": [
        "org.debian.wheezy-lamp-1.2",
        "com.nasos.unicorn_api-7.0.0"
    ], 
    "network_ports": {
        "WEB_UI": 8080 
    }
}

As can be seen, we will use the org.debian.wheezy-lamp-1.2, since we need Python, and we declare the port 8080 for our WEB_UI.

We also depend on the nasos.unicorn_api-7.0.0 package, since we’ll use the NAS API.

API Configuration file

Create the source directory:

mkdir -p ~/Projects/webapp_simple/source

Create the ~/Projects/webapp_simple/source/unicorn_api.conf file with the following content:

{
    "mandatory_perms": [
        "v7.0.nas_authentication.NasAuth",
        "v7.0.volumes.VolumeAdministration", 
        "v7.0.disks.ExternalDiskAdministration",
        "v7.0.services.ServiceAdministration",
        "v7.0.system.System", 
        "v7.0.authentication.groups.Administration",
        "v7.0.services.SmbServiceAdministration",
        "v7.0.services.ServiceListManager", 
        "v7.0.service_by_nic.ServiceByNicManager", 
        "v7.0.raid.RaidManagement", 
        "v7.0.printer.PrinterAdministration", 
        "v7.0.multi_nic.administration.interface_service", 
        "v7.0.multi_nic.administration.host_service", 
        "v7.0.hw_monitoring.Administration", 
        "v7.0.authentication.users.Administration", 
        "v7.0.volume_quotas.QuotaAdministration", 
        "v7.0.sharing.shares.Administration", 
        "v7.0.support.ps_monitoring.Info",
        "v7.0.snmp.SnmpAdministration", 
        "v7.0.simple_sharing.SimpleSharing", 
        "v7.0.port_mapping.administration.port_mapping_service", 
        "v7.0.iscsi_multi_lun.TargetAdministration", 
        "v7.0.iscsi_multi_lun.LunAdministration" 
    ]
}

The Simple module uses all these services from the NAS API.

Install Scripts

Edit the ~/Projects/webapp_simple/scripts/post-install script so it contains:

#!/bin/sh
/usr/bin/unicorn_helper --register
exit 0

Edit the ~/Projects/webapp_simple/scripts/pre-remove script so it contains:

#!/bin/sh
/usr/bin/unicorn_helper --unregister
exit 0

Startup Script

Create the ~/Projects/webapp_simple/source/rc.local file with the following content:

#!/bin/sh -e

# Updates config file with NASOS informations
/usr/bin/unicorn_helper --set port $RAINBOW_PORT_WEB_UI
/usr/bin/unicorn_helper --set path $RAINBOW_WEB_PATH

PIDFILE=/var/run/webapp_simple.pid
case $1 in
    start)
        start-stop-daemon --start \
            --start --startas /opt/www/main.py \
            --make-pidfile --pidfile $PIDFILE \
            --background
        ;;
    stop)
        start-stop-daemon --stop --pidfile $PIDFILE
        rm -f $PIDFILE
        ;;
esac

exit 0

App Source Code

The app is composed of a HTML file, more precisely a template for the web.py framework and of a Python file. Create the ~/Projects/webapp_simple/source/index.html file with the following content:

$def with (path, services, result, choice)

<html>
<head>
    <meta http-equiv="content-type" content= "text/html; charset=UTF-8">
    <title>Using the Simple API</title>
</head>
<body>
    <center><h1>Simple API</h1></center>
    <hr />
    <form action="$(path)/authent">
        <input type="submit" name="login" value="Login" />
        <input type="submit" name="logout" value="Logout" />
    </form>
    <form action="$(path)/API">
        <div class="inlineDirectChildren">
<select name="select" id="method">
$for service in services:
    $ selected = ""
    $if choice == service:
        $ selected = " selected"
    <option value="$service"$selected>$services[service]</option>
</select>
            <input type="submit" value="Get" />
        </div>
    </form>
    <hr />
$if result:
    <h2>Result</h2>
    <form action="$(path)">
        <pre>$(result)</pre>
    </form>
</body>
</html>

Then create the ~/Projects/webapp_simple/source/main.py file, which is the Web server of the App, with the following content:

#!/usr/bin/python

import web
import os
import json

from unicorn_api import simple


# Open the configuration file. To get all the stuff that we need
with open("/etc/unicorn_api.conf") as f:
    info = json.load(f)
    port = int(info["port"])
    path = info["path"]

urls = (
    '%s/*' % path, 'index',
    '%s/authent/*' % path, 'authent',
    '%s/API' % path, 'simple_api',
)

services = {
    "list_services_by_nic": "Services by NIC", "list_myshares": "My Shares",
    "list_mygroups": "My Groups", "list_slots": "Slots",
    "list_volumes": "Volumes", "list_external_disks": "External Disks",
    "list_services": "Services", "list_services_info": "Services Info",
    "get_timezone": "Timezone", "list_smb_hosts": "SMB Hosts",
    "list_printers": "Printers", "list_interfaces": "Interfaces",
    "get_workgroup": "Workgroup", "get_hostname": "Hostname",
    "get_uptime": "Uptime", "list_temperatures": "Temperatures",
    "list_cpus_info": "CPU Info", "list_networks_info": "Network Info",
    "list_drives_info": "Drives Info", "list_users": "Users",
    "list_users_from_domain": "Users from Domain", "list_myquotas": "My Quotas",
    "list_shares": "Shares", "list_groups": "Groups", "get_mySelf": "My Self",
    "get_monitoring_info": "Monitoring Info", "get_snmp_config": "SNMP Config",
    "list_public_shares": "Public Shares", "list_pools": "Pools",
    "list_all_port_mappings": "Port Mappings", "list_iscsis_target": "ISCSI Targets",
    "list_iscsis_lun": "ISCSI Luns", "list_iscsis_initiator": "ISCSI Initiators"
}

CURRENT_FOLDER = os.path.dirname(__file__)
page_html = web.template.frender(os.path.join(CURRENT_FOLDER, "index.html"))


class authent(object): 
    def GET(self):
        try:
            app_user_token = simple.get_user_token()
            inputs = web.input()
            if 'logout' in inputs:
                if not app_user_token:
                    raise Exception('Already logged out')
                app_session_token = simple.get_session_token()
                simple.logout_session()
                return (
                    "<html><meta http-equiv='Refresh' content='0;url=/?app_session_token=%s&app_path=%s/&logout=anonyme'></html>" %
                    (app_session_token, path))
            else:
                app_user_token = inputs.get("app_user_token", app_user_token)
                if app_user_token is None:
                    app_session_token = simple.open_session()
                    return (
                            "<html><meta http-equiv='Refresh' content='0;url=/?app_session_token=%s&app_path=%s/authent&action=login'></html>" %
                            (app_session_token, path))
                else:
                    simple.login_session(app_user_token)
                return page_html(path, services, 'Authentication successful', None)
        except Exception, exc:
            return page_html(path, services, str(exc), None)

class simple_api(object):
    def GET(self):
        try:
            simple.open_session()
            inputs = web.input()
            method = inputs.get("select", None)
            result = getattr(simple, method)()
            return page_html(path, services, str(result), method)
        except Exception, exc:
            return page_html(path, services, str(exc), method)

class index(object):
    def GET(self):
        return page_html(path, services, None, None)

class MyApplication(web.application):
    def run(self, port, *middleware):
        func = self.wsgifunc(*middleware)
        return web.httpserver.runsimple(func, ('0.0.0.0', port))

if __name__ == "__main__":
    web.config.debug = False
    app = MyApplication(urls, globals())
    app.run(port=port)

Build Script

Create the ~/Projects/webapp_simple/build.sh file with the following content:

#!/bin/bash

install -m 755 /home/source/rc.local /etc/
install -m 644 /home/source/unicorn_api.conf /etc/
mkdir -p /opt/www
install -m 755 /home/source/main.py /opt/www/
install -m 644 /home/source/index.html /opt/www/

exit 0

This script:

Build the App

You can then build the app using:

sudo rainbow --build ~/Projects/webapp_simple
sudo rainbow --pack ~/Projects/webapp_simple

Then .rbw package is available in:

~/Projects/webapp_simple/build/x86_64/com.nasos.webapp_simple-1.0-x86_64.rbw

The app cannot be tested inside the NASOS SDK VM, since it uses the NAS API. This means it needs to be installed on an actual NAS for testing. Please refer to the Debugging you App for details.

You will need to install the app and its dependencies on a NAS device, get the app’s URL and open it in a web browser.

You should get something like:

Testing the App

Here we can see the list of all services provided by the Simple module. If some services require privileges, you must log in first and retry again.