lunedì 26 maggio 2014

Patch GhettoVCB

GhettoVCB è uno script sviluppato da William Lam, che permette di eseguire il backup delle virtual machine virtualizzate dal VMM di vmware.
In questo contesto per backup si intende il clone della virtual machine salvata in un qualche storage eventualmente definito come parametro di backup.

Nella versione 2 lo script, prima di effettuare il backup, si preoccupa di eliminare tutte le snapshot associate alla virtual machine.

Questo comportamento può portare a spiacevoli situazioni, nel caso la snapshot in oggetto sia un backup applicativo da mantenere per un eventuale restore.

Per ovviare a questo comportamento, propongo la seguente patch.
L'intento è di eliminare le snapshot che lo script ghettoVCB.sh esegue prima del backup e che possono rimanere associate alla virtual machine per un qualche motivo imprevedibile; ad esempio se lo script viene terminato a metà della sua esecuzione. Mantenendo invece le snapshot dell'utente.

A questo punto è doverosa una precisazione in merito.
Quando si associa una snapshot alla virtual machine, le nuove modifiche saranno registrate su questa snapshot e non al disco virtuale della macchina (che subisce il backup), ne consegue che un backup in presenza di snapshot non può che essere un backup della virtual machine precedente alla prima snapshot.
In questo caso il comportamento è come nella versione precedente: il backup fallisce.

La patch altro non fa che controllare il nome della snapshot, e nel caso inizi con la stringa "ghetto" la elimina:
--- ghettoVCB.sh    2014-05-22 17:13:35.194285000 +0200
+++ ghettoVCBpatching.sh    2014-05-26 17:46:43.723052158 +0200
@@ -910,8 +910,9 @@
                     logger "info" "Snapshot found for ${VM_NAME}, backup will not take place\n"
                     VM_FAILED=1
                 elif [ ${ALLOW_VMS_WITH_SNAPSHOTS_TO_BE_BACKEDUP} -eq 1 ]; then
-                    logger "info" "Snapshot found for ${VM_NAME}, consolidating ALL snapshots now (this can take awhile) ...\n"
-                    $VMWARE_CMD vmsvc/snapshot.removeall ${VM_ID} > /dev/null 2>&1
+                    logger "info" "Snapshot found for ${VM_NAME}, remove snapshot now (this can take awhile) ...\n"
+                    SNAP_GHETTO=`$VMWARE_CMD vmsvc/snapshot.get ${VM_ID} | awk -F: '/^ghetto*/ && $0 != "" { getline; print $2}'`
+                    for snap_n in $SNAP_GHETTO;do $VMWARE_CMD vmsvc/snapshot.remove ${VM_ID} $snap_n;done
                 fi
             fi
             #nfs case and backup to root path of your NFS mount
Ovviamente l'eventuale snapshot che si vuole mantenere non dovrebbe iniziare con la parola chiave "ghetto". Nel caso, si dovrà modificare il "nome snapshot" dato dallo script:

if [[ ! ${POWER_VM_DOWN_BEFORE_BACKUP} -eq 1 ]] && [[ "${ORGINAL_VM_POWER_STATE}" != "Powered off" ]]; then
                    SNAPSHOT_NAME="ghettoVCB-snapshot-$(date +%F)"
                    logger "info" "Creating Snapshot \"${SNAPSHOT_NAME}\" for ${VM_NAME}"
                    ${VMWARE_CMD} vmsvc/snapshot.create ${VM_ID} "${SNAPSHOT_NAME}" "${SNAPSHOT_NAME}" "${VM_SNAPSHOT_MEMORY}" "${VM_SNAPSHOT_QUIESCE}" > /dev/null 2>&1


Preferendo a vmware tecnologie quali L4, LDOM ed exokernel vari, le quali architetture sono incomparabilmente più eleganti, ... concludo il post con una celebre frase ironica del venerabile Knuth.

"Beware of bugs in the above code; I have only proved it correct, not tried it."






venerdì 26 luglio 2013

EIGRP 'no auto-summary'

