Confessioni di un consulente IT

Pianificazione

Posted in Musica, Project Management by pigreco314 on 30 maggio, 2009

Il Tour Production Manager dei Radiohead, Richard Young, parla in un breve articolo dei problemi logistici che deve affrontare per la pianificazione del prossimo tour della band.

I Radiohead hanno deciso infatti di limitare al massimo l’emissione di anidride carbonica coinvolta nello svolgimento del tour e ha posto il vincolo che l’equipaggiamento utilizzato negli spettacoli (strumenti, sistema di luci, ecc.) non deve essere trasportato per via aerea.

Che fareste voi per limitare i costi, rispettare le date e assicurarvi che la band disponga dei propri rarissimi microfoni in ogni data del tour?

Mentre ci pensate su, potete godervi la musica e le immagini di “Pyramid Song” dall’album Amnesiac.

Alla rovescia

Posted in Consulenti, G.M., Progetti, Storie Aziendali by pigreco314 on 20 maggio, 2009
 Relax © by ailatan

Relax © by ailatan

Forse ci siamo, forse incrociando dita, falangi, falangine, falangette e polpastrelli riusciamo a chiudere il dannatissimo progetto K**, difficilissimo Cliente di L*, Germania.

La firma che ci avrebbe permesso di fatturare il residuo sarebbe dovuta arrivare due , quattro no aspetta, sette… un numero imprecisato di mesi fa e invece probabilmente arriverà domani, dopodomani… insomma un giorno della prossima settimana sicuramente.

Avrete capito che trattasi di progetto travagliato, che ha visto coinvolte un discreto numero di persone impegnate a portare a casa un risultato utile, tra cui, in veste di protagonista, l’ormai mitico G.M. Di recente si è aggiunto anche il nuovo acquisto in casa Sales, il promettente A.D., come “supportante” Account Manager.

Negli ultimi 5 mesi con questo Cliente non si è fatto altro che negoziare al mercato delle “issues”: “no questo non è un problema causato dal nostro software bensì dalla vostra infrastruttura di rete”, “questo non l’avevate chiesto e quindi non ve lo sistemiamo a meno che non ci paghiate l’intervento”, “no questo non lo firmo perché non c’è il sotto-vice-assistente-precario del responsabile” (cliente pubblico) ecc.

Suona quindi strano che  presso un Cliente così problematico in una fase così delicata del progetto si organizzi una dimostrazione di un modulo software di analisi statistica e reportistica avanzata per il quale quelli di K** hanno manifestato un notevole interesse. Organizzatori: G.M. e A.D., il dinamico duo.

Della serie: prima risolviamo la faccenduola relativa alla chiusura del progetto e poi vi facciamo vedere tutto quello che volete, vi contiamo in diretta anche i pixel dell’interfaccia grafica utente se volete. Dopo però.

Saltiamo qualche passaggio e diciamo che stando ai resoconti del dinamico duo il Cliente firmerà la chiusura del progetto, consentendoci di fatturare il residuo e pure ordinando un giorno di consulenza per una micro attività aggiuntiva.

Curioso il modo in cui A.D. riporta la notizia, al termine della riunione di ieri:

Vi informo che siamo riusciti nel nostro intento di generare interesse presso K** circa i software X e Y, cosa che era l’obiettivo primario (sic!) della riunione. Tra le altre cose, abbiamo poi stabilito una relazione col Cliente (questa non l’ho capita bene) il quale ha accennato al fatto che firmerà la chiusura del progetto blah blah…

Ovviamente sono sicuro del fatto che l’entusiasmo del dinamico duo è ben motivato e che tra poco vedrò materializzare nella mia inbox (o nel mio GTalk, veggasi articoli sul bot) il pezzo di carta firmato, tuttavia la differenza di prospettiva rispetto a cosa sia veramente importante in una situazione è cosa che colpisce.

PS: alla fine della giornata di lavoro di oggi (20/05), nessuna traccia del pezzo di carta. Seguiranno aggiornamenti.

PPS: nulla nemmeno a tutto il 25/05

