Raccolta di howto, informazioni, consigli, trucchi e documentazione di varia utilità per ricordare tante cose utili

venerdì 18 dicembre 2009

Collegarsi ad un target iSCSI da MSWindows

Per potersi collegare ad un target iSCSI da un PC con Windows è necessario avere un software specifico. Tale software è preinstallato sul sistema in Windows Vista e Windows 7 mentre per XP e 2000 è necessario prelevarlo dal sito microsoft ed installarlo.
Dopo aver installato il software, se necessario, si deve controllare che il servizio denominato "Servizio inizializzatore iSCSI Microsoft" sia avviato o se necessario avviarlo. Andare poi in "Pannello di controllo \ Strumenti di amministrazione" e avviare l'"Inizializzatore iSCSI"; qui sul tab "Destinazioni" possiamo vedere un elenco dei target iSCSI individuati automaticamente, nel caso (molto probabile) il nostro target non sia presente possiamo inserire il suo indirizzo IP nella textbox "Destinazione" del riquadro "Connessione Rapida" e premere il relativo bottone. A questo punto in caso il sistema rlevi un singolo iqn la connessione avverrà automaticamente, in caso contrario selezionare l'iqn voluto ed effettuare la connessione. A connessione avvenuta sarà disponibile un nuovo disco sul nostro PC corrispondente al target iSCSI connesso.
La pagina di riferimento di Microsoft per il protocollo iSCSI è questa.

mercoledì 16 dicembre 2009

Collegarsi ad un target iSCSI al boot del sistema

Dopo aver configurato un nodo iSCSI, come descritto in questo post, può tornare utile avviarlo al boot del sistema.
Il primo passo e di avviare il servizio iscsid al boot, nel caso di un Gentoo Linux occorre utilizzare il comando
rc-update add iscsid default
Occorre poi indicare che il nel file di configurazione del nodo che lo si vuole attivare automaticamente all'avvio del servizio. Il file in questione, nel caso di un Gentoo Linux è
/etc/iscsi/nodes/<iqn_nodename>/<target_ip_and_port>/ifaceX
dove <iqn_nodename> è il qualified name del nodo al quale ci si vuole connettere, <target_ip_and_port> è un nome composto dall'indirizzo ip della macchina ospitante il target iSCSI e ifaceX è il nome dell'interfaccia che abbiamo assegnato al momento della configurazione.
In questo file la voce da modificare è
node.startup=automatic
per evitare lunghi tempi di attesa al boot nel caso il target iSCSI non siia raggiungibile è possibile modificare anche le due seguenti voci:
node.session.initial_login_retry_max
che imposta il massimo numero di retry di connessione iniziale al target
node.conn[0].timeo.login_timeout
che imposta il tempo massimo in secondi che l'initiator attende per ricevere la risposta dal target alla richiesta di login; naturalmente è opportuno ridurre questi parametri solo se initiator e target sono sulla stessa affidabile lan.
Importante notare che il servizio iscsid parte solo quando i filesystem messi in modalità auto in fstab sono già stati montati, per tanto un file system su un device iSCSI non va montato come auto in fstab ma solo successivamente all'avvio di iscsid (per esempio in local)

Configurare un "iscsi initiator" in Linux

L'"iSCSI initiator" è il componente che permette ad un computer di collegarsi ad un disk server mediante il protocollo iSCSI. L'esempio proposto si riferisce ad una distribuzione Gentoo.
Come prima cosa e necessario installare i pacchetti contenenti il software necessario mediante il comando emerge:
emerge sys-block/open-iscsi
Successivamente si deve assegnare un nome al nostro client iSCSI nel file /etc/iscsi/initiatorname.iscsi impostando le due righe
InitiatorName=iqn.2009-12.local.domain.mioclient:LinuxInitiator
InitiatorAlias=MioAlias
Il valore di InitiatorName dovrebbe seguire le convenzioni del protocollo iSCSI per i gli "iSCSI Qualified Name" (iqn). Un riferimento sulla struttura degli iqn e consultabile qui: http://www.cuddletech.com/articles/iscsi/ar01s02.html
Avviare il servizio iscsid con il comando
/etc/init.d/iscsid start
Aggiungere le interfacce di rete da utilizzare alla configurazione con i comandi
iscsiadm -m iface -I iface0 --op=new
iscsiadm -m iface -I iface0 --op=update -n iface.hwaddress -v <mac_address>
dove iface0 è un nome a nostro piacimento che individuerà l'interfaccia di rete per il protocollo iSCSI e <mac_address> è l'effettivo mac address dell'interfaccia di rete da associare.
Per recuperare la lista dei servizi disponibili su una macchina con indirizzo ip noto diamo il comando
iscsiadm -m discovery -t st -p <ip_address> -P 1
l'opzione -P imposta un livello di verbosità tale del comando che ci permette di vedere stampati i servizi target (server) presenti sulla macchina individuata dall' <ip_address> voluto.
Per terminare creiamo un nodo con il comando
iscsiadm -m node -T <target_iqn> -l
dove <target_iqn> è il "qualified name" del target voluto individuato con il precedente comando di discovery; lo switch -l richiede di effettuare immediatamente il login.
Effettuata questa operazione troveremo un nuovo device del tipo /dev/sdX che punta al servizio iscsi appena configurato con gli eventuali device delle partizioni già presenti. A questo punto il disco è utilizzabile in tutto e per tutto come un disco locale.

giovedì 10 dicembre 2009

Ricezione di pacchetti UDP in C

Di seguito la procedura per ricevere un pacchetto UDP attraverso un socket in un sorgente C per linux/unix.
Iniziamo definendo gli opportuni include generici:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
gli include specifici per il funzionamento dei socket
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
e le definizione dell'indirizzo ip e della porta sulla quale porci in ascolto
#define PORT (5000)
Successivamente creiamo il socket UDP
int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1) {
  perror("Creazione socket fallita");
  exit(1);
}
definiamo e valorizziamo la struttura contenente le informazioni sulla porta sul quale effettuare il bind del socket
struct sockaddr_in addr_loc;
memset((char *)&addr, sizeof(addr), 0);
addr_loc.sin_family = AF_INET;
addr_loc.sin_port = htons(PORT);
addr_loc.sin_addr.s_addr = htonl(INADDR_ANY);
bind(s, (sockaddr *)&addr_loc, sizeof(addr_loc));
per porci in ascolto dobbiamo prima creare una struttura nella quale la funzione recvfrom ci restituisca l'indirizzo dal quale proviene il pacchetto
struct sockaddr_in addr_rem;
socklen_t slen = sizeof(addr_rem);
char buf[1500];
int r = recvfrom(s, buf, 1500, 0, (sockaddr *)&addr_rem, &slen);  
ed infine possiamo leggere il contenuto del pacchetto e il suo indirizzo di provenienza
printf("Received packet from %s:%d\nData: %s\n\n", inet_ntoa(addr_rem.sin_addr), ntohs(addr_rem.sin_port), buf);
Per concludere chiudiamo il socket
close(s);
Da notare che l'indirizzo ip della sorgente viene conservato nella variabile  addr_rem.sin_addr.s_addr in forma di intero a 32 bit (4 byte) dove il byte meno significativo è il primo dell'indirizzo ip nella forma numerica standard
dcba (4 byte) = a.b.c.d

mercoledì 9 dicembre 2009

Invio di pacchetti UDP in C (unix)

Di seguito la procedura per inviare un pacchetto UDP attraverso un socket in un sorgente C per linux/unix.
Iniziamo definendo gli opportuni include generici:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
gli include specifici per il funzionamento dei socket
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
e le definizione dell'indirizzo ip e della porta di destinazione
#define IPADDR "192.168.1.100"
#define PORT (5000)
Successivamente creiamo il socket UDP
int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s == -1) {
  perror("Creazione socket fallita");
  exit(1);
}
definiamo e valorizziamo la struttura contenente la destinazione del pacchetto
struct sockaddr_in addr;
memset((char *)&addr, sizeof(addr), 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
inet_aton(IPADDR, &addr.sin_addr);
Creiamo e valorizziamo il buffer con i dati da inviare
int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
ed infine inviamo il pacchetto sulla rete alla destinazione voluta
int len=sendto(s, buf, 10*sizeof(int), 0, (struct sockaddr *)&addr, sizeof(addr));
if(len < (10*sizeof(int))) perror("Invio fallito o incompleto");
Per concludere chiudiamo il socket
close(s);
Di seguito il sorgente completo

#include <stdlib.h>
#include <stdio.h>;
#include <string.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define IPADDR "192.168.1.100"
#define PORT (5000)

int main() {

  int s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  if (s == -1) {
    perror("Creazione socket fallita");
    exit(1);

  }

  struct sockaddr_in addr;
  memset((char *)&addr, sizeof(addr), 0);

  addr.sin_family = AF_INET;
  addr.sin_port = htons(PORT);
  inet_aton(IPADDR, &addr.sin_addr);


  int buf[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

  int len=sendto(s, buf, 10*sizeof(int), 0, (struct sockaddr *)&addr, sizeof(addr));
  if(len < (10*sizeof(int))) perror("Invio fallito o incompleto");

  close(s);

  return 0;
}

mercoledì 2 dicembre 2009

Modifica delle dimensioni del product_model in osCommerce

Nell'installazione di default osCommerce permette un massimo di 12 caratteri nel product model, limite che spesso si ha la necessità di incrementare.
Per ottenere il risultato voluto bisogna incrementare le dimensioni dei seguenti due campi:
  1. Tabella 'products' campo 'products_model'
  2. Tabella 'orders_products' campo 'products_model'
Per il corretto funzionamento del sistema è necessario che questi due campi di tipo varchar siano della stessa dimensione in quanto all'effetuazione di un ordine il 'product_model' viene letto dalla tabella 'products' per essere registrato  nella tabella 'orders_products'.