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"

18 Kommentare

  • Norbert Schmidt

    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

  • Welche ESXi-Version (4.x, 5.x, Free, …) wird denn verwendet, da es da durchaus Unterschiede gibt.

    Seit v5.1 reicht die einzelne Zeile vom Update 03.11.2012 aus.

    Damit das Ganze überhaupt sauber läuft, muss das automatische Herunterfahren der VMs zuvor eingerichtet sein.
    Eine Anleitung dazu findet sich hier:

    Virtuelle Maschinen unter VMware ESXi automatisch starten und beenden

  • Norbert Schmidt

    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…

  • 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.

  • 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…)

  • 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.

  • 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?

  • > 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

  • 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 🙂

  • > 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.

  • 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?

  • Ja, sollte gehen. Die genaue Syntax kenn‘ ich leider nicht und aktuell habe ich keinen ESX zum Testen da.

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

    Kann auch sein, das ein „reboot“ reicht ohne „shutdown.sh“.

    Infos:


    ESXi/ESX 4.x and ESXi 5.x/6.0 shutdown and reboot commands (1013193)

  • 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!!!

  • Wunderbar, wieder was geklärt 😉

  • 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

  • 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?

  • Hallo,
    bei meinem Server ist es leider schon zum zweiten Mal zu einem blöden Fehler gekommen.

    Ich setze die beschriebene Methode „/sbin/shutdown.sh && /sbin/poweroff“ von einem Windows Server 2016 ab. Der Host ist ein ESXi 6.0 Free.

    Wenn von apcupsd ein Shutdown durchgeführt wird, fängt der Server an, die VMs herunterzufahren. Aus irgendeinem Grund wartet er mit dem Poweroff des Hosts aber nicht ab, bis alle VMs wirklich aus sind. Das hat zur Folge, dass die VMs teilweise hart abgeschaltet werden und ich schon zum zweiten Mal den USB-Stick mit der ESXi-Installation neu machen musste, weil die Boot-Dateien auf dem Stick anschließend korrupt waren.
    So ganz erklären kann ich mir das aber nicht, warum sich der Host beim Poweroff selbst zerstört. Die USV hat auf jeden Fall dann noch nicht abgeschaltet, der ganze Prozess dauert weniger als 2 Minuten, eigentlich viel zu kurz.

    Hat jemand eine Idee? Ich würde mich sehr freuen.

  • Hallo Jörg,

    leider bin ich in Sachen VMware nicht auf dem Laufenden.
    Hast du evtl. mal die Methode vor dem Update (Sitchwort Befehlsblock) ausprobiert?
    Damit kann man zum einen mittels sleep (oder der Reihenfolge der Befehle) das Herunterfahren des ESXi beeinflussen.
    Mein Gedanke wäre in etwas dieser:


    rem %SHUTDOWN% -h now
    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"
    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 4"
    GOTO :done

    Also erst die VMs herunterfahren und erst dann den Host. Dabei wäre zu beachten, das die Windows-VM die das steuert ebenfalls Zeit zum Herunterfahren benötigt, das wäre im Beispiel die ID 4.
    „sleep 2m…“ könnte man z.B. auf „5m“ hochsetzen.

Schreibe einen Kommentar

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