Recentemente mi sono trovato a discutere - in un qualche forum - della necessità di eseguire un
# no auto-summary
per una configurazione Cisco in merito al riepilogo di rete del protocollo EIGRP. All'utente non risultava chiaro il significato di questo comando.

Si tratta, al solito, di risolvere problematiche di retrocompatibilità utili più al mass marketing che non al servizio in sè, ma questo si sa, è una vecchia storia....

EIGRP protocollo di routing proprietario Cisco è il successore dell'ormai obsoleto IGRP.
Tra le disgrazie, EIGRP eredita dal progenitore il protocollo classful in fase di riepilogo di rete (summarization).


Con il metodo classful, gli aggiornamenti di routing inviati tra i router non contengono informazioni sulle subnet mask, in quanto implicitamente riconosciute come reti di classe A, B, C a seconda dei casi. Ne consegue che se ci troviamo a gestire due sottoreti, come ad esempio 172.16.1.0/24 e 172.16.2.0/24 connesse da un'ulteriore rete, ad esempio 192.168.0.0/24, con EIGRP e l'auto summary abilitato, il risultato sarà quello illustrato in questa figura:



Le reti 172.16.1.0/24 e 172.16.2.0/24, saranno pubblicizzate al Router_A come reti di classe B: 172.16.0.0/16.
Questo implica conseguenze facilmente immaginabili; il Router_A avrà seri problemi di raggiungibilità per le reti suddette....
Per sopperire a questa "imprevista circostanza" bisogna evitare la procedura di auto summarization da parte del router.
Tale impostazione viene abilitata tramite il comando no auto-summary.

Router(config) # router eigrp as_num
Router(config-router) # no auto-summary 

A seguito di questa modifica, il Router_A riceverà le route corrette per raggiungere le due reti 172.16.1.0/24 e 172.16.2.0/24; il contesto di quanto detto è chiarito da questa figura:


giovedì 27 giugno 2013

Oracle database in backup mode

Durante la mia consulenza su database Oracle, mi è capitato di diagnosticare database in backup mode; ovvia conseguenza di un backup terminato in modo non corretto...
Se ci troviamo a gestire una versione uguale/superiore alla 10g, un semplice

SQL>  ALTER DATABASE END BACKUP;

risolverà il problema (vedi con select * from v$backup), ma per le versioni precedenti, il lavoro diventa più operoso: dovremo tablespace per tablespace eseguire un END BACKUP.

Vediamo di facilitare il compito con uno script che chiamo end_backup.sql.

rem -----------------------------------------------------------------------
rem Filename:   end_backup.sql
rem Purpose:    This script will create a file called end_backup_script.sql
rem                - run it to take all tablespaces out of backup mode.
rem -----------------------------------------------------------------------

column cmd format a80 heading "Text"
set feedback off
set heading  off
set pagesize 0

spool end_backup_script.sql

select   'alter tablespace '||a.tablespace_name||' end backup;' cmd
from     sys.dba_data_files a, sys.v_$backup b
where    b.status = 'ACTIVE'
and      b.file#  = a.file_id
group by a.tablespace_name
/

spool off

set feedback on
set heading  on
set pagesize 24
set termout  on

start end_backup_script.sql



Salviamo lo script in un file, diciamo $ORACLE_HOME/end_backup.sql ed eseguiamo l'accesso nel database con sqlplus utente sys as sysdba.

Una volta entrati nella shell sql lanciamo

SQL> @?/end_backup.sql

Verifichiamo lo stato del database con

SQL> SELECT * FROM V$BACKUP;

NOT ACTIVE = non in backup mode.

venerdì 7 giugno 2013

Debian GNU/Hurd, la rivincita del micro?

Il 23 Maggio è stata rilasciata la distribuzione Debian con kernel GNU/Hurd: un travaglio!
Ormai da più di vent'anni la comunità della Free Software Foundation stava lavorando a questo kernel, che nelle intenzioni di Richard Stallman doveva essere il nucleo pulsante di GNU.

