MQTT in Ember.js

Ember Octane mqtt.js

Less than 2 years ago I started a new project with the company I work for that requires to an Ember Octane app to control several connected IoT devices around the world. We choosed the MQTT publish/subscribe network protocol to interact with our on-field devices for its lightweight message structure and its limited network bandwith requirements.

After googling for a javascript MQTT library I’ve found the MQTT.js client. At the moment of my search the asynchronous version was not yet released, so I had to wrap the event based client into an Ember service and transform it into a Promise based client.

This is a mandatory requirement because I need broker connection before subscribing to a topic or I need topic subscription before publishing on it. Sometimes you had retain messages on a topic for receiving last published value after the subscription. Other times you need publishing an empty value on a topic to request the status of a given device. So you need working subscribtion on a topic before sending a message. That said javascript Promises are the only way to accomplish this tasks.

When I wrote this service I didn’t find an Ember addon ready to do this things. Therefore I decided to dive into the docs and learn how to build an addon. The ember-mqttjs addon is my first Ember addon!

The code

This service extends the Evented Ember object for raising events on new messages as well as connect, disconnect events and many others you can find on its readme. In addition of raising this events it returns a Promise for connect, subscribe, unsubscribe and publish methods.

This is an example of another service that uses the ember-mqttjs service:

import Service, { inject as service } from '@ember/service';
import { bind } from '@ember/runloop';

export default class YourService extends Service {
  @service mqtt;
  constructor() {
    super(...arguments);
    //...
    let _fOnMessage = bind(this, this._onMessage);
    this.mqtt.on('mqtt-message', _fOnMessage); 
  }

  _onMessage(sTopic, sMessage) {
    //code to manage messages received on a certain topic
  }

  async subscribeAndPublish(sTopic, sMessage) {
    try {
      await this.mqtt.connect(HOST, USERNAME, PASSWORD)
    } catch (oError) {
      //code on connection error
    }
    try {
      await this.mqtt.subscribe(sTopic);
    } catch (oError) {
      //code for subscription error
    }
    try {
      await this.mqtt.publish(sTopic, sMessage);
    } catch (oError) {
      //code for message publish error
    }
    return Promise.resolve();
  }
//...
}

I’ve just refactored the addon code to use async/await features and I moved the CI from travis to github action (thanks to this Jeldrik Haschke’s repo).
Many improvements can be done in the future starting from writing more tests to cover other cases.
If you have any suggestions or proposal to improve the code as well as the tests you are welcome!

Contact me or start contributing on GitHub project repo!

Uno script Gulp per automatizzare la compilazione dei files Sass (scss)

Gulpjs

Gulp js è una libreria javascript che permette di automatizzare svariate tipologie di noiose procedure che gli sviluppatori normalmente fanno “a mano”.

Proprio in questa direzione ho deciso di scrivere un breve script gulp che consente di automatizzare la ricompilazione dei fogli di stile SASS (scss), per evitarmi di lanciare, ad ogni modifica dei files, il comando sass sorgente.scss destinazione.css.

L’unico prerequisito per utilizzare gulp è di aver installato Nodejs ed il suo package manager npm (che viene installato di default insieme a node). Una volta installato node e scaricati i sorgenti del mio script basterà lanciare:

sudo npm install

…ed npm installerà per voi tutte le dipendenze necessarie!

Lo script prevede due modalità di esecuzione tramite i seguenti comandi:

  • gulp: compila i vostri scss presenti nella sottocartella src in un unico css nella root directory minifizzato (sass –style compressed)
  • gulp dev: compila gli scss in modalità espansa (sass –style expanded)

Questi due comandi avviano un task che rimane “in ascolto” e ad ogni modifica di un file scss rilancia il comando evitando il noioso compito di lanciare ogni volta la compilazione dei files per vedere le modifiche allo stile delle vostre web app/siti. In questo modo potrete scrivere le direttive di stile come si faceva prima dell’avvento di SASS/LESS e vedere immediatamente le nuove modifiche “live”.

Ho previsto un repository github “gulp-for-sass” con questo mini-progetto, scaricabile e modificabile liberamente!

Django + Supervisor su Ubuntu server

Supervisor, Django e Gunicorn

Continuando ad interessarmi al mondo Django sono venuto a conoscenza di un interessante sistema da utilizzare nello stack per il deploy di un’app sviluppata con questo framework.

