Monday, May 25, 2015

Get status of local VMware ESXi guests using command line

I have been talking a lot about KVM, and showing examples of how to control it from the command line. In fact, just a few posts ago we were talking about USB passthrough in KVM. I guess it is high time to do some in ESXi. After all, some of you -- yours truly included -- also have to deal with ESXi, which is VMware's product.

At this point in the presentation I can see some of you stomping your chests shouting "ESXi is Enterprise level product, not to be compared to the amateur hour likes of Kay-Vee-Em!". I have bad news for you, sunshine: they are all the same. They all can do live migration and clustering and so on. RedHat builds their enterprise turnkey solutions around KVM, which they also own. The differences between them are moving targets. And they are not the only games in town. Deal with it.

Back to the topic, yes ESXi has a nice, albeit C#-dependent (i.e. Windows only), GUI client... which they have been trying to get rid of for a while. But, sometimes I (I will take full blame for this) want to do something that is not available in the GUI. Now, I am aware I could be using PowerCLI, but what if I do want to have something running automagically in the ESXi host? To see what I mean, let's use a simple example: suposed we want to have a nice list of which vm clients ar ein this ESXi host and what they are up to (running/paused/etc). If you can't figure out why we would want to do that right now, hold onto your seat until the later parts of this article.

Of course this assumes you can ssh into the ESXi host.

The command we want to use is vm-support, and the option is -listmvs:

vm-support --listvms
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/mail_1/mail_1.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/Windows 2012/Windows 2012.vmx (Running)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/coreos/coreos.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/devnetbsd/devnetbsd.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/centos64/centos64.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/boot2docker/boot2docker.vmx (Running)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/TheOnion/TheOnion.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/devubuntu/devubuntu.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/freebsd/freebsd.vmx (Registered)
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/devcentos/devcentos.vmx (Registered)
#

As you can see, it shows where each VM disk image (yes, yes, I am lazy but this is just a little blog post. Focus, focus, focus) and a status of Running or Registered. It is a good start; we feel good about ourselves until we realize that Registered canmean the vm is turned off or just saved. Bummer.

Now I know that when you save a vm, it creates a file with a .vmss extension that stores the state of the vm when it was saved. Let me show an example: I know that devcentos is saved for I did that last week. If what I said before is not a lie, we should find a .vmss file:

# ls /vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/devcentos/*.vmss
/vmfs/volumes/52a08b50-984b4bf0-219f-d067e51ce7b7/devcentos/devcentos-aaf17b2a.vmss
#
For those of you who read this blog (why would you do that?), that sounds just like the .save file KVM uses to do the very same thing. Didn't I mention in the end of the day they are the same? So, what we need to do is if we find a vm labelled as Registered, we should also see if it has a .vmss file. If so, it is a saved vm. I could bore you with the details and trials, but here is what I got:

cat > vm_status.sh  << 'EOF'
#!/bin/sh
IFS=$'\n'

for i in $(vm-support --listvms)
do 
   vm_path=$(dirname "$i")
   vm_name=$(basename $vm_path)
   vm_status=$(echo "$i" | awk '{ print $NF}' )

   # Now check status of each vm
   case $vm_status in
      '(Running)' )
         echo "$vm_name is currently running"
         ;;
      '(Registered)' )
         test -f $vm_path/*.vmss \
            && echo "$vm_name is currently saved" \
            || echo "$vm_name is currently off"
         ;;
   esac

done
EOF
chmod +x vm_status.sh
It is not perfect, but it does what I want:
# ./vm_status.sh 
mail_1 is currently off
Windows 2012 is currently running
coreos is currently off
ctfbox is currently off
devnetbsd is currently off
centos64 is currently off
boot2docker is currently running
TheOnion is currently saved
devubuntu is currently off
freebsd is currently off
devcentos is currently saved
#
One thing you need to be aware is that ESXi uses busybox, so do not try to write a full blown Bash script; you will end very disappointed.

"So, what is the point of this script as it runs in the ESXi host?" you might ask, and you have a point. By itself it makes more sense to wire it in PowerCLI and run it that way. But, what if you want to have a script send you periodic reports of which vms are alive and which ones are off? Or what if you need to see if you need to start a given vm or just restore it? This script is small and a bit of a simpleton, but it shows the potential we have for writing proper scripts to be run in the ESXi host. I will show an even more practical example in an upcoming article.

No comments: