Windows: Mit apcupsd einen VMware ESXi herunterfahren

Im Falle eines längeren Stromausfalls sollten Server heruntergefahren werden, bevor die Akkus der USV entladen sind. Bei Servern an denen die USV direkt angeschlossen ist, stellt das in der Regel kein Problem dar. Unter Umständen wird es allerdings in virtualisierten Umgebungen etwas aufwendiger.

In diesem Beispiel geht es darum, einen VMware ESXi 5.0 Update 1 Server, der mehrere virtuelle Maschinen beheimatet, bei einem Stromausfall über apcupsd herunterzufahren.

Wichtig: Eines vorweg, es gibt Unterschiede zwischen der freien und der lizenzierten Version des ESXi. In diesem Artikel geht es um den freien ESXi.

Die USV ist via USB mit dem ESXi verbunden und der USB-Anschluß wird via USB Passthrough an ein virtuelles Windows weitergegeben. Auf dem Windows ist apcupsd installiert. Ferner wird das Tool plink.exe benötigt.

Damit apcupsd den ESXi herunterfahren kann, muss auf Diesem ssh freigeschaltet sein. Das geht entweder lokal am ESXi oder über den vSphere Client. Eine Anleitung wie man ssh über den vSphere Client aktiviert findet sich im ersten Abschnitt dieses Artikel.

Die virtuellen Maschinen sollten so konfiguriert sein, das sie beim Starten und Herunterfahren des Hypervisors ebenfalls gestartet oder heruntergefahren werden.

Leider gibt es bei der freien Version des ESXi 5.0 Update 1 an dieser Stelle derzeit ein Problem. Siehe dazu hier. Das automatische Starten der virtuellen Maschinen funktioniert bis auf weiteres nicht, so das nach einem Neustart des ESXi an dieser Stelle Hand angelegt werden muss.

Als Vorbereitung für das automatische Herunterfahren der virtuellen Maschinen, muss auf dem ESXi via ssh folgender Befehl ausgeführt werden:

vim-cmd vmsvc/getallvms

Dieser Befehl listet alle vorhandenen virtuellen Maschinen samt ID auf. Die IDs werden benötigt, um die virtuellen Maschinen, sofern die VMware Tools installiert sind, herunterfahren zu können. Alternativ kann man auch ssh (Linux) mit shutdown (Windows & Linux) verwenden.

Auf dem Windows , auf dem apcupsd installiert ist, muss die Datei „C:\apcupsd\etc\apcupsd\apccontrol.bat“ editiert werden.

Nun die Zeile 162

%SHUTDOWN% -h now

suchen, mit einem vorangestellten „rem “ auskommentieren und ober- oder unterhalb folgende Befehle einfügen:

Zum Herunterfahren des ESXi, wird zunächst dieser Befehl mit einer Wartezeit von 2 Minuten („… sleep 2m …“) abgesetzt:

start PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "sleep 2m && /sbin/shutdown.sh && /sbin/poweroff"

Das bedeutet, die virtuellen Maschinen haben zwei Minuten Zeit, um herunterzufahren, bevor der ESXi herunterfährt. In Abhängigkeit der Anzahl der virtuellen Maschinen und der Haltezeit der USV muss die Zeit angepasst werden.

Je nachdem wie viele virtuelle Maschinen vorhanden sind, muss die Zeile

PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "vim-cmd vmsvc/power.shutdown ID"

mit der richtigen ID hinzugefügt werden.

Der fertige Befehlsblock sieht dann z.B. so aus:

rem %SHUTDOWN% -h now
start PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "sleep 2m && /sbin/shutdown.sh && /sbin/poweroff"
PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "vim-cmd vmsvc/power.shutdown 1"
PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "vim-cmd vmsvc/power.shutdown 2"
PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "vim-cmd vmsvc/power.shutdown 3" 
GOTO :done

WICHTIG: Die plink.exe sollte einmal in einer Eingabeaufforderung wie folgt ausgeführt werden:

PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "ls"

Bei der ersten Ausführung erscheint eine Abfrage, ob der ssh-fingerprint gespeichert werden soll. Dieses muss man mit „y“ bestätigen, da später sonst keine automatische Anmeldung am ESXi und damit auch kein Herunterfahren der virtuellen Maschinen als auch des Hosts möglich ist.

Anmerkung: In abgewandelter Form funktioniert die hier beschriebene Vorgehensweise auch für virtuelle Linux-Maschinen.

Update 03.11.2012

Mit Version 5.1 des VMware vSphere Hypervisor (ESXi) ist das Problem beim automatischen Herunterfahren als auch Neustarten der virtuellen Maschinen behoben.

Somit reicht es aus, mittels Skript folgenden Befehl abzusetzen:

start PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi "/sbin/shutdown.sh && /sbin/poweroff"

