Moin,
kein Problem. Ich muss jedoch sagen, dass es sich bei dieser Programmierung um mein erstes Python-Werk handelt. Sicherlich kann ein Profi Alles noch wesentlich optimaler realisieren.
Zur Realisierung unter Zabbix:
Das Script ist als Cronjob auf dem Zabbixserver hinterlegt und wird jede Minute ausgeführt. Findet das Script die Datei 'shutdown.lck' nicht im angegebenen Pfad wird es unmittelbar wieder beendet.
Ist eine Datei mit dem Namen 'shutdown.lck' vorhanden, so wird diese gelöscht und die Datei 'shutdown_running.lck' angelegt. Anschließend läuft das Script dann weiter durch.
Das Konstrukt soll verhindern, dass cron den eigentlichen Shutdown jede Minute neu startet!
Zabbix muss nur dafür sorgen, dass die 'shutdown.lck' im richtigen Pfad angelegt wird (Triggerbedingung bzw. Action), damit der Shutdown durchgeführt wird.
Das Script erklärt sich hoffentlich weitgehend selbst.
Das Script schreibt ein LOG.
Die Definition der Gruppen war erforderlich, da wir unbedingt eine gewisse Reihenfolge beim Shutdown einhalten wollen.
vcenter
Her muss der Name der VC VM angegeben werden. Diese darf natürlich nicht bzw. erst als letzte VM heruntergefahren werden!
VM_Group_1, VM Group_2
Hier sind die einzelnen VM's einzutragen, die heruntergefahren werden sollen.
Das Herunterfahren der VM's wird dann angestoßen. Es wird dabei geprüft, ob alle Maschinen von Gruppe1 bzw. Gruppe2 heruntergefahren wurden. Über den Timeout wird sichergestellt, dass nach max. 300s (konfigurierbar) die nächste Gruppe heruntergefahren wird.
Wenn beide Gruppen heruntergefahren wurden bzw. der Timeout erreicht wurde werden alle anderen noch laufenden VM's heruntergefahren. Die VCenter VM wird dabei natürlich nicht heruntergefahren!
Anschließend werden dann die VMHosts in den Wartungsmodus geschaltet und die Hosts abgeschaltet.
Bei uns läuft das als Shutdownscript bei einem Stromausfall. Zabbix schickt uns in dem Fall dann noch eine SMS, wenn der Shutdown losgeht.
Klar, das ist sicher noch nicht Alles perfekt. So gibt es z.B. keine Abbruchmöglichkeit im Script mehr so Bald der Shutdown läuft. Ist der Strom zwischenzeitlich wieder da... Pech gehabt!
Aber einen Tod muss man eben sterben.
Gruß
Dirk
Code: Alles auswählen
#!/usr/bin/python
import sys
import string
import time
import os
### Reihenfolge der VMS die durch das Script heruntergefahren werden ###
VM_Group_1 = ["VM1", "VM2"]
VM_Group_2 = ["VM3", "VM4"]
### Name des vCenter Servers ###
vcserver = "VC_VM"
### Anmeldedaten vCenter ###
sVCServer = "192.168.10.200"
sVCUser = "domain\user"
sVCPassword = "password"
### Pfad und Name zur Datei shutdown.lck und shutdown_running.lck ###
lckfile="/usr/local/share/zabbix/externalscripts/shutdown.lck"
lckshutdown="/usr/local/share/zabbix/externalscripts/shutdown_running.lck"
### Pfad und Name der Log-Datei ###
logfile = '/usr/local/share/zabbix/externalscripts/shutdown.log'
### Wenn Datei shutdown.lck nicht da, exit script ###
if not os.path.isfile(lckfile):
# quit python script
sys.exit(0)
### Wenn Datei shutdown_running.lck da, exit script ###
if os.path.isfile(lckshutdown):
#ggf. shutdown.lck loeschen, exit script
if os.path.isfile(lckfile):
os.remove(lckfile)
sys.exit(0)
else:
sys.exit(0)
### lckshutdown.lck Datei anlegen ###
file = open(lckshutdown,"a")
file.close
### pySphere Module importieren ###
from pysphere import VIServer, VIProperty, VIMor, VITask
from pysphere.vi_virtual_machine import VIVirtualMachine
from pysphere.resources import VimService_services as VI
### Function to save log messages to specified log file
def log(msg):
# open the specified log file
file = open(logfile,"a")
# write log message with timestamp to log file
file.write("%s: %s\n" % (time.strftime("%d.%m.%Y %H:%M:%S"), msg))
# close log file
file.close
def shutdown_vm(vms):
# Wenn VM eingeschaltet herunterfahren
if vms.get_status() == "POWERED ON":
# Pruefung, ob VMTOOLS auf VM laufen
try:
vm_tools_status = vms.wait_for_tools(timeout=5)
#Wenn VMTOOLS laufen, dann VM Shutdown
vms.shutdown_guest()
# VMTOOLS laufen nicht, VM ausschalten
except:
log("VM Tools laufen nicht! VM wird ausgeschaltet")
vms.power_off()
return 0
else:
return -1
### Pruefen, ob alle Maschinen der uebergebenen Gruppe heruntergefahren
def check_shutdown_vmgroup(sArray_Name, VM_Array, Timer):
bVMStatus = False
TimeOut_Start = time.time()
log ("Es wird geprueft ob alle VM der Gruppe: " + sArray_Name + " heruntergefahren sind (max. " + str(Timer) + " Sekunden)!")
while bVMStatus == False:
#Wenn Zeitlimit erreicht, while-Schleife abbrechen
if time.time() > TimeOut_Start + Timer:
return False
for x in VM_Array:
vm = server.get_vm_by_name(x)
sVMStatus = vm.get_status()
if sVMStatus == "POWERED OFF":
bVMStatus = True
else:
log ("VM Status: " + vm.get_property('name', from_cache=False) + " " + sVMStatus)
bVMStatus = False
time.sleep(10)
break
return True
def host_mor(mor):
if not VIMor.is_mor(mor):
return VIMor(mor, "HostSystem")
return mor
def enter_maintenance_mode(host, timeout, evacuate_powered_off_vms=None):
host = host_mor(host)
request = VI.EnterMaintenanceMode_TaskRequestMsg()
_this = request.new__this(host)
_this.set_attribute_type(host.get_attribute_type())
request.set_element__this(_this)
request.set_element_timeout(timeout)
if evacuate_powered_off_vms in [False, True]:
request.set_element_evacuatePoweredOffVms(evacuate_powered_off_vms)
task = server._proxy.EnterMaintenanceMode_Task(request)._returnval
return VITask(task, server)
def shutdown_host(host, force):
host = host_mor(host)
request = VI.ShutdownHost_TaskRequestMsg()
_this = request.new__this(host)
_this.set_attribute_type(host.get_attribute_type())
request.set_element__this(_this)
request.set_element_force(force)
task = server._proxy.ShutdownHost_Task(request)._returnval
return VITask(task, server)
### Pruefen, ob die Datei shutdown.lck vorhanden ###
### Wenn Datei shutdown.lck vorhanden loeschen ###
if os.path.isfile(lckfile):
os.remove(lckfile)
# Eintrag in Logdatei schreiben
log ("schutdown.lck geloescht!")
server = VIServer()
### Anmelden am vCenter bzw. VM-Host
server.connect(sVCServer, sVCUser, sVCPassword)
log ("Anmeldung an VC")
### Hosts herausfinden MOR und in Liste schreiben
aHostList = server.get_hosts().keys()
log ("VM Hosts im VC: " + str(aHostList))
### Host herausfinden auf dem VCServer laeuft
vm = server.get_vm_by_name(vcserver)
sHost_VC = vm.properties.runtime.host._obj
log ("Host auf dem das VC lauft: " + sHost_VC)
### VMS der Gruppe 1 in geplanter Reihenfolge herunterfahren
log ("VM der Gruppe 1 werden heruntergefahren")
for x in VM_Group_1:
vm = server.get_vm_by_name(x)
log ("VM herunterfahren: " + vm.get_property('name', from_cache=False))
nRes = shutdown_vm(vm)
### Shutdown Gruppe 1 pruefen
if check_shutdown_vmgroup("VM_Group_1", VM_Group_1, 300) == True:
log ("Alle VM der Gruppe 1 wurden heruntergefahren!")
else:
log ("Das Zeitlimit zum VM-Shutdown der Gruppe 1 wurde erreicht. Der Shutdown wird fortgesetzt!")
### VMS der Gruppe 2 in geplanter Reihenfolge herunterfahren
log ("VM der Gruppe 2 werden heruntergefahren")
for x in VM_Group_2:
vm = server.get_vm_by_name(x)
log ("VM herunterfahren: " + vm.get_property('name', from_cache=False))
nRes = shutdown_vm(vm)
### Shutdown Gruppe 2 pruefen
if check_shutdown_vmgroup("VM_Group_2", VM_Group_2, 300) == True:
log ("Alle VM der Gruppe 2 wurden heruntergefahren!")
else:
log ("Das Zeitlimit zum VM-Shutdown der Gruppe 2 wurde erreicht. Der Shutdown wird fortgesetzt!")
### alle uebrigen laufenden VM herunterfahren, ausser VCServer!
vmlist = server.get_registered_vms(status='poweredOn')
for x in vmlist:
vm = server.get_vm_by_path(x)
### Nur wenn VM Name <> vCenter shutdown durchfuehren
if vm.get_property('name', from_cache=False) <> vcserver:
log ("VM herunterfahren: " + vm.get_property('name', from_cache=False))
nRes = shutdown_vm(vm)
### Pruefen, ob alle uebrigen VM heruntergefahren
bVMStatus = False
TimeOut_Start = time.time()
TimeOut = 300
log ("Es wird geprueft ob alle uebrigen VM heruntergefahren sind. Timeout (max. " + str(TimeOut) + " Sekunden)!")
while bVMStatus == False:
#Wenn Zeitlimit erreicht, while-Schleife abbrechen
if time.time() > TimeOut_Start + TimeOut:
break
for x in vmlist:
vm = server.get_vm_by_path(x)
### Nur wenn VM Name <> vCenter Status pruefen
if vm.get_property('name', from_cache=False) <> vcserver:
sVMStatus = vm.get_status()
if sVMStatus == "POWERED OFF":
bVMStatus = True
else:
log ("VM Status: " + vm.get_property('name', from_cache=False) + " " + sVMStatus)
bVMStatus = False
time.sleep(10)
break
### Shutdown aller VM bis auf VCenter abgeschlossen
if bVMStatus == True:
log ("Alle VM wurden heruntergefahren!")
else:
log ("Das Zeitlimit zum Herunterfahren der VM wurde erreicht. Der Shutdown wird fortgesetzt!")
### Hosts in den Maintenancemode schalten (Host, Timeout in Sekunden, Evakuierung (True/False))
for x in aHostList:
if x <> sHost_VC:
enter_maintenance_mode(x, 0, 0)
log ("Host in Maintenance-Mode: " + str(x))
### Host ausschalten (Host, Force (True/False))
for x in aHostList:
if x <> sHost_VC:
shutdown_host(x, -1)
log ("Shutdown Host: " + str(x))
### Datei shutdown_running.lck loeschen
if os.path.isfile(lckshutdown):
os.remove(lckshutdown)
log ("Datei shutdown_running.lck wurde geloescht")
### Host auf dem vCenter laeuft herunterfahren
shutdown_host (sHost_VC, -1)
log ("Shutdown VCHost: " + str(sHost_VC))
server.disconnect()