#!/usr/bin/env python3 # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # # Talk to a KVM guest through Libvirt and the Qemu Guest Agent # to retrieve information from the guest # # System VMs have the Qemu Guest Agent installed by default # and should properly respond to such commands # # Talk to KVM Instances through the Qemu Guest Agent # import argparse import json import sys import libvirt import libvirt_qemu COMMANDS = ["info", "ping", "fstrim"] class Libvirt: def __init__(self, uri=None, timeout=5): self.timeout = timeout self.conn = libvirt.open(uri) if not self.conn: raise Exception('Failed to open connection to the hypervisor') def get_domain(self, name): return self.conn.lookupByName(name) def agent_command(self, dom, cmd, flags=0, raw=False): ret = libvirt_qemu.qemuAgentCommand(dom, json.dumps({'execute': cmd}), self.timeout, flags) if raw: return ret return json.loads(ret)['return'] class GuestCommand: def __init__(self, domain, timeout): self.domain = domain self.timeout = timeout self.virt = Libvirt(timeout=self.timeout) self.dom = self.virt.get_domain(self.domain) def ping(self): result = self.virt.agent_command(self.dom, 'guest-ping') res = False code = 1 if len(result) == 0: res = True code = 0 return {'result': res}, code def info(self): info = dict() info['filesystem'] = 'guest-get-fsinfo' info['network'] = 'guest-network-get-interfaces' result = dict() for key, cmd in list(info.items()): result[key] = self.virt.agent_command(self.dom, cmd) return result, 0 def fstrim(self): result = self.virt.agent_command(self.dom, 'guest-fstrim') res = False code = 1 if len(result) > 0: res = True code = 0 return {'result': result}, code def main(args): command = args.command try: guestcmd = GuestCommand(args.instance, args.timeout) result = {'error': 'Command not implemented'} code = 255 if command == 'info': result, code = guestcmd.info() elif command == 'ping': result, code = guestcmd.ping() elif command == 'fstrim': result, code = guestcmd.fstrim() print(json.dumps(result)) sys.exit(code) except libvirt.libvirtError as exc: print(json.dumps({'error': str(exc)})) sys.exit(255) if __name__ == '__main__': parser = argparse.ArgumentParser(description='CloudStack Guest Tool') parser.add_argument('instance', type=str, help='Instance Name') parser.add_argument('--command', type=str, required=False, help='Command to execute', default='info', choices=COMMANDS) parser.add_argument('--timeout', type=int, required=False, help='timeout in seconds', default=5) args = parser.parse_args() main(args)