Sto parlando di Supervisor, un sistema client/server per il controllo di processi Unix. Inizialmente nel mio stack avevo utilizzato Upstart, il controllore di processi presente di default su Ubuntu, ma utilizzando la funzione respawn, ossia per ogni processo terminato ne viene lanciato un altro, il sistema si perde il riferimento con il processo lanciato e i comandi di stop non hanno più effetto. Sentendo parlare bene di Supervisor mi sono deciso a provarlo ed effettivamente funziona alla grande!!! E’ possibile conoscere lo stato di tutti i processi registrati in Supervisor oltre ai classici comandi di start, stop e restart dei vari processi attivi.

Supervisor è presente all’interno del repository dei pacchetti Ubuntu, quindi per installarlo è sufficiente il comando:

sudo apt-get install supervisor

Per il primo avvio è necessario digitare:

service supervisor restart

A questo punto possiamo aggiure un nuovo programma, che nel caso di applicazioni Django sarà lo script python per l’avvio di Gunicorn (il server wsgi per Django di cui ho già ampiamente parlato qui), vediamo un esempio:

command = '/opt/APP_VIRTUAL_ENV/bin/gunicorn'
pythonpath = '/SRC/APP/PATH/'
bind = '127.0.0.1:8000'
workers = 3
user = 'CUSTOM_USER'
pid = '/var/run/APP_NAME.pid'
accesslog = '/var/log/gunicorn/APP_NAME/access.log'
errorlog = '/var/log/gunicorn/APP_NAME/error.log'

Ovviamente questo è un mio esempio di script per il lancio di gunicorn relativo ad una app django, ma questo tipo di configurazione è valido per qualsiasi processo che si vuole controllare, basta specificare all’interno di “command” il comando che supervisor deve lanciare e controllare. Io sono solito mettere questo script in una cartella chiamata appunto “script” allo stesso livello dei sorgenti dell’app, ma può essere posizionato in qualunque punto del sistema. Sarà poi il file di configurazione del programma in supervisor a dover sapere dove recuperare lo script appena preparato.

Come dicevo, supervisor viene informato di un comando da lanciare mediante un file (un file per ogni comando) all’interno della cartella /etc/supervisor/conf.d/APP.conf contenente le seguenti linee:

[program:APP_NAME]
command=/opt/APP_VIRTUAL_ENV/bin/gunicorn APP_NAME.wsgi:application -c/SRC/APP/SCRIPT/PATH/gunicorn_config.py
autostart=true
autorestart=true
stderr_logfile=/var/log/gunicorn/APP_NAME/supervisor_stderr.log
stdout_logfile=/var/log/gunicorn/APP_NAME/supervisor_stdout.log

Non sto a spiegare nel dettaglio il significato della prima linea, che è il comando per avviare Gunicorn con la nostra app django tramite lo script precedentemente scritto, mentre la seconda e la terza linea dicono a Supervisor rispettivamente di avviare il comando all’avvio del sistema e di riavviare i processi che vengono terminati in modo non naturale. Le ultime due linee specificano i percorsi dei files di log di Supervisor.

A questo punto dobbiamo dire a Supervisor di leggere la nuova configurazione:

supervisorctl reread

Seguito dal comando per abilitare il nuovo programma:

supervisorctl update

Adesso la nostra app dovrebbe essere avviata!

Potete controllare lo stato di Supervisor con il semplice comando:

supervisorctl status

Per avviare, stoppare o riavviare i processi sono presenti i comandi:

supervisorctl start
supervisorctl stop
supervisorctl restart

Mentre per avviare la console interattiva di Supervisor è sufficiente digitare:

supervisorctl

Non vi resta che scrivere app (Django, Node, ROR o ciò che più preferite) e farne controllare i loro processi da Supervisor!

Id alfanumerici per le chiavi primarie in django

 

Django web framework

Oggi torno sul blog per scrivere un breve tutorial riguardante il “mondo” Django.

Da buon appassionato di questo framework continuo nei miei esperimenti e in questo articolo spiegherò come modificare le chiavi primarie delle tabelle django da numero intero a stringa alfanumeriche sulla falsa riga degli uuid di PostgreSQL.

Il framework usa come default chiavi primarie di tipo integer che per ovvi limiti di architettura del tipo int possono essere grandi al massimo 32 bit. Con poche righe di codice vedremo come sostituire la chiave primaria con un valore generato tramite il modulo python uuid.

Per prima cosa in genere mi creo un file utils.py nell’app principale, un modulo in cui inserire tutte le funzioni di utilità per l’app. All’interno di questo file andremo a creare la nostra funzione che genererà gli uuid in questo modo:


import uuid

def make_uuid():
   return str(uuid.uuid1())

In questo modo genereremo un id alfanumerico basato sul mac address dell’host da cui viene generato, un numero di sequenza (in questo caso random) e il timestamp corrente. In questo modo non solo avremo id univoci all’interno della tabella, ma addirittura all’interno dell’intero database azzerando di fatto la possibilità di collisioni (l’unica possibilità sarebbe se venissero generati nello stesso istante due id con lo stesso numero di sequenza, non impossibile ma altamente improbabile).

Una volta scritta questa funzione non ci resta che usarla per generare gli id all’interno dei nostri model come nell’esempio sottostante:

from APP_NAME.utils import make_uuid
from django.db import models

class MyModel(models.Model):
   id = models.CharField(max_length = 36, primary_key = True, default = make_uuid, editable = False)
   ... altri campi ...

Come potete vedere si dovrà importare la funzione appena scritta all’interno del file models.py e utilizzarla per specificare il valore di default del campo id (omesso di default in caso di id standard).

Se si volesse evitare di usare il mac address della macchina per generare l’uuid si potrebbe utilizzare una funzione differente. Ad esempio la uuid.uuid4() genera uuid random, ovviamente a discapito di una, seppure remota, possibilità di collisioni.

Template WordPress responsive per il mio blog!

responsive

Come avrete potuto sicuramente notare in questi ultimi giorni, ho finalmente pubblicato la nuova versione del template per il mio blog personale! Siamo arrivati alla versione 4!

Ho deciso di sviluppare un tema WordPress totalmente nuovo, partendo da un foglio bianco ed ispirandomi a “cose” viste qua e là.

La mia esigenza era quella di ottenere, con il minimo sforzo, un template ottimizzato per tutti i dispositivi, da quelli con schermi ad alta risoluzione fino ai “mobile”, sempre più in voga negli ultimi tempi. Ho perciò utilizzato lo standard de facto dei framework CSS: Bootstrap 3! Ed ecco il risultato, un template adatto a desktop, tablet e smartphone!

Mi sono servito di una classe walker scritta ad hoc per utilizzare i menu WordPress con Boostrap, in modo da poter sfruttare la navbar fissata in alto. Per il resto la giusta miscela di codice php e html, qualche file css/js ed ecco qua, il nuovo template!

Il font che ho scelto è l’Open Sans, uno dei più utilizzati ultimamente sul web, e mi viene servito direttamente da Google Fonts.

Spero di essere riuscito nell’intento di fornire una navigazione più piacevole e al tempo stesso più completa. Presto cercherò di rendere disponibile gratuitamente e sotto licenza open source questo tema nel repository di WordPress. Nel frattempo se avete domande/curiosità non esitate a commentare l’articolo o a scrivermi tramite la solita pagina dei contatti.

Invece il prossimo passo che ho in mente per il blog sarà qualche cambiamento “sotto il cofano”, ma non voglio svelarvi niente e mi tengo un po’ di tempo per fare ancora qualche test!

A presto!

Server virtualizzato con VirtualBox 4.0 su Ubuntu Server 10.04 LTS

Oracle Virtualbox

Oggi inauguro la nuova grafica del blog con un articolo molto interessante. Questo tutorial vi aiuterà a virtualizzare dei server con VirtualBox da linea di comando.
Ho installato virtualbox 4.0 su una macchina ubuntu server 10.04, ma repository a parte penso che vada bene su qualsiasi versione di ubuntu e più in generale su qualsiasi debian.

Per chi lavora come me su ubuntu server 10.04 per prima cosa bisogna aggiungere il repository di virtualbox nei sorgenti apt. Aprite il file source.list:

sudo vim /etc/apt/sources.list

E aggiungete in fondo la linea:

deb http://download.virtualbox.org/virtualbox/debian lucid contrib

Salvate e chiudete e scaricate la chiave pubblica:

wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add -

A questo punto aggiornate:

sudo apt-get update

..e installate il software necessario:

sudo apt-get install linux-headers-$(uname -r) build-essential virtualbox-4.0 dkms

Il pacchetto dkms serve per far sì che ogni volta che il kernel verrà aggiornato verrà aggiornato automaticamente anche virtualbox.

A questo punto scaricate l’extension pack di virtualbox

cd /tmp
wget http://download.virtualbox.org/virtualbox/4.0.16/Oracle_VM_VirtualBox_Extension_Pack-4.0.16-75491.vbox-extpack
sudo VBoxManage extpack install Oracle_VM_VirtualBox_Extension_Pack-4.0.16-75491.vbox-extpack

Ora dovrete aggiungere il vostro utente al gruppo utenti di virtualbox:

sudo adduser your_user vboxusers

Ora la configurazione di virtualbox è terminata, possiamo procedere con la creazione di una nuova virtual machine.

VBoxManage createvm --name "ubu_srv_1" --register
VBoxManage modifyvm "ubu_srv_1" --memory 512 --acpi on --boot1 dvd --nic1 bridged --bridgeadapter1 eth0
VBoxManage createhd --filename /home/your_user/vbox/ubu_srv_1/ubu_srv_1.vdi --size 10000
VBoxManage storagectl "ubu_srv_1" --name "IDE Controller" --add ide
VBoxManage storageattach "ubu_srv_1" --storagectl "IDE Controller" --port 0 --device 0 --type hdd --medium /home/your_user/vbox/ubu_srv_1/ubu_srv_1.vdi
VBoxManage storageattach "ubu_srv_1" --storagectl "IDE Controller" --port 1 --device 0 --type dvddrive --medium /home/your_user/downloads/ubuntu-10.04.4-server-amd64.iso

Con queste istruzioni la nuova macchina virtuale è pronta.

Ora per il primo lancio vi consiglio di usare VBoxHeadless che oltre a lanciare la vm appena creata metterà in piedi un server VRDP, in modo che possiate accedere alla macchina con un client di desktop remoto. Per cui, settiamo la porta del vrdp:

VBoxManage modifyvm "ubu_srv_1" --vrde-port 9800

..e lanciamo la macchina virtuale (abbiate cura di mettere la “&” al fondo del comando in modo da poter continuare sulla stessa shell senza chiudere bruscamente il processo della virtual machine):

VBoxHeadless --startvm "ubu_srv_1" &

Quindi aprite il vostro client di desktop remoto preferito e collegatevi all’ip della vostra macchina su cui avete installato virtualbox aggiungendo “:9800”. Il mio indirizzo a cui rispondeva il server rdp era ad esempio 192.168.0.200:9800.
Potete quindi installare normalmente ubuntu server come se foste su una macchina fisica. Finita l’installazione riavviando la macchina partirà il sistema in automatico. Collegatevi e come prima cosa controllate l’ip (meglio assegnarne uno fisso). Prima di poter dire di avere la vm pronta dobbiamo fare in modo che al prossimo lancio non parta più l’immagine di installazione, per cui spegnete la macchina e ritornate sulla shell del server virtualbox:

VBoxManage modifyvm "ubu_srv_1" --boot1 disk

Adesso siete davvero pronti per lanciare la vostra nuova virtual machine. I passi successivi servono per ottimizzare l’utilizzo di ram del vostro server.

Riavviate la macchina fisica che ospita la/le macchina/e virtuale/i e ricollegatevi. Da shell modificate ancora la vm con il seguente comando per non lanciare il server vrdp quando avviate la vm, così da occupare la sola ram indicata per la vostra vm:

VBoxManage modifyvm "ubu_srv_1" --vrde off

Ora potete nuovamente lanciare la vostra macchina virtuale con il comando:

VBoxManage startvm "ubu_srv_1" --type headless &

Per tutti i comandi di VBoxManage fate riferimento all’help:

VBoxManage --help

Per spegnere o mettere in pausa la macchina i comandi sono:

VBoxManage controlvm "ubu_srv_1" poweroff
VBoxManage controlvm "ubu_srv_1" pause

Buon divertimento!

Installare Ubuntu Server 10.04 LTS con RAID 10 e LVM

Eccomi qua! Dopo un po’ di tempo con poche “scoperte” interessanti, oggi ritorno con un articolo che riguarda i server.

Ovviamente quando parlo di server, parlo di linux e ancora più nello specifico di Ubuntu.

Ultimamente per andare sul sicuro mi sono abituato ad utilizzare solo più le versioni LTS ossia le Long Term Support, le versioni supportate per 3 anni, decisamente molto più stabili rispetto alle altre.

