kvm/cloudstack-guest-tool: Tool to query Qemu Guest Agent (#3519)

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>
This commit is contained in:
Wido den Hollander 2019-09-10 18:31:03 +02:00 committed by Rohit Yadav
parent fbec3b367f
commit 8da0556f63
4 changed files with 134 additions and 0 deletions

129
agent/bindir/cloud-guest-tool.in Executable file
View File

@ -0,0 +1,129 @@
#!/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)

1
debian/rules vendored
View File

@ -52,6 +52,7 @@ override_dh_auto_install:
install -D agent/target/transformed/cloud-ssh $(DESTDIR)/usr/bin/cloudstack-ssh install -D agent/target/transformed/cloud-ssh $(DESTDIR)/usr/bin/cloudstack-ssh
install -D agent/target/transformed/cloudstack-agent-profile.sh $(DESTDIR)/$(SYSCONFDIR)/profile.d/cloudstack-agent-profile.sh install -D agent/target/transformed/cloudstack-agent-profile.sh $(DESTDIR)/$(SYSCONFDIR)/profile.d/cloudstack-agent-profile.sh
install -D agent/target/transformed/cloudstack-agent-upgrade $(DESTDIR)/usr/bin/cloudstack-agent-upgrade install -D agent/target/transformed/cloudstack-agent-upgrade $(DESTDIR)/usr/bin/cloudstack-agent-upgrade
install -D agent/target/transformed/cloud-guest-tool $(DESTDIR)/usr/bin/cloudstack-guest-tool
install -D agent/target/transformed/libvirtqemuhook $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/ install -D agent/target/transformed/libvirtqemuhook $(DESTDIR)/usr/share/$(PACKAGE)-agent/lib/
install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent install -D agent/target/transformed/* $(DESTDIR)/$(SYSCONFDIR)/$(PACKAGE)/agent

View File

@ -319,6 +319,7 @@ install -D agent/target/transformed/environment.properties ${RPM_BUILD_ROOT}%{_s
install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml
install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent
install -D agent/target/transformed/cloudstack-agent-upgrade ${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade install -D agent/target/transformed/cloudstack-agent-upgrade ${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade
install -D agent/target/transformed/cloud-guest-tool ${RPM_BUILD_ROOT}%{_bindir}/%{name}-guest-tool
install -D agent/target/transformed/libvirtqemuhook ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook install -D agent/target/transformed/libvirtqemuhook ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook
install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh
install -D agent/target/transformed/cloudstack-agent-profile.sh ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh install -D agent/target/transformed/cloudstack-agent-profile.sh ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh
@ -562,6 +563,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
%files agent %files agent
%attr(0755,root,root) %{_bindir}/%{name}-setup-agent %attr(0755,root,root) %{_bindir}/%{name}-setup-agent
%attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade %attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade
%attr(0755,root,root) %{_bindir}/%{name}-guest-tool
%attr(0755,root,root) %{_bindir}/%{name}-ssh %attr(0755,root,root) %{_bindir}/%{name}-ssh
%attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-agent %attr(0755,root,root) %{_sysconfdir}/init.d/%{name}-agent
%attr(0644,root,root) %{_sysconfdir}/profile.d/%{name}-agent-profile.sh %attr(0644,root,root) %{_sysconfdir}/profile.d/%{name}-agent-profile.sh

View File

@ -294,6 +294,7 @@ install -D agent/target/transformed/environment.properties ${RPM_BUILD_ROOT}%{_s
install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml install -D agent/target/transformed/log4j-cloud.xml ${RPM_BUILD_ROOT}%{_sysconfdir}/%{name}/agent/log4j-cloud.xml
install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent install -D agent/target/transformed/cloud-setup-agent ${RPM_BUILD_ROOT}%{_bindir}/%{name}-setup-agent
install -D agent/target/transformed/cloudstack-agent-upgrade ${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade install -D agent/target/transformed/cloudstack-agent-upgrade ${RPM_BUILD_ROOT}%{_bindir}/%{name}-agent-upgrade
install -D agent/target/transformed/cloud-guest-tool ${RPM_BUILD_ROOT}%{_bindir}/%{name}-guest-tool
install -D agent/target/transformed/libvirtqemuhook ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook install -D agent/target/transformed/libvirtqemuhook ${RPM_BUILD_ROOT}%{_datadir}/%{name}-agent/lib/libvirtqemuhook
install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh install -D agent/target/transformed/cloud-ssh ${RPM_BUILD_ROOT}%{_bindir}/%{name}-ssh
install -D agent/target/transformed/cloudstack-agent-profile.sh ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh install -D agent/target/transformed/cloudstack-agent-profile.sh ${RPM_BUILD_ROOT}%{_sysconfdir}/profile.d/%{name}-agent-profile.sh
@ -510,6 +511,7 @@ pip install --upgrade /usr/share/cloudstack-marvin/Marvin-*.tar.gz
%files agent %files agent
%attr(0755,root,root) %{_bindir}/%{name}-setup-agent %attr(0755,root,root) %{_bindir}/%{name}-setup-agent
%attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade %attr(0755,root,root) %{_bindir}/%{name}-agent-upgrade
%attr(0755,root,root) %{_bindir}/%{name}-guest-tool
%attr(0755,root,root) %{_bindir}/%{name}-ssh %attr(0755,root,root) %{_bindir}/%{name}-ssh
%attr(0644,root,root) %{_unitdir}/%{name}-agent.service %attr(0644,root,root) %{_unitdir}/%{name}-agent.service
%config(noreplace) %{_sysconfdir}/default/%{name}-agent %config(noreplace) %{_sysconfdir}/default/%{name}-agent