Я использую qemu / kvm с мостовой сетью. В хост-машине есть несколько сетевых интерфейсов «vnetX» без IP. Я ищу способ узнать, какой vnetX принадлежит виртуальной машине.
Я попытался сопоставить значения MAC-адресов на этих интерфейсах с MAC-адресами виртуальных машин (или XML, который их определяет), но не совпал.
Есть brctl show, которое показывает интерфейсы vnet, принадлежащие мосту, но это бесполезная информация.
Есть ли способ узнать эту связь? Спасибо!!
Как насчет этого (пример для vnet13
):
$ VNET=vnet13; for vm in $(virsh list | grep running | awk '{print $2}'); do virsh dumpxml $vm|grep -q "$VNET" && echo $vm; done
Здесь мы используем virsh dumpxml
для отображения динамических свойств виртуальной машины, которые недоступны в статическом XML-определении виртуальной машины в /etc/libvirt/qemu/foo.xml. Который vnetX
интерфейс, к которому ВМ является таким динамическим свойством. То же самое и с MAC-адресами виртуальной машины.
Пытаться virsh dumpxml $domain
, вы увидите что-то вроде:
<interface type='network'>
<mac address='52:54:00:9d:9d:10'/>
<source network='default'/>
<target dev='vnet1'/>
<model type='e1000'/>
<alias name='net1'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0c' function='0x0'/>
в alias name
это то, что используется в командной строке qemu-kvm, поэтому, если вы запустите ps -ef |grep qemu|grep net1
в моем примере вы увидите фактический синтаксис команд, используемый для этого интерфейса.
Каждое из приведенных выше решений предполагает, что виртуальные машины управляются libvirt. Вполне возможно запустить виртуальные машины QEMU без этого, и в этом случае вы не сможете использовать virsh или посмотреть XML, чтобы найти ответ.
В случае запуска виртуальных машин QEMU из «сырой» командной строки:
tcpdump -i tap0 -f 'icmp' (замените любой интересующий вас интерфейс касания)
Отправляйте эхо-запросы каждой виртуальной машины-кандидата, пока не увидите пакеты в трассировке. Интерфейс, который вы отслеживаете при появлении пакетов ICMP, - это именно тот, который вы ищете!
И наоборот, вы можете запустить ping для конкретной виртуальной машины, а затем tcpdump для каждого интерфейса по очереди, пока один из них не «загорится». Зависит от того, хотите ли вы найти виртуальную машину, которая соответствует интерфейсу касания, или интерфейс касания, который соответствует виртуальной машине.
Сопоставление IP-адресов из кэша Arp с виртуальной машиной
# vm mac address list
for vm in $(virsh list | grep running | awk '{print $2}'); do \
echo -n "$vm "; \
virsh dumpxml $vm| grep -oP "52:54:[\da-f:]+" ;
done > vm_mac.list
# vm ip list
arp -i virbr0 | grep '52:' | while read addr ; do \
ip=$(echo $addr | awk '{print $1}'); \
mac=$(echo $addr | awk '{print $3}'); \
vm=$(grep "$mac" vm_mac.list | awk '{print $1}'); \
echo "$vm $ip $mac"; \
done | sort
Пример вывода:
vm66 192.168.191.112 52:54:00:ab:e8:cb
vm67 192.168.191.207 52:54:00:88:66:e7
vm67 192.168.191.241 52:54:00:88:66:e7
vm68 192.168.191.197 52:54:00:c5:e1:30
vm69 192.168.191.254 52:54:00:b6:f6:0f
vm70 192.168.191.232 52:54:00:08:7f:49
vm71 192.168.191.113 52:54:00:e7:6f:2b
На основе ответа @daff:
for vm in $(virsh list | grep running | awk '{print $2}'); do echo "$vm: " && virsh dumpxml $vm | grep "vnet" | sed 's/[^'']*''\([^'']*\)''[^'']*/\t\1/g'; done
Пример вывода:
vm1:
vnet0
vm2:
vnet1
vm3:
vnet2
vm4:
vnet3
vnet4
vm5:
vnet5
MAC-адрес vnetX
интерфейсы принадлежат хосту, а не гостю. brctl showmacs br0
покажет MAC-адреса, обнаруженные мостом, но тогда вам нужно будет указать перекрестную ссылку на номер порта со списком интерфейсов из brctl show
.
for vm in $(virsh list --state-running --name); do \
echo $vm; \
virsh domifaddr $vm; \
done
Пример вывода:
client1
Nombre dirección MAC Protocol Address
------------------------------------------------------------------------------
vnet2 52:54:00:2c:7a:f0 ipv4 192.168.122.63/24