QMP: add scripts/qmp

Populate it with all scripts stored in QMP/. Also fixes trailing
whitespaces in qmp-shell and qmp.py.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Luiz Capitulino 2013-09-10 16:39:23 -04:00
parent 6c2679fc19
commit 22f3946bc5
8 changed files with 2 additions and 2 deletions

301
scripts/qmp/qemu-ga-client Executable file
View file

@ -0,0 +1,301 @@
#!/usr/bin/python
# QEMU Guest Agent Client
#
# Copyright (C) 2012 Ryota Ozaki <ozaki.ryota@gmail.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
# Usage:
#
# Start QEMU with:
#
# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
# -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
#
# Run the script:
#
# $ qemu-ga-client --address=/tmp/qga.sock <command> [args...]
#
# or
#
# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock
# $ qemu-ga-client <command> [args...]
#
# For example:
#
# $ qemu-ga-client cat /etc/resolv.conf
# # Generated by NetworkManager
# nameserver 10.0.2.3
# $ qemu-ga-client fsfreeze status
# thawed
# $ qemu-ga-client fsfreeze freeze
# 2 filesystems frozen
#
# See also: http://wiki.qemu.org/Features/QAPI/GuestAgent
#
import base64
import random
import qmp
class QemuGuestAgent(qmp.QEMUMonitorProtocol):
def __getattr__(self, name):
def wrapper(**kwds):
return self.command('guest-' + name.replace('_', '-'), **kwds)
return wrapper
class QemuGuestAgentClient:
error = QemuGuestAgent.error
def __init__(self, address):
self.qga = QemuGuestAgent(address)
self.qga.connect(negotiate=False)
def sync(self, timeout=3):
# Avoid being blocked forever
if not self.ping(timeout):
raise EnvironmentError('Agent seems not alive')
uid = random.randint(0, (1 << 32) - 1)
while True:
ret = self.qga.sync(id=uid)
if isinstance(ret, int) and int(ret) == uid:
break
def __file_read_all(self, handle):
eof = False
data = ''
while not eof:
ret = self.qga.file_read(handle=handle, count=1024)
_data = base64.b64decode(ret['buf-b64'])
data += _data
eof = ret['eof']
return data
def read(self, path):
handle = self.qga.file_open(path=path)
try:
data = self.__file_read_all(handle)
finally:
self.qga.file_close(handle=handle)
return data
def info(self):
info = self.qga.info()
msgs = []
msgs.append('version: ' + info['version'])
msgs.append('supported_commands:')
enabled = [c['name'] for c in info['supported_commands'] if c['enabled']]
msgs.append('\tenabled: ' + ', '.join(enabled))
disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']]
msgs.append('\tdisabled: ' + ', '.join(disabled))
return '\n'.join(msgs)
def __gen_ipv4_netmask(self, prefixlen):
mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2)
return '.'.join([str(mask >> 24),
str((mask >> 16) & 0xff),
str((mask >> 8) & 0xff),
str(mask & 0xff)])
def ifconfig(self):
nifs = self.qga.network_get_interfaces()
msgs = []
for nif in nifs:
msgs.append(nif['name'] + ':')
if 'ip-addresses' in nif:
for ipaddr in nif['ip-addresses']:
if ipaddr['ip-address-type'] == 'ipv4':
addr = ipaddr['ip-address']
mask = self.__gen_ipv4_netmask(int(ipaddr['prefix']))
msgs.append("\tinet %s netmask %s" % (addr, mask))
elif ipaddr['ip-address-type'] == 'ipv6':
addr = ipaddr['ip-address']
prefix = ipaddr['prefix']
msgs.append("\tinet6 %s prefixlen %s" % (addr, prefix))
if nif['hardware-address'] != '00:00:00:00:00:00':
msgs.append("\tether " + nif['hardware-address'])
return '\n'.join(msgs)
def ping(self, timeout):
self.qga.settimeout(timeout)
try:
self.qga.ping()
except self.qga.timeout:
return False
return True
def fsfreeze(self, cmd):
if cmd not in ['status', 'freeze', 'thaw']:
raise StandardError('Invalid command: ' + cmd)
return getattr(self.qga, 'fsfreeze' + '_' + cmd)()
def fstrim(self, minimum=0):
return getattr(self.qga, 'fstrim')(minimum=minimum)
def suspend(self, mode):
if mode not in ['disk', 'ram', 'hybrid']:
raise StandardError('Invalid mode: ' + mode)
try:
getattr(self.qga, 'suspend' + '_' + mode)()
# On error exception will raise
except self.qga.timeout:
# On success command will timed out
return
def shutdown(self, mode='powerdown'):
if mode not in ['powerdown', 'halt', 'reboot']:
raise StandardError('Invalid mode: ' + mode)
try:
self.qga.shutdown(mode=mode)
except self.qga.timeout:
return
def _cmd_cat(client, args):
if len(args) != 1:
print('Invalid argument')
print('Usage: cat <file>')
sys.exit(1)
print(client.read(args[0]))
def _cmd_fsfreeze(client, args):
usage = 'Usage: fsfreeze status|freeze|thaw'
if len(args) != 1:
print('Invalid argument')
print(usage)
sys.exit(1)
if args[0] not in ['status', 'freeze', 'thaw']:
print('Invalid command: ' + args[0])
print(usage)
sys.exit(1)
cmd = args[0]
ret = client.fsfreeze(cmd)
if cmd == 'status':
print(ret)
elif cmd == 'freeze':
print("%d filesystems frozen" % ret)
else:
print("%d filesystems thawed" % ret)
def _cmd_fstrim(client, args):
if len(args) == 0:
minimum = 0
else:
minimum = int(args[0])
print(client.fstrim(minimum))
def _cmd_ifconfig(client, args):
print(client.ifconfig())
def _cmd_info(client, args):
print(client.info())
def _cmd_ping(client, args):
if len(args) == 0:
timeout = 3
else:
timeout = float(args[0])
alive = client.ping(timeout)
if not alive:
print("Not responded in %s sec" % args[0])
sys.exit(1)
def _cmd_suspend(client, args):
usage = 'Usage: suspend disk|ram|hybrid'
if len(args) != 1:
print('Less argument')
print(usage)
sys.exit(1)
if args[0] not in ['disk', 'ram', 'hybrid']:
print('Invalid command: ' + args[0])
print(usage)
sys.exit(1)
client.suspend(args[0])
def _cmd_shutdown(client, args):
client.shutdown()
_cmd_powerdown = _cmd_shutdown
def _cmd_halt(client, args):
client.shutdown('halt')
def _cmd_reboot(client, args):
client.shutdown('reboot')
commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m]
def main(address, cmd, args):
if not os.path.exists(address):
print('%s not found' % address)
sys.exit(1)
if cmd not in commands:
print('Invalid command: ' + cmd)
print('Available commands: ' + ', '.join(commands))
sys.exit(1)
try:
client = QemuGuestAgentClient(address)
except QemuGuestAgent.error, e:
import errno
print(e)
if e.errno == errno.ECONNREFUSED:
print('Hint: qemu is not running?')
sys.exit(1)
if cmd == 'fsfreeze' and args[0] == 'freeze':
client.sync(60)
elif cmd != 'ping':
client.sync()
globals()['_cmd_' + cmd](client, args)
if __name__ == '__main__':
import sys
import os
import optparse
address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None
usage = "%prog [--address=<unix_path>|<ipv4_address>] <command> [args...]\n"
usage += '<command>: ' + ', '.join(commands)
parser = optparse.OptionParser(usage=usage)
parser.add_option('--address', action='store', type='string',
default=address, help='Specify a ip:port pair or a unix socket path')
options, args = parser.parse_args()
address = options.address
if address is None:
parser.error('address is not specified')
sys.exit(1)
if len(args) == 0:
parser.error('Less argument')
sys.exit(1)
main(address, args[0], args[1:])

126
scripts/qmp/qmp Executable file
View file

@ -0,0 +1,126 @@
#!/usr/bin/python
#
# QMP command line tool
#
# Copyright IBM, Corp. 2011
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPLv2 or later.
# See the COPYING file in the top-level directory.
import sys, os
from qmp import QEMUMonitorProtocol
def print_response(rsp, prefix=[]):
if type(rsp) == list:
i = 0
for item in rsp:
if prefix == []:
prefix = ['item']
print_response(item, prefix[:-1] + ['%s[%d]' % (prefix[-1], i)])
i += 1
elif type(rsp) == dict:
for key in rsp.keys():
print_response(rsp[key], prefix + [key])
else:
if len(prefix):
print '%s: %s' % ('.'.join(prefix), rsp)
else:
print '%s' % (rsp)
def main(args):
path = None
# Use QMP_PATH if it's set
if os.environ.has_key('QMP_PATH'):
path = os.environ['QMP_PATH']
while len(args):
arg = args[0]
if arg.startswith('--'):
arg = arg[2:]
if arg.find('=') == -1:
value = True
else:
arg, value = arg.split('=', 1)
if arg in ['path']:
if type(value) == str:
path = value
elif arg in ['help']:
os.execlp('man', 'man', 'qmp')
else:
print 'Unknown argument "%s"' % arg
args = args[1:]
else:
break
if not path:
print "QMP path isn't set, use --path=qmp-monitor-address or set QMP_PATH"
return 1
if len(args):
command, args = args[0], args[1:]
else:
print 'No command found'
print 'Usage: "qmp [--path=qmp-monitor-address] qmp-cmd arguments"'
return 1
if command in ['help']:
os.execlp('man', 'man', 'qmp')
srv = QEMUMonitorProtocol(path)
srv.connect()
def do_command(srv, cmd, **kwds):
rsp = srv.cmd(cmd, kwds)
if rsp.has_key('error'):
raise Exception(rsp['error']['desc'])
return rsp['return']
commands = map(lambda x: x['name'], do_command(srv, 'query-commands'))
srv.close()
if command not in commands:
fullcmd = 'qmp-%s' % command
try:
os.environ['QMP_PATH'] = path
os.execvp(fullcmd, [fullcmd] + args)
except OSError, (errno, msg):
if errno == 2:
print 'Command "%s" not found.' % (fullcmd)
return 1
raise
return 0
srv = QEMUMonitorProtocol(path)
srv.connect()
arguments = {}
for arg in args:
if not arg.startswith('--'):
print 'Unknown argument "%s"' % arg
return 1
arg = arg[2:]
if arg.find('=') == -1:
value = True
else:
arg, value = arg.split('=', 1)
if arg in ['help']:
os.execlp('man', 'man', 'qmp-%s' % command)
return 1
arguments[arg] = value
rsp = do_command(srv, command, **arguments)
print_response(rsp)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

