Automating CLI Command Execution with Paramiko

I spend my time always playing around with environments. Sometimes it’s simple spinning up multiple VMs with Terraform, configuring with Ansible, or just running simple stress tests. In this particular case, I had spun up four CentOS VMs all of which have the same application running Folding@Home. Incase you don’t know what Folding@Home is:

Folding@home is a distributed computing project which studies protein folding, misfolding, aggregation, and related diseases. We use novel computational methods and large scale distributed computing to simulate timescales thousands to millions of times longer than previously achieved.”

I figured running this application in my Nutanix environment would be a fun project. Currently, I’m running playbooks from my Prism Central instance to automate powering on and off of these VMs based on pre-defined hours of the day. But what if I want to spin them up without logging into Prism Element? While you can define the power state of VMs with Terraform, sadly, you’re not able to yet with Nutanix. I decided to use an old friend, Python with Paramiko.

Note: Ok, I lied. It’s a combination of Python, Paramiko, and Nutanix ACLI.

What you’ll need:
1. CVM IP Address
2. Login credentials for said CVM
3. Python 3.0 installed
4. Image UUID

Alrighty, SSH into any of your CVMs with the appropriate user credentials. From here, you’ll need to gather the VMs you’d like to power on. Use the command: acli image.list

Copy to a clipboard the Image UUID.

Go to your editor of choice and use my already created script as a template.

I use Microsoft Visual Studio Code for my editing, but anything really works.

import paramiko
import sys
import config

username = sys.argv[1] # First command after your script
password = sys.argv[2] # Second command after your script

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('10.48.2.15', port=22, username=username, password=password)
stdin, stdout, stderr = client.exec_command("acli vm.on cbd69a63-c0a1-404c-969a-9816e085372f && acli vm.on b637a621-6cf2-442c-a513-5caeb108e96f && acli vm.on 28d4c186-c05c-4709-814f-eb635b4f269d")
lines = stdout.read()

print(lines)
client.close()

The script is pretty standard from what you’ll get on Paramiko’s documentation site. There are two points that I want to highlight for your future uses:

1. In the documentation, you’d need to store your username and password in plain text on the same script. This works, but it is a HUUUGE no no as it is a security issue. You can store your passwords in a separate file, but I decided to import sys so I can use the sys.argv[] feature to input the username and password on the command line instead.

2. client.exec_command(“”) is where you’ll need to enter your Nutanix acli commands. Since I want to power on three VMs at the same time, I added “&&” in between each command so they will all be run at the same time. The commands being acli vm.off <Image_UUID>

When you’re done making your edits, go ahead and run the script from your command line.

python PowerOnVM.py admin password

After the python script, there is the username (admin) and password (password) that you need to enter to log into the CVM and execute the acli commands.

And that’s it! Simple way to execute terminal commands on a remote host.