how to get vm ip address from api

vinnyvinny

New Member
Dec 11, 2017
8
0
1
34
belarus, minsk
Anybody please tell me, is there a way to get ip address vm's via api interface?

i try this script
Code:
#!/bin/bash
# proxvm
# Output in specifed format (default csv) all virtual machines on proxmox 4+
SERVER=localhost
USERNAME=apiread@pve
PASSWORD=123456
FORMAT=csv

while [[ $# > 0 ]]; do
    key="$1"
    case $key in
    -p)
    PASSWORD=$2
    shift
    ;;
    -u)
    USERNAME=$2
    shift
    ;;
    -h)
    SERVER=$2
    shift
    ;;
    -f)
    FORMAT=$2
    shift
    ;;
    -h|--help|-?)
    echo "Usage:"
    echo "$0 [options]"
    echo " -h <server>   Server to connect to, default $SERVER"
    echo " -u <username> Username, default $USERNAME"
    echo " -p <password> Password, default $PASSWORD"
    echo " -f <format>   Output format (csv, json), default $FORMAT"
    exit 0
    ;;
    *)
    # unknown option
    echo "Error: unknown option $1"
    exit 1
    ;;
    esac
    shift # past argument or value
done

#echo Connecting to $SERVER:8006 as $USERNAME:$PASSWORD
TOKEN=`curl -s -k -d "username=$USERNAME&password=$PASSWORD" https://$SERVER:8006/api2/json/access/ticket | jq -r .data.ticket`
if [ "${PIPESTATUS[0]}" != "0" ]; then
    echo Auth failed
    exit 1
fi

function csv() {
    echo $VMID,$NODE,$1,$NAME,$HWADDR,$IP
}

function start_csv() {
    echo vmid,node,type,name,mac,ip
}

function end_csv() {
    echo -n
}

function json() {
    if [ "$2" != "0" ]; then
    echo ","
    fi
    echo "{"
    echo "\"vmid\": \"$VMID\","
    echo "\"node\": \"$NODE\","
    echo "\"type\": \"$1\","
    echo "\"name\": \"$NAME\","
    echo "\"mac\": \"$HWADDR\","
    echo "\"ip\": \"$IP\""
    echo -n "}"
}

function start_json() {
    echo "["
}

function end_json() {
    echo "]"
}

start_$FORMAT
POS=0

NODES=`curl -s -k https://$SERVER:8006/api2/json/nodes -b "PVEAuthCookie=$TOKEN" | jq -r '.data[].node'`
for NODE in `echo $NODES`; do
    curl -s -k https://$SERVER:8006/api2/json/nodes/$NODE/lxc -b "PVEAuthCookie=$TOKEN" > /tmp/proxvm-lxc.json
    curl -s -k https://$SERVER:8006/api2/json/nodes/$NODE/qemu -b "PVEAuthCookie=$TOKEN" > /tmp/proxvm-qemu.json

    for VMID in `cat /tmp/proxvm-lxc.json | jq -r '.data[].vmid'`; do
        curl -s -k https://$SERVER:8006/api2/json/nodes/$NODE/lxc/$VMID/config -b "PVEAuthCookie=$TOKEN" > /tmp/proxvm-$VMID.json
        JSON=`cat /tmp/proxvm-lxc.json | jq -r ".data[] | select(.vmid | tonumber | contains($VMID))"`
        NAME=`echo $JSON | jq -r .name`
        NET=`cat /tmp/proxvm-$VMID.json | jq -r .data.net0`
        HWADDR=`echo $NET | sed -re "s/.*hwaddr=([a-zA-Z0-9:]+),[a-zA-Z0-9]+=.*/\1/g"`
        IP=`arp -a | grep $HWADDR | sed -re "s/.*\(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/g"`
        $FORMAT lxc $POS
        POS=`expr $POS + 1`
    done

    for VMID in `cat /tmp/proxvm-qemu.json | jq -r '.data[].vmid'`; do
    curl -s -k https://$SERVER:8006/api2/json/nodes/$NODE/qemu/$VMID/config -b "PVEAuthCookie=$TOKEN" > /tmp/proxvm-$VMID.json
        JSON=`cat /tmp/proxvm-qemu.json | jq -r ".data[] | select(.vmid | tonumber | contains($VMID))"`
        NAME=`echo $JSON | jq -r .name`
        NET=`cat /tmp/proxvm-$VMID.json | jq -r .data.net0`
        HWADDR=`echo $NET | sed -re "s/[a-zA-Z0-9]+=([a-zA-Z0-9:]+),.*/\1/g"`
        IP=`arp -a | grep $HWADDR | sed -re "s/.*\(([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*/\1/g"`
        $FORMAT qemu $POS
        POS=`expr $POS + 1`
    done
done

end_$FORMAT

rm /tmp/proxvm-*.json

he return all, except ip addresses of virtual machines

I use proxmox ve 5.1
also I tried to access to qemu agent
https://x.x.x.x:8006/api2/json/nodes/<node id>/qemu/100/agent
but he return empty file
 
Last edited:
Hi Vinny

For such a task I would use one the API client library.
You can either use proxmoxer ( https://github.com/swayf/proxmoxer) if python is your thing or our own libpve-apiclient-perl, that you can install on any debian based system ( no need to be a PVE system )

When you use these libraries you have much less code to write, since you can work directly with the native data structures instead of converting the json output first.

This is an example on how get the IP of adress of a container using libpve-apiclient-perl:

Code:
#!/usr/bin/perl

use strict;
use warnings;
use PVE::APIClient::LWP;

my $ct_id = $ARGV[0] || '103';

my $conn = PVE::APIClient::LWP->new(
    username => 'manu@pve',
    password => $ENV{PVE4_PASS},
    host => 'pve4',
    cached_fingerprints => {
   '29:07:C0:3A:5A:6B:D8:B9:3F:2E:A6:ED:3D:33:8F:77:26:25:A4:7D:F6:66:05:DE:5C:D3:65:E7:99:08:C2:9A' => 1
    });

my $api_path = "/nodes/pve4/lxc/${ct_id}/config";
my $ct_config = $conn->get($api_path);

if ($ct_config->{net0} =~ m/,ip=(.*)\/\d{1,2}/) {
    print $1 . "\n";
}


notes:
* the host I am contacting is pve4
* cached_fingerprint is the sha256 ssl fingerprint of your PVE host ( so you can get SSL cert validation even using our default self signed cert ) you can with the command:

openssl x509 -noout -fingerprint -sha256 -in /etc/pve/nodes/pve4/pve-ssl.pem

* the password of the API node is put in the environment variable PVE_PASS

as you see much less to write :)
 
  • Like
Reactions: vinnyvinny
Hi Vinny

For such a task I would use one the API client library.
You can either use proxmoxer if python is your thing or our own libpve-apiclient-perl, that you can install on any debian based system ( no need to be a PVE system )

When you use these libraries you have much less code to write, since you can work directly with the native data structures instead of converting the json output first.

This is an example on how get the IP of adress of a container using libpve-apiclient-perl:

Code:
#!/usr/bin/perl

use strict;
use warnings;
use PVE::APIClient::LWP;

my $ct_id = $ARGV[0] || '103';

my $conn = PVE::APIClient::LWP->new(
    username => 'manu@pve',
    password => $ENV{PVE4_PASS},
    host => 'pve4',
    cached_fingerprints => {
   '29:07:C0:3A:5A:6B:D8:B9:3F:2E:A6:ED:3D:33:8F:77:26:25:A4:7D:F6:66:05:DE:5C:D3:65:E7:99:08:C2:9A' => 1
    });

my $api_path = "/nodes/pve4/lxc/${ct_id}/config";
my $ct_config = $conn->get($api_path);

