libvirt:获取 guest 账户的IP地址

举报
何其不顾四月天 发表于 2020/12/29 01:15:22 2020/12/29
【摘要】 文章目录 libvirt 获取 guest账户的IP方案方案方案一:virsh 命令方案二:调用API接口 相关错误解决方法:思考 libvirt 获取 guest账户的IP方案 方案 目前找到两种方案。方案一:libvirt命令获取。 方案二:调用libvirt-api获取。 方案一:virsh 命令 相关命令如下: virsh #进入v...

libvirt 获取 guest账户的IP方案

方案

目前找到两种方案。方案一:libvirt命令获取。 方案二:调用libvirt-api获取。

方案一:virsh 命令

相关命令如下:

virsh  #进入virsh 命令模式
list --all # 查看所有在线的虚拟机列表

  
 
  • 1
  • 2

虚拟机列表输出结果如下:

 Id Name State
----------------------------------------------------
 1 151 running
 - 170 shut off
 - win10 shut off

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

可以看出正在运行的虚拟机 为 151

查看151支持的相关命令

 qemu-agent-command 151 '{"execute":"guest-info"}'

  
 
  • 1

输出结果如下:

{"return":{"version":"0.12.1","supported_commands":[{"enabled":true,"name":"guest-set-user-password"},{"enabled":true,"name":"guest-get-vcpus"},{"enabled":true,"name":"guest-suspend-ram"},{"enabled":true,"name":"guest-suspend-disk"},{"enabled":true,"name":"guest-fsfreeze-thaw"},{"enabled":true,"name":"guest-fsfreeze-freeze"},{"enabled":true,"name":"guest-fsfreeze-status"},{"enabled":true,"name":"guest-shutdown"},{"enabled":true,"name":"guest-info"},{"enabled":true,"name":"guest-set-time"},{"enabled":true,"name":"guest-get-time"},{"enabled":true,"name":"guest-ping"},{"enabled":true,"name":"guest-sync"},{"enabled":true,"name":"guest-sync-delimited"}]}}

  
 
  • 1

获取虚拟机IP的主要命令如下:

qemu-agent-command 151 '{"execute":"guest-network-get-interfaces"}'

  
 
  • 1

输出结果如下:

{"return":[{"name":"��̫��e","ip-addresses":[{"ip-address-type":"ipv6","ip-address":"fe80::9ded:74ad:cbc9:7ec2%5","prefix":64},{"ip-address-type":"ipv4","ip-address":"172.26.106.102","prefix":24}],"statistics":{"tx-packets":183723,"tx-errs":0,"rx-bytes":482140384,"rx-dropped":4781392,"rx-packets":329018,"rx-errs":0,"tx-bytes":12037307,"tx-dropped":0},"hardware-address":"52:54:00:89:0e:2b"},{"name":"Loopback Pseudo-Interface 1","ip-addresses":[{"ip-address-type":"ipv6","ip-address":"::1","prefix":128},{"ip-address-type":"ipv4","ip-address":"127.0.0.1","prefix":8}],"statistics":{"tx-packets":0,"tx-errs":0,"rx-bytes":0,"rx-dropped":0,"rx-packets":0,"rx-errs":0,"tx-bytes":0,"tx-dropped":0}},{"name":"Teredo Tunneling Pseudo-Interface","ip-addresses":[{"ip-address-type":"ipv6","ip-address":"2001:0:348b:fb58:28bf:26c3:2ca1:2326","prefix":64},{"ip-address-type":"ipv6","ip-address":"fe80::28bf:26c3:2ca1:2326%3","prefix":64}],"statistics":{"tx-packets":165,"tx-errs":0,"rx-bytes":18504,"rx-dropped":0,"rx-packets":191,"rx-errs":0,"tx-bytes":18780,"tx-dropped":0},"hardware-address":"00:00:00:00:00:00"}]}

  
 
  • 1

所有相关的ip信息如下: ip地址类型,ip地址,硬件地址

方案二:调用API接口

官方接口地址:https://libvirt.org/html/libvirt-libvirt-domain.html#virDomainIPAddress

相关结构体如下:

