The patch covers all nwfilter api provided by libvirt.py. It includes define/undefine/list nwfilters and check them via checking ebtables rule. The following new files are added. cases/nwfilter.conf repos/nwfilter/__init__.py repos/nwfilter/nwfilter_check.py * Check the nwfilter via checking ebtales repos/nwfilter/nwfilter_define.py * Define the nwfilter using specified value repos/nwfilter/nwfilter_list.py * List all of the available network filters repos/nwfilter/nwfilter_undefine.py * Undefine the specified nwfilter repos/nwfilter/xmls/nwfilter.xml --- cases/nwfilter.conf | 59 +++++++++++++++++ repos/nwfilter/nwfilter_check.py | 120 +++++++++++++++++++++++++++++++++++ repos/nwfilter/nwfilter_define.py | 54 ++++++++++++++++ repos/nwfilter/nwfilter_list.py | 76 ++++++++++++++++++++++ repos/nwfilter/nwfilter_undefine.py | 43 +++++++++++++ repos/nwfilter/xmls/nwfilter.xml | 3 + 6 files changed, 355 insertions(+), 0 deletions(-) create mode 100644 cases/nwfilter.conf create mode 100644 repos/nwfilter/__init__.py create mode 100644 repos/nwfilter/nwfilter_check.py create mode 100644 repos/nwfilter/nwfilter_define.py create mode 100644 repos/nwfilter/nwfilter_list.py create mode 100644 repos/nwfilter/nwfilter_undefine.py create mode 100644 repos/nwfilter/xmls/nwfilter.xml
diff --git a/cases/nwfilter.conf b/cases/nwfilter.conf new file mode 100644 index 0000000..b394ee5 --- /dev/null +++ b/cases/nwfilter.conf @@ -0,0 +1,59 @@ +domain:install_linux_cdrom + guestname + $defaultname + guestos + $defaultos + guestarch + $defaultarch + vcpu + $defaultvcpu + memory + $defaultmem + hddriver + $defaulthd + nicdriver + $defaultnic + imageformat + qcow2 + macaddr + 54:52:00:4a:16:30 + +nwfilter:nwfilter_list + +# chain -- ipv4, ipv6, arp .etc +# action -- mandatory; drop, accept, return +# direction -- mandatory; must either be in, out or inout +nwfilter:nwfilter_define + nwfiltername + disallow-arp + chain + arp + action + drop + direction + inout + +nwfilter:nwfilter_list + +nwfilter:nwfilter_check + nwfiltername + disallow-arp + guestname + $defaultname + +nwfilter:nwfilter_define + nwfiltername + disallow-ipv6 + chain + ipv6 + action + drop + direction + in + +nwfilter:nwfilter_undefine + nwfiltername + disallow-ipv6 + +nwfilter:nwfilter_list + diff --git a/repos/nwfilter/__init__.py b/repos/nwfilter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/repos/nwfilter/nwfilter_check.py b/repos/nwfilter/nwfilter_check.py new file mode 100644 index 0000000..b2c7ece --- /dev/null +++ b/repos/nwfilter/nwfilter_check.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +import time +import xml.dom.minidom + +from libvirt import libvirtError +from utils import utils +from xml.dom import minidom + +from src import sharedmod + +required_params = ('nwfiltername','guestname',) +optional_params = {} + +EBTABLES = "ebtables -t nat -L" + +def get_ebtables(): + """ Get the output of ebtables """ + (status, output) = utils.exec_cmd(EBTABLES,shell=True) + logger.info("Execute command:" + EBTABLES) + ebtables_list = [] + + if status: + logger.error("Executing " + EBTABLES + " failed") + logger.error(output) + return False + else: + for i in range(len(output)): + ebtables_list.append(output[i]) + logger.info("Get the output of ebtables list: %s" \ + % ebtables_list) + + return ebtables_list + +def check_ebtables(*args): + """ Check the ebtables """ + (nwfiltername,conn)= args + ebtables_list = get_ebtables() + + #Get the filter' attribute value + nwfilter_xml = conn.nwfilterLookupByName(nwfiltername).XMLDesc(0) + nwfilter_parsedxml = minidom.parseString(nwfilter_xml) + chain = nwfilter_parsedxml.getElementsByTagName("filter")[0].\ + getAttribute("chain") + rule = nwfilter_parsedxml.getElementsByTagName("rule")[0] + action = rule.getAttribute("action").upper() + direction = rule.getAttribute("direction") + logger.info("The nwfilter chain:%s ,action:%s ,direction:%s " %\ + (chain,action,direction) ) + in_vnet_chain = "I-vnet0-" + chain + out_vnet_chain = "O-vnet0-" + chain + + if cmp(direction,"inout") == 0 : + if len(ebtables_list) == 21 and in_vnet_chain in ebtables_list[-5]\ + and out_vnet_chain in ebtables_list[-2] \ + and action in ebtables_list[-1] \ + and action in ebtables_list[-4]: + return True + else: + return False + elif cmp(direction,"in") == 0: + if len(ebtables_list) == 14 and out_vnet_chain in ebtables_list[-2]\ + and action in ebtables_list[-1]: + return True + else: + return False + + elif cmp(direction,"out") == 0: + if len(ebtables_list) == 14 and in_vnet_chain in ebtables_list[-2] \ + and action in ebtables_list[-1]: + return True + else: + return False + +def nwfilter_check(params): + """Check the nwfilter via checking ebtales""" + global logger + logger = params['logger'] + nwfiltername = params['nwfiltername'] + guestname = params['guestname'] + domain_nwfilter_xml = "" + + conn = sharedmod.libvirtobj['conn'] + domobj = conn.lookupByName(guestname) + + try: + + #Create the nwfilter's element and append it to domain xml + domxml = domobj.XMLDesc(0) + domain_parsedxml = minidom.parseString(domxml) + domain_ifxml = domain_parsedxml.getElementsByTagName("interface") + filterxml = domain_parsedxml.createElement("filterref") + filterxml.setAttribute("filter", nwfiltername) + domain_ifxml[0].appendChild(filterxml) + + #Destroy the domain and redefine it with nwfilter + domobj.destroy() + time.sleep(5) + domobj.undefine() + + #Define the new domain with the nwfilter + dom_nwfilter = conn.defineXML(domain_parsedxml.toxml()) + logger.debug("The xml of new defined domain with nwfilter %s" % \ + dom_nwfilter.XMLDesc(0)) + + #Start the new defined domain + dom_nwfilter.create() + time.sleep(5) + + if check_ebtables(nwfiltername,conn): + logger.info("Successfully create nwfilter") + return 0 + else: + logger.error("Failed to create nwfilter") + return 1 + + except libvirtError, e: + logger.error("API error message: %s" % e.message) + return 1 + + return 0 \ No newline at end of file diff --git a/repos/nwfilter/nwfilter_define.py b/repos/nwfilter/nwfilter_define.py new file mode 100644 index 0000000..e20fd2d --- /dev/null +++ b/repos/nwfilter/nwfilter_define.py @@ -0,0 +1,54 @@ +#! /usr/bin/env python + + + +from libvirt import libvirtError +from src import sharedmod + + +required_params = ('nwfiltername','chain','action','direction') +optional_params = {'xml' : 'xmls/nwfilter.xml',} + +def nwfilter_define(params): + """ Define network filters.""" + logger = params['logger'] + conn = sharedmod.libvirtobj['conn'] + xmlstr = params['xml'] + nwfiltername = params['nwfiltername'] + chain = params['chain'] + action = params['action'] + direction = params['direction'] + + + xmlstr = xmlstr.replace('NWFILTERNAME', nwfiltername) + xmlstr = xmlstr.replace('CHAIN', chain) + xmlstr = xmlstr.replace('ACTION', action) + xmlstr = xmlstr.replace('DIRECTION', direction) + try: + logger.info("nwfiltername:%s chain:%s action:%s direction:%s" % \ + (nwfiltername,chain,action,direction)) + logger.info("The nwfilter's xml is %s" % xmlstr) + + #Define the nwfilter with given attribute value from nwfilter.conf""" + conn.nwfilterDefineXML(xmlstr) + nwfilterxml = conn.nwfilterLookupByName(nwfiltername).XMLDesc(0) + + if nwfiltername in conn.listNWFilters(): + logger.info("The nwfilter list includes the defined nwfilter") + if cmp(xmlstr,nwfilterxml): + logger.info("Successfully define the nwfilter %s" % \ + nwfiltername) + return 0 + else: + logger.error("Fail to define the nwfilter %s" % nwfiltername) + return 1 + else: + logger.error("Failed,nwfilter list doesn't include the defined \ + nwfilter") + return 1 + + except libvirtError, e: + logger.error("API error message: %s" % e.message) + return 1 + + return 0 \ No newline at end of file diff --git a/repos/nwfilter/nwfilter_list.py b/repos/nwfilter/nwfilter_list.py new file mode 100644 index 0000000..056ee1f --- /dev/null +++ b/repos/nwfilter/nwfilter_list.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +from libvirt import libvirtError +from utils import utils + +from src import sharedmod + +required_params = () +optional_params = {} + +NWFILTER_LIST_API_DIR = "ls /etc/libvirt/nwfilter" + +def get_nwfilterlist_dir(): + """ Get the nwfilter list from dir """ + + (status, output) = utils.exec_cmd(NWFILTER_LIST_API_DIR,shell=True) + logger.info("Execute command:" + NWFILTER_LIST_API_DIR) + nwfilter_list_api_dir = [] + if status: + logger.error("Executing " + NWFILTER_LIST_API_DIR + " failed") + logger.error(output) + return False + else: + for i in range(len(output)): + nwfilter_list_api_dir.append(output[i][:-4]) + logger.info("Get nwfilters name list under dir: %s" \ + % nwfilter_list_api_dir) + return nwfilter_list_api_dir + +def nwfilter_list(params): + """ List all of the available network filters.""" + global logger + logger = params['logger'] + conn = sharedmod.libvirtobj['conn'] + + try: + #Get the nwfilter name list from API """ + nwfilter_namelist_api = conn.listNWFilters() + + #Get the nwfilter object list + nwfilter_list_api = conn.listAllNWFilters(0) + logger.info("The connection URI %s" % \ + nwfilter_list_api[0].connect().getURI()) + + #Get the number of nwfilters from API + nwfilter_num = conn.numOfNWFilters() + + nwfilter_list_dir = get_nwfilterlist_dir() + if nwfilter_num == len(nwfilter_list_api) and \ + len(nwfilter_list_api) == len(nwfilter_list_dir) and \ + cmp(nwfilter_namelist_api,nwfilter_list_dir): + logger.info("The number of available network filters is %s" % \ + nwfilter_num) + else: + logger.error("Failed to get the nwfilters list") + return 1 + + for nwfilter_item in nwfilter_list_api: + if nwfilter_item.name()in nwfilter_list_dir and \ + nwfilter_item.name()in nwfilter_namelist_api: + logger.info("The name is %s" % nwfilter_item.name()) + else: + logger.error("Failed to get nwfilter's name.") + return 1 + if cmp(str(nwfilter_item.UUID()),nwfilter_item.UUIDString()): + logger.info("The UUID is %s" % nwfilter_item.UUIDString()) + else: + logger.error("Failed to get nwfilter's uuid.") + return 1 + + + except libvirtError, e: + logger.error("API error message: %s" % e.message) + return 1 + + return 0 \ No newline at end of file diff --git a/repos/nwfilter/nwfilter_undefine.py b/repos/nwfilter/nwfilter_undefine.py new file mode 100644 index 0000000..b9ea332 --- /dev/null +++ b/repos/nwfilter/nwfilter_undefine.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python + +from libvirt import libvirtError + +from src import sharedmod + +required_params = ('nwfiltername',) +optional_params = {} + +def nwfilter_undefine(params): + """Undefine the specified nwfilter""" + logger = params['logger'] + nwfiltername = params['nwfiltername'] + conn = sharedmod.libvirtobj['conn'] + + try: + nwfilter = conn.nwfilterLookupByName(nwfiltername) + uuidstr = nwfilter.UUIDString() + uuid = nwfilter.UUID() + # Lookup by nwfilter's uuid string + nwfilter_uuidstr = conn.nwfilterLookupByUUIDString(uuidstr) + # Lookup by nwfilter's uuid + nwfilter_uuid = conn.nwfilterLookupByUUID(uuid) + + # Check if the nwfilter lookup by name/uuid/uuidstr is the same one + if cmp(nwfilter,nwfilter_uuidstr) and cmp(nwfilter_uuidstr,\ + nwfilter_uuid): + # Undefine the nwfilter + nwfilter.undefine() + # Check if the nwfiler list includes the undefined nwfilter + if nwfiltername not in conn.listNWFilters(): + logger.info("Successfully undefine the nwfilter %s" % \ + nwfiltername) + return 0 + else: + logger.error("Failed to undefine the nwfilter %s" % nwfiltername) + return 1 + + except libvirtError, e: + logger.error("API error message: %s" % e.message) + return 1 + + return 0 diff --git a/repos/nwfilter/xmls/nwfilter.xml b/repos/nwfilter/xmls/nwfilter.xml new file mode 100644 index 0000000..6d52d5d --- /dev/null +++ b/repos/nwfilter/xmls/nwfilter.xml @@ -0,0 +1,3 @@ +<filter name='NWFILTERNAME' chain='CHAIN'> + <rule action='ACTION' direction='DIRECTION' priority='500'/> +</filter> -- 1.7.7.6 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list