In today’s IT landscape, efficient management and monitoring of virtual environments are crucial for system administrators and Managed Service Providers (MSPs). Virtual environments, like those managed by Proxmox, require regular oversight to ensure smooth operation and optimal performance.
Automating the collection of virtual machine (VM) status and basic information not only saves time but also reduces the risk of human error. This blog post explores a bash script designed to fetch and display the status and details of Proxmox guests, demonstrating its utility and how it can streamline IT operations.
Background
Proxmox is a popular open-source virtualization management solution, combining KVM and container-based virtualization in a single platform. For IT professionals and MSPs, monitoring the state of VMs and containers is a routine yet vital task. This script addresses the need for an automated, consistent method to gather and display VM information, presenting it in a user-friendly format that can be easily accessed and interpreted.
The Script
#!/usr/bin/env bash # Description: This script gets the status and basic info of all Proxmox guests on a host and saves it to a WYSIWYG custom field. # # Release Notes: Initial Release # By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. # Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. # Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. # Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. # Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. # Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. # Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. # EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA). # # Below are all the (case sensitive) valid parameters for this script. # Only the custom field name is required! # Preset Parameter: "Custom_Field_Name" # Custom_Field_Name: The name of the WYSIWYG custom field to save the VM info to. Custom_Field_Name=$1 if [[ -n "${customFieldName}" ]]; then Custom_Field_Name="${customFieldName}" fi if [[ -z "${Custom_Field_Name}" || "${Custom_Field_Name}" == "null" ]]; then echo "The custom field name is required." echo " Example: guests" exit 1 fi # Check that we have the required tools if ! command -v pvesh &> /dev/null; then echo "The Proxmox VE API tool 'pvesh' is required." exit 1 fi if ! command -v python3 &> /dev/null; then echo "The python3 is required. Should already be installed." exit 1 fi # Check that we are running as root if [[ $EUID -ne 0 ]]; then echo "This script must be run as root." exit 1 fi function SetCustomField() { /opt/NinjaRMMAgent/programdata/ninjarmm-cli "$@" } # Get the status and basic info of all Proxmox VMs on a host qemu_guests=$(pvesh get /nodes/localhost/qemu --output-format=json) # Create a table to store the VM info with the headers: Name, Status, Memory, CPUs, Disk Sizes vm_table="<table><tr><th>Status</th><th>ID</th><th>Name</th><th>Memory</th><th>CPUs</th><th>Disk Sizes Combined</th></tr>" # Loop through each VM and add the info to the table qemu_table=$(echo "$qemu_guests" | python3 -c ' import sys, json # Function to convert bytes to human readable format def human_readable_size(size): for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: if size < 1024: return f"{size:.2f} {unit}" size /= 1024 qemu_guests = json.load(sys.stdin) vm_table = "" for qemu in qemu_guests: qemu_id = qemu["vmid"] qemu_name = qemu["name"] qemu_status = qemu["status"] # Convert the memory from bytes to GB qemu_mem = human_readable_size(qemu["maxmem"]) qemu_cpus = qemu["cpus"] # Convert the disk size from bytes to GB qemu_disk = human_readable_size(qemu["maxdisk"]) # Add HTML blank space if values are empty qemu_id = qemu_id if qemu_id else " " qemu_name = qemu_name if qemu_name else " " qemu_mem = qemu_mem if qemu_mem else " " qemu_cpus = qemu_cpus if qemu_cpus else " " qemu_disk = qemu_disk if qemu_disk else " " if "running" in qemu_status: status_text = "<tr class='"'success'"'><td>Running</td>" elif "stopped" in qemu_status: status_text = "<tr class='"'danger'"'><td>Stopped</td>" else: status_text = "<tr class='"'other'"'><td>{}</td>".format(qemu_status) vm_table += "{}<td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>".format( status_text, qemu_id, qemu_name, qemu_mem, qemu_cpus, qemu_disk ) print(vm_table) ') vm_table="$vm_table$qemu_table" # Loop through each lxc and add the info to the table lxc_guests=$(pvesh get /nodes/localhost/lxc --output-format=json) # Loop through each lxc and add the info to the table lxc_table=$(echo "$lxc_guests" | python3 -c ' import sys, json # Function to convert bytes to human readable format def human_readable_size(size): for unit in ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB"]: if size < 1024: return f"{size:.2f} {unit}" size /= 1024 lxc_guests = json.load(sys.stdin) vm_table = "" for lxc in lxc_guests: lxc_id = lxc["vmid"] lxc_name = lxc["name"] lxc_status = lxc["status"] # Convert the memory from bytes to GB lxc_mem = human_readable_size(lxc["maxmem"]) lxc_cpus = lxc["cpus"] # Convert the disk size from bytes to GB lxc_disk = human_readable_size(lxc["maxdisk"]) # Add HTML blank space if values are empty lxc_id = lxc_id if lxc_id else " " lxc_name = lxc_name if lxc_name else " " lxc_mem = lxc_mem if lxc_mem else " " lxc_cpus = lxc_cpus if lxc_cpus else " " lxc_disk = lxc_disk if lxc_disk else " " if "running" in lxc_status: status_text = "<tr class='"'success'"'><td>Running</td>" elif "stopped" in lxc_status: status_text = "<tr class='"'danger'"'><td>Stopped</td>" else: status_text = "<tr class='"'other'"'><td>{}</td>".format(lxc_status) vm_table += "{}<td>{}</td><td>{}</td><td>{}</td><td>{}</td><td>{}</td></tr>".format( status_text, lxc_id, lxc_name, lxc_mem, lxc_cpus, lxc_disk ) print(vm_table) ') vm_table="$vm_table$lxc_table" # Close the table vm_table="$vm_table</table>" # Highlight the running and stopped VMs vm_table=$(echo "$vm_table" | sed 's/<tr><td>running<\/td>/<tr class="success"><td>Running<\/td>/') vm_table=$(echo "$vm_table" | sed 's/<tr><td>stopped<\/td>/<tr class="danger"><td>Stopped<\/td>/') # Save the table to the custom field if ! SetCustomField set "$Custom_Field_Name" "$vm_table"; then echo "Failed to save the Proxmox VM info to the custom field: $Custom_Field_Name" exit 1 fi echo "The Proxmox VM info has been saved to the custom field: $Custom_Field_Name"
Access over 300+ scripts in the NinjaOne Dojo
Detailed Breakdown
The provided bash script retrieves the status and essential information of all Proxmox guests on a host and saves this data to a custom field. This is particularly useful for environments with numerous VMs, where manual checks can be time-consuming and error-prone.
Step-by-Step Explanation
1. Script Initialization and Parameter Handling:
- The script begins by defining the custom field name, which is a mandatory parameter. This field name will store the VM information.
- If the custom field name is not provided or is invalid, the script exits with an error message.
2. Tool Availability Check:
- The script verifies the availability of required tools: pvesh (Proxmox VE API tool) and python3. If these tools are not found, the script exits with an appropriate error message.
3. Root Privileges Verification:
- The script checks if it is running with root privileges. If not, it exits with an error message.
4. Fetching VM Information:
- Using pvesh, the script retrieves information about QEMU VMs and LXC containers from the Proxmox host.
- This information is processed using Python to generate an HTML table with details such as status, ID, name, memory, CPUs, and combined disk sizes.
5. Generating HTML Table:
- The Python script embedded within the bash script formats the retrieved JSON data into an HTML table. This table is styled to highlight running and stopped VMs differently.
6. Saving the Table to a Custom Field:
- The generated HTML table is saved to the specified custom field using the NinjaRMM CLI tool.
Potential Use Cases
Imagine an MSP managing multiple Proxmox environments for various clients. Manually checking the status and resource allocation of each VM across different hosts can be cumbersome. By deploying this script, the MSP can automate the collection of this data and have it readily available in a custom field, accessible through their management interface. This not only enhances efficiency but also ensures that they can quickly respond to any issues that arise.
Comparisons
Other methods to gather VM information might involve manually running commands and compiling results, which is time-consuming and prone to errors. Tools like Proxmox’s web interface provide the needed information but require manual navigation and checking. In contrast, this script automates the entire process, ensuring consistency and saving valuable time.
FAQs
Q: What if the script fails to find pvesh or python3?
A: The script checks for these dependencies at the start and exits with a clear error message if they are not found, guiding the user to install the missing tools.
Q: Can the script be run without root privileges?
A: No, the script must be run as root to access the necessary system information.
Q: What if the custom field name is not provided?
A: The script requires the custom field name as a parameter. If it is not provided, the script will exit with an error message.
Implications
Automating the collection of VM information not only improves operational efficiency but also enhances IT security. Regular, automated checks ensure that all VMs are accounted for and running as expected, reducing the risk of unnoticed downtimes or resource misallocations.
Recommendations
When using this script, ensure that:
- The script is run on a regular schedule to keep the VM information up-to-date.
- Proper permissions are set for the script to run as root.
- Dependencies (pvesh, python3, NinjaRMM CLI) are installed and correctly configured.
Final Thoughts
This script is a valuable tool for IT professionals managing Proxmox environments, streamlining the process of gathering and displaying VM information. For those utilizing NinjaOne, this script further integrates into their workflow, making it easier to maintain a clear and updated view of their virtual infrastructure. By automating routine tasks, IT professionals can focus on more strategic activities, enhancing overall productivity and system reliability.