16 Gedanken zu „Windows: Mit apcupsd einen VMware ESXi herunterfahren

  1. Sehr schöne Anleitung und ansich auch ein problemarmer Ansatz, aber ich habe ein Problem mit der Zeile:
    start PFAD\plink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „sleep 2m && /sbin/shutdown.sh && /sbin/poweroff“

    Hier bleibt bei mir die Batchausführung stehen, bis die 2 Minuten rum sind wodurch die anderen VM Maschinen gar nicht mehr runter gefahren werden, sondern die ganze Maschine nach den 2 Minuten hart runter fährt.
    Was mach ich da falsch? Muß ich die Zeile zum runterfahren des ESXi hinter alle anderen „root@IP-DES-ESXi „vim-cmd vmsvc/power.shutdown 1″“ Zeilen einfügen?

    Gruß
    Norbert

  2. Ich setze die Free Version ESXi 5 ein Image Profil: ESXi-5.0.0-469512
    Ich habe jetzt das automatische Runterfahren eingerichtet, so wie in Deinem Link beschrieben. Jedoch wird es wahrscheinlich nicht funktionieren, da ich noch eine 5.0er Version habe.
    Ich habe jetzt die Zeile zum Herunterfahren des ESXi Hosts ans Ende gestellt. damit die virtuellen Maschinen schon unten sind, habe aber die Sorge, dass ich die virtuelle Maschine auf der das Batch-Script läuft dann schon runter gefahren habe und somit der letzte Befehl gar nicht mehr ausgeführt wird.
    Auf einen meiner missglückten Versuche hat eine VM etwas allergisch reagiert, weshalb ich nicht gerne weitere Tests mache, die mir unter Umständen die VM’s in Probleme schmeißen…

  3. Deswegen wurde der Befehl zum Herunterfahren des ESXi ursprünglich mit „start…“ am Anfang des Skript gesetzt.
    Evtl. mit einem anderen ESXi-Host zuerst testen, kann ja auch eine Whitebox sein.

  4. Vielen Dank für die tolle Anelitung! Bin dem Ganzen so einen Schritt näher gekommen.

    Eine sehr wichtige Anmerkung allerdings noch:
    Ein einfacher Aufruf von plink.exe aus einem Command-Line-Window genügt u.U. nicht:
    Wird für den Aufruf des Scriptes und somit von plink.exe nämlich ein Service verwendet, welcher unter einem anderen Benutzer (meist NT-AUTHORITY\SYSTEM) aufgerufen wird, so sind diesem die SSH-Fingerprints nach wie vor unbekannt und die plink.exes bleiben einfach hängen. Grund ist, dass die Fingerprints per User gespeichert werden.

    Um dem entgegen zu wirken gibt es mindestens eine Möglichkeit:
    Nachdem das Skript fertiggestellt ist, sich an der Maschine welche den Befehl absetzen soll anmelden und dann einen Stromausfall provozieren. Sobald der Shutdown initiiert wird, erscheint auf der Maschine eine Meldung:
    „Erkennung interaktiver Dienste
    Von einem auf diesem Computer ausgeführten Programm wird versucht, eine Meldung anzuzeigen.“
    Mit einem Klick auf „Meldung anzeigen“ werden die gestoppten plink.exes angezeigt, bei welchen nun überall mit „y“ der Fingerprint akzeptiert werden muss. Ab sofort funktioniert das Shutdown-Script unbeaufsichtigt.

    Getestet wurde dies auf einem Windows 7 32bit in einer Server 2012 Domänenumgebung auf einem ESXi 5.1-799733.

    Eine andere, einfachere, allerdings von mir nicht getestete Möglichkeit wäre, den APCUPS-Service unter einem anderen Benutzer auszuführen, welchem die SSH-Fingerprints weniger umständlich bekannt gemacht werden können. (zB via cmd -> „Ausführen als…“ -> plink.exe -ssh…)

  5. Mittels
    echo yes | PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „/sbin/shutdown.sh && /sbin/poweroff“

    kann der ssh-fingerprint automatisch angenommen werden.

  6. Hallo,

    vielen Dank für die Anleitung, bin schon sehr weit damit gekommen! Das einzige was nervt ist, dass ich gerne erreichen möchte, dass die apccontrol.bat erst ausgelöst wird bei einem Ausfall der länger ist als 30 Sek. wenn ich den die Standard apccontrol.bat nehme und die Zeile Einfüge: start PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „sleep 2m && /sbin/shutdown.sh && /sbin/poweroff“ dann wartet der glaube ich so lange bis der Akku einen gewissen %Stand hat oder? Wenn ich eine apccontrol.bat erstellen und nur start PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „sleep 2m && /sbin/shutdown.sh && /sbin/poweroff“ einfüge und mehr nicht, dann reicht schon eine Sek. und die batch startet. Meine Frage nun wie und wo muss ich da was anpassen?

  7. > Das einzige was nervt ist, dass ich gerne erreichen möchte, dass die apccontrol.bat erst ausgelöst wird bei einem Ausfall der länger ist als 30 Sek.

    Bislang sind mir nur die „klassischen“ Szenarien bekannt, das ab einer gewissen Restkapazität bzw. Restlaufzeit (+ Reserve) die Computer heruntergefahren werden sollen.

    Was man evtl. tun könnte ist:

    In der „apccontrol.bat“ stehen nur die Aktionen drin, die ausgeführt werden sollen.
    Die Schwellenwerte wie z.B. Restlaufzeit werden in der „apcupsd.conf“ eingestellt.

    Soweit mir bekannt ist, gibt es direkt keine Möglichkeit, das geforderte Szenario umzusetzen.
    Man könnte allerdings sobald auf Akku gewechselt wird ein Skript anstarten, das 30 Sekunden wartet und dann den Shutdown durchführt.

    Der Startpunkt wäre „apccontrol.bat“, ab Zeile 114:

    :onbattery
    %POPUP% "Power failure. Running on UPS batteries."

    GOTO :done

    Man müsste dann noch etwas einbauen, das den Shutdown verhindert, sollte der Ausfall nicht länger als 30 Sekunden dauert:

    Zeile 118:

    :offbattery
    %POPUP% "Power has returned. No longer running on UPS batteries."

    GOTO :done

  8. Danke für die Hinweise habe das jetzt so gelöst, dass ich die die Zeile auf start PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „sleep 1m && /sbin/shutdown.sh && /sbin/poweroff“ auf eine Min. angepasst habe und den Auslösezeitpunkt auf 15 Min Restlaufzeit. Heisst: Wenn nur noch für 15 Min. Saft da ist löst er aus und wenn strom vorher wieder da ist auch gut! 1 Min. reicht aus um dem Host zu sagen fahre runter und in den Autostart des Host für die VMs habe ich gesagt 60 Sek. Gast herunterfahren. Ich habe 9 VM am laufen zzgl. des Host. Macht das also ca. 10-12 Min. bis alle unten sind, dann habe ich eine Reserve von 3 Min. Sollte passen oder?

    Was ich mich gerade frage ist, kann ich eigentlich in der batch die Zeile

    start PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „sleep 1m && /sbin/shutdown.sh && /sbin/poweroff“

    Zwei mal einfügen für Host 1 und für einen zweiten auch?

    Danke für deine Hilfe 🙂

  9. > Sollte passen oder?

    So beim kurzen drüberlesen sieht das ok aus.

    Man kann soweit ich weiß beliebige viele Befehle einfügen.
    Bedenken muss man, das bei Netzwerkgeräten der Switch ebenfalls an der USV hängen sollte, sonst erreicht man diese im Falle des Stromausfalls schlichtweg nicht.

  10. Ja das mit dem Switch habe ich schon berücksichtigt, hängt an einer anderen USV. Sag mal was anderes: Das hier: start PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi „sleep 1m && /sbin/shutdown.sh && /sbin/poweroff“

    Könnte man doch auch benutzen, um den ESXI einmal durchzustarten oder? Ich weiss nur nicht was ich da ändern muss?

  11. Das war die Lösung ich habe es immer mit Restart versucht 😉

    start PFADplink.exe -ssh -pw KENNWORT -2 root@IP-DES-ESXi reboot

    so gehts!!!

  12. Hallo bei mir unter Win 2012 R2 habe ich irgendein Problem mit dem Skript. Die USV wird erkannt und der richtige Treiber von apcuspd ist installiert. Das plink command läuft auch durch, die Zertifikatswarnung habe ich bestätigt und beide Methoden (Dienst als Normaluser ausführen oder echo…) getestet. Der Server fährt einfach nicht runter wenn ich den Stecker ziehe, keiner der Guests. Führe ich das Skript manuell aus erhalte ich die folgende Meldung. Ich habe die besagte Stelle auch auskommentiert, bekomme dann aber eben die Meldung das das Skript nicht als Normaluser ausgeführt werden sollte.

    Hier die Meldung:

    C:apcupsdetcapcupsd>apccontrol.bat
    „=“ == „“ FOR %A IN () DO SET sbindir=%A“ kann syntaktisch an dieser Stelle nicht verarbeitet werden.

    Gruß

    Sven

  13. Ich vermute mal es geht um Zeile 16 der „apccontrol.bat“.
    Die Variable „sbindir“ ist wichtig, damit apcupsd den Pfad zu den binaries findet.
    Wenn mich nicht alles täuscht, sollte diese (per Standard) zu „C:apcupsdbin“ führen, dieser Pfad wird als Blindparamter (%5) an „apccontrol.bat“ vom Dienst übergeben, bin mir aber nicht sicher, ob das wirklich so ist. Die Frage lautet also, warum der Pfad fehlt oder nicht stimmt. Zum Testen könnte man z.B. die Variable selbst manuell setzen (Zeile 10 auskommentieren):

    set sbindir=C:apcupsdbin

    Andererseits wäre es evtl. hilfreich zu erfahren, was da als Blindparameter übergeben wird.

    Funktioniert denn das Herunterfahren einer oder aller VMs, wenn man die plink-Befehle unabhängig von apcupsd ausführt?

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.