From 211b180d55591098d68666003d29d04866e5e11a Mon Sep 17 00:00:00 2001 From: Rene Diepstraten Date: Thu, 25 Jul 2013 15:45:27 +0200 Subject: [PATCH] Replaced virsh() by python-libvirt functions Signed-off-by: Rene Diepstraten --- debian/control | 2 +- packaging/centos63/cloud.spec | 1 + scripts/vm/network/security_group.py | 133 ++++++++++++++++++++------- 3 files changed, 101 insertions(+), 35 deletions(-) diff --git a/debian/control b/debian/control index 46dd50536b0..e6d1ef088f2 100644 --- a/debian/control +++ b/debian/control @@ -22,7 +22,7 @@ Description: CloudStack server library Package: cloudstack-agent Architecture: all -Depends: openjdk-6-jre | openjdk-7-jre, cloudstack-common (= ${source:Version}), lsb-base (>= 3.2), libcommons-daemon-java, libjna-java, openssh-client, libvirt0, sysvinit-utils, qemu-kvm, libvirt-bin, uuid-runtime, rsync, grep, iproute, perl-base, perl-modules, ebtables, vlan, wget, jsvc, ipset +Depends: openjdk-6-jre | openjdk-7-jre, cloudstack-common (= ${source:Version}), lsb-base (>= 3.2), libcommons-daemon-java, libjna-java, openssh-client, libvirt0, sysvinit-utils, qemu-kvm, libvirt-bin, uuid-runtime, rsync, grep, iproute, perl-base, perl-modules, ebtables, vlan, wget, jsvc, ipset, python-libvirt Conflicts: cloud-agent, cloud-agent-libs, cloud-agent-deps, cloud-agent-scripts Description: CloudStack agent The CloudStack agent is in charge of managing shared computing resources in diff --git a/packaging/centos63/cloud.spec b/packaging/centos63/cloud.spec index 61e00bd75d3..588b16ff733 100644 --- a/packaging/centos63/cloud.spec +++ b/packaging/centos63/cloud.spec @@ -122,6 +122,7 @@ Requires: jsvc Requires: jakarta-commons-daemon Requires: jakarta-commons-daemon-jsvc Requires: perl +Requires: libvirt-python Provides: cloud-agent Obsoletes: cloud-agent < 4.1.0 Obsoletes: cloud-agent-libs < 4.1.0 diff --git a/scripts/vm/network/security_group.py b/scripts/vm/network/security_group.py index 2ce558fa5f7..a23617ee43b 100755 --- a/scripts/vm/network/security_group.py +++ b/scripts/vm/network/security_group.py @@ -26,11 +26,11 @@ import xml.dom.minidom from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError import re import traceback +import libvirt logpath = "/var/run/cloud/" # FIXME: Logs should reside in /var/log/cloud iptables = Command("iptables") bash = Command("/bin/bash") -virsh = Command("virsh") ebtablessave = Command("ebtables-save") ebtables = Command("ebtables") def execute(cmd): @@ -83,6 +83,78 @@ def ipset(ipsetname, proto, start, end, ips): return result ''' +def virshlist(*states): + + libvirt_states={ 'running' : libvirt.VIR_DOMAIN_RUNNING, + 'shutoff' : libvirt.VIR_DOMAIN_SHUTOFF, + 'shutdown' : libvirt.VIR_DOMAIN_SHUTDOWN, + 'paused' : libvirt.VIR_DOMAIN_PAUSED, + 'nostate' : libvirt.VIR_DOMAIN_NOSTATE, + 'blocked' : libvirt.VIR_DOMAIN_BLOCKED, + 'crashed' : libvirt.VIR_DOMAIN_CRASHED, + } + + searchstates = list(libvirt_states[state] for state in states) + + conn = libvirt.openReadOnly('qemu:///system') + if conn == None: + print 'Failed to open connection to the hypervisor' + sys.exit(3) + + alldomains = map(conn.lookupByID, conn.listDomainsID()) + alldomains += map(conn.lookupByName, conn.listDefinedDomains()) + + domains = [] + for domain in alldomains: + if domain.info()[0] in searchstates: + domains.append(domain.name()) + + conn.close() + + return domains + +def virshdomstate(domain): + + libvirt_states={ libvirt.VIR_DOMAIN_RUNNING : 'running', + libvirt.VIR_DOMAIN_SHUTOFF : 'shut off', + libvirt.VIR_DOMAIN_SHUTDOWN : 'shut down', + libvirt.VIR_DOMAIN_PAUSED : 'paused', + libvirt.VIR_DOMAIN_NOSTATE : 'no state', + libvirt.VIR_DOMAIN_BLOCKED : 'blocked', + libvirt.VIR_DOMAIN_CRASHED : 'crashed', + } + + conn = libvirt.openReadOnly('qemu:///system') + if conn == None: + print 'Failed to open connection to the hypervisor' + sys.exit(3) + + try: + dom = (conn.lookupByName (domain)) + except libvirt.libvirtError: + return None + + state = libvirt_states[dom.info()[0]] + conn.close() + + return state + +def virshdumpxml(domain): + + conn = libvirt.openReadOnly('qemu:///system') + if conn == None: + print 'Failed to open connection to the hypervisor' + sys.exit(3) + + try: + dom = (conn.lookupByName (domain)) + except libvirt.libvirtError: + return None + + xml = dom.XMLDesc(0) + conn.close() + + return xml def destroy_network_rules_for_vm(vm_name, vif=None): vmchain = vm_name @@ -509,13 +581,9 @@ def get_rule_log_for_vm(vmName): return ','.join([_vmName, _vmID, _vmIP, _domID, _signature, _seqno]) def check_domid_changed(vmName): - curr_domid = '-1' - try: - curr_domid = getvmId(vmName) - if (curr_domid is None) or (not curr_domid.isdigit()): - curr_domid = '-1' - except: - pass + curr_domid = getvmId(vmName) + if (curr_domid is None) or (not curr_domid.isdigit()): + curr_domid = '-1' vm_name = vmName; logfilename = logpath + vm_name + ".log" @@ -592,8 +660,7 @@ def network_rules_for_rebooted_vm(vmName): return True def get_rule_logs_for_vms(): - cmd = "virsh list|awk '/running/ {print $2}'" - vms = bash("-c", cmd).stdout.split("\n") + vms = virshlist('running') result = [] try: @@ -623,11 +690,7 @@ def cleanup_rules(): if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]: vm_name = chain - cmd = "virsh list |awk '/" + vm_name + "/ {print $3}'" - try: - result = execute(cmd).strip() - except: - result = None + result = virshdomstate(vm_name) if result == None or len(result) == 0: logging.debug("chain " + chain + " does not correspond to a vm, cleaning up iptable rules") @@ -643,11 +706,7 @@ def cleanup_rules(): if 1 in [ chain.startswith(c) for c in ['r-', 'i-', 's-', 'v-'] ]: vm_name = chain - cmd = "virsh list |awk '/" + vm_name + "/ {print $3}'" - try: - result = execute(cmd).strip() - except: - result = None + result = virshdomstate(vm_name) if result == None or len(result) == 0: logging.debug("chain " + chain + " does not correspond to a vm, cleaning up ebtable rules") @@ -727,9 +786,6 @@ def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif vmName = vm_name domId = getvmId(vmName) - - - changes = [] changes = check_rule_log_for_vm(vmName, vm_id, vm_ip, domId, signature, seqno) @@ -827,9 +883,8 @@ def add_network_rules(vm_name, vm_id, vm_ip, signature, seqno, vmMac, rules, vif def getVifs(vmName): vifs = [] - try: - xmlfile = virsh("dumpxml", vmName).stdout - except: + xmlfile = virshdumpxml(vmName) + if xmlfile == None: return vifs dom = xml.dom.minidom.parseString(xmlfile) @@ -841,9 +896,8 @@ def getVifs(vmName): def getVifsForBridge(vmName, brname): vifs = [] - try: - xmlfile = virsh("dumpxml", vmName).stdout - except: + xmlfile = virshdumpxml(vmName) + if xmlfile == None: return vifs dom = xml.dom.minidom.parseString(xmlfile) @@ -858,9 +912,8 @@ def getVifsForBridge(vmName, brname): def getBridges(vmName): bridges = [] - try: - xmlfile = virsh("dumpxml", vmName).stdout - except: + xmlfile = virshdumpxml(vmName) + if xmlfile == None: return bridges dom = xml.dom.minidom.parseString(xmlfile) @@ -871,8 +924,20 @@ def getBridges(vmName): return list(set(bridges)) def getvmId(vmName): - cmd = "virsh list |awk '/" + vmName + "/ {print $1}'" - return bash("-c", cmd).stdout.strip() + + conn = libvirt.openReadOnly('qemu:///system') + if conn == None: + print 'Failed to open connection to the hypervisor' + sys.exit(3) + + try: + dom = (conn.lookupByName (domain)) + except libvirt.libvirtError: + return None + + conn.close() + + return dom.ID() def addFWFramework(brname): try: