qemu-ga

13350 단어 socketqemu
1. virsh 의 xml 정의 에 channel 지정 host 의 socket 을 추가 하여 guest 의 dev 에 매 핑 합 니 다.
virsh 로 가상 컴퓨터 를 시작 할 때
채널 추가 주의

 <channel type='unix'>  
      <source mode='bind' path='/var/lib/libvirt/qemu/test.agent'/>  
      <target type='virtio' name='com.haoning.spice.0'/>  
      <alias name='channel0'/>  
      <address type='virtio-serial' controller='0' bus='0' port='1'/>  
 </channel>  

2. guest 에서 qemu - ga 시작 하기
qemu-ga -v -p /dev/virtio-ports/com.haoning.spice.0

3. host 에 python 소켓 이나 socat 를 사용 합 니 다.
socat unix-connect:/var/lib/libvirt/qemu/test.agent readline

구체 적 인 control. xml

<domain type='kvm' id='12'>
  <name>control</name>
  <uuid>d07d7290-9b1d-f33e-f54a-70a821252410</uuid>
  <memory unit='KiB'>4194304</memory>
  <currentMemory unit='KiB'>4194304</currentMemory>
  <vcpu placement='static'>1</vcpu>
  <os>
    <type arch='x86_64' machine='rhel6.5.0'>hvm</type>
    <boot dev='hd'/>
  </os>
  <features>
    <acpi/>
    <apic/>
    <pae/>
  </features>
  <clock offset='utc'/>
  <on_poweroff>destroy</on_poweroff>
  <on_reboot>restart</on_reboot>
  <on_crash>restart</on_crash>
  <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='cdrom'>
      <driver name='qemu' type='raw'/>
      <source file='/home/rhel-server-6.5-x86_64-dvd.iso'/>
      <target dev='hdc' bus='ide'/>
      <readonly/>
      <alias name='ide0-1-0'/>
      <address type='drive' controller='0' bus='1' target='0' unit='0'/>
    </disk>
    <disk type='file' device='disk'>
      <driver name='qemu' type='qcow2' cache='none'/>
      <source file='/home/control.img'/>
      <target dev='vda' bus='virtio'/>
      <alias name='virtio-disk0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </disk>
    <controller type='usb' index='0'>
      <alias name='usb0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
    </controller>
    <controller type='ide' index='0'>
      <alias name='ide0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='virtio-serial' index='0'>
      <alias name='virtio-serial0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </controller>
    <interface type='bridge'>
      <mac address='52:54:02:a1:90:81'/>
      <source bridge='br0'/>
      <target dev='vnet0'/>
      <model type='virtio'/>
      <alias name='net0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
      <source path='/dev/pts/1'/>
      <target port='0'/>
      <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/1'>
      <source path='/dev/pts/1'/>
      <target type='serial' port='0'/>
      <alias name='serial0'/>
    </console>
    <channel type='unix'>
      <source mode='bind' path='/var/lib/libvirt/qemu/test.agent'/>
      <target type='virtio' name='com.haoning.spice.0'/>
      <alias name='channel0'/>
      <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <input type='mouse' bus='ps2'/>
    <graphics type='vnc' port='5900' autoport='no' listen='0.0.0.0'>
      <listen type='address' address='0.0.0.0'/>
    </graphics>
    <sound model='ich6'>
      <alias name='sound0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
    </sound>
    <video>
      <model type='cirrus' vram='9216' heads='1'/>
      <alias name='video0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
      <alias name='balloon0'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </memballoon>
  </devices>
  <seclabel type='dynamic' model='selinux' relabel='yes'>
    <label>system_u:system_r:svirt_t:s0:c681,c978</label>
    <imagelabel>system_u:object_r:svirt_image_t:s0:c681,c978</imagelabel>
  </seclabel>
</domain>

virsh define control.xml
virsh start control
guest 에서

[root@control ~]# qemu-ga -v -p /dev/virtio-ports/com.haoning.spice.0 
1437616495.53279: debug: received EOF
1437616495.153410: debug: received EOF
1437616495.253627: debug: received EOF
1437616495.353849: debug: received EOF
1437616495.454057: debug: received EOF
1437616495.554266: debug: received EOF
1437616495.654507: debug: received EOF
1437616495.754719: debug: received EOF
1437616495.854928: debug: received EOF
1437616495.955151: debug: received EOF
1437616496.55375: debug: received EOF
1437616496.155490: debug: received EOF
^C1437616496.170249: debug: received signal num 2, quitting
[root@control ~]# 