286
scripts/qmp/qmp-shell Executable file
View file

@ -0,0 +1,286 @@
#!/usr/bin/python
#
# Low-level QEMU shell on top of QMP.
#
# Copyright (C) 2009, 2010 Red Hat Inc.
#
# Authors:
# Luiz Capitulino <lcapitulino@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
#
# Usage:
#
# Start QEMU with:
#
# # qemu [...] -qmp unix:./qmp-sock,server
#
# Run the shell:
#
# $ qmp-shell ./qmp-sock
#
# Commands have the following format:
#
# < command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
#
# For example:
#
# (QEMU) device_add driver=e1000 id=net1
# {u'return': {}}
# (QEMU)
import qmp
import readline
import sys
import pprint
class QMPCompleter(list):
def complete(self, text, state):
for cmd in self:
if cmd.startswith(text):
if not state:
return cmd
else:
state -= 1
class QMPShellError(Exception):
pass
class QMPShellBadPort(QMPShellError):
pass
# TODO: QMPShell's interface is a bit ugly (eg. _fill_completion() and
# _execute_cmd()). Let's design a better one.
class QMPShell(qmp.QEMUMonitorProtocol):
def __init__(self, address, pp=None):
qmp.QEMUMonitorProtocol.__init__(self, self.__get_address(address))
self._greeting = None
self._completer = None
self._pp = pp
def __get_address(self, arg):
"""
Figure out if the argument is in the port:host form, if it's not it's
probably a file path.
"""
addr = arg.split(':')
if len(addr) == 2:
try:
port = int(addr[1])
except ValueError:
raise QMPShellBadPort
return ( addr[0], port )
# socket path
return arg
def _fill_completion(self):
for cmd in self.cmd('query-commands')['return']:
self._completer.append(cmd['name'])
def __completer_setup(self):
self._completer = QMPCompleter()
self._fill_completion()
readline.set_completer(self._completer.complete)
readline.parse_and_bind("tab: complete")
# XXX: default delimiters conflict with some command names (eg. query-),
# clearing everything as it doesn't seem to matter
readline.set_completer_delims('')
def __build_cmd(self, cmdline):
"""
Build a QMP input object from a user provided command-line in the
following format:
< command-name > [ arg-name1=arg1 ] ... [ arg-nameN=argN ]
"""
cmdargs = cmdline.split()
qmpcmd = { 'execute': cmdargs[0], 'arguments': {} }
for arg in cmdargs[1:]:
opt = arg.split('=')
try:
if(len(opt) > 2):
opt[1] = '='.join(opt[1:])
value = int(opt[1])
except ValueError:
if opt[1] == 'true':
value = True
elif opt[1] == 'false':
value = False
else:
value = opt[1]
qmpcmd['arguments'][opt[0]] = value
return qmpcmd
def _execute_cmd(self, cmdline):
try:
qmpcmd = self.__build_cmd(cmdline)
except:
print 'command format: <command-name> ',
print '[arg-name1=arg1] ... [arg-nameN=argN]'
return True
resp = self.cmd_obj(qmpcmd)
if resp is None:
print 'Disconnected'
return False
if self._pp is not None:
self._pp.pprint(resp)
else:
print resp
return True
def connect(self):
self._greeting = qmp.QEMUMonitorProtocol.connect(self)
self.__completer_setup()
def show_banner(self, msg='Welcome to the QMP low-level shell!'):
print msg
version = self._greeting['QMP']['version']['qemu']
print 'Connected to QEMU %d.%d.%d\n' % (version['major'],version['minor'],version['micro'])
def read_exec_command(self, prompt):
"""
Read and execute a command.
@return True if execution was ok, return False if disconnected.
"""
try:
cmdline = raw_input(prompt)
except EOFError:
print
return False
if cmdline == '':
for ev in self.get_events():
print ev
self.clear_events()
return True
else:
return self._execute_cmd(cmdline)
class HMPShell(QMPShell):
def __init__(self, address):
QMPShell.__init__(self, address)
self.__cpu_index = 0
def __cmd_completion(self):
for cmd in self.__cmd_passthrough('help')['return'].split('\r\n'):
if cmd and cmd[0] != '[' and cmd[0] != '\t':
name = cmd.split()[0] # drop help text
if name == 'info':
continue
if name.find('|') != -1:
# Command in the form 'foobar|f' or 'f|foobar', take the
# full name
opt = name.split('|')
if len(opt[0]) == 1:
name = opt[1]
else:
name = opt[0]
self._completer.append(name)
self._completer.append('help ' + name) # help completion
def __info_completion(self):
for cmd in self.__cmd_passthrough('info')['return'].split('\r\n'):
if cmd:
self._completer.append('info ' + cmd.split()[1])
def __other_completion(self):
# special cases
self._completer.append('help info')
def _fill_completion(self):
self.__cmd_completion()
self.__info_completion()
self.__other_completion()
def __cmd_passthrough(self, cmdline, cpu_index = 0):
return self.cmd_obj({ 'execute': 'human-monitor-command', 'arguments':
{ 'command-line': cmdline,
'cpu-index': cpu_index } })
def _execute_cmd(self, cmdline):
if cmdline.split()[0] == "cpu":
# trap the cpu command, it requires special setting
try:
idx = int(cmdline.split()[1])
if not 'return' in self.__cmd_passthrough('info version', idx):
print 'bad CPU index'
return True
self.__cpu_index = idx
except ValueError:
print 'cpu command takes an integer argument'
return True
resp = self.__cmd_passthrough(cmdline, self.__cpu_index)
if resp is None:
print 'Disconnected'
return False
assert 'return' in resp or 'error' in resp
if 'return' in resp:
# Success
if len(resp['return']) > 0:
print resp['return'],
else:
# Error
print '%s: %s' % (resp['error']['class'], resp['error']['desc'])
return True
def show_banner(self):
QMPShell.show_banner(self, msg='Welcome to the HMP shell!')
def die(msg):
sys.stderr.write('ERROR: %s\n' % msg)
sys.exit(1)
def fail_cmdline(option=None):
if option:
sys.stderr.write('ERROR: bad command-line option \'%s\'\n' % option)
sys.stderr.write('qemu-shell [ -p ] [ -H ] < UNIX socket path> | < TCP address:port >\n')
sys.exit(1)
def main():
addr = ''
qemu = None
hmp = False
pp = None
try:
for arg in sys.argv[1:]:
if arg == "-H":
if qemu is not None:
fail_cmdline(arg)
hmp = True
elif arg == "-p":
if pp is not None:
fail_cmdline(arg)
pp = pprint.PrettyPrinter(indent=4)
else:
if qemu is not None:
fail_cmdline(arg)
if hmp:
qemu = HMPShell(arg)
else:
qemu = QMPShell(arg, pp)
addr = arg
if qemu is None:
fail_cmdline()
except QMPShellBadPort:
die('bad port number in command-line')
try:
qemu.connect()
except qmp.QMPConnectError:
die('Didn\'t get QMP greeting message')
except qmp.QMPCapabilitiesError:
die('Could not negotiate capabilities')
except qemu.error:
die('Could not connect to %s' % addr)
qemu.show_banner()
while qemu.read_exec_command('(QEMU) '):
pass
qemu.close()
if __name__ == '__main__':
main()

196
scripts/qmp/qmp.py Normal file
View file

@ -0,0 +1,196 @@
# QEMU Monitor Protocol Python class
#
# Copyright (C) 2009, 2010 Red Hat Inc.
#
# Authors:
# Luiz Capitulino <lcapitulino@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
import json
import errno
import socket
class QMPError(Exception):
pass
class QMPConnectError(QMPError):
pass
class QMPCapabilitiesError(QMPError):
pass
class QEMUMonitorProtocol:
def __init__(self, address, server=False):
"""
Create a QEMUMonitorProtocol class.
@param address: QEMU address, can be either a unix socket path (string)
or a tuple in the form ( address, port ) for a TCP
connection
@param server: server mode listens on the socket (bool)
@raise socket.error on socket connection errors
@note No connection is established, this is done by the connect() or
accept() methods
"""
self.__events = []
self.__address = address
self.__sock = self.__get_sock()
if server:
self.__sock.bind(self.__address)
self.__sock.listen(1)
def __get_sock(self):
if isinstance(self.__address, tuple):
family = socket.AF_INET
else:
family = socket.AF_UNIX
return socket.socket(family, socket.SOCK_STREAM)
def __negotiate_capabilities(self):
greeting = self.__json_read()
if greeting is None or not greeting.has_key('QMP'):
raise QMPConnectError
# Greeting seems ok, negotiate capabilities
resp = self.cmd('qmp_capabilities')
if "return" in resp:
return greeting
raise QMPCapabilitiesError
def __json_read(self, only_event=False):
while True:
data = self.__sockfile.readline()
if not data:
return
resp = json.loads(data)
if 'event' in resp:
self.__events.append(resp)
if not only_event:
continue
return resp
error = socket.error
def connect(self, negotiate=True):
"""
Connect to the QMP Monitor and perform capabilities negotiation.
@return QMP greeting dict
@raise socket.error on socket connection errors
@raise QMPConnectError if the greeting is not received
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock.connect(self.__address)
self.__sockfile = self.__sock.makefile()
if negotiate:
return self.__negotiate_capabilities()
def accept(self):
"""
Await connection from QMP Monitor and perform capabilities negotiation.
@return QMP greeting dict
@raise socket.error on socket connection errors
@raise QMPConnectError if the greeting is not received
@raise QMPCapabilitiesError if fails to negotiate capabilities
"""
self.__sock, _ = self.__sock.accept()
self.__sockfile = self.__sock.makefile()
return self.__negotiate_capabilities()
def cmd_obj(self, qmp_cmd):
"""
Send a QMP command to the QMP Monitor.
@param qmp_cmd: QMP command to be sent as a Python dict
@return QMP response as a Python dict or None if the connection has
been closed
"""
try:
self.__sock.sendall(json.dumps(qmp_cmd))
except socket.error, err:
if err[0] == errno.EPIPE:
return
raise socket.error(err)
return self.__json_read()
def cmd(self, name, args=None, id=None):
"""
Build a QMP command and send it to the QMP Monitor.
@param name: command name (string)
@param args: command arguments (dict)
@param id: command id (dict, list, string or int)
"""
qmp_cmd = { 'execute': name }
if args:
qmp_cmd['arguments'] = args
if id:
qmp_cmd['id'] = id
return self.cmd_obj(qmp_cmd)
def command(self, cmd, **kwds):
ret = self.cmd(cmd, kwds)
if ret.has_key('error'):
raise Exception(ret['error']['desc'])
return ret['return']
def pull_event(self, wait=False):
"""
Get and delete the first available QMP event.
@param wait: block until an event is available (bool)
"""
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
if not self.__events and wait:
self.__json_read(only_event=True)
event = self.__events[0]
del self.__events[0]
return event
def get_events(self, wait=False):
"""
Get a list of available QMP events.
@param wait: block until an event is available (bool)
"""
self.__sock.setblocking(0)
try:
self.__json_read()
except socket.error, err:
if err[0] == errno.EAGAIN:
# No data available
pass
self.__sock.setblocking(1)
if not self.__events and wait:
self.__json_read(only_event=True)
return self.__events
def clear_events(self):
"""
Clear current list of pending events.
"""
self.__events = []
def close(self):
self.__sock.close()
self.__sockfile.close()
timeout = socket.timeout
def settimeout(self, timeout):
self.__sock.settimeout(timeout)
def get_sock_fd(self):
return self.__sock.fileno()
def is_scm_available(self):
return self.__sock.family == socket.AF_UNIX

138
scripts/qmp/qom-fuse Executable file
View file

@ -0,0 +1,138 @@
#!/usr/bin/python
##
# QEMU Object Model test tools
#
# Copyright IBM, Corp. 2012
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later. See
# the COPYING file in the top-level directory.
##
import fuse, stat
from fuse import Fuse
import os, posix
from errno import *
from qmp import QEMUMonitorProtocol
fuse.fuse_python_api = (0, 2)
class QOMFS(Fuse):
def __init__(self, qmp, *args, **kwds):
Fuse.__init__(self, *args, **kwds)
self.qmp = qmp
self.qmp.connect()
self.ino_map = {}
self.ino_count = 1
def get_ino(self, path):
if self.ino_map.has_key(path):
return self.ino_map[path]
self.ino_map[path] = self.ino_count
self.ino_count += 1
return self.ino_map[path]
def is_object(self, path):
try:
items = self.qmp.command('qom-list', path=path)
return True
except:
return False
def is_property(self, path):
try:
path, prop = path.rsplit('/', 1)
for item in self.qmp.command('qom-list', path=path):
if item['name'] == prop:
return True
return False
except:
return False
def is_link(self, path):
try:
path, prop = path.rsplit('/', 1)
for item in self.qmp.command('qom-list', path=path):
if item['name'] == prop:
if item['type'].startswith('link<'):
return True
return False
return False
except:
return False
def read(self, path, length, offset):
if not self.is_property(path):
return -ENOENT
path, prop = path.rsplit('/', 1)
try:
data = str(self.qmp.command('qom-get', path=path, property=prop))
data += '\n' # make values shell friendly
except:
return -EPERM
if offset > len(data):
return ''
return str(data[offset:][:length])
def readlink(self, path):
if not self.is_link(path):
return False
path, prop = path.rsplit('/', 1)
prefix = '/'.join(['..'] * (len(path.split('/')) - 1))
return prefix + str(self.qmp.command('qom-get', path=path,
property=prop))
def getattr(self, path):
if self.is_link(path):
value = posix.stat_result((0755 | stat.S_IFLNK,
self.get_ino(path),
0,
2,
1000,
1000,
4096,
0,
0,
0))
elif self.is_object(path):
value = posix.stat_result((0755 | stat.S_IFDIR,
self.get_ino(path),
0,
2,
1000,
1000,
4096,
0,
0,
0))
elif self.is_property(path):
value = posix.stat_result((0644 | stat.S_IFREG,
self.get_ino(path),
0,
1,
1000,
1000,
4096,
0,
0,
0))
else:
value = -ENOENT
return value
def readdir(self, path, offset):
yield fuse.Direntry('.')
yield fuse.Direntry('..')
for item in self.qmp.command('qom-list', path=path):
yield fuse.Direntry(str(item['name']))
if __name__ == '__main__':
import sys, os
fs = QOMFS(QEMUMonitorProtocol(os.environ['QMP_SOCKET']))
fs.main(sys.argv)

67
scripts/qmp/qom-get Executable file
View file

@ -0,0 +1,67 @@
#!/usr/bin/python
##
# QEMU Object Model test tools
#
# Copyright IBM, Corp. 2011
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later. See
# the COPYING file in the top-level directory.
##
import sys
import os
from qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
path = None
prop = None
def usage():
return '''environment variables:
QMP_SOCKET=<path | addr:port>
usage:
%s [-h] [-s <QMP socket path | addr:port>] <path>.<property>
''' % cmd
def usage_error(error_msg = "unspecified error"):
sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
exit(1)
if len(args) > 0:
if args[0] == "-h":
print usage()
exit(0);
elif args[0] == "-s":
try:
socket_path = args[1]
except:
usage_error("missing argument: QMP socket path or address");
args = args[2:]
if not socket_path:
if os.environ.has_key('QMP_SOCKET'):
socket_path = os.environ['QMP_SOCKET']
else:
usage_error("no QMP socket path or address given");
if len(args) > 0:
try:
path, prop = args[0].rsplit('.', 1)
except:
usage_error("invalid format for path/property/value")
else:
usage_error("not enough arguments")
srv = QEMUMonitorProtocol(socket_path)
srv.connect()
rsp = srv.command('qom-get', path=path, property=prop)
if type(rsp) == dict:
for i in rsp.keys():
print '%s: %s' % (i, rsp[i])
else:
print rsp

64
scripts/qmp/qom-list Executable file
View file

@ -0,0 +1,64 @@
#!/usr/bin/python
##
# QEMU Object Model test tools
#
# Copyright IBM, Corp. 2011
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later. See
# the COPYING file in the top-level directory.
##
import sys
import os
from qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
path = None
prop = None
def usage():
return '''environment variables:
QMP_SOCKET=<path | addr:port>
usage:
%s [-h] [-s <QMP socket path | addr:port>] [<path>]
''' % cmd
def usage_error(error_msg = "unspecified error"):
sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
exit(1)
if len(args) > 0:
if args[0] == "-h":
print usage()
exit(0);
elif args[0] == "-s":
try:
socket_path = args[1]
except:
usage_error("missing argument: QMP socket path or address");
args = args[2:]
if not socket_path:
if os.environ.has_key('QMP_SOCKET'):
socket_path = os.environ['QMP_SOCKET']
else:
usage_error("no QMP socket path or address given");
srv = QEMUMonitorProtocol(socket_path)
srv.connect()
if len(args) == 0:
print '/'
sys.exit(0)
for item in srv.command('qom-list', path=args[0]):
if item['type'].startswith('child<'):
print '%s/' % item['name']
elif item['type'].startswith('link<'):
print '@%s/' % item['name']
else:
print '%s' % item['name']

64
scripts/qmp/qom-set Executable file
View file

@ -0,0 +1,64 @@
#!/usr/bin/python
##
# QEMU Object Model test tools
#
# Copyright IBM, Corp. 2011
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
#
# This work is licensed under the terms of the GNU GPL, version 2 or later. See
# the COPYING file in the top-level directory.
##
import sys
import os
from qmp import QEMUMonitorProtocol
cmd, args = sys.argv[0], sys.argv[1:]
socket_path = None
path = None
prop = None
value = None
def usage():
return '''environment variables:
QMP_SOCKET=<path | addr:port>
usage:
%s [-h] [-s <QMP socket path | addr:port>] <path>.<property> <value>
''' % cmd
def usage_error(error_msg = "unspecified error"):
sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
exit(1)
if len(args) > 0:
if args[0] == "-h":
print usage()
exit(0);
elif args[0] == "-s":
try:
socket_path = args[1]
except:
usage_error("missing argument: QMP socket path or address");
args = args[2:]
if not socket_path:
if os.environ.has_key('QMP_SOCKET'):
socket_path = os.environ['QMP_SOCKET']
else:
usage_error("no QMP socket path or address given");
if len(args) > 1:
try:
path, prop = args[0].rsplit('.', 1)
except:
usage_error("invalid format for path/property/value")
value = args[1]
else:
usage_error("not enough arguments")
srv = QEMUMonitorProtocol(socket_path)
srv.connect()
print srv.command('qom-set', path=path, property=prop, value=sys.argv[2])