From 82f1a7eb5535b30a95b1e71ff18c315d40d1e6f0 Mon Sep 17 00:00:00 2001 From: Stuart Mackie Date: Fri, 29 Jan 2016 16:00:57 -0800 Subject: OpenContrail test suite Change-Id: I61168093a2a05d47377ef47c8638ae1554b1a999 Signed-off-by: Stuart Mackie --- Testcases/cfgm_common/ifmap/__init__.py | 29 ++++ Testcases/cfgm_common/ifmap/__init__.pyc | Bin 0 -> 846 bytes Testcases/cfgm_common/ifmap/client.py | 263 +++++++++++++++++++++++++++++ Testcases/cfgm_common/ifmap/client.pyc | Bin 0 -> 8050 bytes Testcases/cfgm_common/ifmap/id.py | 191 +++++++++++++++++++++ Testcases/cfgm_common/ifmap/id.pyc | Bin 0 -> 8855 bytes Testcases/cfgm_common/ifmap/metadata.py | 36 ++++ Testcases/cfgm_common/ifmap/metadata.pyc | Bin 0 -> 1674 bytes Testcases/cfgm_common/ifmap/operations.py | 75 ++++++++ Testcases/cfgm_common/ifmap/operations.pyc | Bin 0 -> 5131 bytes Testcases/cfgm_common/ifmap/request.py | 106 ++++++++++++ Testcases/cfgm_common/ifmap/request.pyc | Bin 0 -> 7617 bytes Testcases/cfgm_common/ifmap/response.py | 55 ++++++ Testcases/cfgm_common/ifmap/response.pyc | Bin 0 -> 2465 bytes Testcases/cfgm_common/ifmap/util.py | 34 ++++ Testcases/cfgm_common/ifmap/util.pyc | Bin 0 -> 933 bytes 16 files changed, 789 insertions(+) create mode 100644 Testcases/cfgm_common/ifmap/__init__.py create mode 100644 Testcases/cfgm_common/ifmap/__init__.pyc create mode 100644 Testcases/cfgm_common/ifmap/client.py create mode 100644 Testcases/cfgm_common/ifmap/client.pyc create mode 100644 Testcases/cfgm_common/ifmap/id.py create mode 100644 Testcases/cfgm_common/ifmap/id.pyc create mode 100644 Testcases/cfgm_common/ifmap/metadata.py create mode 100644 Testcases/cfgm_common/ifmap/metadata.pyc create mode 100644 Testcases/cfgm_common/ifmap/operations.py create mode 100644 Testcases/cfgm_common/ifmap/operations.pyc create mode 100644 Testcases/cfgm_common/ifmap/request.py create mode 100644 Testcases/cfgm_common/ifmap/request.pyc create mode 100644 Testcases/cfgm_common/ifmap/response.py create mode 100644 Testcases/cfgm_common/ifmap/response.pyc create mode 100644 Testcases/cfgm_common/ifmap/util.py create mode 100644 Testcases/cfgm_common/ifmap/util.pyc (limited to 'Testcases/cfgm_common/ifmap') diff --git a/Testcases/cfgm_common/ifmap/__init__.py b/Testcases/cfgm_common/ifmap/__init__.py new file mode 100644 index 0000000..189d225 --- /dev/null +++ b/Testcases/cfgm_common/ifmap/__init__.py @@ -0,0 +1,29 @@ +#!/usr/bin/python +# +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE +# + +""" +ifmap-python client is an implementation of the TCG IF-MAP 2.0 protocol as a client library. +""" + +import sys + +# +# Project properties +# + +__version__ = '0.1' +__build__="" + +# +# Exceptions +# +class Error(Exception): + """ + Base class for exception handling + """ + def __init__(self, msg): + Exception.__init__(self, "Error: '%s'" % msg) diff --git a/Testcases/cfgm_common/ifmap/__init__.pyc b/Testcases/cfgm_common/ifmap/__init__.pyc new file mode 100644 index 0000000..263aa50 Binary files /dev/null and b/Testcases/cfgm_common/ifmap/__init__.pyc differ diff --git a/Testcases/cfgm_common/ifmap/client.py b/Testcases/cfgm_common/ifmap/client.py new file mode 100644 index 0000000..d4d4df8 --- /dev/null +++ b/Testcases/cfgm_common/ifmap/client.py @@ -0,0 +1,263 @@ +#!/usr/bin/python +# +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE +# + +from _ssl import PROTOCOL_SSLv3, PROTOCOL_SSLv23, PROTOCOL_TLSv1 +import gevent +import geventhttpclient +from geventhttpclient import HTTPClient + +import urllib + +import base64 +import cStringIO +import sys + + +from logging import getLogger + +log = getLogger(__name__) # when imported, the logger will be named "ifmap.client" + +# Import either httplib2 or urllib2 and map to same name +try: + import httplib2 as http_client_lib + Http = http_client_lib.Http + HttpException = http_client_lib.HttpLib2Error +except ImportError: + import urllib2 as http_client_lib + HttpException = (http_client_lib.URLError, http_client_lib.HTTPError) + class Http(): # wrapper to use when httplib2 not available + def request(self, url, method, body, headers): + f = http_client_lib.urlopen(http_client_lib.Request(url, body, headers)) + return f.info(), f.read() + +#import urllib2 as http_client_lib +#class Http(): # wrapper to use when httplib2 not available +# def request(self, url, method, body, headers): +# f = http_client_lib.urlopen(http_client_lib.Request(url, body, headers)) +# return f.info(), f.read() + +namespaces = { + 'env' : "http://www.w3.org/2003/05/soap-envelope", + 'ifmap' : "http://www.trustedcomputinggroup.org/2010/IFMAP/2", + 'meta' : "http://www.trustedcomputinggroup.org/2010/IFMAP-METADATA/2" +} + +# NOTE(sahid): It seems that the geventhttpclient uses gevent.queue.LifoQueue +# to maintain a pool of connections and according to the doc it is possible +# to configure the maxsize of the queue with None or a value less than 0 to +# set the number of connections ulimited otherwise It is actually not possible +# to set it to None or less than 0 since lock.BoundedSemaphore will return an +# exception. https://github.com/gwik/geventhttpclient/blob/master/src/geventhttpclient/connectionpool.py#L37 +concurrency = 1 # arbitrary value since it is not possible to use ulimited. + +class AsyncReadWrapper(object): + """ Perform the socket read in a separate greenlet """ + def __init__(self, request): + self._greenlet = gevent.spawn(self.AsyncRead, request) + self._content = None + + def AsyncRead(self, request): + self._content = request.read() + + def __str__(self, *args, **kwargs): + self._greenlet.join() + return self._content + + def __repr__(self, *args, **kwargs): + self._greenlet.join() + return self._content + +class client: + """ + IF-MAP client + """ + + __url = None + __session_id = None + __publisher_id = None + __last_sent = None + __last_received = None + __namespaces = None + __ssl_options = { + 'cert_reqs' : gevent.ssl.CERT_NONE, + 'ssl_version' : PROTOCOL_SSLv23, + } + if sys.version_info >= (2,7): + __ssl_options['ciphers'] = "RC4-SHA" + + __envelope =""" + + + %(body)s + + +""" + + def __init__(self, url, user=None, password=None, namespaces={}, ssl_opts=None): + if user and password: +# self.__password_mgr=http_client_lib.HTTPPasswordMgrWithDefaultRealm() +# self.__password_mgr.add_password(None, url, user, password) +# handler = http_client_lib.HTTPBasicAuthHandler(self.__password_mgr) +# opener = http_client_lib.build_opener(handler) +# http_client_lib.install_opener(opener) + + #pycurl.global_init(pycurl.GLOBAL_SSL) + + pass + + #if namespaces: + self.__namespaces = namespaces + if ssl_opts: + self.__ssl_options.update(ssl_opts) + + self.__url = url + self.__username = user + self.__password = password + try: + self._http = HTTPClient(*self.__url, ssl = True, + connection_timeout = None, + network_timeout = None, + ssl_options = self.__ssl_options, + insecure = True, + concurrency = concurrency) + except TypeError: + self._http = HTTPClient(*self.__url, ssl = True, + connection_timeout = None, + network_timeout = None, + ssl_options = self.__ssl_options, + concurrency = concurrency) + + + def last_sent(self): + return self.__last_sent + + def last_received(self): + return self.__last_received + + def envelope(self, body) : + _ns = "" + for ns_prefix, ns_uri in self.__namespaces.items(): + #if ns_prefix == "env": break # don't add the envelope namespace again + if ns_prefix == "env": continue # don't add the envelope namespace again + _ns += "xmlns:"+ns_prefix+'="'+ns_uri+'" ' + return str(self.__envelope % {'body':body, 'ns': _ns}) + + def call(self, method, body): + xml = self.envelope(body) + #headers={ + # 'Content-type': 'text/xml; charset="UTF-8"', + # 'Content-length': str(len(xml)), + # "SOAPAction": '"%s"' % (method), + #} + + base64string = base64.encodestring('%s:%s' % (self.__username, self.__password)).replace('\n', '') + # pycurl + #headers=[ + # 'Content-type: text/xml; charset="UTF-8"', + # 'Content-length: %s' %(str(len(xml))), + # 'Authorization : Basic %s' %(base64string), + # 'SOAPAction: %s' % (method), + #] + + # geventhttp + headers={ + 'Content-type': 'text/xml; charset="UTF-8"', + 'Content-length': '%s' %(str(len(xml))), + 'Authorization': 'Basic %s' %(base64string), + 'SOAPAction': '%s' % (method), + } + + try: + log.info("sending IF-MAP message to server") + log.debug("======== sending IF-MAP message ========") + log.debug("\n%s\n", xml) + log.debug("======== /sending IF-MAP message ========") + + #response, content = self.http.request(self.__url,"POST", body=xml, headers=headers ) + + #self.http = pycurl.Curl() + #self.http.setopt(pycurl.URL, self.__url) + #self.http.setopt(pycurl.HTTPHEADER, headers) + #self.http.setopt(pycurl.POSTFIELDS, xml) + #self.http.setopt(pycurl.VERBOSE, True) + #self.http.setopt(pycurl.SSL_VERIFYPEER, 0) + #self.http.setopt(pycurl.SSL_VERIFYHOST, 0) + #content = cStringIO.StringIO() + #self.http.setopt(pycurl.WRITEFUNCTION, + # content.write) + #self.http.perform() + + #self.http = HTTPClient(*self.__url, ssl = True, + # ssl_options = {'cert_reqs': gevent.ssl.CERT_NONE, + # 'ssl_version': PROTOCOL_SSLv3}) + #response = self.http.post('/', body = xml, headers = headers) + response = self._http.post('/', body = xml, headers = headers) + content = response.read() + + self.__last_sent = xml + + #self.__last_received = content + #pycurl self.__last_received = content.getvalue() + self.__last_received = content + + log.debug("======== received IF-MAP response ========") + #log.debug("\n%s\n", content) + #pycurl log.debug("\n%s\n", content.getvalue()) + log.debug("\n%s\n", content) + log.debug("======== /receive IF-MAP response ========") + + #return content + #pycurl return content.getvalue() + return content + + except HttpException, e: + log.error("HTTP Connection error in IF-MAP client: %s", e.reason) + except Exception as e: + log.error("Uknown error sending IF-MAP message to server %s", str(e)) + raise + + def call_async_result(self, method, body): + xml = self.envelope(body) + base64string = base64.encodestring('%s:%s' % (self.__username, self.__password)).replace('\n', '') + + # geventhttp + headers={ + 'Content-type': 'text/xml; charset="UTF-8"', + 'Content-length': '%s' %(str(len(xml))), + 'Authorization': 'Basic %s' %(base64string), + 'SOAPAction': '%s' % (method), + } + + try: + response = self._http.post('/', body = xml, headers = headers) + content = AsyncReadWrapper(response) + + return content + + except HttpException, e: + log.error("HTTP Connection error in IF-MAP client: %s", e.reason) + except: + log.error("Uknown error sending IF-MAP message to server") + raise + + def set_session_id(self, session_id): + self.__session_id = session_id + + def set_publisher_id(self, publisher_id): + self.__publisher_id = publisher_id + + def get_session_id(self): + return self.__session_id + + def get_publisher_id(self): + return self.__publisher_id + + +if __name__ == "__main__": + print """The ifmap client library is not meant to be run from the command line or python interpreter +- you should use it by including it in your python software. See testmap.py for an example. +Hint: add this line to use the library - 'from ifmap import ifmapClient' """ diff --git a/Testcases/cfgm_common/ifmap/client.pyc b/Testcases/cfgm_common/ifmap/client.pyc new file mode 100644 index 0000000..3670f20 Binary files /dev/null and b/Testcases/cfgm_common/ifmap/client.pyc differ diff --git a/Testcases/cfgm_common/ifmap/id.py b/Testcases/cfgm_common/ifmap/id.py new file mode 100644 index 0000000..7a71d51 --- /dev/null +++ b/Testcases/cfgm_common/ifmap/id.py @@ -0,0 +1,191 @@ +# +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE + +# Module with ID factories for creating IF-MAP Identifiers. +# Identifiers are used, for example, when publishing to an IF-MAP server, to represent an IP address. +# The XML for such the IP address identifier would be generated by ifmap.id.IPAddress +# example: +# >>> print ifmap.id.IPAdress('10.0.0.1') + +from util import attr + +class ifmapIDFactory: + pass + + +class IPAddress(ifmapIDFactory): + """ + XML Factory for an IP Address IF-MAP Identifier + """ + def __init__(self, ip_address, type=None, administrative_domain=None): + self.__ip_address = ip_address + self.__type = type + self.__administrative_domain = administrative_domain + + def administrative_domain(self): + return self.__administrative_domain + + def ip_address(self): + return self.__ip_address + + def type(self): + return self.__type + + def __str__(self): + _attr = attr({'value':self.__ip_address,'type':self.__type,'administrative-domain':self.__administrative_domain}) + return '' + +class MACAddress(ifmapIDFactory): + """ + XML Factory for a MAC Address IF-MAP Identifier + """ + + def __init__(self, mac_address, administrative_domain=None): + self.__mac_address = mac_address + self.__administrative_domain = administrative_domain + return None; + + def administrative_domain(self): + return self.__administrative_domain + + def mac_address(self): + return self.__mac_address + + def __str__(self): + _attr = attr({'value':self.__mac_address,'administrative-domain':self.__administrative_domain}) + return '' + + +class Device(ifmapIDFactory): + """ + XML Factory for a Device IF-MAP Identifier + """ + + def __init__(self, name, aik_name=None): + self.__name = name + self.__aik_name = aik_name + return None; + + def aik_name(self): + return self.__aik_name + + def name(self): + return self.__name + + def __str__(self): + self.__XML = "" + self.__XML += ''+self.__name+'' + # aik_name is optional + if self.__aik_name: + self.__XML += ''+self.__aik_name+'' + self.__XML += "" + return self.__XML + +class AccessRequest(ifmapIDFactory): + """ + XML Factory for an Access Request IF-MAP Identifier + """ + + def __init__(self, name, administrative_domain=None): + self.__name = name + self.__administrative_domain = administrative_domain + return None; + + def administrative_domain(self): + return self.__administrative_domain + + def name(self): + return self.__name + + def __str__(self): + self.__XML = "<' + self.__name + self.__ns_uri + __attr + '>' + self.__value + self.__elements + '' + diff --git a/Testcases/cfgm_common/ifmap/metadata.pyc b/Testcases/cfgm_common/ifmap/metadata.pyc new file mode 100644 index 0000000..7c4ec60 Binary files /dev/null and b/Testcases/cfgm_common/ifmap/metadata.pyc differ diff --git a/Testcases/cfgm_common/ifmap/operations.py b/Testcases/cfgm_common/ifmap/operations.py new file mode 100644 index 0000000..c4c2055 --- /dev/null +++ b/Testcases/cfgm_common/ifmap/operations.py @@ -0,0 +1,75 @@ +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE +# +from util import attr, link_ids + +class OperationBase: + """ foundation class for operation factory """ + pass + +class PublishUpdateOperation(OperationBase): + def __init__(self, id1, metadata, id2=None, lifetime=None): + self.__id = link_ids(id1, id2) + self.__metadata = metadata + self.__lifetime = lifetime + + def __str__(self): + if self.__lifetime: + _attr = attr({'lifetime':self.__lifetime}) + return '' % _attr + self.__id + self.__metadata + '' + else: + return '' + self.__id + self.__metadata + '' + +class PublishDeleteOperation(OperationBase): + def __init__(self, id1, id2=None, filter=None): + self.__id = link_ids(id1, id2) + self.__filter = filter + + def __str__(self): + if self.__filter: + _attr = attr({'filter':self.__filter}) + return '' % _attr + self.__id + '' + else: + return '' + self.__id + '' + +class PublishNotifyOperation(OperationBase): + def __init__(self, id1, metadata, id2=None): + self.__id = link_ids(id1, id2) + self.__metadata = metadata + + def __str__(self): + return '' + self.__id + self.__metadata + '' + +class SubscribeUpdateOperation(OperationBase): + """ + SubscribeUpdate factory + name + identifier (single, or linked with link_ids()) + search_parameters - dictionary eg. {'max_depth':'3', 'max_size':'10000'} + result_filter => string, #Optional. Rules for extracting specific data from the results + match_links => string, #Optional. Filter to match links to be followed, unmatched links will not be followed in the search process + max_depth => number, #Optional. Maximum distance of any included identifiers. Start depth is equal to 0 + max_size => number, #Optional. Maximum size in bytes of the results + terminal_identifier_type => string, #Optional. Terminal identifier type of the search request + """ + def __init__(self, name, identifier, search_parameters={}): + self.__name = name + self.__identifier = identifier + self.__parameters = search_parameters + + def __str__(self): + __attr = attr(self.__parameters) + return '' + self.__identifier +'' + +class SubscribeDeleteOperation(OperationBase): + def __init__(self, name): + self.__name = name + + def __str__(self): + return '' + + + + + \ No newline at end of file diff --git a/Testcases/cfgm_common/ifmap/operations.pyc b/Testcases/cfgm_common/ifmap/operations.pyc new file mode 100644 index 0000000..d07368a Binary files /dev/null and b/Testcases/cfgm_common/ifmap/operations.pyc differ diff --git a/Testcases/cfgm_common/ifmap/request.py b/Testcases/cfgm_common/ifmap/request.py new file mode 100644 index 0000000..47bc1f6 --- /dev/null +++ b/Testcases/cfgm_common/ifmap/request.py @@ -0,0 +1,106 @@ +#!/usr/bin/python +# +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE +# +from util import attr + +class RequestBase: + """ foundation class for request factory """ + pass + +class NewSessionRequest(RequestBase): + def __init__(self, max_poll_result=None): + self.__max_poll_result = max_poll_result + + def __str__(self): + #import pdb; pdb.set_trace() + return ''; + +class RenewSessionRequest(RequestBase): + def __init__(self, session_id): + self.__session_id = session_id + + def __str__(self): + return ''; + +class EndSessionRequest(RequestBase): + def __init__(self, session_id): + self.__session_id = session_id + + def __str__(self): + return ''; + +class PublishRequest(RequestBase): + __session_id = None + def __init__(self, session_id, operations, namespaces=None, validation=None): + self.__session_id = session_id + self.__namespaces = namespaces + self.__validation = validation + self.__operations = operations + + def __str__(self): + _attr = attr({'session-id': self.__session_id, 'validation' : self.__validation}) + return '' + self.__operations + '' + +class SearchRequest(RequestBase): + """ + Search request factory + session_id + identifier (single, or linked with link_ids()) + namespaces + validation "None"|"BaseOnly"|"MetadataOnly"|"All" + search_parameters - dictionary eg. {'max_depth':'3', 'max_size':'10000'} + result_filter => string, #Optional. Rules for extracting specific data from the results + match_links => string, #Optional. Filter to match links to be followed, unmatched links will not be followed in the search process + max_depth => number, #Optional. Maximum distance of any included identifiers. Start depth is equal to 0 + max_size => number, #Optional. Maximum size in bytes of the results + terminal_identifier_type => string, #Optional. Terminal identifier type of the search request + """ + def __init__(self, session_id, identifier, namespaces=None, validation=None, search_parameters={}): + self.__session_id = session_id + self.__identifier = identifier + self.__namespaces = namespaces + self.__validation = validation + self.__parameters = search_parameters + + def __str__(self): + _params = attr(self.__parameters) + _attr = attr({'session-id': self.__session_id, 'validation' : self.__validation}) + return '' + self.__identifier + '' + +class SubscribeRequest(RequestBase): + """ + Subscribe request factory + """ + + def __init__(self, session_id, validation=None, namespaces=None, operations=None): + self.__session_id = session_id + self.__namespaces = namespaces + self.__validation = validation + self.__operations = operations + + def __str__(self): + _attr = attr({'session-id': self.__session_id, 'validation' : self.__validation}) + return '' + self.__operations + '' + +class PollRequest(RequestBase): + def __init__(self, session_id, validation=None, namespaces=None): + self.__session_id = session_id + self.__namespaces = namespaces + self.__validation = validation + + def __str__(self): + _attr = attr({'session-id': self.__session_id, 'validation' : self.__validation}) + return '' + +class PurgeRequest(RequestBase): + def __init__(self, session_id, publisher_id=None, validation=None): + self.__session_id = session_id + self.__publisher_id = publisher_id + self.__validation = validation + + def __str__(self): + __attr = attr({'session-id':self.__session_id, 'validation':self.__validation,'ifmap-publisher-id':self.__publisher_id}) + return ''; diff --git a/Testcases/cfgm_common/ifmap/request.pyc b/Testcases/cfgm_common/ifmap/request.pyc new file mode 100644 index 0000000..94537b5 Binary files /dev/null and b/Testcases/cfgm_common/ifmap/request.pyc differ diff --git a/Testcases/cfgm_common/ifmap/response.py b/Testcases/cfgm_common/ifmap/response.py new file mode 100644 index 0000000..179fd01 --- /dev/null +++ b/Testcases/cfgm_common/ifmap/response.py @@ -0,0 +1,55 @@ +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE +# + +from xml.etree import ElementTree + +class Response(): + """ + Base class to handle and parse IF-MAP responses + """ + __xml = "" + + def __init__(self, result): + """ + Take a result string and process it + """ + if result: + env = ElementTree.fromstring(result) + body = env.find('{http://www.w3.org/2003/05/soap-envelope}Body') + response = body.find('{http://www.trustedcomputinggroup.org/2010/IFMAP/2}response') + # xml.etree.ElementTree find is broken in python 2.6 + children = response.findall('*') + if len(children): + self.__xml = children[0] + + def element(self): + """ + Returns the raw Element object + """ + return self.__xml + + def __str__(self): + """ + Print the XML tree as a string + """ + return ElementTree.tostring(self.__xml) + +class newSessionResult(Response): + """ + newSessionResult + """ + def __init__(self, result): + #import pdb; pdb.set_trace() + self.__newSession = Response(result).element() + + def get_session_id(self): + return self.__newSession.attrib['session-id'] + + def get_publisher_id(self): + return self.__newSession.attrib['ifmap-publisher-id'] + + + + diff --git a/Testcases/cfgm_common/ifmap/response.pyc b/Testcases/cfgm_common/ifmap/response.pyc new file mode 100644 index 0000000..93710a8 Binary files /dev/null and b/Testcases/cfgm_common/ifmap/response.pyc differ diff --git a/Testcases/cfgm_common/ifmap/util.py b/Testcases/cfgm_common/ifmap/util.py new file mode 100644 index 0000000..e4d06dd --- /dev/null +++ b/Testcases/cfgm_common/ifmap/util.py @@ -0,0 +1,34 @@ +#!/usr/bin/python +# +# Copyright 2011, Infoblox, All Rights Reserved +# +# Open Source, see LICENSE +# + +def attr(attributes): + """ + attr creates an XML string for any attribute that has a value + attr({'session-id': '2345', 'validation':'metadata'}) + """ + if attributes and (type(attributes) == type({})): # check if it is a dictionary + __xml = "" + for label, value in attributes.items(): + if value != None: + __xml += label + '="' + value + '" ' + return __xml + else: + return '' + +def link_ids(id1, id2): + """ + Takes two id arguments. + Returns XML for id1 or links id1 and id2 together + """ + if id1 and id2: # Both exist, so link them + #return '' + id1 + id2 + '' + return id1 + id2 + else: + return id1 + + + diff --git a/Testcases/cfgm_common/ifmap/util.pyc b/Testcases/cfgm_common/ifmap/util.pyc new file mode 100644 index 0000000..bb357e3 Binary files /dev/null and b/Testcases/cfgm_common/ifmap/util.pyc differ -- cgit 1.2.3-korg