Message ID | 20180817180440.49687-2-vsementsov@virtuozzo.com |
---|---|
State | New |
Headers | show |
Series | block nodes graph visualization | expand |
On Fri, Aug 17, 2018 at 09:04:39PM +0300, Vladimir Sementsov-Ogievskiy wrote: > Render block nodes graph with help of graphviz. This new function is > for debugging, so there is no sense to put it into qemu.py as a method > of QEMUMachine. Let's instead put it separately. > > Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> > --- > scripts/render_block_graph.py | 78 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 78 insertions(+) > create mode 100644 scripts/render_block_graph.py > > diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py > new file mode 100644 > index 0000000000..7048a0bac8 > --- /dev/null > +++ b/scripts/render_block_graph.py > @@ -0,0 +1,78 @@ > +# Render Qemu Block Graph [...] What about making the script work from the command-line? Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> --- diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py old mode 100644 new mode 100755 index 7048a0bac8..e29fe0fc41 --- a/scripts/render_block_graph.py +++ b/scripts/render_block_graph.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # Render Qemu Block Graph # # Copyright (c) 2017 Parallels International GmbH @@ -16,8 +17,9 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -import os +import os, sys from graphviz import Digraph +from qmp.qmp import QEMUMonitorProtocol def perm(arr): s = 'w' if 'write' in arr else '_' @@ -27,16 +29,16 @@ def perm(arr): s += 's' if 'resize' in arr else '_' return s -def render_block_graph(vm, filename, pointers=False, format='png'): +def render_block_graph(qmp, filename, pointers=False, format='png'): ''' Render graph in text (dot) representation into "@filename" and representation in @format into "@filename.@format" ''' - nodes = vm.command('query-named-block-nodes') + nodes = qmp.command('query-named-block-nodes') nodes_info = {n['node-name']: n for n in nodes} - block_graph = vm.command('x-query-block-graph') + block_graph = qmp.command('x-query-block-graph') graph = Digraph(comment='Block Nodes Graph') graph.format = format @@ -76,3 +78,9 @@ def render_block_graph(vm, filename, pointers=False, format='png'): graph.edge(str(e['parent']), str(e['child']), label=label) graph.render(filename) + +if __name__ == '__main__': + #TODO: use argparse for command-line arguments + qmp = QEMUMonitorProtocol(sys.argv[1]) + qmp.connect() + render_block_graph(qmp, sys.argv[2])
17.08.2018 21:25, Eduardo Habkost wrote: > On Fri, Aug 17, 2018 at 09:04:39PM +0300, Vladimir Sementsov-Ogievskiy wrote: >> Render block nodes graph with help of graphviz. This new function is >> for debugging, so there is no sense to put it into qemu.py as a method >> of QEMUMachine. Let's instead put it separately. >> >> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> >> --- >> scripts/render_block_graph.py | 78 +++++++++++++++++++++++++++++++++++++++++++ >> 1 file changed, 78 insertions(+) >> create mode 100644 scripts/render_block_graph.py >> >> diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py >> new file mode 100644 >> index 0000000000..7048a0bac8 >> --- /dev/null >> +++ b/scripts/render_block_graph.py >> @@ -0,0 +1,78 @@ >> +# Render Qemu Block Graph > [...] > > What about making the script work from the command-line? > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> > --- > diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py > old mode 100644 > new mode 100755 > index 7048a0bac8..e29fe0fc41 > --- a/scripts/render_block_graph.py > +++ b/scripts/render_block_graph.py > @@ -1,3 +1,4 @@ > +#!/usr/bin/env python > # Render Qemu Block Graph > # > # Copyright (c) 2017 Parallels International GmbH > @@ -16,8 +17,9 @@ > # along with this program. If not, see <http://www.gnu.org/licenses/>. > # > > -import os > +import os, sys > from graphviz import Digraph > +from qmp.qmp import QEMUMonitorProtocol > > def perm(arr): > s = 'w' if 'write' in arr else '_' > @@ -27,16 +29,16 @@ def perm(arr): > s += 's' if 'resize' in arr else '_' > return s > > -def render_block_graph(vm, filename, pointers=False, format='png'): > +def render_block_graph(qmp, filename, pointers=False, format='png'): > ''' > Render graph in text (dot) representation into "@filename" and > representation in @format into "@filename.@format" > ''' > > - nodes = vm.command('query-named-block-nodes') > + nodes = qmp.command('query-named-block-nodes') > nodes_info = {n['node-name']: n for n in nodes} > > - block_graph = vm.command('x-query-block-graph') > + block_graph = qmp.command('x-query-block-graph') > > graph = Digraph(comment='Block Nodes Graph') > graph.format = format > @@ -76,3 +78,9 @@ def render_block_graph(vm, filename, pointers=False, format='png'): > graph.edge(str(e['parent']), str(e['child']), label=label) > > graph.render(filename) > + > +if __name__ == '__main__': > + #TODO: use argparse for command-line arguments > + qmp = QEMUMonitorProtocol(sys.argv[1]) > + qmp.connect() > + render_block_graph(qmp, sys.argv[2]) > > Cool, thanks. so, how to use it then? for python iotest a proper parameter would be vm._qmp, yes? is there a way to dump running libvirt vm graph? I've started libvirt guest, qemu process has cmdline parameters -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-3-tmp/monitor.sock,server,nowait -mon chardev=charmonitor,id=monitor,mode=control command virsh qemu-monitor-command tmp '{"execute": "x-query-block-graph"}' works fine, but script hangs on connection: # python ./scripts/render_block_graph.py /var/lib/libvirt/qemu/domain-3-tmp/monitor.sock ^CTraceback (most recent call last): File "./scripts/render_block_graph.py", line 85, in <module> qmp.connect() File "/work/src/qemu/up-new-fleecing/scripts/qmp/qmp.py", line 140, in connect self.__sock.connect(self.__address) File "/usr/lib64/python2.7/socket.py", line 224, in meth return getattr(self._sock,name)(*args) KeyboardInterrupt ./scripts/qmp/qmp-shell /var/lib/libvirt/qemu/domain-3-tmp/monitor.sock outputs nothing...
On Fri, Aug 17, 2018 at 09:59:41PM +0300, Vladimir Sementsov-Ogievskiy wrote: > 17.08.2018 21:25, Eduardo Habkost wrote: > > On Fri, Aug 17, 2018 at 09:04:39PM +0300, Vladimir Sementsov-Ogievskiy wrote: > > > Render block nodes graph with help of graphviz. This new function is > > > for debugging, so there is no sense to put it into qemu.py as a method > > > of QEMUMachine. Let's instead put it separately. > > > > > > Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> > > > --- > > > scripts/render_block_graph.py | 78 +++++++++++++++++++++++++++++++++++++++++++ > > > 1 file changed, 78 insertions(+) > > > create mode 100644 scripts/render_block_graph.py > > > > > > diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py > > > new file mode 100644 > > > index 0000000000..7048a0bac8 > > > --- /dev/null > > > +++ b/scripts/render_block_graph.py > > > @@ -0,0 +1,78 @@ > > > +# Render Qemu Block Graph > > [...] > > > > What about making the script work from the command-line? > > > > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> > > --- > > diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py > > old mode 100644 > > new mode 100755 > > index 7048a0bac8..e29fe0fc41 > > --- a/scripts/render_block_graph.py > > +++ b/scripts/render_block_graph.py > > @@ -1,3 +1,4 @@ > > +#!/usr/bin/env python > > # Render Qemu Block Graph > > # > > # Copyright (c) 2017 Parallels International GmbH > > @@ -16,8 +17,9 @@ > > # along with this program. If not, see <http://www.gnu.org/licenses/>. > > # > > -import os > > +import os, sys > > from graphviz import Digraph > > +from qmp.qmp import QEMUMonitorProtocol > > def perm(arr): > > s = 'w' if 'write' in arr else '_' > > @@ -27,16 +29,16 @@ def perm(arr): > > s += 's' if 'resize' in arr else '_' > > return s > > -def render_block_graph(vm, filename, pointers=False, format='png'): > > +def render_block_graph(qmp, filename, pointers=False, format='png'): > > ''' > > Render graph in text (dot) representation into "@filename" and > > representation in @format into "@filename.@format" > > ''' > > - nodes = vm.command('query-named-block-nodes') > > + nodes = qmp.command('query-named-block-nodes') > > nodes_info = {n['node-name']: n for n in nodes} > > - block_graph = vm.command('x-query-block-graph') > > + block_graph = qmp.command('x-query-block-graph') > > graph = Digraph(comment='Block Nodes Graph') > > graph.format = format > > @@ -76,3 +78,9 @@ def render_block_graph(vm, filename, pointers=False, format='png'): > > graph.edge(str(e['parent']), str(e['child']), label=label) > > graph.render(filename) > > + > > +if __name__ == '__main__': > > + #TODO: use argparse for command-line arguments > > + qmp = QEMUMonitorProtocol(sys.argv[1]) > > + qmp.connect() > > + render_block_graph(qmp, sys.argv[2]) > > > > > > Cool, thanks. > > so, how to use it then? > > for python iotest a proper parameter would be vm._qmp, yes? Yes, assuming you just want to do it locally just for debugging. One thing we could do later: refactor QEMUMachine and QEMUMonitorProtocol so their method names are the same and both 'vm' and 'vm._qmp' work here. > > is there a way to dump running libvirt vm graph? > > I've started libvirt guest, qemu process has cmdline parameters > -chardev socket,id=charmonitor,path=/var/lib/libvirt/qemu/domain-3-tmp/monitor.sock,server,nowait > -mon chardev=charmonitor,id=monitor,mode=control > > command > virsh qemu-monitor-command tmp '{"execute": "x-query-block-graph"}' > works fine, > > but script hangs on connection: > # python ./scripts/render_block_graph.py > /var/lib/libvirt/qemu/domain-3-tmp/monitor.sock > ^CTraceback (most recent call last): > File "./scripts/render_block_graph.py", line 85, in <module> > qmp.connect() > File "/work/src/qemu/up-new-fleecing/scripts/qmp/qmp.py", line 140, in > connect > self.__sock.connect(self.__address) > File "/usr/lib64/python2.7/socket.py", line 224, in meth > return getattr(self._sock,name)(*args) > KeyboardInterrupt > > ./scripts/qmp/qmp-shell /var/lib/libvirt/qemu/domain-3-tmp/monitor.sock > outputs nothing... I don't know why it doesn't work with a running instance started by libvirt, but it works if I run QEMU manually using "-qmp unix:/tmp/qmp,server".
diff --git a/scripts/render_block_graph.py b/scripts/render_block_graph.py new file mode 100644 index 0000000000..7048a0bac8 --- /dev/null +++ b/scripts/render_block_graph.py @@ -0,0 +1,78 @@ +# Render Qemu Block Graph +# +# Copyright (c) 2017 Parallels International GmbH +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + +import os +from graphviz import Digraph + +def perm(arr): + s = 'w' if 'write' in arr else '_' + s += 'r' if 'consistent-read' in arr else '_' + s += 'u' if 'write-unchanged' in arr else '_' + s += 'g' if 'graph-mod' in arr else '_' + s += 's' if 'resize' in arr else '_' + return s + +def render_block_graph(vm, filename, pointers=False, format='png'): + ''' + Render graph in text (dot) representation into "@filename" and + representation in @format into "@filename.@format" + ''' + + nodes = vm.command('query-named-block-nodes') + nodes_info = {n['node-name']: n for n in nodes} + + block_graph = vm.command('x-query-block-graph') + + graph = Digraph(comment='Block Nodes Graph') + graph.format = format + graph.node('permission symbols:\l' + ' w - Write\l' + ' r - consistent-Read\l' + ' u - write - Unchanged\l' + ' g - Graph-mod\l' + ' s - reSize\l' + 'edge label scheme:\l' + ' <child type>\l' + ' <perm>\l' + ' <shared_perm>\l', shape='none') + + + for n in block_graph['nodes']: + if n['type'] == 'block': + info = nodes_info[n['node-name']] + label = n['node-name'] + ' [' + info['drv'] + ']' + shape = 'ellipse' + else: + assert n['type'] == 'other' + label = n['description'] + shape = 'box' + + if pointers: + label += '\n0x%x' % n['id'] + + if n['type'] == 'block' and info['drv'] == 'file': + label += '\n' + os.path.basename(info['file']) + + graph.node(str(n['id']), label, shape=shape) + + for e in block_graph['edges']: + label = '%s\l%s\l%s\l' % (e['name'], perm(e['perm']), + perm(e['shared-perm'])) + graph.edge(str(e['parent']), str(e['child']), label=label) + + graph.render(filename)
Render block nodes graph with help of graphviz. This new function is for debugging, so there is no sense to put it into qemu.py as a method of QEMUMachine. Let's instead put it separately. Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com> --- scripts/render_block_graph.py | 78 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 scripts/render_block_graph.py