Yesterday, I posted a screenshot on Twitter where I pulled the CPU temperature from a Raspberry Pi running ESXi-Arm using curl. If that is possible, it would be a great option to pull the data for monitoring or graphing purposes:
I got a few messages on whether this really works, or is a fake. So, here is how I did it...
Disclaimer: This is not supported by VMware, use at your own risk.
We all know the webserver running on the ESXi hosts that serves the Web Client. The root directory from that webserver is located in /usr/lib/vmware/hostd/docroot/ and it is quite easy to add custom files. But this webserver can only serve static content like images or HTML pages.
A second webserver has the ability to run python-based CGI scripts to allow administrators the download of esxcfg-info output and vm-support bundles:
- https://[esx]/cgi-bin/esxcfg-info.cgi
- https://[esx]/cgi-bin/vm-support.cgi
The scripts that are delivered by the hostdCgiServer are located in /usr/lib/vmware/hostd/cgi-bin/ and my idea was to add custom scripts here. Unfortunately, there are two problems:
First Problem: You can't just add custom scripts. You can place whatever you want in the cgi-bin directory, but the hostdCgiServer just ignores it. I've added my script to the cgi-bin directory and tried to open the site using a browser, which resulted in HTTP ERROR 404 - Page not found. The log file (/var/log/hostdCgiServer.log) did not give a hint on what's happening. Apparently, the hostdCgiServer only accepts a hardcoded list of files.
2020-11-13T15:57:16.387Z info hostdCgiServer[137140] [Originator@6876 sub=CgiHandler] Received HTTP GET request for URI /cgi-bin/temp.cgi 2020-11-13T15:57:16.387Z info hostdCgiServer[137140] [Originator@6876 sub=CgiHandler] Authorizing SOAP cookie ... 2020-11-13T15:57:16.388Z verbose hostdCgiServer[137140] [Originator@6876 sub=vmomi.soapStub[7]] Connected to host <cs p:000000878adfbf00, TCP:localhost:80> using vim25/6.0 (vim.version.version10) 2020-11-13T15:57:16.395Z verbose hostdCgiServer[137140] [Originator@6876 sub=HttpConnectionPool-000008] HttpConnectionPoolImpl created. maxPoolConnections = 1; idleTimeout = 900000000; maxOpenConnections = 1; maxConnectionAge = 0 2020-11-13T15:57:16.403Z info hostdCgiServer[137140] [Originator@6876 sub=CgiHandler] Authorizing user 'root' 2020-11-13T15:57:16.403Z verbose hostdCgiServer[137140] [Originator@6876 sub=vmomi.soapStub[8]] Connected to host <cs p:000000878adf5cb0, TCP:localhost:80> using vim25/6.0 (vim.version.version10) 2020-11-13T15:57:16.411Z verbose hostdCgiServer[137140] [Originator@6876 sub=HttpConnectionPool-000009] HttpConnectionPoolImpl created. maxPoolConnections = 1; idleTimeout = 900000000; maxOpenConnections = 1; maxConnectionAge = 0 2020-11-13T15:57:16.479Z verbose hostdCgiServer[137140] [Originator@6876 sub=Default] Hostd operation failed: N5Vmomi5Fault15InvalidArgument9ExceptionE(Fault cause: vmodl.fault.InvalidArgument --> ) --> [context]zKq7AWICAgAAAEhzBAEAaG9zdGRDZ2lTZXJ2ZXIA[/context] 2020-11-13T15:57:16.479Z verbose hostdCgiServer[137140] [Originator@6876 sub=CgiHandler] Hostd error. Authorizing with PAM 2020-11-13T15:57:16.509Z verbose hostdCgiServer[137140] [Originator@6876 sub=CgiHandler] Sent Not Found response
So, why not modify the existing files?
Second Problem:
# ls -l /usr/lib/vmware/hostd/cgi-bin/esxcfg-info.cgi -r-xr-xr-x 1 root root 5374 Oct 21 20:09 /usr/lib/vmware/hostd/cgi-bin/esxcfg-info.cgi # chmod +w esxcfg-info.cgi chmod: esxcfg-info.cgi: Operation not permitted
According to KB78689, the root account can no longer change permissions since ESXi 7.0. So you can't modify the files that are already there. Now what? After inspecting the hostdCgiServer I figured out that it is actually hardcoded to only listen on 3 files:
- esxcfg-info.cgi
- vm-support.cgi
- hostd-operation.cgi
"hostd-operation.cgi" what? That file does not even exist! And here we go!
How to Pull CPU Temperature using Curl
- Install the thpimon driver by Tom Hebel
- Disable the ESXi Firewall
# esxcli network firewall set --enabled false
- Download and unzip the fgrehl/esxi-raspi repository from GitHub to a datastore
# cd /vmfs/volumes/[DATASTORE]/ # wget https://github.com/fgrehl/esxi-raspi/archive/main.zip # unzip main.zip
- Make the python script executable
# cd esxi-raspi-main/pyUtil/ # chmod +x hostd-operation.cgi
- Create a soft link to hostd-operation.cgi and the pimonLib directory in the cgi-bin directory. Make sure to use the correct path to your datastore.
# ln -s '/vmfs/volumes/[datastore]/esxi-raspi-main/pyUtil/hostd-operation.cgi' /usr/lib/vmware/hostd/cgi-bin/hostd-operation.cgi # ln -s '/vmfs/volumes/[datastore]/esxi-raspi-main/pyUtil/pimonLib/' /usr/lib/vmware/hostd/cgi-bin/pimonLib
- You can now access the script using a browser or curl. Keep in mind that you have to login using the root account, like you know it from the vSphere Client:https://[ESXi-URL]/cgi-bin/hostd-operation.cgi?getTemp
https://[ESXi-URL]/cgi-bin/hostd-operation.cgi?getPiMonJson
If you want to use curl, use either "-u USER:PASSWORD", or a netrc auth file.
# curl https://esx8.virten.lab/cgi-bin/hostd-operation.cgi?getTemp -u root:[PASSWORD] 43.0 # curl https://esx8.virten.lab/cgi-bin/hostd-operation.cgi?getTemp --netrc-file .authVirten 43.0 # curl https://esx8.virten.lab/cgi-bin/hostd-operation.cgi?getPiMonJson --netrc-file .authVirten | python -m json.tool { "BoardModel": 0, "BoardRev": "0xd03114", "FWRev": "0x5f440c10", "Temp": 42.0, "boardMACStr": "58:be:c8:32:a6:dc", "boardSerial": "0x0000008b5b8b21" } # cat .authVirten machine esx8.virten.lab login root password [PASSWORD]
If you do not have a valid certificate, use the --insecure option.
# curl https://esx8.virten.lab/cgi-bin/hostd-operation.cgi?getTemp -u root:[PASSWORD] --insecure 43.0
Hi,
thank you for effort. it been a good practice and solution. I could not find any good practice for how to get esxi pi temp information.
i tried to execute your script but I get some error like below test. can you please give any solution opinion about that problem.
many thanks regards.
2020-09-01T14:22:47.037Z info hostdCgiServer[133477] [Originator@6876 sub=CgiHandler] Received HTTP GET request for URI /cgi-bin/hostd-operation.cgi?getPiMonJson
2020-09-01T14:22:47.037Z info hostdCgiServer[133477] [Originator@6876 sub=CgiHandler] Authorizing user 'root'
2020-09-01T14:22:47.037Z verbose hostdCgiServer[133477] [Originator@6876 sub=vmomi.soapStub[8]] Connected to host using vim25/6.0 (vim.version.version10)
2020-09-01T14:22:47.044Z verbose hostdCgiServer[133477] [Originator@6876 sub=HttpConnectionPool-000009] HttpConnectionPoolImpl created. maxPoolConnections = 1; idleTimeout = 900000000; maxOpenConnections = 1; maxConnectionAge = 0
2020-09-01T14:22:47.120Z info hostdCgiServer[133477] [Originator@6876 sub=SysCommandPosix] ForkExec(/usr/lib/vmware/hostd/cgi-bin/hostd-operation.cgi) 133714
2020-09-01T14:22:47.120Z verbose hostdCgiServer[133477] [Originator@6876 sub=CGI:hostd-operation.cgi] CGI script started
2020-09-01T14:22:47.372Z verbose hostdCgiServer[132861] [Originator@6876 sub=CGI:hostd-operation.cgi] Close
2020-09-01T14:22:47.372Z error hostdCgiServer[132861] [Originator@6876 sub=CGI:hostd-operation.cgi] CGI command produced incorrect headers
2020-09-01T14:22:47.373Z verbose hostdCgiServer[132861] [Originator@6876 sub=CGI:hostd-operation.cgi] Sent Internal Server Error response
2020-09-01T14:22:47.373Z error hostdCgiServer[132861] [Originator@6876 sub=CGI:hostd-operation.cgi] CGI command failed (1): Traceback (most recent call last):
--> File "/usr/lib/vmware/hostd/cgi-bin/hostd-operation.cgi", line 4, in
--> from pimonLib import *
--> File "/vmfs/volumes/5f4e574a-53b40903-e9da-dca632c53c84/esxi-raspi-main/pyUtil/pimonLib/__init__.py", line 32, in
--> PIMON_DEVICE_PATH = glob.glob('/dev/vmgfx*')[0]
--> IndexError: list index out of range
-->
Do you have thpimon installed and rebooted? (https://www.virten.net/2020/11/get-raspberry-pi-cpu-temperature-on-esxi-arm/)
Can you check if there is any /dev/vmgfx device in /dev ? (# ls -l /dev/ |grep vmgfx)