L'architettura del kernel negli anni è stata implementata in diverse versioni; inizialmente basata su kernel Mach, poi L4 ed infine Coyotos (successore di EROS).

Dalle note di rilascio, si evince la scelta iniziale: il kernel Mach; ma cos'è questo GNU/Hurd e perché non è poi così significativo il suo rilascio?

Kernel Monolitico
Un sistema operativo dovrebbe, come prima funzionalità, essere affidabile e funzionare senza problemi, ma, sfortunatamente, i sistemi operativi di oggi disattendono queste prospettive (il riferimento è al mercato mainstream/enterprise).
Le maggiori problematiche, derivano in primis proprio dall'architettura monolitica dei più comuni sistemi oggi in produzione.
In un sistema monolitico (come il kernel Linux, seppur modulare), il sistema operativo è un unico blocco di codice eseguito in modalità privilegiata che implementa tutte le funzionalità tipiche di un sistema operativo.
Ergo, tutte queste funzioni in kernel-mode non garantiscono un isolamento al fault del codice, perciò ogni bug può potenzialmente compromettere l'intero sistema. Molti ricercatori hanno evidenziato come il 70-80% dei casi di panic del kernel, derivino dai driver eseguiti in kernel-mode.

Kernel Single-Server
Il Single-Server è un kernel ridotto che esegue un sistema monolitico in user-mode. Sfortunatamente, l'affidabilità del sistema non si discosta di molto da un sistema monolitico in quanto anche in questa architettura è presente un 'single point of failure'.
Esempi di kernel Single-Server sono considerati il Mach-UX e il L4Linux.
Per la cronaca, uno dei primi sistemi Single-Server fu il Mach-UX che eseguiva un BSD sopra ad un Mach 3 a microkernel, noto ai più per le sue basse performance: circa 50% più lento della versione normale del BSD.



Kernel Multiserver
L'architettura dominante nelle installazioni mission critical real time (RTOS) è data da sistemi Multiserver System a microkernel (QNX, LynxOS, per citarne un paio), dove un qualsivoglia software di terze parti è destinato a lavorare isolato in user-mode.
Un kernel di questo tipo non dovrebbe superare le 50000 linee di codice (per i monolitici siamo oltre i 7 milioni), cosa che rende il sistema agevolmente comprensibile e di facile manutenzione.
Come esempio, prendo in esame il microkernel di Minix 3 un sistema operativo UNIX-like in grado di perdurare al crash di componenti critici, come ad esempio un device driver.


Il kernel di Minix è costituito solo dal gestore IRQ, IPC e da uno scheduler più due kernel task: SYS e CLOCK. Tutto il resto (Networking, File system, Drivers, ecc.) gira al difuori del kernel in user-mode, incapsulato in uno spazio di indirizzi privato che viene protetto dall'hardware attraverso l'MMU. In questo modo, è garantita un'alta affidabilità del sistema.

I detrattori del microkernel hanno sempre sostenuto che questo modo di agire penalizzava fortemente le performance. Se ciò poteva essere vero negli anni '80, ad oggi è solo uno sproposito, basti pensare al utilizzo di QNX per alcuni apparati Cisco (IOS XR): ...possiamo credere che Cisco è certamente interessata alle performance!


Affidabilità dunque è il tema dominante e GNU/Hurd è un microkernel multiserver rilasciato sotto licenza GPL con l'aspirazione di scalzare il dominio del kernel Linux sul software GNU.

Il progetto però è in costante ritardo e si deve misurare con altri progetti simili e ben più blasonati, già consolidati nel mercato embedded. Rimane da conquistare il mercato mainstream ed enterprise. Omnia cum tempora...


sabato 20 aprile 2013

Port Address Translation? No, Puoi Anche Trascurarlo

Viste le tante definizioni di PAT che ho sentito nelle mie attività di consulente, faccio fede a quanto dichiara Cisco:

Port Address Translation (PAT) is a feature of a network device that translates TCP or UDP communications made between hosts on a private network and hosts on a public network. It allows a single public IP address to be used by many hosts on the private network, which is usually called a Local Area Network or LAN. ...