PPPS: 28 maggio, giornata storica il sign-off è arrivato!!!!!

PPPPS: non ci credo: abbiamo chiuso il progetto e fatturato il 29 maggio 2009

Progetto GTalk Bot #3

Posted in Geek Corner, Programmazione by pigreco314 on 20 maggio, 2009

Nell’ultimo mese il progetto GTalk Bot è proseguito seguendo ramificazioni inattese ma assai feconde.GTalk Bot

Quei quattro lettori che mi seguono sapranno senz’altro di che progetto sto parlando. Per gli ospiti di passaggio è disponibile la serie delle due puntate precedenti (parte #1 e parte #2)

Nella versione attuale (ancora piuttosto alfa) il bot ha migliorato il supporto LDAP e ora accetta anche query complesse, permettendo amenità varie come estrarre la lista di tutti i riporti di un determinato manager con un comando del tipo:

d -q "manager=Mario Rossi"

Vi ricordo che la sintassi è totalmente arbitraria (il "dir" del post precedente si è contratto in "d" per comodità di digitazione sui dispositivi mobili)

Visto che un pezzo della Corporation sta su Active Directory ho dovuto estendere il supporto delle query LDAP su un secondo server, cosa che, con l’aiuto di uno dei tanti tool di esplorazione LDAP, è risultata particolarmente semplice in quanto l’unica modifica ha riguardato la modalità di autenticazione e il “base dn”.

Ma la cosa di cui vado particolarmente fiero è l’interfaccia con Outlook 2007 (o meglio Exchange 2007) implementata tramite invocazione dei web services di Exchange su protocollo SOAP, risultato che mi è costato qualche notte insonne e un cambio abbastanza radicale in termini di design.

Python e SOAP

L’idea iniziale di utilizzare una soluzione basata su weboutlook si è rivelata poco praticabile e un po’ troppo rozza (sostanzialmente effettua un parsing della pagina web di Outlook Web Access).

I web services di Exchange di 2007 sono invece splendidamente documentati. Il problema quindi si “riduceva” a implementare in Python (il linguaggio con cui avevo iniziato a sviluppare il bot) le chiamate SOAP ai servizi di Exchange.

Seguendo l’eccellente introduzione di Dive Into Python ho cominciato a sperimentare SOAP su python. Dopo aver appreso le basi, ho tentato di attaccare i web services di Exchange con scarsi e snervanti risultati. Purtroppo il debugging di una applicazione SOAP non è per niente banale. Le librerie SOAP di Python che vanno per la maggiore sono due:

  • SOAPpy: abbastanza semplice da usare scarsamente documentata e credo non più sviluppata
  • ZSI: ben documentata (ma vi serve qualche base di SOAP) e attivamente sviluppata

Quando dal debugging della mia applicazione sono passato al debugging delle librerie medesime per risalire alla causa di certi errori (anche il passaggio dei tipi di variable complessi via SOAP può diventare un incubo) ho pensato che forse il supporto SOAP di Python non era sufficientemente maturo per i miei scopi.

Php

L’articolo Talking SOAP with Exchange ha attirato la mia attenzione su Php che già conoscevo come linguaggio di scripting per applicazioni web.

Vi si descrive più o meno quello che mi serviva, ossia implementare un client SOAP per servizi Exchange 2007. Il ché mi ha indotto a considerare l’ipotesi di scrivere in Php un front-end semplificato per i servizi di Exchange e fare in modo che il bot Gtalk scritto in Python consumasse questi web services surrogati invece degli originali più complessi.

In realtà Php, dalla versione 4.3.0, può essere utilizzato anche per realizzare script eseguibili dalla linea di comando senza necessariamente utilizzarlo all’interno di un web server, assumendo così dignità di linguaggio di scripting di sistema alla pari di python, perl ecc.

Mi sono pertanto chiesto se per caso qualche anima pia non avesse anche provveduto a sviluppare un supporto Php per XMPP/Jabber, il protocollo di Google Talk.

Si dà il caso che grazie al lavoro Nathan Fritz (per sempre grato,Nat!), Php supporti il protocollo XMPP/Jabber.

A quel punto, l’idea di scrivere il GTalk Bot in Php ha preso forma.

Mi spiaceva un po’ abbandonare l’approccio di python-jabberbot e il suo elegante meccanismo di funzioni callback e quindi, come prima cosa, ho riscritto jabberbot in Php (a breve penso di pubblicarlo su Google Code).

Con il php-jabberbot, creare un bot Google Talk che ritorni lo user Id del proprio interlocutore e dica che ore sono è semplice come scrivere:

<?php

include "jabberbot.php";

class GtalkBot extends JabberBot {

public function bot_hello($msg,$args) {

list($jid,$client)=split("/",$msg['from']);

return "Hello $jid , it is now ".strftime("%H:%M:%S %d/%b/%Y");

}

}

$gtb = new GtalkBot(<username_gtalk>,<password_gtalk>');

$gtb->serve_forever();

?>

Collegandosi a Google Talk con un secondo account e aprendo una chat con l’utente fittizio utilizzato dal bot, digitando il messaggio “hello”, il nostro amico risponderà salutandovi cortesemente e ragguagliandovi circa ora e data in uso sul proprio server.

Se avete urgenza di mettere le mani sul codice di php-jabberbot è sufficiente che lasciate un commento a questo post.

Php e NuSOAP

Torniamo a SOAP ed Exchange. L’articolo Talking SOAP with Exchange sopracitato è un ottima introduzione al tema ma ha il difetto di basarsi sull’estensione SOAP di PHP 5 che non supporta l’autenticazione NTLM richiesta da Exchange (l’articolo fornisce anche la soluzione a questo problema).

In realtà, di librerie SOAP per Php ve ne sono almeno tre:

  • la già citata estensione SOAP di PHP 5 (su Windows è la dll php_soap.dll)
  • il package PEAR:Soap
  • la libreria NuSOAP (la versione che ho scaricato dal repository reca numero 0.7.3)

La terza è quella con cui mi sono trovato meglio: buona documentazione, supporto autenticazione NTLM nonché Basic HTTP e sufficiente diagnostica per il debugging.

Ho quindi iniziato a sperimentare NuSOAP con alcuni web services disponibili in rete (per esempio XMethods.net).

Php, NuSOAP e Exchange 2007

Rinfrancato dai primi successi, sono passato a studiare la documentazione disponibile e a fare qualche esperimento infastidendo il nostro server Exchange 2007.

La faccio breve e vi presento qui sotto un esempio di come sia possibile usare NuSOAP per interrogare Exchange e ottenere informazioni sui messaggi non letti presenti nella vostra casella di posta elettronica.

Personalmente ho trovato l’introduzione a SOAP di Dive Into Python (anche se centrata su Python) più che sufficiente per i miei scopi. Qualunque altra introduzione all’argomento va bene. I concetti che vi servono sono il meccanismo Request/Response di SOAP, il modo in cui i messaggi vengono formattati in XML e i descrittori di webservices WSDL.

Le interrogazioni di questo esempio useranno l’approccio WSDL.

Gli ingredienti:

  • un server Exchange 2007 (es. https://exchange.example.com) e relativo account; inoltre dovrete farvi dire quale tipo di autenticazione è configurata sul server (nel mio caso Basic HTTP, altra possibile opzione è NTML)
  • PHP 5
  • NuSOAP 0.7.x: io sto usando la 0.7.3
  • Php_curl: l’unica dipendenza richiesta da NuSOAP

Anche se il bot verrà messo in produzione su Linux, in fase di test opero in ambiente Windows:  I love  scripting languages!

Cominciate a procurarvi i seguenti file dal vostro server Exchange. Dovrebbero essere reperibili agli indirizzi indicati qui sotto:

Salvateli in una directory locale nel vostro ambiente di sviluppo. Questi file XML contengono le specifiche dei web services esposti da Exchange. Teoricamente non è necessario utilizzarli localmente, tuttavia, secondoTalking SOAP with Exchange, il wsdl di Exchange 2007 è malformato (!) in quanto mancante di una dichiarazione senza la quale non si ha conformità con le specifiche SOAP. In effetti, se provate a usare il file così com’è, le interrogazioni SOAP falliscono. La soluzione più semplice, una volta salvato il file in locale, è aggiungervi in coda la parte mancante come riportato qui sotto e nell’articolo (sostituite ovviamente il nome del server con quello reale):

<wsdl:service name="ExchangeServices">

<wsdl:port name="ExchangeServicePort" binding="tns:ExchangeServiceBinding">

<soap:address location=

"https://exchange.esempio.com/EWS/Exchange.asmx"/>

</wsdl:port>

</wsdl:service>

<!-- la riga successiva dovrebbe già essere nel vostro file WSDL -->

</wsdl:definitions>

Autenticazione

Nel frammento qui sotto, si spiega come usare NuSOAP per autenticarsi in Basic HTTP sul server Exchange:

require_once('nusoap.php');

//percorso dove avete salvato il file wsdl, i file .xsd verranno cercati nella medesima directory:

$client = new nusoap_client('file://c:/Temp/Services.wsdl',true);
$err = $client->getError();
if ($err) {
print "\nClient error". $err . ".\n";
}

//basic HTTP autentication:

$client->setCredentials ('username','password','basic');

Il client è pronto per inviare interrogazioni al server Exchange.

“Request

Esaminando la documentazione dei web services di Exchange scopriamo che la operation FindItem, ritorna i messaggi contenuti in un determinato folder Outlook.

La richiesta deve rispettare questa struttura:

<FindItem Traversal="Shallow">

<ItemShape>

<t:BaseShape>Default</t:BaseShape>

</ItemShape>

<!-apre la dichiarazione per una condizione di ricerca -->
<Restriction>
<!-apre una clausola di euguaglianza -->

<t:IsEqualTo>

<FieldURI FieldURI="message:isRead"/>

<!-message:isRead deve essere zero,ovvero messaggio non letto-->

<FieldURIOrConstant><Constant Value="0"/>

</FieldURIOrConstant>

</t:IsEqualTo>

</Restriction>

<ParentFolderIds>

<!-identifica il folder-->

<t:DistinguishedFolderId Id="inbox"/>

</ParentFolderIds>

</FindItem>

Con NuSOAP, la “request” qui sopra si può costruire creando diversi oggetti soapval innestati, partendo da quelli più interni:

$BaseShape = new soapval(

// nome dell'oggetto come da struttura sopra:

'BaseShape',

// nome del tipo: si ricava dalla documentazione Microsoft:

'DefaultShapeNamesType',

// valore: si ricava dalla documentazione Microsoft

'AllProperties',

// namespace del tipo:si ricava dalla documentazione Microsoft
// ho riscontrato che l'interrogazione fallisce se non
// viene specificato

'http://schemas.microsoft.com/exchange/services/2006/types',

// namespace dell'elemento (opzionale):si ricava dalla
// documentazione Microsoft

false,

// eventuali attributi dell'elemento

false);

 

$ItemShape = new soapval ('ItemShape',

'ItemResponseShapeType',

// ItemShape contiene BaseShape come valore:

$BaseShape,

'http://schemas.microsoft.com/exchange/services/2006/messages',

false,

false);


$FieldURI = new soapval('FieldURI',

'PathToUnindexedFieldType',

// l'elemento FieldURI non ha valore bensì un attributo (vedi sotto)

'',

'http://schemas.microsoft.com/exchange/services/2006/types',

false,

// attributo FieldURI dell'elemento FieldURI
// incidentalmente hanno lo stesso nome
// per la dichiarazione si usa il formato chiave=>valore: 

array('FieldURI'=>'message:IsRead'));

 

$Constant = new soapval('Constant',

'ConstantValueType',

'',

'http://schemas.microsoft.com/exchange/services/2006/types',

false,

array('Value'=>'0'));

 

$FieldURIOrConstant = new soapval('FieldURIOrConstant',

'FieldURIOrConstantType',

$Constant,

'http://schemas.microsoft.com/exchange/services/2006/types',

false,

false );

 

$IsEqualTo = new soapval('IsEqualTo',

'IsEqualToType',

array($FieldURI,$FieldURIOrConstant),

'http://schemas.microsoft.com/exchange/services/2006/types',

false,

false);

 

$Restriction = new soapval('Restriction',

'RestrictionType',

$IsEqualTo,

'http://schemas.microsoft.com/exchange/services/2006/messages',

false,

false);

$DistinguishedFolderId = new soapval('DistinguishedFolderId',

'DistinguishedFolderIdType',

'',

'http://schemas.microsoft.com/exchange/services/2006/types',

false,

array('Id'=>'inbox'));

 

$ParentFolderIds = new soapval('ParentFolderIds',

'NonEmptyArrayOfBaseFolderIdsType',

$DistinguishedFolderId,

'http://schemas.microsoft.com/exchange/services/2006/messages',

false,

false);

 

$FindItem = new soapval('FindItem',

'FindItemType',

// quando l'elemento contiene più sottoelementi,
// questi vengono combinati in un array:

array($ItemShape,$Restriction,$ParentFolderIds),

'http://schemas.microsoft.com/exchange/services/2006/messages',

false,

array('Traversal'=>'Shallow'));

 

 

A questo punto la variabile $FindItem contiene la nostra richiesta. Rimane solo da inviarla al server. Ecco come fare:

$xmlout = $FindItem->serialize('literal');

$items=$client->call('FindItem',$xmlout);

$err = $client->getError();

if ($err) {

print "\nMethod error". $err . ".\n";

}

// nel caso vogliate esaminare la struttura della risposta del server:

//print_r($items);

“Response

La documentazione di Microsoft riporta anche le specifiche dettagliate delle risposte del server.

Queste vengono astratte da NuSOAP sotto forma di array innestati. Vi rimando alla documentazione o alle prove sul campo per i dettagli.

Mi limito qui a riportare il codice che potete utilizzare per stampare le informazioni relative ai messaggi non letti presenti nella inbox e ritornati nella variabile $items di cui sopra:

// numero di messaggi trovati

$num_items =  $items['ResponseMessages']['FindItemResponseMessage']['RootFolder']['!TotalItemsInView'];

// loop sui messaggi: attenzione, questo loop
// funziona solo se $num_items > 1.
// occorre gestire il caso 0 o 1 messaggio separatamente

foreach ($items['ResponseMessages']['FindItemResponseMessage']['RootFolder']['Items']['Message'] as $message) {

print "Subject: ". $message['Subject']. "\n" .

"From: ". $message['From']['Mailbox']['Name']. "\n" .

"Size: ". $message['Size']. "\n" .

"Date Sent: ". $message['DateTimeSent']. "\n" .

"Date Created: ". $message['DateTimeCreated']. "\n" .

}

Oltre

Ricapitoliamo.

Con questa soluzione posso accedere via instant messaging di GTalk a una serie di servizi disponibili normalmente solo all’interno della nostra rete aziendale, come info LDAP e posta.

In realtà, la recente migrazione ad Outlook 2007 (un altro pianeta rispetto a Lotus Notes) ha reso questa necessità meno impellente  in quanto finalmente, dopo anni, possiamo accedere alla nostra posta via Web fuori dalla VPN grazie a Outlook Web Access su https. Ho già sperimentato l’interfaccia utente su iPod Touch (dal Nokia E65 ho un problema di cookie).

L’interrogazione via instant messaging può però in diversi casi essere più agevole e immediata e consentire anche interessanti estensioni che coinvolgano il servizio Twitter. Il bot potrebbe infatti mettersi in ascolto di un account twitter fittizio al quale inviare messaggi via SMS. Questi messaggi verrebbero in realtà interpretati come comandi da eseguire esattamente come se l’interazione avvenisse via IM. Come gestire l’invio delle risposte in questo caso? Ovviamente sempre via SMS, usando una SIM dedicata collegata al server su cui gira il bot o un interessante side effect di Google Calendar.

Ma questo è materiale per il prossimo articolo.