]> git.proxmox.com Git - mirror_qemu.git/blame - python/qemu/utils/qom.py
python/qemu: rename command() to cmd()
[mirror_qemu.git] / python / qemu / utils / qom.py
CommitLineData
c750c028
JS
1"""
2QEMU Object Model testing tools.
3
176c5490 4usage: qom [-h] {set,get,list,tree,fuse} ...
c750c028
JS
5
6Query and manipulate QOM data
7
8optional arguments:
9 -h, --help show this help message and exit
10
11QOM commands:
176c5490 12 {set,get,list,tree,fuse}
c750c028
JS
13 set Set a QOM property value
14 get Get a QOM property value
15 list List QOM properties at a given path
16 tree Show QOM tree from a given path
176c5490 17 fuse Mount a QOM tree as a FUSE filesystem
c750c028
JS
18"""
19##
20# Copyright John Snow 2020, for Red Hat, Inc.
21# Copyright IBM, Corp. 2011
22#
23# Authors:
24# John Snow <jsnow@redhat.com>
25# Anthony Liguori <aliguori@amazon.com>
26#
27# This work is licensed under the terms of the GNU GPL, version 2 or later.
28# See the COPYING file in the top-level directory.
29#
30# Based on ./scripts/qmp/qom-[set|get|tree|list]
31##
32
33import argparse
34
37094b6d 35from qemu.qmp import ExecuteError
8d6cdc51 36
c750c028
JS
37from .qom_common import QOMCommand
38
39
176c5490
JS
40try:
41 from .qom_fuse import QOMFuse
00376d13
JS
42except ModuleNotFoundError as _err:
43 if _err.name != 'fuse':
176c5490
JS
44 raise
45else:
46 assert issubclass(QOMFuse, QOMCommand)
47
48
c750c028
JS
49class QOMSet(QOMCommand):
50 """
51 QOM Command - Set a property to a given value.
52
53 usage: qom-set [-h] [--socket SOCKET] <path>.<property> <value>
54
55 Set a QOM property value
56
57 positional arguments:
58 <path>.<property> QOM path and property, separated by a period '.'
59 <value> new QOM property value
60
61 optional arguments:
62 -h, --help show this help message and exit
63 --socket SOCKET, -s SOCKET
64 QMP socket path or address (addr:port). May also be
65 set via QMP_SOCKET environment variable.
66 """
67 name = 'set'
68 help = 'Set a QOM property value'
69
70 @classmethod
71 def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
72 super().configure_parser(parser)
73 cls.add_path_prop_arg(parser)
74 parser.add_argument(
75 'value',
76 metavar='<value>',
77 action='store',
78 help='new QOM property value'
79 )
80
81 def __init__(self, args: argparse.Namespace):
82 super().__init__(args)
83 self.path, self.prop = args.path_prop.rsplit('.', 1)
84 self.value = args.value
85
86 def run(self) -> int:
684750ab 87 rsp = self.qmp.cmd(
c750c028
JS
88 'qom-set',
89 path=self.path,
90 property=self.prop,
91 value=self.value
92 )
93 print(rsp)
94 return 0
95
96
97class QOMGet(QOMCommand):
98 """
99 QOM Command - Get a property's current value.
100
101 usage: qom-get [-h] [--socket SOCKET] <path>.<property>
102
103 Get a QOM property value
104
105 positional arguments:
106 <path>.<property> QOM path and property, separated by a period '.'
107
108 optional arguments:
109 -h, --help show this help message and exit
110 --socket SOCKET, -s SOCKET
111 QMP socket path or address (addr:port). May also be
112 set via QMP_SOCKET environment variable.
113 """
114 name = 'get'
115 help = 'Get a QOM property value'
116
117 @classmethod
118 def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
119 super().configure_parser(parser)
120 cls.add_path_prop_arg(parser)
121
122 def __init__(self, args: argparse.Namespace):
123 super().__init__(args)
124 try:
125 tmp = args.path_prop.rsplit('.', 1)
126 except ValueError as err:
127 raise ValueError('Invalid format for <path>.<property>') from err
128 self.path = tmp[0]
129 self.prop = tmp[1]
130
131 def run(self) -> int:
684750ab 132 rsp = self.qmp.cmd(
c750c028
JS
133 'qom-get',
134 path=self.path,
135 property=self.prop
136 )
137 if isinstance(rsp, dict):
138 for key, value in rsp.items():
139 print(f"{key}: {value}")
140 else:
141 print(rsp)
142 return 0
143
144
145class QOMList(QOMCommand):
146 """
147 QOM Command - List the properties at a given path.
148
149 usage: qom-list [-h] [--socket SOCKET] <path>
150
151 List QOM properties at a given path
152
153 positional arguments:
154 <path> QOM path
155
156 optional arguments:
157 -h, --help show this help message and exit
158 --socket SOCKET, -s SOCKET
159 QMP socket path or address (addr:port). May also be
160 set via QMP_SOCKET environment variable.
161 """
162 name = 'list'
163 help = 'List QOM properties at a given path'
164
165 @classmethod
166 def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
167 super().configure_parser(parser)
168 parser.add_argument(
169 'path',
170 metavar='<path>',
171 action='store',
172 help='QOM path',
173 )
174
175 def __init__(self, args: argparse.Namespace):
176 super().__init__(args)
177 self.path = args.path
178
179 def run(self) -> int:
180 rsp = self.qom_list(self.path)
181 for item in rsp:
182 if item.child:
183 print(f"{item.name}/")
184 elif item.link:
185 print(f"@{item.name}/")
186 else:
187 print(item.name)
188 return 0
189
190
191class QOMTree(QOMCommand):
192 """
193 QOM Command - Show the full tree below a given path.
194
195 usage: qom-tree [-h] [--socket SOCKET] [<path>]
196
197 Show QOM tree from a given path
198
199 positional arguments:
200 <path> QOM path
201
202 optional arguments:
203 -h, --help show this help message and exit
204 --socket SOCKET, -s SOCKET
205 QMP socket path or address (addr:port). May also be
206 set via QMP_SOCKET environment variable.
207 """
208 name = 'tree'
209 help = 'Show QOM tree from a given path'
210
211 @classmethod
212 def configure_parser(cls, parser: argparse.ArgumentParser) -> None:
213 super().configure_parser(parser)
214 parser.add_argument(
215 'path',
216 metavar='<path>',
217 action='store',
218 help='QOM path',
219 nargs='?',
220 default='/'
221 )
222
223 def __init__(self, args: argparse.Namespace):
224 super().__init__(args)
225 self.path = args.path
226
227 def _list_node(self, path: str) -> None:
228 print(path)
229 items = self.qom_list(path)
230 for item in items:
231 if item.child:
232 continue
233 try:
684750ab
VSO
234 rsp = self.qmp.cmd('qom-get', path=path,
235 property=item.name)
c750c028 236 print(f" {item.name}: {rsp} ({item.type})")
8d6cdc51 237 except ExecuteError as err:
c750c028
JS
238 print(f" {item.name}: <EXCEPTION: {err!s}> ({item.type})")
239 print('')
240 for item in items:
241 if not item.child:
242 continue
243 if path == '/':
244 path = ''
245 self._list_node(f"{path}/{item.name}")
246
247 def run(self) -> int:
248 self._list_node(self.path)
249 return 0
250
251
252def main() -> int:
253 """QOM script main entry point."""
254 parser = argparse.ArgumentParser(
255 description='Query and manipulate QOM data'
256 )
257 subparsers = parser.add_subparsers(
258 title='QOM commands',
259 dest='command'
260 )
261
262 for command in QOMCommand.__subclasses__():
263 command.register(subparsers)
264
265 args = parser.parse_args()
266
267 if args.command is None:
268 parser.error('Command not specified.')
269 return 1
270
271 cmd_class = args.cmd_class
272 assert isinstance(cmd_class, type(QOMCommand))
273 return cmd_class.command_runner(args)