if ($ct_config->{net0} =~ m/,ip=(.*)\/\d{1,2}/) {
    print $1 . "\n";
}


notes:
* the host I am contacting is pve4
* cached_fingerprint is the sha256 ssl fingerprint of your PVE host ( so you can get SSL cert validation even using our default self signed cert ) you can with the command:

openssl x509 -noout -fingerprint -sha256 -in /etc/pve/nodes/pve4/pve-ssl.pem

* the password of the API node is put in the environment variable PVE_PASS

as you see much less to write :)

Hello Manu, thanks for a quick reply, I'll try your method
 
For LXC containers, the IP adress you set in the configuration are then applied inside the LXC container.
So it is them same in the end ( NB: in your shell script you also read the IP adress from the configuration)

As long as your containers are not using DHCP, this should work.
If not, please exapling what is exactly your purpose (ie why are you writing such a script )
 
For LXC containers, the IP adress you set in the configuration are then applied inside the LXC container.
So it is them same in the end ( NB: in your shell script you also read the IP adress from the configuration)

As long as your containers are not using DHCP, this should work.
If not, please exapling what is exactly your purpose (ie why are you writing such a script )

I want write script which gets ip address from within the OS, in case OS gets address by DHCP. First I found a script that I wrote on top, but address is taken from the host table arp with which it starts, this is not a good way and he doesn't work.
Then I read at this forum that if the guest OS has QEMU-GUEST-AGENT can be done API request like https://x.x.x.x:8006/api2/json/nodes/nodeid/qemu/vmid/agent. This request should return many parameters and ip address one of them. I install qemu-guest-agent, but request return "null" value.
 
If you use DHCP, then you can configure the DHCP server to send a fixed IP address corresponding to the Mac Adress of your container.

You can get the IP address of a VM (not LXC ) via qemu-guest-agent, but this only works with Linux VMs
(if you build the agent yourselt it will work for windows too, see https://bugzilla.redhat.com/show_bug.cgi?id=1444934)
 
If you use DHCP, then you can configure the DHCP server to send a fixed IP address corresponding to the Mac Adress of your container.

You can get the IP address of a VM (not LXC ) via qemu-guest-agent, but this only works with Linux VMs
(if you build the agent yourselt it will work for windows too, see https://bugzilla.redhat.com/show_bug.cgi?id=1444934)

But qemu guest agent doesn't resolve any information. I install correctly guest agent to linux vm, checked it with command
pvesh create nodes/nodeid/qemu/vmid/agent -command ping
but command
https://x.x.x.x:8006/api2/json/nodes/nodeid/qemu/vmid/agent
returns "null"
 
For those who are exploring their options in 2024 with the VMWare exodus, here is a script I wrote that pulls the IP address of a vm with qemu agent installed:

Bash:
#!/bin/bash
# Check if VM ID was passed as an argument
if [ "$#" -ne 1 ]; then
        echo "Usage: $0 VM_ID"
            exit 1
fi
VM_ID=$1
# Ask for the Proxmox API password
echo "Enter the Proxmox API password:"
read -s PASSWORD
# Set the Proxmox server IP address and credentials
PROXMOX_IP="10.0.0.10" # Example IPs
USERNAME="root@pam"
# Authenticate and obtain a ticket
RESPONSE=$(curl -k -s -d "username=${USERNAME}" -d "password=${PASSWORD}" "https://${PROXMOX_IP}:8006/api2/json/access/ticket")
# Extract the ticket and CSRFPreventionToken using jq
TICKET=$(echo $RESPONSE | jq -r '.data.ticket')
# Check if we successfully obtained a ticket
if [ -z "$TICKET" ] || [ "$TICKET" == "null" ]; then
        echo "Failed to obtain a ticket from Proxmox API."
            exit 1
fi
echo "Obtained ticket: $TICKET"
# Assuming NODE variable is set or hardcoded here, or you could prompt for it
NODE="proxmox" # Adjust the node name as necessary
# Use the ticket to list information for the specific VM by VM_ID
# For a QEMU VM:
echo "Getting info for QEMU VM ID $VM_ID on node $NODE..."
VM_INFO=$(curl -k -s -b "PVEAuthCookie=$TICKET" "https://${PROXMOX_IP}:8006/api2/json/nodes/${NODE}/qemu/${VM_ID}/status/current")
# Parse the VM information using jq
echo "VM Status: $(echo $VM_INFO | jq -r '.data.status')"
echo "VM CPU Usage: $(echo $VM_INFO | jq -r '.data.cpu')"
echo "VM Memory Usage: $(echo $VM_INFO | jq -r '.data.mem')"
# Fetch the VM agent information
echo "Fetching VM agent network interface information..."
VM_AGENT_INFO=$(curl -k -s -b "PVEAuthCookie=$TICKET" "https://${PROXMOX_IP}:8006/api2/json/nodes/${NODE}/qemu/${VM_ID}/agent/network-get-interfaces")
# Print the raw VM agent information
echo "Raw VM agent network interface information:"
echo $VM_AGENT_INFO
# Extract the IP address from the VM agent information
IP_ADDRESS=$(echo $VM_AGENT_INFO | jq -r '.data.result[] | select(.name != "lo") | .["ip-addresses"][] | select(.["ip-address-type"] == "ipv4") | .["ip-address"]')
echo "VM IP Address: $IP_ADDRESS"

and here it is in Python:

Python:
import requests
import getpass
def get_vm_info(proxmox_ip, username, vm_id):
    password = getpass.getpass("Enter the Proxmox API password: ")
    # Authenticate and obtain a ticket
    response = requests.post(
        f"https://{proxmox_ip}:8006/api2/json/access/ticket",
        data={"username": username, "password": password},
        verify=False
    )
    response.raise_for_status()  # Raise an error for bad responses
    data = response.json()
    ticket = data['data']['ticket']
    csrf_token = data['data']['CSRFPreventionToken']
    cookies = {'PVEAuthCookie': ticket}
    headers = {'CSRFPreventionToken': csrf_token}
    # Assuming NODE variable is set or hardcoded here
    node = "proxmox"  # Adjust the node name as necessary
    # Get information for the specific VM by VM_ID
    vm_info_response = requests.get(
        f"https://{proxmox_ip}:8006/api2/json/nodes/{node}/qemu/{vm_id}/status/current",
        cookies=cookies,
        verify=False
    )
    vm_info_response.raise_for_status()
    vm_info = vm_info_response.json()['data']
    print(f"VM Status: {vm_info['status']}")
    print(f"VM CPU Usage: {vm_info['cpu']}")
    print(f"VM Memory Usage: {vm_info['mem']}")
    # Fetch the VM agent network interface information
    vm_agent_info_response = requests.get(
        f"https://{proxmox_ip}:8006/api2/json/nodes/{node}/qemu/{vm_id}/agent/network-get-interfaces",
        cookies=cookies,
        verify=False
    )
    vm_agent_info_response.raise_for_status()
    vm_agent_info = vm_agent_info_response.json()['data']['result']
    print("Raw VM agent network interface information:")
    print(vm_agent_info)
    # Extract and print IP addresses
    for interface in vm_agent_info:
        if interface['name'] != "lo":
            for ip_info in interface.get("ip-addresses", []):
                if ip_info["ip-address-type"] == "ipv4":
                    print(f"VM IP Address: {ip_info['ip-address']}")
if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print("Usage: python script.py VM_ID")
        sys.exit(1)
    vm_id = sys.argv[1]
    proxmox_ip = "10.0.0.1"  # Set the Proxmox server IP address, example IP
    username = "root@pam"  # Set the Proxmox server username
    get_vm_info(proxmox_ip, username, vm_id)
 
Last edited:

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!