Argomento certo nobile.

Supponiamo di avere due device con ip 10.0.0.1 e 10.0.0.2 che accedono ad Internet attraverso un router NAT con un ip pubblico 88.88.88.1.
Quando l'ip 10.0.0.1 vuole accedere ad un web server, come ad esempio www.google.it, il datagramma viene inviato al router NAT che sostituisce l'ip sorgente con il suo ip pubblico (88.88.88.1) e come porta sorgente mantiene quella del device, supponiamo 5000, così rappresentata nella tabella di NAT:
10.0.0.1:5000 to 88.88.88.1:5000     --->     IPgoogle:80
Diciamo che nello stesso momento il device 10.0.0.2 invia una richiesta a www.google.it; come detto in precedenza,  il router sostituisce l'ip sorgente con 88.88.88.1 e mantiene la porta sorgente del device, supponiamo 5001, così rappresentata nella tabella di NAT:
10.0.0.2:5001 to 88.88.88.1:5001     --->     IPgoogle:80
Quando il pacchetto ritorna al router, avrà come ip di destinazione 88.88.88.1 e come porta di destinazione 5000 o 5001. In questo modo il router riesce a decidere se il datagramma va inoltrato al device 10.0.0.1 o 10.0.0.2 basando cioè la sua decisione sulla porta di destinazione (demultiplexing).
Ma cosa succede se entrambi i device usano la porta 5000 come porta sorgente?
A questo punto il router non sarà più in grado di distinguere le due connessioni.

La soluzione è implementare nel router la funzione di sostituzione della porta sorgente; in questo contesto, se il device 10.0.0.1 invia una richiesta web a www.google.it, il router sostituirà la porta sorgente con una presa tra un intervallo compreso tra 1024:65535. Ad esempio:
10.0.0.1:5000 -> 88.88.88.1:5550
Se nello stesso momento il secondo device inviasse una richiesta a www.google.it, il router andrà a generare una tabella di NAT tipo:
10.0.0.2:5000 -> 88.88.88.1:5551
Con questa definizione, quando il pacchetto ritorna dal web server avrà come destinazione 88.88.88.1:5550 oppure 88.88.88.1:5551. è chiaro che in questo modo il router sarà in grado di inoltrare il pacchetto al device corretto.

Tutto ciò è stato affrontato e risolto dalle specifiche NAT - vedi RFC 5135 e RFC 1918 -. 
Non si capisce dunque il motivo per cui si persiste a chiamare una tecnologia implementata nel NAT con un nome diverso quale PAT, come se fosse un nuovo servizio di rete destinato ad essere implementato da quei pochi netadmin "che loro sì, conoscono la tecnologia"...


Per quanto detto, il netadmin quadratico medio, si dovrebbe solo preoccupare del fatto che il suo sistema che implementa funzionalità di NAT abbia adottato le RFC sopra citate, mentre ogni altra allusione a PAT o affini va quanto prima eliminata perché  inutile e fuorviante.

martedì 26 marzo 2013

simulatore MIPS

Per chi volesse iniziare un percorso formativo sulla programmazione MIPS, consiglio vivamente questo ambiente di simulazione: SPIM
meglio che mai in accoppiata con MIPSter

Una volta installato, eseguiamo un test di verifica con il seguente codice:

 .data
hello_str:   .asciiz "Test MIPSTer\nHello World!!!"

    .text

main:

    la $a0, hello_str
    li $v0, 4
    syscall

    li $v0, 10
    syscall
  
    # Fine programma


 
 Questa la bibliografia riguardo ai MIPS tradizionali:

  • D. Sweetman, "See MIPS run ! 2nd"
  • R. Britton, "MIPS Assembly Language Programming"
  • Farquhar & Bunce, "The Mips Programmer's Handbook"  
 Buon divertimento!!!

sabato 9 marzo 2013

VT questo sconosciuto