[root@node11 ~]# ls
poll_qemu_guest_agent.py
[root@node11 ~]# cat poll_qemu_guest_agent.py 
#! /usr/bin/python

import base64
import json
import select
import socket

#sock_file = "/tmp/foo.sock"
sock_file = "/var/lib/libvirt/qemu/test.agent"

#import pdb;pdb.set_trace()
READ_LEN = 1024
read_file = "/proc/cpuinfo"
send_cmds = [{"execute": "guest-file-open", "arguments": {"path": read_file, "mode": "r"}},
             {"execute": "guest-file-read", "arguments": {"handle": None, "count": READ_LEN}},
             {"execute": "guest-file-close", "arguments": {"handle": None}}]

serversocket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
serversocket.connect(sock_file)
serversocket.setblocking(0)

vm_fileno = serversocket.fileno()
instances = {}
instances[vm_fileno] = "instance-000004e8"

epoll = select.epoll()
epoll.register(vm_fileno, select.EPOLLIN | select.EPOLLOUT | select.EPOLLET)

try:
    #import ipdb;ipdb.set_trace()
    cmd = 0
    stop = False
    while True:
        print '-'*10 + 'start epoll' + '-'*10
        events = epoll.poll(1)
        for fileno, event in events:
            if fileno in instances.keys():# new client is connecting
                print 'instance: ' + instances[fileno]
            if event & select.EPOLLIN:    # new msg is coming in
                print "<<<<<<<<<<<recv"
                try:
                    vm_resp = ''
                    while True:
                        vm_resp += serversocket.recv(READ_LEN)
                except socket.error:
                    pass

                epoll.modify(fileno, select.EPOLLOUT | select.EPOLLET)

                try:
                    vm_resps = vm_resp.split('
') ok_resp = None for resp in vm_resps: if 'error' not in resp and 'return' in resp: ok_resp = resp break elif 'error' in resp: print 'error occurs: ', resp if ok_resp is not None: resp = json.loads(ok_resp) else: print 'no valid data recv' break except ValueError: print 'response content error: ', vm_resp break if len(send_cmds) <= cmd: stop = True print resp break try: if cmd == 1: print('+'*10 + 'receive:' + '+'*10 + '
' + vm_resp) handle = resp["return"] send_cmds[cmd]["arguments"]["handle"] = handle send_cmds[cmd+1]["arguments"]["handle"] = handle elif cmd == 2: decoded_file = base64.decodestring(resp["return"]["buf-b64"]) print 'file content:
', decoded_file print resp["return"]["count"] print 'EOF: ', resp["return"]["eof"] except (KeyError, ValueError, TypeError): print 'response content error: ', resp elif event & select.EPOLLOUT: # new msg need send out print ">>>>>>>>>send" if len(send_cmds) <= cmd: print 'no data to send' break try: byteswritten = 0 data = json.dumps(send_cmds[cmd]) while True: byteswritten += serversocket.send(data[byteswritten:]) if byteswritten == len(data): print '*'*10 + 'send over' + '*'*10 break except socket.error: pass epoll.modify(fileno, select.EPOLLIN | select.EPOLLET) cmd += 1 elif event & select.EPOLLHUP: # connect closed epoll.unregister(serversocket.fileno()) serversocket.close() print '-'*10 + 'end epoll' + '-'*10 + '
' if stop: print 'stop now' break finally: epoll.unregister(serversocket.fileno()) epoll.close() serversocket.close() [root@node11 ~]#

socat 로 호출

socat unix-connect:/tmp/qga.sock readline
 {"execute":"guest-sync", "arguments":{"id":1234}}
 {"return": 1234}

socat 참조
http://wiki.qemu.org/Features/QAPI/GuestAgent
libvirt 설정 참조
http://wiki.libvirt.org/page/Qemu_guest_agent
기타 참고 사항
http://aspirer2004.blog.163.com/blog/static/1067647201352423628885/

좋은 웹페이지 즐겨찾기