From patchwork Wed Apr 18 22:37:04 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anthony Liguori X-Patchwork-Id: 153617 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B835FB6FA3 for ; Thu, 19 Apr 2012 08:37:21 +1000 (EST) Received: from localhost ([::1]:56048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKdV1-0006wm-Ke for incoming@patchwork.ozlabs.org; Wed, 18 Apr 2012 18:37:19 -0400 Received: from eggs.gnu.org ([208.118.235.92]:47637) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKdUr-0006vQ-GB for qemu-devel@nongnu.org; Wed, 18 Apr 2012 18:37:12 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SKdUp-0007rc-Lx for qemu-devel@nongnu.org; Wed, 18 Apr 2012 18:37:09 -0400 Received: from cpe-70-123-132-139.austin.res.rr.com ([70.123.132.139]:60072 helo=localhost6.localdomain6) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SKdUp-0007rK-E2 for qemu-devel@nongnu.org; Wed, 18 Apr 2012 18:37:07 -0400 Received: from localhost6.localdomain6 (localhost.localdomain [127.0.0.1]) by localhost6.localdomain6 (8.14.4/8.14.4/Debian-2ubuntu2) with ESMTP id q3IMb5pE025735; Wed, 18 Apr 2012 17:37:05 -0500 Received: (from anthony@localhost) by localhost6.localdomain6 (8.14.4/8.14.4/Submit) id q3IMb4bA025734; Wed, 18 Apr 2012 17:37:04 -0500 From: Anthony Liguori To: qemu-devel@nongnu.org Date: Wed, 18 Apr 2012 17:37:04 -0500 Message-Id: <1334788624-25698-1-git-send-email-aliguori@us.ibm.com> X-Mailer: git-send-email 1.7.5.4 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 70.123.132.139 Cc: Anthony Liguori Subject: [Qemu-devel] [PATCH] qom: quick and dirty QOM filesystem based on FUSE X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 files changed, 138 insertions(+), 0 deletions(-) create mode 100755 QMP/qom-fuse diff --git a/QMP/qom-fuse b/QMP/qom-fuse new file mode 100755 index 0000000..5c6754a --- /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)