Quando si installa un server generalmente si ha a che fare con la necessità di mantenere il più possibile al sicuro i dati che vi verranno salvati e per fare ciò è buona norma gestire lo spazio a propria disposizione con il RAID ossiamo un sistema di replica delle informazioni in tempo reale che tenta di ridurre al minimo le possibilità di perdita di dati (ridurre, non eliminare, ne ho le prove ;-) ).

L’installazione di Ubuntu consente di creare un RAID software nel caso in cui il server che stiamo preparando non abbia un sistema di RAID hardware.

Tralasciamo la discussione sulla scelta del RAID, per quello che ho potuto provare sulla mia pelle in genere è sempre meglio un RAID 0 o un RAID 1 o meglio ancora un RAID 1+0 detto anche RAID 10 perchè a differenza dell’alternativo RAID 5 lascia i dati in chiaro e quindi leggibili in qualsiasi momento, anche collegandolo su un’altra macchina (in caso di problemi). Detto ciò, veniamo a come preparare le partizioni per costruire il RAID.

Prendendo l’esempio di 2 dischi da 500 Gb vi conviene creare due partizioni primarie per ciascun disco (scegliete la voce “partizionamento manuale”): una dimensionata il doppio della ram presente sul server, e una con lo spazio rimanente. Ripetete la stessa cosa con le altre due partizioni dell’altro disco. Per ogni partizione alla voce “usare come” dobbiamo ricordarci di impostare “volume per il raid”. Fatto ciò possiamo terminare il partizionamento e configurare gli array raid tramite l’apposito menu, scegliendo il raid desiderato e settando quanti dischi usare per il raid (2) e quanti dischi di spare(0).

Come detto dobbiamo configurare due array, uno per la swap e uno per il sistema vero e proprio. Per il primo array scegliamo i due volumi a cui abbiamo assegnato il doppio della dimensione della ram, confermiamo e passiamo alla configurazione del secondo array con i restanti due volumi.

Finita la configurazione dei due array del raid possiamo terminare l’operazione e scrivere le modifiche.

Quando apparirà nuovamente la schermata con le tabelle delle partizioni potremo notare che sono state aggiunte due voci all’elenco, ossia quelle corrispondenti ai due arrays. A questo punto possiamo creare due partizioni (una per array) e impostare la voce “usare come” su “volume per LVM”.

L’LVM è un gestore dei volumi logici, ossia consente di creare dei volumi “estendibili” in qualsiasi momento. Infatti smontando i volumi si possono aumentare le loro dimensioni senza dover formattare e senza subire perdite di dati, e addiritture si possono raggruppare in un unico volume più dischi (anche aggiunti in un secondo momento). Un po’ quello che si può fare tramite l’ormai conosciutissimo GParted in Ubuntu desktop.

Tornando all’installazione del nostro ubuntu server, una volta impostate le nostre partizioni come volumi per LVM possiamo procedere alla creazione dei due volumi logici, come già detto uno per lo swap e uno per il sistema. Una volta confermata la creazione dei due volumi logici (dovrete assegnare un nome ai volumi da creare, ad esempio “swap” e “srv”) nella tabelle delle partizioni troveremo altre due voci, rappresentati i due nuovi volumi appena creati.

A questo punto possiamo procedere alla creazione delle partizioni da far usare all’installazione di Ubuntu: una da impostare come “volume swap” e l’altra da impostare con ext4 (o ext3 per i più tradizionalisti :-P ). Ovviamente la partizione formattata con ext4 dovrà avere come punto di mount “/” (root). Confermate queste modifiche l’installazione procederà a gonfie vele, e in pochi minuti il vostro server sarà pronto per l’uso! :-)

Creare un web service con SOAP e PHP

Ai tempi dell’università, nel corso di programmazione in rete tenuto dal Prof. Matteo Baldoni, avevamo realizzato un ottimo progetto in Java di agenti che interagivano tra di loro.
Era anche questo una specie di servizio web anche se era realizzato con RMI ovvero Remote Method Invocation, ossia una funzione di java che consente di invocare metodi di oggetti remoti da altre java virtual machine.

Oggi visto che sono ancora a casa per l’influenza, ho deciso di documentarmi sui web services in php, dato che probabilmente dovrò realizzare un progetto in cui potrebbero tornarmi utili.

Seguendo l’ottima guida “PHP 6, Guida per lo sviluppatore” di Lecky-Thompson, Novicki e Myer (ve la consiglio vivamente se siete interessati all’argomento, è davvero ottima), ho deciso di riprodurre l’esempio di un client-server SOAP(Simple Object Access Protocol). Innanzitutto SOAP è un protocollo per lo scambio di messaggi tra agenti software, ossia un client tramite soap può richiamare funzioni di un server inviando e ricevendo parametri. E fin qui nulla di strano mi direte voi… Infatti, la cosa interessante deve ancora arrivare! La peculiarità di scrivere software implementando SOAP è che client e server possono essere scritti in linguaggi diversi, essendo quest’ultimo appunto un protocollo e non una componente software. Tutti i linguaggi più comuni hanno delle classi che implementano SOAP, sia lato server sia lato client. Diventa così facile capire che una volta scritto un server SOAP che implementa alcune funzioni, possono esserci N client che sfruttano queste funzioni per leggere dati comuni o interagire con applicazioni sul web.

Ecco allora che ci spieghiamo come sia possibile che tutte le applicazioni web più famose, da quelle di google, a facebook fino a twitter, mettano a disposizione metodi per interagire dall’esterno con i loro servizi (le famose API, Application Programming Interface).

Come vi dicevo ho messo in pratica l’esempio che ho trovato sulla guida di PHP, potete raggiungerla a questo indirizzo. L’esempio non fa altro che realizzare un server che ha un metodo che prende in input un nome e restituisce un saluto, comprensivo del nome inviato. Il client ovviamente preso in input il nome invia la richiesta al server e stampa il saluto ricevuto. Nulla di complicato, ma si riescono ad intuire le potenzialità di questo protocollo.

I due script in php come vedrete fra poco, sono molto semplici, e non richiedono più di una decina di righe di codice ciascuno, la parte fondamentale di questo esempio è però il file wsdl, ossia il file xml di dichiarazione dei metodi messi a disposizione dal server. Questo file non è indispensabile ma è utile a chi implementa i client per sfruttare tutte le funzioni messe a disposizione da SOAP.

Come vi dicevo dal lato server il codice php è semplice:

function sayHello($name){
    $salutation="Ciao ".$name.", sarai lieto di sapere che sto funzionando!";
    return $salutation;
}
$server= new SoapServer("test.wsdl");
$server->addFunction("sayHello");
$server->handle();

Il file xml per le dichiarazioni è invece un po’ più complesso ma con un po’ di attenzione non sarà difficile comprenderne il significato:

<?xml version="1.0" encoding="UTF-8" ?>
<definitions name="test"
targetNamespace="http://URL_CARTELLA_SERVER_SOAP"
xmlns:tns="http://URL_CARTELLA_SERVER_SOAP"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">

    <message name="sayHelloRequest">
        <part name="name" type="xsd:string"/>
    </message>
    <message name="sayHelloResponse">
        <part name="salutation" type="xsd:string"/>
    </message>

    <portType name="sayHelloPortType">
        <operation name="sayHello">
            <input message="tns:sayHelloRequest" />
            <output message="tns:sayHelloResponse" />
        </operation>
    </portType>

    <binding name="sayHelloBinding" type="tns:sayHelloPortType">
        <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
        <operation name="sayHello">
            <soap:operation soapAction="" />

            <input>
                <soap:body use="encoded" namespace="" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </input>
            <output>
                <soap:body use="encoded" namespace="" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" />
            </output>
        </operation>
    </binding>
    <documentation>UNA VOSTRA DESCRIZIONE DEL SERVIZIO</documentation>
    <service name="sayHelloService">
        <port name="sayHelloPort" binding="sayHelloBinding">
            <soap:address location="http://URL_SCRIPT_PHP_SERVER_SOAP" />
        </port>
    </service>
</definitions>

Fatto ciò, non ci resta che scrivere il codice per il client (tralascio il banale form html, ma metto a disposizione lo zip con tutto dentro):

$wsdl_url="http://URL_AL_DEL_FILE_WSDL";
if(isset($_POST['name'])){
    if($_POST['name']!=null){
        $client=new SoapClient($wsdl_url);
        print_r($client->sayHello(htmlentities($_POST['name'])));
    }
}

La cosa fondamentale per poter utilizzare SOAP è che il vostro php abbia l’estensione php_soap abilitata, ma se ho capito bene, da php6 viene inclusa di default tra le funzioni del core di php. Tra l’altro essendo inclusa nelle funzioni default di php è scritta in C per cui molto più veloce rispetto a scrivere codice php, di conseguenza, in queste applicazioni l’unico collo di bottiglia potrebbe essere la lentezza della linea o i tempi di ping/risposta di client e/o server.

Se siete pigri e volete testare il codice senza dovervi sbattere, eccolo qui, pronto per voi già impacchettato ;-)

Prossimamente testerò anche REST un altro metodo per realizzare web service con meno rogne, non serve infatti nessun file di dichiarazione, ma anche meno rigido e controllato.

Installare un server VPN con OpenVPN su Ubuntu Server

Qualche giorno fa, a lavoro ho configurato il mio primo server vpn. Avevamo la necessità di accedere alla rete dell’ufficio anche dall’esterno. Insomma ci avrebbe fatto comodo essere “virtualmente” in ufficio quando fisicamente non è possibile. Avevo ricevuto consigli in merito a queste necessità, e mi era stato detto che come OpenVPN non ce n’erano molti. Ovviamente Open VPN è un software gratuito e multipiattaforma, aveva quindi tutti i prerequisiti necessari per piacermi.

Diciamo che prima di intraprendere il lavoro ho perso qualche minuto a cercare la documentazione necessaria, che mi avrebbe accompagnato durante il cammino.

Inizialmente avevo preso un pc davvero modesto (con processore AMD Duron, qualcosa di simile al Sempron ma un po’ più vecchio ;-) ) con 40 ghiga di disco e 512 Mb di ram SO DIMM, credendo di usarlo come test per la macchina vera. Ovviamente ho installato Ubuntu server come sistema operativo, scaricando l’ultima versione (10.04) siccome è un LTS. Nell’installazione del S.O. non c’è stato alcun inghippo, oramai queste ultime versioni sono una pacchia, filano dritte dritte in pochi minuti verso il traguardo ;-).

Una volta installato Ubuntu ho seguito il wiki in inglese per la corretta installazione di open vpn. Come prima passo, la guida consiglia di configurare un bridge sulla scheda ethernet per consentire al segmento LAN di essere connesso al segmento WAN, consentendo (se si vuole) di filtrare i pacchetti che li attraversano con un firewall. Per fare ciò basta installare un pacchetto chiamato bridge-utils con il comando:

sudo apt-get install bridge-utils

Fatto ciò si deve editare il file di configurazione della rete con il comando:

sudo vim /etc/network/interfaces

modificarlo come segue:

auto lo
iface lo inet loopback

auto br0
iface br0 inet static
        address 192.168.0.10
        network 192.168.0.0
        netmask 255.255.255.0
        broadcast 192.168.0.255
        gateway 192.168.0.1
        bridge_ports eth0
        bridge_fd 9
        bridge_hello 2
        bridge_maxage 12
        bridge_stp off

Così facendo si assegna il bridge all’interfaccia eth0 con l’ip 192.168.0.10.

Adesso potete riavviare il servizio networking:

sudo /etc/init.d/networking restart

(per evitare di dover digitare sempre il comando sudo davanti ad ogni comando vi consiglio di digitare sudo su una volta per tutte)

Ora possiamo passare all’installazione vera e propria di OpenVPN:

apt-get install openvpn

Finita l’installazione del pacchetto creiamo una cartella che conterrà i programmi per generare le chiavi e le chiavi stesse:

cp -r /usr/share/doc/openvpn/examples/easy-rsa/2.0 /etc/openvpn/
mv /etc/openvpn/2.0 /etc/openvpn/easy-rsa

Dopodichè editiamo il file vars in modo da modificare le seguenti linee con le informazioni che ci riguardano:

export KEY_COUNTRY="US"
export KEY_PROVINCE="NC"
export KEY_CITY="Winston-Salem"
export KEY_ORG="Example Company"
export KEY_EMAIL="steve@example.com"

Salvate il file e chiudetelo. Accertandovi di essere loggati come utente di root, iniziate la procedura di generazione delle chiavi:

cd /etc/openvpn/easy-rsa/
source ./vars
./clean-all
./build-dh
./pkitool --initca
./pkitool --server server
cd keys
openvpn --genkey --secret ta.key
cp server.crt server.key ca.crt dh1024.pem ta.key /etc/openvpn/

Ora che abbiamo generato le chiavi e i certificati per il server procediamo a generare quelli per il client (basterà ripetere la prossima procedura modificando l’identificativo del client per generare altre chiavi/certificati):

cd /etc/openvpn/easy-rsa/
source vars
./pkitool client1

Copiate ora sul client i file:

  • /etc/openvpn/ca.crt
  • /etc/openvpn/easy-rsa/keys/client1.crt
  • /etc/openvpn/easy-rsa/keys/client1.key
  • /etc/openvpn/ta.key

Ora non ci resta che editare i file di configurazione per server e client (partiamo da una configurazione di esempio):

cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/
gzip -d /etc/openvpn/server.conf.gz
vim /etc/openvpn/server.conf

Accertatevi di correggere le seguenti linee con i vostri dati:

local 192.168.0.10
dev tap0
script-security 3
up "/etc/openvpn/up.sh br0"
down "/etc/openvpn/down.sh br0"
proto tcp
;server 10.8.0.0 255.255.255.0
server-bridge 192.168.0.10 255.255.255.0 192.168.0.100 192.168.0.110
push "route 192.168.0.1 255.255.255.0"
tls-auth ta.key 0 # This file is secret
user nobody
group nogroup
cipher AES-256-CBC

La voce local sarà quella corrispondente all’indirizzo del vostro bridge, come la prima voce accanto a server-bridge. La seconda voce di server-bridge sarà la subnet mask mentre la terza e la quarta sarà il range di ip che openvpn assegnerà ai client che si connetteranno alla rete.
Il comando push “route… servirà per creare una rotta sugli indirizzi della LAN.
Fatto ciò, creiamo i due script per l’avvio e la chiusura dell’interfaccia virtuale (la tap0 che vedete nel file di configurazione). Creiamo il file up.sh come segue:

vim /etc/openvpn/up.sh
#!/bin/sh
BR=$1
DEV=$2
MTU=$3
/sbin/ifconfig $DEV mtu $MTU promisc up
/usr/sbin/brctl addif $BR $DEV

e il file down.sh così:

vim /etc/openvpn/down.sh
#!/bin/sh
BR=$1
DEV=$2
/usr/sbin/brctl delif $BR $DEV
/sbin/ifconfig $DEV down

Rendiamoli eseguibili:

chmod 755 /etc/openvpn/down.sh
chmod 755 /etc/openvpn/up.sh

Ora che il server è correttamente configurato, possiamo dare una riavviata al servizion openvpn:

/etc/init.d/openvpn/restart

Adesso passiamo al file di configurazione del client:

sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn

Il quale dovrà contenere:

dev tap
proto tcp
remote 192.168.0.10 1194
cert client1.crt
key client1.key
tls-auth ta.key 1
cipher AES-256-CBC

Ora copiate nella cartella di configurazione del client il file appena editato (chiamatelo client1.conf o client1.ovpn). Ovviamente si presuppone che i file delle chiavi e dei certificati siano nella stessa cartella di quest’ultimo file (sul client). Riavviate anche qui openvpn e il gioco è quasi fatto. Dico quasi perchè per potervi connettere al server dall’esterno dovrete dire al vostro router di aprirvi la porta 1194 e reindirizzare il traffico proveniente dall’esterno verso l’ip 192.168.0.10 (quello del bridge).

Ora siete davvero pronti per collegarvi dall’esterno alla vostra LAN (così com’è stato configurato openvpn non è possibile accedere da dentro la LAN alla vpn appena creata).

Spero di non aver dimenticato niente! ;-)

Che ve ne pare?

Pollycoke sta tornando…

A quanto pare, l’abbassamento delle luci sul miglior sito italiano del mondo “linux-e-non-solo” era solo (come tutti noi speravamo) temporaneo, e come scritto dal buon Felipe nell’ultimo articolo (datato 19/01/2009), sembra che qualcosa si stia muovendo.

Intanto ci suggerisce di aggiornare i puntatori al suo blog cambiando l’url dal vecchio pollycoke al nuovo-vecchio pollycoke.org.

In attesa del completamento delle operazioni preliminari sul nuovo dominio, io ho ascoltato il consiglio, e ora aspetto di vedere tutte le altre novità per poter definitivamente dire “bentornato pollycoke”!
[ad]