La comprensione della tecnologia Wintel VT-x o AMD-V introdotta nel 2005, resta ancora abbastanza fumosa ai più, se non per la sua implementazione a più alto livello.
Queste righe hanno lo scopo di chiarire l'idiosincrasia verso questo tipo di architettura.

La virtualizzazione non è certo invenzione dei giorni nostri, visto che già negli anni 70 l'IBM pionieristicamente introdusse questa tecnologia sui suoi sistemi denominati IBM/370.
Semplificando, diremo che il trucco sta nel servirsi della partizione del tempo d'uso della cpu (con opportuni algoritmi di scheduling), e delle tecniche della memoria virtuale. Un sistema operativo può creare così l'illusione che un processo disponga della propria CPU con la propria memoria (virtuale).
Ciò detto, dobbiamo precisare che gli approcci alla virtualizzazione sono di due tipi, detti di hypervisor di tipo 1, ove l’hypervisor è eseguito sul nudo hardware. La macchina virtuale è eseguita come un processo utente in modalità utente e come tale non gli è consentita l’esecuzione di istruzioni privilegiate. La macchina virtuale esegue un sistema operativo guest che pensa di essere in modalità kernel, sebbene sia in modalità utente. Diversamente, un hypervisor di tipo 2 non è altro che un programma utente (che gira su un sistema tipo Windows, Unix, ecc.) dove l’hypervisor viene eseguito come un qualsiasi programma applicativo e ne segue le regole ancorchè applicate al contesto della virtualizzazione.
Sebbene ci si possa aspettare che la tecnica adottata dal hypervisor di tipo 1 dia prestazioni maggiori di quella di tipo 2, in realtà non è così.
Semmai l’hypervisor di tipo 1 può sfruttare le caratteristiche peculiari del tipo 2 per migliorare le proprie performante, dando vita ad una sorta di sistema ibrido dove vengono prese in prestito le migliori caratteristiche dei due tipi di architetture.
Per completezza dobbiamo dire che esiste una terza tecnica (migliorativa) di virtualizzazione detta paravirtualizzazione, le cui specifiche esulano dallo scopo di questo post.
Il motivo dell’esistenza dei due tipi di hypervisor ha a che fare con i difetti dell’architettura del processore Wintel 386, portati avanti servilmente nelle nuove CPU per vent’anni, in nome di una retrocompatibilità.
In parole povere, ogni CPU con la modalità kernel e la modalità utente ha un insieme di istruzioni eseguibile solo in modalità kernel, come le istruzioni che fanno l’I/O, il cambio delle impostazioni dell’MMU e così via.
Ci sono anche delle istruzioni che, se eseguite in modalità utente, provocano un trap.
Nelle architetture I386 se si prova a fare qualcosa in modalità utente che non dovrebbe essere eseguito in modalità utente, l’hardware dovrebbe eseguire un trap. Diversamente dall'IBM/370, che possedeva questa proprietà, non era così per il 386. Un discreto numero di istruzioni significative, se eseguite in modalità utente, erano ignorate. Per esempio, l’istruzione POPF sostituisce il registro dei flag, cambiando il bit che abilita/disabilita gli interrupt. In modalità utente questo bit semplicemente non cambia. Conseguentemente, il 386 e i suoi sucessori non potrebbero supportare un hypervisor di tipo 1.
In realtà, la situazione è leggermente peggiore di quanto delineato. Oltre ai problemi relativi alle istruzioni che non riescono ad eseguire il trap in modalità utente, ci sono istruzioni che possono leggere lo stato sensibile in modalità utente senza provocare un trap.
Questi problemi furono risolti dal Intel (una ventina d'anni dopo questo documento) introducendo o meglio migliorando la virtualizzazione sui loro processori, quelli che oggi tutti conosciamo come VT.
La soluzione intrapresa è quella di far girare le machine virtuali in una sorta di container, una zona del processore che, detta in modo semplicistico ma lapalissiano, emula un IBM/370.
Ogni considerazione sulla (in)voluzione della tecnologia è lasciata come esercizio al lettore...