[gestion/iscsi] création d'un module slonlib
darcs-hash:20081217131852-c41ad-390349e9eefc27174449f5323f5d08f98194efb5.gz
This commit is contained in:
parent
a7d7d6f006
commit
9a0f43b6dd
2 changed files with 106 additions and 61 deletions
|
@ -9,80 +9,24 @@
|
||||||
u'''Outil pour récupérer le mapping lun/volume depuis la baie de
|
u'''Outil pour récupérer le mapping lun/volume depuis la baie de
|
||||||
stockage'''
|
stockage'''
|
||||||
|
|
||||||
import telnetlib, re, sys
|
import slonlib, re, sys
|
||||||
|
|
||||||
sys.path.append("/usr/scripts/gestion")
|
sys.path.append("/usr/scripts/gestion")
|
||||||
from config import ISCSI_MAP_FILE
|
from config import ISCSI_MAP_FILE
|
||||||
import affich_tools
|
import affich_tools
|
||||||
|
|
||||||
# Ce script utilise l'interface telnet de la baie.
|
|
||||||
|
|
||||||
# La réponse à la commande "show volume-map" est une séquence
|
|
||||||
# d'éléments de la forme:
|
|
||||||
#
|
|
||||||
# nom du volume
|
|
||||||
# |
|
|
||||||
# v
|
|
||||||
# > Volume [SN 00c0ffd5e51800004ca1454901000000, Name (o2_slash)] mapping view:
|
|
||||||
# > CH ID LUN Access Host-Port-Identifier Nickname
|
|
||||||
# > -------------------------------------------------------------------------------
|
|
||||||
# > 0,1 0 4 rw all other hosts
|
|
||||||
# ^
|
|
||||||
# |
|
|
||||||
# lun
|
|
||||||
|
|
||||||
# On utilise cette expression un peu barbare pour récupérer les deux
|
|
||||||
# informations qui nous intéressses:
|
|
||||||
volume_regexp = re.compile("Volume \[SN [0-9a-f]+, Name \(([^)]*)\)\][^\n]*\n[^\n]*\n[^\n]*\n[0-9,-]+ *[0-9]+ *([0-9]+)[^\n]*\n")
|
|
||||||
|
|
||||||
username = ""
|
|
||||||
password = ""
|
|
||||||
|
|
||||||
# Récupération des identifiants. Cela écrase les deux variables
|
|
||||||
# username et password:
|
|
||||||
execfile("/etc/crans/secrets/slon.py")
|
|
||||||
|
|
||||||
print u"Connection à la baie de stockage..."
|
print u"Connection à la baie de stockage..."
|
||||||
|
|
||||||
tn = telnetlib.Telnet("slon.adm.crans.org")
|
slon = slonlib.Slon()
|
||||||
|
|
||||||
# Identification
|
|
||||||
tn.read_until("Login: ")
|
|
||||||
tn.write(username + "\r\n")
|
|
||||||
tn.read_until("Password: ")
|
|
||||||
tn.write(password + "\r\n")
|
|
||||||
|
|
||||||
# Ça c'est pour attendre la l'invite de commande:
|
|
||||||
tn.read_until("#")
|
|
||||||
|
|
||||||
print u"Récupération des informations..."
|
print u"Récupération des informations..."
|
||||||
|
|
||||||
tn.write("show volume-maps" + "\r\n")
|
map = slon.volume_map().items()
|
||||||
resp = ""
|
map.sort()
|
||||||
# Lecture de la réponse, c'est terminé quand on atteint un nouveau
|
|
||||||
# prompt:
|
|
||||||
while resp.find("#") < 0:
|
|
||||||
resp = resp + tn.read_some()
|
|
||||||
# Parfois le serveur attend que l'on appuie sur une touche pour
|
|
||||||
# continuer à envoyer les données:
|
|
||||||
if resp.endswith("Press any key to continue (Q to quit)"):
|
|
||||||
tn.write(" ")
|
|
||||||
|
|
||||||
print u"Déconnection..."
|
print u"Déconnection..."
|
||||||
|
|
||||||
tn.write("exit\r\n")
|
slon.logout()
|
||||||
tn.read_all()
|
|
||||||
tn.close()
|
|
||||||
|
|
||||||
# On retire les messages parasites
|
|
||||||
junk = re.compile("Press any key to continue \(Q to quit\)\x0d *\x0d")
|
|
||||||
resp = junk.sub("", resp)
|
|
||||||
|
|
||||||
# Parsing de la réponse
|
|
||||||
map = []
|
|
||||||
for m in volume_regexp.finditer(resp):
|
|
||||||
map.append((int(m.group(2)), m.group(1)))
|
|
||||||
map.sort()
|
|
||||||
|
|
||||||
print u"Enregistrement des informations..."
|
print u"Enregistrement des informations..."
|
||||||
|
|
||||||
|
|
101
gestion/iscsi/slonlib.py
Executable file
101
gestion/iscsi/slonlib.py
Executable file
|
@ -0,0 +1,101 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# slonlib.py
|
||||||
|
# ----------
|
||||||
|
# Copyright : (c) 2008, Jeremie Dimino <jeremie@dimino.org>
|
||||||
|
# Licence : BSD3
|
||||||
|
|
||||||
|
u'''Librairie pour accéder à la baie de stockage'''
|
||||||
|
|
||||||
|
import telnetlib, re
|
||||||
|
|
||||||
|
# Message envoyé par le serveur pour attendre l'appuie sur touche
|
||||||
|
junk_regexp = re.compile("Press any key to continue \(Q to quit\)\r *\r")
|
||||||
|
|
||||||
|
# Matching des fin de lignes avec \r\n
|
||||||
|
crlf_regexp = re.compile("\r\n")
|
||||||
|
|
||||||
|
username = ""
|
||||||
|
password = ""
|
||||||
|
|
||||||
|
# Récupére des identifiants
|
||||||
|
execfile("/etc/crans/secrets/slon.py")
|
||||||
|
|
||||||
|
# La réponse à la commande "show volume-maps" est une séquence
|
||||||
|
# d'éléments de la forme:
|
||||||
|
#
|
||||||
|
# nom du volume
|
||||||
|
# |
|
||||||
|
# v
|
||||||
|
# > Volume [SN 00c0ffd5e51800004ca1454901000000, Name (o2_slash)] mapping view:
|
||||||
|
# > CH ID LUN Access Host-Port-Identifier Nickname
|
||||||
|
# > -------------------------------------------------------------------------------
|
||||||
|
# > 0,1 0 4 rw all other hosts
|
||||||
|
# ^
|
||||||
|
# |
|
||||||
|
# lun
|
||||||
|
#
|
||||||
|
# On utilise cette expression un peu barbare pour récupérer les deux
|
||||||
|
# informations qui nous intéressses:
|
||||||
|
volume_map_regexp = re.compile("Volume \[SN [0-9a-f]+, Name \(([^)]*)\)\][^\n]*\n[^\n]*\n[^\n]*\n[0-9,-]+ *[0-9]+ *([0-9]+)[^\n]*\n")
|
||||||
|
|
||||||
|
class Slon:
|
||||||
|
u'''Object représentant la baie de stockage'''
|
||||||
|
|
||||||
|
def __init__(self, host="slon.adm.crans.org"):
|
||||||
|
self.tn = telnetlib.Telnet(host)
|
||||||
|
|
||||||
|
# Identification
|
||||||
|
self.tn.read_until("Login: ")
|
||||||
|
self.tn.write(username + "\r\n")
|
||||||
|
self.tn.read_until("Password: ")
|
||||||
|
self.tn.write(password + "\r\n")
|
||||||
|
|
||||||
|
# Ça c'est pour attendre l'invite de commande initiale:
|
||||||
|
self.tn.read_until("# ")
|
||||||
|
|
||||||
|
# On met un nombre de lignes le plus élévé possible pour
|
||||||
|
# éviter que le serveur ne se mette en attente de l'appuie sur
|
||||||
|
# une touche
|
||||||
|
self.cmd("stty rows 32767")
|
||||||
|
# Au delà de cette valeur il y a un overflow
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
u'''Déconnexion de la baie'''
|
||||||
|
self.tn.write("exit\r\n")
|
||||||
|
self.tn.read_all()
|
||||||
|
self.tn.close()
|
||||||
|
|
||||||
|
def cmd(self, cmd):
|
||||||
|
u'''Exécute une commande et renvoie le résultat. Lance
|
||||||
|
l'exception Error si la commande échoue'''
|
||||||
|
self.tn.write(cmd + "\r\n")
|
||||||
|
resp = ""
|
||||||
|
# Lecture de la réponse, c'est terminé quand on atteint un
|
||||||
|
# nouveau prompt:
|
||||||
|
while not resp.endswith("# "):
|
||||||
|
resp = resp + self.tn.read_some()
|
||||||
|
# Parfois le serveur attend que l'on appuie sur une touche
|
||||||
|
# pour continuer à envoyer les données:
|
||||||
|
if resp.endswith("Press any key to continue (Q to quit)"):
|
||||||
|
self.tn.write(" ")
|
||||||
|
|
||||||
|
# On retire les messages parasites
|
||||||
|
resp = junk_regexp.sub("", resp)
|
||||||
|
|
||||||
|
# On retire le prompt
|
||||||
|
[resp, _] = resp.rsplit("\r\n", 1)
|
||||||
|
|
||||||
|
# Remplace les fins de ligne dos pas des fin de lignes unix
|
||||||
|
resp = crlf_regexp.sub("\n", resp)
|
||||||
|
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def volume_map(self):
|
||||||
|
u'''Retourne le mapping lun<->nom de volume'''
|
||||||
|
map = {}
|
||||||
|
for m in volume_map_regexp.finditer(self.cmd("show volume-maps")):
|
||||||
|
map[int(m.group(2))] = m.group(1)
|
||||||
|
return map
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue