[Baie de disques] On remplace slon par nols là où c'est bien.
Ignore-this: 26bbaee2a355c1c1b8170d1fa58aea59 darcs-hash:20120807200036-ab199-cfb522d47031cd8ecca7c8961f430d9034df6315.gz
This commit is contained in:
parent
9e4d3f9ab4
commit
209719cfc1
3 changed files with 197 additions and 2 deletions
54
gestion/iscsi/nols-get-volume-mapping.py
Executable file
54
gestion/iscsi/nols-get-volume-mapping.py
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# nols-get-volume-mapping.py
|
||||||
|
# --------------------------
|
||||||
|
# Qui taper si ça marche pas : Pierre-Elliott Bécue <peb@crans.org>
|
||||||
|
# Merci à : Jérémie Dimino <jeremie@dimino.org>, je n'ai fait que s/slon/nols/ sur ce script.
|
||||||
|
# Licence : BSD3
|
||||||
|
|
||||||
|
u'''Outil pour récupérer le mapping lun/volume depuis la baie de
|
||||||
|
stockage'''
|
||||||
|
|
||||||
|
import nolslib, re, sys
|
||||||
|
|
||||||
|
sys.path.append("/usr/scripts/gestion")
|
||||||
|
from config import ISCSI_MAP_FILE
|
||||||
|
import affich_tools
|
||||||
|
|
||||||
|
print u"Connexion à la baie de stockage..."
|
||||||
|
|
||||||
|
nols = nolslib.Nols()
|
||||||
|
|
||||||
|
print u"Récupération des informations..."
|
||||||
|
|
||||||
|
map = nols.volume_map().items()
|
||||||
|
map.sort()
|
||||||
|
|
||||||
|
print u"Déconnexion..."
|
||||||
|
|
||||||
|
nols.logout()
|
||||||
|
|
||||||
|
print u"Enregistrement des informations..."
|
||||||
|
|
||||||
|
f = open(ISCSI_MAP_FILE, "w")
|
||||||
|
f.write((u"""\
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Fichier de mapping lun -> nom de volume
|
||||||
|
#
|
||||||
|
# Ce fichier est généré par %s
|
||||||
|
|
||||||
|
map = {
|
||||||
|
""" % sys.argv[0]).encode("UTF-8"))
|
||||||
|
|
||||||
|
for lun, name in map:
|
||||||
|
f.write(' %d : "%s",\n' % (lun, name))
|
||||||
|
|
||||||
|
f.write("}\n")
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
print u"Terminé, mapping enregistré dans %s" % ISCSI_MAP_FILE
|
||||||
|
|
||||||
|
print u"Le mapping actuel est:"
|
||||||
|
print affich_tools.tableau(titre = ["lun", "nom"], data = map, alignement = ["g", "c"])
|
141
gestion/iscsi/nolslib.py
Executable file
141
gestion/iscsi/nolslib.py
Executable file
|
@ -0,0 +1,141 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# baie_lib.py
|
||||||
|
# ----------
|
||||||
|
# Type à taper si ça chie : Pierre-Elliott Bécue <peb@crans.org>
|
||||||
|
# Licence : WTFPL
|
||||||
|
|
||||||
|
'''Bibliothèque pour accéder à la baie de stockage nols, récupère les données
|
||||||
|
formatées en XML'''
|
||||||
|
|
||||||
|
import telnetlib, re
|
||||||
|
from xml.etree.ElementTree import ElementTree, fromstring
|
||||||
|
|
||||||
|
# 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/nols.py")
|
||||||
|
|
||||||
|
class Nols(object):
|
||||||
|
'''Objet représentant la baie de stockage'''
|
||||||
|
|
||||||
|
def __init__(self, host="nols.adm.crans.org"):
|
||||||
|
self.tn = telnetlib.Telnet(host)
|
||||||
|
|
||||||
|
# Identification
|
||||||
|
self.tn.expect(["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 veut des sorties en XML
|
||||||
|
self.cmd("set cli-parameters api-embed")
|
||||||
|
|
||||||
|
# On se débarasse des "appuie sur un bouton pour voir la suite"
|
||||||
|
self.cmd("set cli-parameters pager off")
|
||||||
|
|
||||||
|
def logout(self):
|
||||||
|
'''Déconnexion de la baie'''
|
||||||
|
self.tn.write("exit\r\n")
|
||||||
|
self.tn.read_all()
|
||||||
|
self.tn.close()
|
||||||
|
print ("Si vous avez effectué des modifications pensez à exécuter:\n" +
|
||||||
|
"/usr/scripts/gestion/iscsi/update.sh sur chacun des dom0\n")
|
||||||
|
|
||||||
|
def cmd(self, cmd, mode='text'):
|
||||||
|
'''Exécute une commande et renvoie le résultat. Lève
|
||||||
|
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 api-embed\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")
|
||||||
|
resp = ""
|
||||||
|
# Lecture de la réponse, c'est terminé quand on atteint un
|
||||||
|
# nouveau prompt:
|
||||||
|
resp = self.tn.read_until("# ")
|
||||||
|
|
||||||
|
# On retire les messages parasites s'il en reste par hasard
|
||||||
|
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
|
||||||
|
[resp, _] = resp.rsplit("\r\n", 1)
|
||||||
|
|
||||||
|
# Remplace les fins de ligne dos par des fin de lignes unix
|
||||||
|
resp = crlf_regexp.sub("\n", resp)
|
||||||
|
return resp
|
||||||
|
|
||||||
|
def show(self, what):
|
||||||
|
'''Raccourci pour: print slon.cmd("show <what>")'''
|
||||||
|
print self.cmd("show " + what)
|
||||||
|
|
||||||
|
def help(self, what = ""):
|
||||||
|
'''Raccourci pour: print slon.cmd("help <what>")'''
|
||||||
|
print self.cmd("help " + what)
|
||||||
|
|
||||||
|
def volume_map(self):
|
||||||
|
'''Retourne le mapping lun<->nom de volume'''
|
||||||
|
map = {}
|
||||||
|
XML_map = self.cmd("show volume-map", mode="XML")
|
||||||
|
root = fromstring(XML_map)
|
||||||
|
tree = ElementTree(root)
|
||||||
|
Objects = tree.findall("OBJECT[@name='volume-view']")
|
||||||
|
for Object in Objects:
|
||||||
|
name = Object.findall("PROPERTY[@name='volume-name']")[0].text
|
||||||
|
lun = Object.findall("OBJECT/PROPERTY[@name='lun']")[0].text
|
||||||
|
if lun is None:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
map[int(lun)] = name
|
||||||
|
return map
|
||||||
|
|
||||||
|
def create_volume(self, name, size, unit="GiB", vdisk="VD1"):
|
||||||
|
'''Crée un nouveau volume. Retourne le lun sur lequel il est
|
||||||
|
mappé. L'unité doit être "B", "K(i)B", "M(i)B", "G(i)B" ou T(i)B.
|
||||||
|
Par défault l'unité est le giga octet binaire : Gib.'''
|
||||||
|
|
||||||
|
# On récupère le mapping pour chercher un lun de libre
|
||||||
|
map = self.volume_map()
|
||||||
|
lun = 0
|
||||||
|
while lun in map: lun = lun + 1
|
||||||
|
|
||||||
|
# Création du volume
|
||||||
|
self.cmd("create volume vdisk %s size %d%s lun %d %s" % (vdisk, size, unit, lun, name))
|
||||||
|
|
||||||
|
return "Le volume %s a été créé, son numéri d'identification est %d" %(name, lun)
|
||||||
|
|
||||||
|
def delete_volume(self, name):
|
||||||
|
'''Supprime un volume'''
|
||||||
|
|
||||||
|
self.cmd("delete volume %s" % (name))
|
||||||
|
|
||||||
|
def expand_volume(self, name, size, unit="GiB"):
|
||||||
|
'''Permet d'étendre un volume, la taille par défaut est le giga octet
|
||||||
|
binaire (GiB), les unités possibles sont B, K(i)B, M(i)B, G(i)B, T(i)B.'''
|
||||||
|
|
||||||
|
self.cmd("expand volume size %d%s %s" % (size, unit, name))
|
||||||
|
|
||||||
|
def rename_volume(self, origin_name, new_name):
|
||||||
|
'''Renomme un volume.'''
|
||||||
|
|
||||||
|
self.cmd("set volume name %s %s" % (new_name, orig_name))
|
|
@ -5,7 +5,7 @@
|
||||||
# Copyright : (c) 2008, Jeremie Dimino <jeremie@dimino.org>
|
# Copyright : (c) 2008, Jeremie Dimino <jeremie@dimino.org>
|
||||||
# Licence : BSD3
|
# Licence : BSD3
|
||||||
|
|
||||||
# Ce script fait tous ce qu'il faut après l'ajout d'un volume sur la
|
# Ce script fait tout ce qu'il faut après l'ajout d'un volume sur la
|
||||||
# baie de stockage.
|
# baie de stockage.
|
||||||
|
|
||||||
exec_cmd() {
|
exec_cmd() {
|
||||||
|
@ -27,7 +27,7 @@ exec_cmd() {
|
||||||
}
|
}
|
||||||
|
|
||||||
exec_cmd "Récupération du mapping lun<->nom de volume" \
|
exec_cmd "Récupération du mapping lun<->nom de volume" \
|
||||||
python /usr/scripts/gestion/iscsi/slon-get-volume-mapping.py
|
python /usr/scripts/gestion/iscsi/nols-get-volume-mapping.py
|
||||||
|
|
||||||
exec_cmd "Rechargement des règles de udev" \
|
exec_cmd "Rechargement des règles de udev" \
|
||||||
invoke-rc.d udev reload
|
invoke-rc.d udev reload
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue