#!/usr/bin/python

# QEMU Guest Agent Client
#
# Copyright (C) 2012 Ryota Ozaki <ozaki.ryota@gmail.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.  See
# the COPYING file in the top-level directory.
#
# Usage:
#
# Start QEMU with:
#
# # qemu [...] -chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
#   -device virtio-serial -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0
#
# Run the script:
#
# $ qemu-ga-client --address=/tmp/qga.sock <command> [args...]
#
# or
#
# $ export QGA_CLIENT_ADDRESS=/tmp/qga.sock
# $ qemu-ga-client <command> [args...]
#
# For example:
#
# $ qemu-ga-client cat /etc/resolv.conf
# # Generated by NetworkManager
# nameserver 10.0.2.3
# $ qemu-ga-client fsfreeze status
# thawed
# $ qemu-ga-client fsfreeze freeze
# 2 filesystems frozen
#
# See also: http://wiki.qemu.org/Features/QAPI/GuestAgent
#

import base64
import random

import qmp


class QemuGuestAgent(qmp.QEMUMonitorProtocol):
    def __getattr__(self, name):
        def wrapper(**kwds):
            return self.command('guest-' + name.replace('_', '-'), **kwds)
        return wrapper


class QemuGuestAgentClient:
    error = QemuGuestAgent.error

    def __init__(self, address):
        self.qga = QemuGuestAgent(address)
        self.qga.connect(negotiate=False)

    def sync(self, timeout=3):
        # Avoid being blocked forever
        if not self.ping(timeout):
            raise EnvironmentError('Agent seems not alive')
        uid = random.randint(0, (1 << 32) - 1)
        while True:
            ret = self.qga.sync(id=uid)
            if isinstance(ret, int) and int(ret) == uid:
                break

    def __file_read_all(self, handle):
        eof = False
        data = ''
        while not eof:
            ret = self.qga.file_read(handle=handle, count=1024)
            _data = base64.b64decode(ret['buf-b64'])
            data += _data
            eof = ret['eof']
        return data

    def read(self, path):
        handle = self.qga.file_open(path=path)
        try:
            data = self.__file_read_all(handle)
        finally:
            self.qga.file_close(handle=handle)
        return data

    def info(self):
        info = self.qga.info()

        msgs = []
        msgs.append('version: ' + info['version'])
        msgs.append('supported_commands:')
        enabled = [c['name'] for c in info['supported_commands'] if c['enabled']]
        msgs.append('\tenabled: ' + ', '.join(enabled))
        disabled = [c['name'] for c in info['supported_commands'] if not c['enabled']]
        msgs.append('\tdisabled: ' + ', '.join(disabled))

        return '\n'.join(msgs)

    def __gen_ipv4_netmask(self, prefixlen):
        mask = int('1' * prefixlen + '0' * (32 - prefixlen), 2)
        return '.'.join([str(mask >> 24),
                         str((mask >> 16) & 0xff),
                         str((mask >> 8) & 0xff),
                         str(mask & 0xff)])

    def ifconfig(self):
        nifs = self.qga.network_get_interfaces()

        msgs = []
        for nif in nifs:
            msgs.append(nif['name'] + ':')
            if 'ip-addresses' in nif:
                for ipaddr in nif['ip-addresses']:
                    if ipaddr['ip-address-type'] == 'ipv4':
                        addr = ipaddr['ip-address']
                        mask = self.__gen_ipv4_netmask(int(ipaddr['prefix']))
                        msgs.append("\tinet %s  netmask %s" % (addr, mask))
                    elif ipaddr['ip-address-type'] == 'ipv6':
                        addr = ipaddr['ip-address']
                        prefix = ipaddr['prefix']
                        msgs.append("\tinet6 %s  prefixlen %s" % (addr, prefix))
            if nif['hardware-address'] != '00:00:00:00:00:00':
                msgs.append("\tether " + nif['hardware-address'])

        return '\n'.join(msgs)

    def ping(self, timeout):
        self.qga.settimeout(timeout)
        try:
            self.qga.ping()
        except self.qga.timeout:
            return False
        return True

    def fsfreeze(self, cmd):
        if cmd not in ['status', 'freeze', 'thaw']:
            raise StandardError('Invalid command: ' + cmd)

        return getattr(self.qga, 'fsfreeze' + '_' + cmd)()

    def fstrim(self, minimum=0):
        return getattr(self.qga, 'fstrim')(minimum=minimum)

    def suspend(self, mode):
        if mode not in ['disk', 'ram', 'hybrid']:
            raise StandardError('Invalid mode: ' + mode)

        try:
            getattr(self.qga, 'suspend' + '_' + mode)()
            # On error exception will raise
        except self.qga.timeout:
            # On success command will timed out
            return

    def shutdown(self, mode='powerdown'):
        if mode not in ['powerdown', 'halt', 'reboot']:
            raise StandardError('Invalid mode: ' + mode)

        try:
            self.qga.shutdown(mode=mode)
        except self.qga.timeout:
            return


def _cmd_cat(client, args):
    if len(args) != 1:
        print('Invalid argument')
        print('Usage: cat <file>')
        sys.exit(1)
    print(client.read(args[0]))


def _cmd_fsfreeze(client, args):
    usage = 'Usage: fsfreeze status|freeze|thaw'
    if len(args) != 1:
        print('Invalid argument')
        print(usage)
        sys.exit(1)
    if args[0] not in ['status', 'freeze', 'thaw']:
        print('Invalid command: ' + args[0])
        print(usage)
        sys.exit(1)
    cmd = args[0]
    ret = client.fsfreeze(cmd)
    if cmd == 'status':
        print(ret)
    elif cmd == 'freeze':
        print("%d filesystems frozen" % ret)
    else:
        print("%d filesystems thawed" % ret)


def _cmd_fstrim(client, args):
    if len(args) == 0:
        minimum = 0
    else:
        minimum = int(args[0])
    print(client.fstrim(minimum))


def _cmd_ifconfig(client, args):
    print(client.ifconfig())


def _cmd_info(client, args):
    print(client.info())


def _cmd_ping(client, args):
    if len(args) == 0:
        timeout = 3
    else:
        timeout = float(args[0])
    alive = client.ping(timeout)
    if not alive:
        print("Not responded in %s sec" % args[0])
        sys.exit(1)


def _cmd_suspend(client, args):
    usage = 'Usage: suspend disk|ram|hybrid'
    if len(args) != 1:
        print('Less argument')
        print(usage)
        sys.exit(1)
    if args[0] not in ['disk', 'ram', 'hybrid']:
        print('Invalid command: ' + args[0])
        print(usage)
        sys.exit(1)
    client.suspend(args[0])


def _cmd_shutdown(client, args):
    client.shutdown()
_cmd_powerdown = _cmd_shutdown


def _cmd_halt(client, args):
    client.shutdown('halt')


def _cmd_reboot(client, args):
    client.shutdown('reboot')


commands = [m.replace('_cmd_', '') for m in dir() if '_cmd_' in m]


def main(address, cmd, args):
    if not os.path.exists(address):
        print('%s not found' % address)
        sys.exit(1)

    if cmd not in commands:
        print('Invalid command: ' + cmd)
        print('Available commands: ' + ', '.join(commands))
        sys.exit(1)

    try:
        client = QemuGuestAgentClient(address)
    except QemuGuestAgent.error, e:
        import errno

        print(e)
        if e.errno == errno.ECONNREFUSED:
            print('Hint: qemu is not running?')
        sys.exit(1)

    if cmd == 'fsfreeze' and args[0] == 'freeze':
        client.sync(60)
    elif cmd != 'ping':
        client.sync()

    globals()['_cmd_' + cmd](client, args)


if __name__ == '__main__':
    import sys
    import os
    import optparse

    address = os.environ['QGA_CLIENT_ADDRESS'] if 'QGA_CLIENT_ADDRESS' in os.environ else None

    usage = "%prog [--address=<unix_path>|<ipv4_address>] <command> [args...]\n"
    usage += '<command>: ' + ', '.join(commands)
    parser = optparse.OptionParser(usage=usage)
    parser.add_option('--address', action='store', type='string',
                      default=address, help='Specify a ip:port pair or a unix socket path')
    options, args = parser.parse_args()

    address = options.address
    if address is None:
        parser.error('address is not specified')
        sys.exit(1)

    if len(args) == 0:
        parser.error('Less argument')
        sys.exit(1)

    main(address, args[0], args[1:])
