From 5ade76748588627770b312ac592e3118f8541a53 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Wed, 18 Apr 2012 17:37:04 -0500 Subject: [PATCH] qom: quick and dirty QOM filesystem based on FUSE Here's an example session: anthony@titi:~/git/qemu/QMP$ QMP_SERVER=/tmp/server.sock ./qom-fuse tmp anthony@titi:~/git/qemu/QMP$ ls tmp machine sysbus type anthony@titi:~/git/qemu/QMP$ ls tmp/machine i440fx peripheral peripheral-anon type unattached anthony@titi:~/git/qemu/QMP$ ls tmp/machine/i440fx ioapic parent_bus pci.0 type anthony@titi:~/git/qemu/QMP$ ls tmp/machine/i440fx/pci.0 child[0] child[1] child[2] child[3] child[4] child[5] type anthony@titi:~/git/qemu/QMP$ ls tmp/machine/i440fx/pci.0/child[4] addr legacy-addr multifunction type command_serr_enable legacy-command_serr_enable parent_bus ide.0 legacy-multifunction rombar ide.1 legacy-romfile romfile anthony@titi:~/git/qemu/QMP$ cat tmp/machine/i440fx/pci.0/child[4]/type piix3-ide anthony@titi:~/git/qemu/QMP$ ls -al tmp/machine/i440fx/pci.0/child\[4\]/parent_bus lrwxr-xr-x 2 anthony anthony 4096 1969-12-31 18:00 tmp/machine/i440fx/pci.0/child[4]/parent_bus -> ../../../machine/i440fx/pci.0 Signed-off-by: Anthony Liguori --- QMP/qom-fuse | 138 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100755 QMP/qom-fuse diff --git a/QMP/qom-fuse b/QMP/qom-fuse new file mode 100755 index 000000000..5c6754aa6 --- /dev/null +++ b/QMP/qom-fuse @@ -0,0 +1,138 @@ +#!/usr/bin/python +## +# QEMU Object Model test tools +# +# Copyright IBM, Corp. 2012 +# +# Authors: +# Anthony Liguori +# +# 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) -- 2.39.5