struct virDomainIPAddress { //ip信息结构体 int	type; //virIPAddrType char *	addr; //IP address unsigned int	prefix;		//IP address prefix
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
struct virDomainInterface { //接口信息结构体 char *	name; //interface name char *	hwaddr; //hardware address, may be NULL unsigned int	naddrs; //number of items in @addrs virDomainIPAddressPtr	addrs;		//array of IP addresses
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
/*
Return a pointer to the allocated array of pointers to interfaces present in given domain along with their IP and MAC addresses. Note that single interface can have multiple or even 0 IP addresses
*/
int	virDomainInterfaceAddresses	(virDomainPtr dom, virDomainInterfacePtr ** ifaces, unsigned int source, unsigned int flags) //interface接口地址获取方法 
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
enum virDomainInterfaceAddressesSource { //ip地址的枚举类型 
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE	=	0 (0x0)	,//Parse DHCP lease file
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT	=	1 (0x1)	,//Query qemu guest agent
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP	=	2 (0x2)	,//Query ARP tables
VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST	=	3 (0x3)
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

目前笔者用的 类型为 VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT ,获取指定虚拟机IP。 VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE为获取 DHCP 方式的虚拟机IP。VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARPVIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LAST这两种类型,笔者的libvirt版本不支持也就没有测试。

官方Demo样例如下:

virDomainInterfacePtr *ifaces = NULL; //接口指针初始化 --网卡
int ifaces_count = 0; //接口个数
size_t i, j; 
virDomainPtr dom = /*... obtain a domain here ...*/;

if ((ifaces_count = virDomainInterfaceAddresses(dom, &ifaces, VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE)) < 0) goto cleanup;
//... do something with returned values, for example:
for (i = 0; i < ifaces_count; i++) { printf("name: %s", ifaces[i]->name); if (ifaces[i]->hwaddr) //网卡个数,硬件地址 MAC printf(" hwaddr: %s", ifaces[i]->hwaddr); for (j = 0; j < ifaces[i]->naddrs; j++) { virDomainIPAddressPtr ip_addr = ifaces[i]->addrs + j; printf("[addr: %s prefix: %d type: %d]", ip_addr->addr, ip_addr->prefix, ip_addr->type); } printf("\n");
}

cleanup: if (ifaces && ifaces_count > 0) for (i = 0; i < ifaces_count; i++) virDomainInterfaceFree(ifaces[i]); free(ifaces);//释放接口指针内存

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
/*参数说明
dom:		domain object
ifaces:		pointer to an array of pointers pointing to interface objects
source:		one of the virDomainInterfaceAddressesSource constants
flags:		currently unused, pass zero
Returns:	the number of interfaces on success, -1 in case of error.
*/

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

测试代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>
#include <libvirt/libvirt-domain.h>
#include <string.h>

#define MAX_LEN (1024*10)

int main(int argc, char** argv)
{ virConnectPtr conn; virDomainInterfacePtr* ifaces =  NULL; int ret = -1; int  ifaces_count = 0; int i,j; conn = virConnectOpen("qemu:///system"); if(conn == NULL){ printf("failed to open connection to qemu\n");
	return 1; } printf("success to open connection to qemu\n"); char* xml = malloc(MAX_LEN); memset(xml,0,MAX_LEN); FILE* fp = NULL; //filename 作者写为了固定地址。也可以利用 argv参数进行传参 char filename[128] = {"/etc/libvirt/qemu/151.xml"}; fp = fopen(filename,"r"); if(fp != NULL){ int len = fread(xml,1,MAX_LEN,fp);
	printf("len = %d\n",len); } else{ printf("fp is null!\n"); } if(fp != NULL){ fclose(fp); } virDomainPtr dom; dom = virDomainDefineXML(conn,xml); if(!dom){ printf("domain definition failed\n"); } if((ifaces_count = virDomainInterfaceAddresses(dom,&ifaces,VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT ,0))<0) { goto cleanup; } for( i=0;i<ifaces_count;i++) { printf("name:%s \n",ifaces[i]->name); if(ifaces[i]->hwaddr) printf("hwaddr:%s\n",ifaces[i]->hwaddr); for( j = 0;j < ifaces[i]->naddrs;j++) { virDomainIPAddressPtr ip_addr = ifaces[i]->addrs + j; printf("[addr: %s prefix: %d type: %d]\n", ip_addr->addr, ip_addr->prefix, ip_addr->type); } }
cleanup: if (ifaces && ifaces_count > 0) for (i = 0; i < ifaces_count; i++) virDomainInterfaceFree(ifaces[i]); free(ifaces); return ret;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

编译:

gcc add.c -lvirt -o add

  
 
  • 1

输出结果如下:

success to open connection to qemu
len = 4214 
name:��̫��e 
hwaddr:52:54:00:89:0e:2b
[addr: fe80::9ded:74ad:cbc9:7ec2%5 prefix: 64 type: 1]
[addr: 172.26.106.102 prefix: 24 type: 0]
name:Loopback Pseudo-Interface 1 
[addr: ::1 prefix: 128 type: 1]
[addr: 127.0.0.1 prefix: 8 type: 0]
name:Teredo Tunneling Pseudo-Interface 
hwaddr:00:00:00:00:00:00
[addr: fe80::ffff:ffff:fffe%3 prefix: 64 type: 1]

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

相关错误解决方法:

  • 错误一:

    libvirt: QEMU Driver error : internal error: unable to execute QEMU agent command 'guest-network-get-interfaces': The command guest-network-get-interfaces has been disabled for this instance
    
        
       
    • 1

    解决方法:

    1.查看命令是否启用。网络上黑白名单,但是作者是 ubuntu 系统,并没有找到相关的json文件。查看命令是否被禁用,如果被禁用,则启用。
    2.利用 qemu-agent-command 151 '{"execute":"guest-info"}' 命令查看libvirt支持命令,打印信息并没有 guest-network-get-interfaces 命令。原因为;在虚拟机,里边没有安装 qga 即 qemu-ga-x86_64.msi
    
        
       
    • 1
    • 2
  • 错误二:

    libvirt: QEMU Driver error : argument unsupported: QEMU guest agent is not configured
    
        
       
    • 1

    解决方法:

    错误原因:在对应xml文件中,没有增加对应的接口通道 unix 接口 传输信息。接口如下:
    
        
       
    • 1
    <channel type='unix'>
    	<target type='virtio' name='org.qemu.guest_agent.0'/>
    	<address type='virtio-serial' controller='0' bus='0' port='2'/>
    </channel>
    
        
       
    • 1
    • 2
    • 3
    • 4

思考

其实两个方案本质上都是调用libvirt底层API。只不过命令方式,只是自己封了一层调用命令。

文章来源: blog.csdn.net,作者:何其不顾四月天,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/u011218356/article/details/106195682

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。