]> Git Repo - qemu.git/blame - scripts/qmp/qemu-ga-client
linux-user: fix GPROF build failure
[qemu.git] / scripts / qmp / qemu-ga-client
CommitLineData
f513cbf7
RO
1#!/usr/bin/python
2
3# QEMU Guest Agent Client
4#
5# Copyright (C) 2012 Ryota Ozaki <[email protected]>
6#
7# This work is licensed under the terms of the GNU GPL, version 2. See
8# the COPYING file in the top-level directory.
9#
10# Usage:
11#
12# Start QEMU with:
13#
14# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
15# -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
16#
17# Run the script:
18#
19# $ qemu-ga-client --address=/tmp/qga.sock <command> [args...]
20#
21# or
22#
23# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock
24# $ qemu-ga-client <command> [args...]
25#
26# For example:
27#
28# $ qemu-ga-client cat /etc/resolv.conf
29# # Generated by NetworkManager
30# nameserver 10.0.2.3
31# $ qemu-ga-client fsfreeze status
32# thawed
33# $ qemu-ga-client fsfreeze freeze
34# 2 filesystems frozen
35#
70b7fba9 36# See also: https://wiki.qemu.org/Features/QAPI/GuestAgent
f513cbf7
RO
37#
38
f03868bd 39from __future__ import print_function
8f8fd9ed
CR
40import os
41import sys
f513cbf7
RO
42import base64
43import random
44
8f8fd9ed
CR
45sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'python'))
46from qemu import qmp
f513cbf7
RO
47
48
49class QemuGuestAgent(qmp.QEMUMonitorProtocol):
50 def __getattr__(self, name):
51 def wrapper(**kwds):
52 return self.command('guest-' + name.replace('_', '-'), **kwds)
53 return wrapper
54
55
56class QemuGuestAgentClient:
57 error = QemuGuestAgent.error
58
59 def __init__(self, address):
60 self.qga = QemuGuestAgent(address)
61 self.qga.connect(negotiate=False)
62
63 def sync(self, timeout=3):
64 # Avoid being blocked forever
65 if not self.ping(timeout):
66 raise EnvironmentError('Agent seems not alive')
67 uid = random.randint(0, (1 << 32) - 1)
68 while True:
69 ret = self.qga.sync(id=uid)
70 if isinstance(ret, int) and int(ret) == uid:
71 break
72
73 def __file_read_all(self, handle):
74 eof = False
75 data = ''
76 while not eof:
77 ret = self.qga.file_read(handle=handle, count=1024)
78 _data = base64.b64decode(ret['buf-b64'])
79 data += _data
80 eof = ret['eof']
81 return data
82
83 def read(self, path):
84 handle = self.qga.file_open(path=path)
85 try:
86 data = self.__file_read_all(handle)
87 finally:
88 self.qga.file_close(handle=handle)
89 return data
90
91 def info(self):
92 info = self.qga.info()
93
94 msgs = []
95 msgs.append('version: ' + info['version'])
96 msgs.append('supported_commands:')
97 enabled = [c['name'] for c in info['supported_commands'] if c['enabled']]
98 msgs.append('\tenabled: ' + ', '.join(enabled))
99 disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']]
100 msgs.append('\tdisabled: ' + ', '.join(disabled))
101
102 return '\n'.join(msgs)
103
104 def __gen_ipv4_netmask(self, prefixlen):
105 mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2)
106 return '.'.join([str(mask >> 24),
107 str((mask >> 16) & 0xff),
108 str((mask >> 8) & 0xff),
109 str(mask & 0xff)])
110
111 def ifconfig(self):
112 nifs = self.qga.network_get_interfaces()
113
114 msgs = []
115 for nif in nifs:
116 msgs.append(nif['name'] + ':')
117 if 'ip-addresses' in nif:
118 for ipaddr in nif['ip-addresses']:
119 if ipaddr['ip-address-type'] == 'ipv4':
120 addr = ipaddr['ip-address']
121 mask = self.__gen_ipv4_netmask(int(ipaddr['prefix']))
122 msgs.append("\tinet %s netmask %s" % (addr, mask))
123 elif ipaddr['ip-address-type'] == 'ipv6':
124 addr = ipaddr['ip-address']
125 prefix = ipaddr['prefix']
126 msgs.append("\tinet6 %s prefixlen %s" % (addr, prefix))
127 if nif['hardware-address'] != '00:00:00:00:00:00':
128 msgs.append("\tether " + nif['hardware-address'])
129
130 return '\n'.join(msgs)
131
132 def ping(self, timeout):
133 self.qga.settimeout(timeout)
134 try:
135 self.qga.ping()
136 except self.qga.timeout:
137 return False
138 return True
139
140 def fsfreeze(self, cmd):
141 if cmd not in ['status', 'freeze', 'thaw']:
050c5d86 142 raise Exception('Invalid command: ' + cmd)
f513cbf7
RO
143
144 return getattr(self.qga, 'fsfreeze' + '_' + cmd)()
145
146 def fstrim(self, minimum=0):
147 return getattr(self.qga, 'fstrim')(minimum=minimum)
148
149 def suspend(self, mode):
150 if mode not in ['disk', 'ram', 'hybrid']:
050c5d86 151 raise Exception('Invalid mode: ' + mode)
f513cbf7
RO
152
153 try:
154 getattr(self.qga, 'suspend' + '_' + mode)()
155 # On error exception will raise
156 except self.qga.timeout:
157 # On success command will timed out
158 return
159
160 def shutdown(self, mode='powerdown'):
161 if mode not in ['powerdown', 'halt', 'reboot']:
050c5d86 162 raise Exception('Invalid mode: ' + mode)
f513cbf7
RO
163
164 try:
165 self.qga.shutdown(mode=mode)
166 except self.qga.timeout:
167 return
168
169
170def _cmd_cat(client, args):
171 if len(args) != 1:
172 print('Invalid argument')
173 print('Usage: cat <file>')
174 sys.exit(1)
175 print(client.read(args[0]))
176
177
178def _cmd_fsfreeze(client, args):
179 usage = 'Usage: fsfreeze status|freeze|thaw'
180 if len(args) != 1:
181 print('Invalid argument')
182 print(usage)
183 sys.exit(1)
184 if args[0] not in ['status', 'freeze', 'thaw']:
185 print('Invalid command: ' + args[0])
186 print(usage)
187 sys.exit(1)
188 cmd = args[0]
189 ret = client.fsfreeze(cmd)
190 if cmd == 'status':
191 print(ret)
192 elif cmd == 'freeze':
193 print("%d filesystems frozen" % ret)
194 else:
195 print("%d filesystems thawed" % ret)
196
197
198def _cmd_fstrim(client, args):
199 if len(args) == 0:
200 minimum = 0
201 else:
202 minimum = int(args[0])
203 print(client.fstrim(minimum))
204
205
206def _cmd_ifconfig(client, args):
207 print(client.ifconfig())
208
209
210def _cmd_info(client, args):
211 print(client.info())
212
213
214def _cmd_ping(client, args):
215 if len(args) == 0:
216 timeout = 3
217 else:
218 timeout = float(args[0])
219 alive = client.ping(timeout)
220 if not alive:
221 print("Not responded in %s sec" % args[0])
222 sys.exit(1)
223
224
225def _cmd_suspend(client, args):
226 usage = 'Usage: suspend disk|ram|hybrid'
227 if len(args) != 1:
228 print('Less argument')
229 print(usage)
230 sys.exit(1)
231 if args[0] not in ['disk', 'ram', 'hybrid']:
232 print('Invalid command: ' + args[0])
233 print(usage)
234 sys.exit(1)
235 client.suspend(args[0])
236
237
238def _cmd_shutdown(client, args):
239 client.shutdown()
240_cmd_powerdown = _cmd_shutdown
241
242
243def _cmd_halt(client, args):
244 client.shutdown('halt')
245
246
247def _cmd_reboot(client, args):
248 client.shutdown('reboot')
249
250
251commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m]
252
253
254def main(address, cmd, args):
255 if not os.path.exists(address):
256 print('%s not found' % address)
257 sys.exit(1)
258
259 if cmd not in commands:
260 print('Invalid command: ' + cmd)
261 print('Available commands: ' + ', '.join(commands))
262 sys.exit(1)
263
264 try:
265 client = QemuGuestAgentClient(address)
cf6c6345 266 except QemuGuestAgent.error as e:
f513cbf7
RO
267 import errno
268
269 print(e)
270 if e.errno == errno.ECONNREFUSED:
271 print('Hint: qemu is not running?')
272 sys.exit(1)
273
e2682db0
TS
274 if cmd == 'fsfreeze' and args[0] == 'freeze':
275 client.sync(60)
276 elif cmd != 'ping':
f513cbf7
RO
277 client.sync()
278
279 globals()['_cmd_' + cmd](client, args)
280
281
282if __name__ == '__main__':
283 import sys
284 import os
285 import optparse
286
287 address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None
288
289 usage = "%prog [--address=<unix_path>|<ipv4_address>] <command> [args...]\n"
290 usage += '<command>: ' + ', '.join(commands)
291 parser = optparse.OptionParser(usage=usage)
292 parser.add_option('--address', action='store', type='string',
293 default=address, help='Specify a ip:port pair or a unix socket path')
294 options, args = parser.parse_args()
295
296 address = options.address
297 if address is None:
298 parser.error('address is not specified')
299 sys.exit(1)
300
301 if len(args) == 0:
302 parser.error('Less argument')
303 sys.exit(1)
304
305 main(address, args[0], args[1:])
This page took 0.346548 seconds and 4 git commands to generate.