I recently had a short discussion with my colleague on implementing CLIs with vSphere Java API. One problem is that if you have multiple commands to run, each of them connects to the server and authenticate over and over. You’d better remember to logout the connection each time after you are done, or leave many un-used connections on the server that could significantly slow down your ESX or vCenter server (read this blog for details).
You can have two solutions to this problem. The first one is to have your own “interpreter” command. After you type the command, it shows you prompt for more sub-commands. It’s very much like the “ftp” command in that sense. You can have subcommands like “login” or “open” or “connect” for connecting to a server, and other commands. The “interpreter” command can then hold the ServiceInstance object until it’s closed in the end.
Lost VMs or Containers? Too Many Consoles? Too Slow GUI? Time to learn how to "Google" and manage your VMware and clouds in a fast and secure HTML5 App.
You can save about 0.3 to 0.5 second on creating new HTTPS connection and login for each command after the first one. It’s not a big deal given that vSphere Java API has hugely reduced that time from 3 to 4 seconds with Apache AXIS. So if you switch to vSphere Java API, you get instant 10 time performance gain. Still, if you have many commands to run, it could be a decent saving.
With this solution, you can also implement batch mode in which you can save all your commands into a file and then execute them all with one command. You can find many examples like PowerShell which support interactive mode and batch mode.
Another solution is just having normal commands. The problem becomes how to avoid the authentication for each command after the first. Luckily we have something for you in the API. The ServiceInstance type has a constructor like the following. It was originally designed for vSphere Client Plug-in which reuses the same session ID of the vSphere Client.
public ServiceInstance(URL url, String sessionStr, boolean ignoreCert, String namespace)
The expected session string is as follows. Note that you have to escape the ” if you include it in your Java source code.
What you can do is to get the session ID and save it to a well-known temporary file. Each command checks if the file exists. If yes, it loads the session string and pass into the above constructor. By default a session expires for 30 minutes on server side. You have to guide against this in your code with normal login if that happens.
“But wait, how can I get the session ID from an existing ServiceInstance?” you may ask. It’s in fact pretty easy. From any ManagedObject like ServiceInstance, you can have one line like this:
String sessionStr = si.getServerConnection().getSessionStr();
It will have the same format as you would pass in to the above constructor.