mirror of
				https://github.com/apache/cloudstack.git
				synced 2025-11-04 00:02:37 +01:00 
			
		
		
		
	Using this tool on a hypervisor admins can query KVM Instances running
on that hypervisor if they have the Qemu Guest Agent installed.
All System VMs have this and they can be queried.
For example:
$ cloudstack-guest-tool i-2-25-VM
This will print some information about network and filesystem status.
root@hv-138-a05-23:~# ./cloudstack-guest-tool s-11-VM --command info|jq
{
  "network": [
    {
      "ip-addresses": [
        {
          "prefix": 8,
          "ip-address": "127.0.0.1",
          "ip-address-type": "ipv4"
        }
      ],
      "name": "lo",
      "hardware-address": "00:00:00:00:00:00"
    },
    {
      "ip-addresses": [
        {
          "prefix": 16,
          "ip-address": "169.254.242.169",
          "ip-address-type": "ipv4"
        }
      ],
      "name": "eth0",
      "hardware-address": "0e:00:a9:fe:f2:a9"
    },
 ...
 ...
  "filesystem": [
    {
      "mountpoint": "/var",
      "disk": [
        {
          "bus": 0,
          "bus-type": "virtio",
          "target": 0,
          "unit": 0,
          "pci-controller": {
            "slot": 7,
            "bus": 0,
            "domain": 0,
            "function": 0
          }
        }
      ],
      "type": "ext4",
      "name": "vda6"
    },
Signed-off-by: Wido den Hollander <wido@widodh.nl>
		
	
			
		
			
				
	
	
		
			130 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
# 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 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)
 |