Slon supporte le XML, et son vdisk par défaut devient slon2
This commit is contained in:
parent
1171bc8ca6
commit
03a6d1b92a
1 changed files with 43 additions and 15 deletions
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
'''Bibliothèque pour accéder à la baie de stockage'''
|
'''Bibliothèque pour accéder à la baie de stockage'''
|
||||||
|
|
||||||
import telnetlib, re
|
import telnetlib
|
||||||
|
import re
|
||||||
|
from xml.etree.ElementTree import ElementTree, fromstring
|
||||||
|
|
||||||
# Message envoyé par le serveur pour attendre l'appuie sur touche
|
# 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")
|
junk_regexp = re.compile("Press any key to continue \(Q to quit\)\r *\r")
|
||||||
|
@ -58,7 +60,7 @@ class Slon(object):
|
||||||
# On met un nombre de lignes le plus élévé possible pour
|
# 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
|
# éviter que le serveur ne se mette en attente de l'appuie sur
|
||||||
# une touche
|
# une touche
|
||||||
self.cmd("stty rows 32767")
|
self.cmd("set cli-parameters pager off")
|
||||||
# Au delà de cette valeur il y a un overflow
|
# Au delà de cette valeur il y a un overflow
|
||||||
|
|
||||||
def logout(self):
|
def logout(self):
|
||||||
|
@ -69,28 +71,38 @@ class Slon(object):
|
||||||
print ("Si vous avez effectué des modifications pensez à exécuter:\n" +
|
print ("Si vous avez effectué des modifications pensez à exécuter:\n" +
|
||||||
"/usr/scripts/gestion/iscsi/update.sh sur chacun des dom0\n")
|
"/usr/scripts/gestion/iscsi/update.sh sur chacun des dom0\n")
|
||||||
|
|
||||||
def cmd(self, cmd):
|
def cmd(self, cmd, mode='text'):
|
||||||
'''Exécute une commande et renvoie le résultat. Lance
|
'''Exécute une commande et renvoie le résultat. Lève
|
||||||
l'exception Error si la commande échoue'''
|
l'exception Error si la commande échoue'''
|
||||||
|
|
||||||
|
# Si c'est le script qui bosse, on utilise le mode XML, sinon
|
||||||
|
# on peut aussi lancer des commandes en mode texte
|
||||||
|
if mode == 'XML':
|
||||||
|
self.tn.write("set cli-parameters xml\r\n")
|
||||||
|
self.tn.read_until("# ")
|
||||||
|
else:
|
||||||
|
self.tn.write("set cli-parameters console\r\n")
|
||||||
|
self.tn.read_until("# ")
|
||||||
|
|
||||||
self.tn.write(cmd + "\r\n")
|
self.tn.write(cmd + "\r\n")
|
||||||
resp = ""
|
resp = ""
|
||||||
# Lecture de la réponse, c'est terminé quand on atteint un
|
# Lecture de la réponse, c'est terminé quand on atteint un
|
||||||
# nouveau prompt:
|
# nouveau prompt:
|
||||||
while not resp.endswith("# "):
|
resp = self.tn.read_until("# ")
|
||||||
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
|
# On retire les messages parasites s'il en reste par hasard
|
||||||
resp = junk_regexp.sub("", resp)
|
resp = junk_regexp.sub("", resp)
|
||||||
|
|
||||||
|
# On vire la commande qui est là et dont on veut pas
|
||||||
|
[_, resp] = resp.split(cmd+"\r\n", 1)
|
||||||
|
|
||||||
# On retire le prompt
|
# On retire le prompt
|
||||||
[resp, _] = resp.rsplit("\r\n", 1)
|
[resp, _] = resp.rsplit("\r\n", 1)
|
||||||
|
|
||||||
# Remplace les fins de ligne dos pas des fin de lignes unix
|
# Remplace les fins de ligne dos par des fin de lignes unix
|
||||||
resp = crlf_regexp.sub("\n", resp)
|
resp = crlf_regexp.sub("\n", resp)
|
||||||
|
if resp.lower().startswith("error"):
|
||||||
|
raise NolsError(resp.replace("Error: ", ""))
|
||||||
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
@ -105,11 +117,27 @@ class Slon(object):
|
||||||
def volume_map(self):
|
def volume_map(self):
|
||||||
'''Retourne le mapping lun<->nom de volume'''
|
'''Retourne le mapping lun<->nom de volume'''
|
||||||
map = {}
|
map = {}
|
||||||
for m in volume_map_regexp.finditer(self.cmd("show volume-maps")):
|
XML_map = self.cmd("show volume-maps", mode="XML")
|
||||||
map[int(m.group(2))] = m.group(1)
|
root = fromstring(XML_map)
|
||||||
|
tree = ElementTree(root)
|
||||||
|
|
||||||
|
# XML c'est trobyien
|
||||||
|
tree = tree.findall("volume-view")[0]
|
||||||
|
Objects = tree.findall("volume_view")
|
||||||
|
|
||||||
|
for Object in Objects:
|
||||||
|
name = None
|
||||||
|
lun = None
|
||||||
|
name = Object.findall("volume_name")[0].text
|
||||||
|
lun = Object.findall("lun")[0].text
|
||||||
|
|
||||||
|
if lun is None:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
map[int(lun)] = name
|
||||||
return map
|
return map
|
||||||
|
|
||||||
def create_volume(self, name, size, unit="GB", vdisk="slon1"):
|
def create_volume(self, name, size, unit="GB", vdisk="slon2"):
|
||||||
'''Créé un nouveau volume. Retourne le lun sur lequel il est
|
'''Créé un nouveau volume. Retourne le lun sur lequel il est
|
||||||
mappé. La taille est en Giga-octet. L'unité doit être "KB",
|
mappé. La taille est en Giga-octet. L'unité doit être "KB",
|
||||||
"MB" ou "GB". Par défault c'est "GB".'''
|
"MB" ou "GB". Par défault c'est "GB".'''
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue