Skip to content

Instantly share code, notes, and snippets.

@tensorfields
Created January 3, 2013 22:02
Show Gist options
  • Save tensorfields/4447791 to your computer and use it in GitHub Desktop.
Save tensorfields/4447791 to your computer and use it in GitHub Desktop.
Get a KVM guest's IP address
#!/bin/bash
# Returns the IP address of a running KVM guest VM
# Assumes a working KVM/libvirt environment
#
# Install:
# Add this bash function to your ~/.bashrc and `source ~/.bashrc`.
# Usage:
# $ virt-addr vm-name
# 192.0.2.16
#
virt-addr() {
VM="$1"
arp -an | grep "`virsh dumpxml $VM | grep "mac address" | sed "s/.*'\(.*\)'.*/\1/g"`" | awk '{ gsub(/[\(\)]/,"",$2); print $2 }'
}
@kevteljeur
Copy link

Here's an updated, 'extended mix' which parses out a whole lot more information. It is a bit slow, however, so I'll look at doing some caching of the XML to speed it all up...

virt-uuid() {
    VM="$1"
    uuid=$(virsh dumpxml $VM | grep "<uuid" | sed "s/.*<uuid>\(.*\)<\/uuid>.*/\1/g" );
    echo $uuid
}

virt-mem() {
    VM="$1"
    mem=$(virsh dumpxml $VM | grep "<memory" | sed "s/.*<memory unit='KiB'>\(.*\)<\/memory>.*/\1/g" );
    echo $( expr $mem / 1024 )
}

virt-currmem() {
    VM="$1"
    mem=$(virsh dumpxml $VM | grep "<currentMemory" | sed "s/.*<currentMemory unit='KiB'>\(.*\)<\/currentMemory>.*/\1/g" );
    echo $( expr $mem / 1024 )
}

virt-vcpu() {
    VM="$1"
    vcpu=$(virsh dumpxml $VM | grep "<vcpu" | sed "s/.*<vcpu[^>]*>\(.*\)<\/vcpu>.*/\1/g" );
    echo $vcpu
}

virt-store() {
    VM="$1"
   # Oops! Not implemented yet, but basically this will retrieve the path to the VM file. Might not be true in all cases, however.
}

virt-info() {
    echo "------------------------------------------------------------------------------------------------------------------------";
    printf "%-30s%-17s%-12s%-12s%-8s%-40s\n" "VM Name" "IP Address" "Memory" "Current" "VCPUs" "UUID";
    virsh -c qemu:///system list --all | grep -o '[0-9]* [a-z]*.*running' | while read -r line;
    do
        line_cropped=$(echo "$line" | sed 's/[0-9][ ]*\([-._0-9a-zA-Z]*\)[ ]*running/\1/' );
        printf "%-30s%-17s%-12s%-12s%-8s%-40s\n" "$line_cropped" $( virt-addr "$line_cropped" ) $( virt-mem $line ) $( virt-currmem $line ) $( virt-vcpu $line ) $( virt-uuid $line );
    done;
    echo "------------------------------------------------------------------------------------------------------------------------";
}

@kevteljeur
Copy link

I've forked it here: https://gist.github.com/kevteljeur/ad73ca9ca0cfe8f14458 - with some performance improvements to my listing code (it really is slow when re-reading the same file over and over) and it now also displays info for VMs that aren't running. Hope it helps someone, and if you're reading this and have a faster way to do anything, please share!

@dehai
Copy link

dehai commented May 11, 2016

if the VMs network is bridge network. the script doesn't work with it. because ' arp -an' cann't find those VMs IP and MAC , could anybody help on this. thanks!!

@dehai
Copy link

dehai commented May 12, 2016

I found a way to solve my problem. but need do something on virt-manager or virsh edit domain
1:using virt-manager , need add new hardware with channel. channel device need named of org.qemu.guest_agent.0. make sure the guest VM already installed the qemu-guest-agent package. enable and start this service of qemu-ga.service . if you have done those two process . that you can use the script to show the VMs IP.
2: using virsh command , just same with virt-manager. only edit the domain XML file. you can use virsh edit your-VM-domain.add the below hardware info:

<channel type='unix'>
      <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/**your-domain-name**.org.qemu.guest_agent.0'/>
      <target type='virtio' name='org.qemu.guest_agent.0' state='connected'/>
      <alias name='channel0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>

after that: you can follow the method of using virt-manager. make sure installed qemu-guest-agent, and enable service of qemu-ga.service

@lukehinds
Copy link

lukehinds commented Jun 8, 2016

Note there is now a command which returns IPs:

virsh domifaddr <domain> [interface] [–full] [–source lease|agent]

Example:

 # virsh domifaddr fedora_vm --full
 Name       MAC address          Protocol     Address
 -------------------------------------------------------------------------------
 vnet0      52:54:00:2e:45:ce    ipv6         2001:db8:0:f101::2/64
 vnet1      52:54:00:b1:70:19    ipv4         192.168.105.201/16
 vnet1      52:54:00:b1:70:19    ipv6         2001:db8:ca2:2:1::bd/128
 vnet3      52:54:00:20:70:3d    ipv4         192.168.105.240/16

And for DHCP leases:

# virsh net-dhcp-leases --network default
Expiry Time          MAC address        Protocol  IP address                Hostname        Client ID or DUID
-------------------------------------------------------------------------------------------------------------------
2014-06-16 03:40:14  52:54:00:85:90:e2  ipv4      192.168.150.231/24        fedora20-test   01:52:54:00:85:90:e2
2014-06-16 03:40:17  52:54:00:85:90:e2  ipv6      2001:db8:ca2:2:1::c0/64   fedora20-test   00:04:b1:d8:86:42:e1:6a:aa:cf:d5:86:94:23:6f:94:04:cd
2014-06-16 03:34:42  52:54:00:e8:73:eb  ipv4      192.168.150.181/24        ubuntu14-vm     -
2014-06-16 03:34:46  52:54:00:e8:73:eb  ipv6      2001:db8:ca2:2:1::5b/64   -               00:01:00:01:1b:30:c6:aa:52:54:00:e8:73:eb  

@marafa
Copy link

marafa commented Jan 7, 2017

VM=fedora25;
sudo virsh domifaddr $VM|tail -2 | awk '{print $4}'| cut -d/ -f1

i am sure a bash expert can make that line even better but it works for me and "if its not broken don't fix it" is a good rule for me

@norpol
Copy link

norpol commented May 22, 2017

@marafa and rest here is an awk only script:
virsh domifaddr $VM | awk -F'[ /]+' '{if (NR>2) print $5}'

@IAlwaysBeCoding
Copy link

virt-info() {
    echo "------------------------------------------------------------------------------------------------------------------------";
    printf "%-30s%-17s%-12s%-12s%-8s%-40s\n" "VM Name" "IP Address" "Memory" "Current" "VCPUs" "UUID";
    virsh -c qemu:///system list --all | grep -o '[0-9]* [a-z]*.*running' | while read -r line;
    do
        line_cropped=$(echo "$line" | sed 's/[0-9][ ]*\([-._0-9a-zA-Z]*\)[ ]*running/\1/' );
        printf "%-30s%-17s%-12s%-12s%-8s%-40s\n" "$line_cropped" $( virt-addr "$line_cropped" ) $( virt-mem $line ) $( virt-currmem $line ) $( virt-vcpu $line ) $( virt-uuid $line );
    done;
    echo "------------------------------------------------------------------------------------------------------------------------";
}

This breaks if the ID is higher than 9

Change this line

line_cropped=$(echo "$line" | sed 's/[0-9][ ]*\([-._0-9a-zA-Z]*\)[ ]*running/\1/' );

To

line_cropped=$(echo "$line" | sed 's/[0-9]*[ ]*\([-._0-9a-zA-Z]*\)[ ]*running/\1/' );

@elico
Copy link

elico commented Jul 18, 2018

@mistofvongola and the others.
If you have qmeu-agent installed on the guest machine you can user virsh to fetch the details directly from the VM using virsh.
Example commad: virsh domifaddr Squid-4.1-CentOS-Testing --source agent --full (the --source agent flag is important)

[root@kvm4 ~]# virsh list
 Id    Name                           State
----------------------------------------------------
 1     KVM4-MANAGER                   running
 2     Fast-Windows-10                running
 3     CHR-LAB-CLIENT1                running
 4     CHR-LAB-PX3                    running
 5     CHR-LAB-SERVER1                running
 6     CHR-R1                         running
 7     Squid-4.1-CentOS-Testing       running

[root@kvm4 ~]# virsh domifaddr Squid-4.1-CentOS-Testing --source agent --full
Name       MAC address          Protocol     Address
-------------------------------------------------------------------------------
 lo         00:00:00:00:00:00    ipv4         127.0.0.1/8
 lo         00:00:00:00:00:00    ipv6         ::1/128
 eth0       52:54:00:7e:7f:29    ipv4         192.168.89.59/24
 eth0       52:54:00:7e:7f:29    ipv6         fe80::125d:b868:7bf7:11f0/64
 eth1       52:54:00:18:05:6b    N/A          N/A
 eth2       52:54:00:fd:79:85    N/A          N/A
 eth3       52:54:00:cc:ac:c8    N/A          N/A

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment