X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=test%2Fcsit%2Flibraries%2FXmlComparator.py;fp=test%2Fcsit%2Flibraries%2FXmlComparator.py;h=0000000000000000000000000000000000000000;hb=59e81c38620fa1b61e15771191e35771450b9499;hp=7bd8fff2fdf01835b5dd07721e1f7ca85e88371f;hpb=072f6e3a8d1bdf8f4c663843589c22d93ba07791;p=integration%2Ftest.git diff --git a/test/csit/libraries/XmlComparator.py b/test/csit/libraries/XmlComparator.py deleted file mode 100644 index 7bd8fff2fd..0000000000 --- a/test/csit/libraries/XmlComparator.py +++ /dev/null @@ -1,370 +0,0 @@ -''' -Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. - -This program and the accompanying materials are made available under the -terms of the Eclipse Public License v1.0 which accompanies this distribution, -and is available at http://www.eclipse.org/legal/epl-v10.html - -Created on May 21, 2014 - -@author: Vaclav Demcak -''' -from xml.dom.minidom import Element -import ipaddr -import xml.dom.minidom as md -import copy - -KEY_NOT_FOUND = '' # KeyNotFound for dictDiff - - -class XMLtoDictParserTools(): - - @staticmethod - def parseTreeToDict(node, returnedDict=None, ignoreList=[]): - """ - Return Dictionary representation of the xml Tree DOM Element. - Repeated tags are put to the array sorted by key (id or order) - otherwise is the value represented by tag key name. - @param node: DOM Element - @param returnedDict : dictionary (default value None) - @param ignereList : list of ignored tags for the xml Tree DOM Element - (default value is empty list) - @return: dict representation for the input DOM Element - """ - returnedDict = {} if returnedDict is None else returnedDict - if (node.nodeType == Element.ELEMENT_NODE): - nodeKey = (node.localName).encode('utf-8', 'ignore') - if nodeKey not in ignoreList: - if node.childNodes is not None: - childDict = {} - for child in node.childNodes: - if child.nodeType == Element.TEXT_NODE: - nodeValue = (child.nodeValue).encode('utf-8', 'ignore') - if (len(nodeValue.strip(' \t\n\r'))) > 0: - XMLtoDictParserTools.addDictValue(returnedDict, nodeKey, nodeValue) - nodeKey = None - break - elif child.nodeType == Element.ELEMENT_NODE: - childDict = XMLtoDictParserTools.parseTreeToDict(child, childDict, ignoreList) - - XMLtoDictParserTools.addDictValue(returnedDict, nodeKey, childDict) - - return returnedDict - - @staticmethod - def addDictValue(m_dict, key, value): - - def _allign_address(value): - """unifies output""" - n = ipaddr.IPNetwork(value) - return '{0}/{1}'.format(n.network.exploded, n.prefixlen) - - def _convert_numbers(value): - if value.startswith("0x"): - return str(long(value, 16)) - return str(long(value)) - - if key is not None: - if (isinstance(value, str)): - # we need to predict possible differences - # for same value in upper or lower case - value = value.lower() - if key not in m_dict: - # lets add mask for ips withot mask - if key in ['ipv4-destination', 'ipv4-source', 'ipv6-destination', 'ipv6-source', 'ipv6-nd-target']: - nvalue = _allign_address(value) - m_dict[key] = nvalue - elif key in ['tunnel-mask', 'type', 'metadata-mask', 'out_port', 'out_group']: - nvalue = _convert_numbers(value) - m_dict[key] = nvalue - else: - m_dict[key] = value - else: - exist_value = m_dict.get(key) - if (type(exist_value) is dict): - list_values = [exist_value, value] - key_for_sort = XMLtoDictParserTools.searchKey(exist_value) - if key_for_sort is not None: - list_values = sorted(list_values, key=lambda k: k[key_for_sort]) - m_dict[key] = list_values - elif (isinstance(exist_value, list)): - exist_value.append(value) - list_values = exist_value - key_for_sort = XMLtoDictParserTools.searchKey(value) - if key_for_sort is not None: - list_values = sorted(list_values, key=lambda k: k[key_for_sort]) - m_dict[key] = list_values - else: - m_dict[key] += value - - @staticmethod - def searchKey(dictionary): - """ - Return an order key for the array ordering. OF_13 - allows only two possible kind of the order keys - 'order' or '*-id' - @param dictionary: dictionary with data - @return: the array order key - """ - subKeyStr = ['-id', 'order'] - for substr in subKeyStr: - for key in dictionary: - if key == substr: - return key - elif key.endswith(substr): - return key - return None - - @staticmethod - def getDifferenceDict(original_dict, responded_dict): - """ - Return a dict of keys that differ with another config object. If a value is - not found in one fo the configs, it will be represented by KEY_NOT_FOUND. - @param original_dict: Fist dictionary to diff. - @param responded_dict: Second dictionary to diff. - @return diff: Dict of Key => (original_dict.val, responded_dict.val) - Dict of Key => (original_key, KEY_NOT_FOUND) - Dict of Key => (KEY_NOT_FOUNE, original_key) - """ - diff = {} - # Check all keys in original_dict dict - for key in original_dict.keys(): - if key not in responded_dict: - # missing key in responded dict - diff[key] = (key, KEY_NOT_FOUND) - # check values of the dictionaries - elif (original_dict[key] != responded_dict[key]): - # values are not the same # - - orig_dict_val = original_dict[key] - resp_dict_val = responded_dict[key] - - # check value is instance of dictionary - if isinstance(orig_dict_val, dict) and isinstance(resp_dict_val, dict): - sub_dif = XMLtoDictParserTools.getDifferenceDict(orig_dict_val, resp_dict_val) - if sub_dif: - diff[key] = sub_dif - - # check value is instance of list - # TODO - > change a basic comparator to compare by id or order - elif isinstance(orig_dict_val, list) and isinstance(resp_dict_val, list): - sub_list_diff = {} - # the list lengths - orig_i, resp_i = len(orig_dict_val), len(resp_dict_val) - # define a max iteration length (less from both) - min_index = orig_i if orig_i < resp_i else resp_i - for index in range(0, min_index, 1): - if (orig_dict_val[index] != resp_dict_val[index]): - sub_list_diff[index] = (orig_dict_val[index], resp_dict_val[index]) - if (orig_i > min_index): - # original is longer as responded dict - for index in range(min_index, orig_i, 1): - sub_list_diff[index] = (orig_dict_val[index], None) - elif (resp_i > min_index): - # responded dict is longer as original - for index in range(min_index, resp_i, 1): - sub_list_diff[index] = (None, resp_dict_val[index]) - if sub_list_diff: - diff[key] = sub_list_diff - - else: - diff[key] = (original_dict[key], responded_dict[key]) - - # Check all keys in responded_dict dict to find missing - for key in responded_dict.keys(): - if key not in original_dict: - diff[key] = (KEY_NOT_FOUND, key) - return diff - -IGNORED_TAGS_FOR_OPERATIONAL_COMPARISON = ['id', 'flow-name', 'barrier', 'cookie_mask', 'installHw', 'flags', - 'strict', 'byte-count', 'duration', 'packet-count', 'in-port', - 'vlan-id-present', 'out_group', 'out_port', 'hard-timeout', 'idle-timeout', - 'flow-statistics', 'cookie', 'clear-actions'] # noqa - -IGNORED_PATHS_FOR_OC = [(['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'controller-action'], True), # noqa - (['flow', 'instructions', 'instruction', 'clear-actions', 'action'], False), - (['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'push-vlan-action', 'vlan-id'], False), # noqa - (['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'drop-action'], True), - (['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'flood-action'], True), - ] - -TAGS_TO_ADD_FOR_OC = [(['flow', 'instructions', 'instruction', 'apply-actions', 'action', 'output-action'], 'max-length', '0'), # noqa - ] - - -TAGS_TO_MODIFY_FOR_OC = [(['flow', 'match', 'metadata'], 'metadata', 'metadata-mask'), - (['flow', 'match', 'tunnel'], 'tunnel-id', 'tunnel-mask'), - ] - - -class XmlComparator: - - def is_flow_configured(self, requested_flow, configured_flows): - - orig_tree = md.parseString(requested_flow) - xml_resp_stream = configured_flows.encode('utf-8', 'ignore') - xml_resp_tree = md.parseString(xml_resp_stream) - nodeListOperFlows = xml_resp_tree.getElementsByTagNameNS("*", 'flow') - origDict = XMLtoDictParserTools.parseTreeToDict(orig_tree._get_documentElement()) - - reportDict = {} - index = 0 - for node in nodeListOperFlows: - nodeDict = XMLtoDictParserTools.parseTreeToDict(node) - XMLtoDictParserTools.addDictValue(reportDict, index, nodeDict) - index += 1 - # print nodeDict - # print origDict - if nodeDict == origDict: - return True, '' - if nodeDict['flow']['priority'] == origDict['flow']['priority']: - return False, 'Flow found with diferences {0}'.format( - XMLtoDictParserTools.getDifferenceDict(nodeDict, origDict)) - return False, '' - - def is_flow_operational2(self, requested_flow, oper_resp): - def _rem_unimplemented_tags(tagpath, recurs, tdict): - # print "_rem_unimplemented_tags", tagpath, tdict - if len(tagpath) > 1 and tagpath[0] in tdict: - _rem_unimplemented_tags(tagpath[1:], recurs, tdict[tagpath[0]]) - - # when not to delete anything - if len(tagpath) == 1 and tagpath[0] not in tdict: - return - if len(tagpath) == 0: - return - - # when to delete - if len(tagpath) == 1 and tagpath[0] in tdict: - del tdict[tagpath[0]] - if len(tagpath) > 1 and recurs is True and tagpath[0] in tdict and tdict[tagpath[0]] == {}: - del tdict[tagpath[0]] - if tdict.keys() == ['order']: - del tdict['order'] - # print "leaving", tdict - - def _add_tags(tagpath, newtag, value, tdict): - '''if whole tagpath exists and the tag is not present, it is added with given value''' - # print "_add_tags", tagpath, newtag, value, tdict - if len(tagpath) > 0 and tagpath[0] in tdict: - _add_tags(tagpath[1:], newtag, value, tdict[tagpath[0]]) - elif len(tagpath) == 0 and newtag not in tdict: - tdict[newtag] = value - - def _to_be_modified_tags(tagpath, tag, related_tag, tdict): - '''if whole tagpath exists and the tag is not present, it is added with given value''' - # print "_to_be_modified_tags", tagpath, tag, related_tag, tdict - if len(tagpath) > 0 and tagpath[0] in tdict: - _to_be_modified_tags(tagpath[1:], tag, related_tag, tdict[tagpath[0]]) - elif len(tagpath) == 0 and tag in tdict and related_tag in tdict: - tdict[tag] = str(long(tdict[tag]) & long(tdict[related_tag])) - - orig_tree = md.parseString(requested_flow) - xml_resp_stream = oper_resp.encode('utf-8', 'ignore') - xml_resp_tree = md.parseString(xml_resp_stream) - nodeListOperFlows = xml_resp_tree.getElementsByTagNameNS("*", 'flow') - origDict = XMLtoDictParserTools.parseTreeToDict( - orig_tree._get_documentElement(), - ignoreList=IGNORED_TAGS_FOR_OPERATIONAL_COMPARISON) - - # origDict['flow-statistics'] = origDict.pop( 'flow' ) - reportDict = {} - index = 0 - for node in nodeListOperFlows: - nodeDict = XMLtoDictParserTools.parseTreeToDict( - node, - ignoreList=IGNORED_TAGS_FOR_OPERATIONAL_COMPARISON) - XMLtoDictParserTools.addDictValue(reportDict, index, nodeDict) - index += 1 - # print nodeDict - # print origDict - # print reportDict - if nodeDict == origDict: - return True, '' - if nodeDict['flow']['priority'] == origDict['flow']['priority']: - for p in IGNORED_PATHS_FOR_OC: - td = copy.copy(origDict) - _rem_unimplemented_tags(p[0], p[1], td) - for (p, t, v) in TAGS_TO_ADD_FOR_OC: - _add_tags(p, t, v, td) - for (p, t, rt) in TAGS_TO_MODIFY_FOR_OC: - _to_be_modified_tags(p, t, rt, td) - - # print "comparing1", nodeDict - # print "comparing2", td - if nodeDict == td: - return True, '' - if nodeDict == origDict: - return True, '' - return False, 'Flow found with diferences {0}'.format( - XMLtoDictParserTools.getDifferenceDict(nodeDict, origDict)) - return False, '' - - def get_data_for_flow_put_update(self, xml): - # action only for yet - xml_dom_input = md.parseString(xml) - actionList = xml_dom_input.getElementsByTagName('action') - if actionList is not None and len(actionList) > 0: - action = actionList[0] - for child in action.childNodes: - if child.nodeType == Element.ELEMENT_NODE: - nodeKey = (child.localName).encode('utf-8', 'ignore') - if nodeKey != 'order': - if nodeKey != 'drop-action': - new_act = child.ownerDocument.createElement('drop-action') - else: - new_act = child.ownerDocument.createElement('output-action') - onc = child.ownerDocument.createElement('output-node-connector') - onc_content = child.ownerDocument.createTextNode('TABLE') - onc.appendChild(onc_content) - new_act.appendChild(onc) - ml = child.ownerDocument.createElement('max-length') - ml_content = child.ownerDocument.createTextNode('60') - ml.appendChild(ml_content) - new_act.appendChild(ml) - child.parentNode.replaceChild(new_act, child) - return xml_dom_input.toxml(encoding='utf-8') - - def get_flow_content(self, tid=1, fid=1, priority=1): - """Returns an xml flow content identified by given details. - - Args: - :param tid: table id - :param fid: flow id - :param priority: flow priority - """ - - flow_template = ''' - - false - - - 0 - - - 0 - - - - - - %s - %s - 4294967295 - false - - - - 2048 - - - 10.0.0.1/32 - - %s - %s - %s - false -''' - - flow_data = flow_template % (tid, fid, fid, 'TestFlow-{0}'.format(fid), priority) - return flow_data