[asterisk-scf-commits] asterisk-scf/integration/testsuite.git branch "review" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Thu Jul 14 12:41:37 CDT 2011


branch "review" has been updated
       via  c4e33bf6a032263f7804a86de4fe7caf3a2f4f12 (commit)
       via  cba220aa1bf60b3cb6773fbb6b6486e21c15bb33 (commit)
       via  0dc2138c082b4aba3be357a510faae5204dc2082 (commit)
       via  f086d32e062d90d46799573ca8484216e0a2d3db (commit)
       via  d9094868d1551e598c3c6d5509e1938a0273db67 (commit)
       via  074c8a6252e94b331e352091d9b2d63ec0a428e3 (commit)
       via  e4ae470d24f2db7cd16dced914439a95999901c2 (commit)
       via  b1895219f5f6229ad9592367112cac6d675e445b (commit)
       via  b6deb04acc1a485add2f10133174332c0e142dc0 (commit)
       via  294d1e829abba45da2dcd147fb86471f0871db79 (commit)
      from  73b89897b3b75d2a6faeae74e238180268e7596c (commit)

Summary of changes:
 contrib/ubuntu/init.d/testsuite-remote |    2 +-
 lib/python/TestSuite.py                |   71 +++++++++----
 lib/python/plugins.py                  |    7 +-
 lib/python/yaml_parser.py              |   51 ++++++----
 plugins/asteriskscf_configurator.py    |   22 ++--
 plugins/failover.py                    |  184 +++++++++++++++++++++++++++-----
 plugins/protos.py                      |    2 +-
 plugins/sipp.py                        |   22 +++-
 plugins/testsuite_remotes.py           |   12 ++-
 plugins/wireshark.py                   |    2 +-
 remote.py                              |    2 +-
 testsuite.py                           |   22 ++++-
 12 files changed, 298 insertions(+), 101 deletions(-)


- Log -----------------------------------------------------------------
commit c4e33bf6a032263f7804a86de4fe7caf3a2f4f12
Author: Darren Sessions <dsessions at digium.com>
Date:   Thu Jul 14 12:41:34 2011 -0500

    modified the subprocess buffer size in the remote agent script to be unbuffered.

diff --git a/remote.py b/remote.py
index 2502e1a..48dca4c 100755
--- a/remote.py
+++ b/remote.py
@@ -115,7 +115,7 @@ class RemoteAgent(object):
         if os.path.exists(execCmd[0]) and os.access(execCmd[0], os.X_OK):
             p = subprocess.Popen(
                 execCmd,
-                bufsize=-1,
+                bufsize=0,
                 shell=False,
                 stdin=logArtifactFile,
                 stdout=logArtifactFile,

commit cba220aa1bf60b3cb6773fbb6b6486e21c15bb33
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:21:44 2011 -0500

    updated the wireshark plugin to use the new rpc override code.

diff --git a/plugins/wireshark.py b/plugins/wireshark.py
index cace55f..8b2ad92 100644
--- a/plugins/wireshark.py
+++ b/plugins/wireshark.py
@@ -23,7 +23,7 @@ class plugin(TestSuite.RemoteBaseClass):
                 if 'host_filter' in testData['cmd'][cmd]:
                     ''' Quick check to make sure we can connect to the remotes before we do anything else. '''
                     for remoteHost in testData['cmd'][cmd]['host_filter']:
-                        rpc[remoteHost] = self.RPC().connect(remoteHost)
+                        rpc[remoteHost] = self.RPC().connect(globalVars, remoteHost)
                         if rpc[remoteHost]['success'] == False:
                             return rpc[remoteHost]
                         ipv6 = rpc[remoteHost]['ipv6']

commit 0dc2138c082b4aba3be357a510faae5204dc2082
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:21:18 2011 -0500

    modified the remote restart code so it actually checks the results and updated the plugin for the new rpc override support.

diff --git a/plugins/testsuite_remotes.py b/plugins/testsuite_remotes.py
index b680e3b..a7a938b 100644
--- a/plugins/testsuite_remotes.py
+++ b/plugins/testsuite_remotes.py
@@ -21,14 +21,18 @@ class plugin(TestSuite.BaseClass):
             if cmd == 'startup':
                 ''' Restart remotes '''
                 for remote in testData['cmd']['startup']:
-                    rpc[remote] = self.RPC().connect(remote)
+                    rpc[remote] = self.RPC().connect(globalVars, remote)
                     if rpc[remote]['success'] == False:
                         return rpc[remote]
-                    rpc[remote]['rpc']('restart')
+                    results = rpc[remote]['rpc']('restart')
+                    if results['success'] == False:
+                        return results
+
+                time.sleep(2)
 
                 ''' Check to make sure we can connect to the remotes again before we do anything else. '''
                 for remote in testData['cmd']['startup']:
-                    rpc[remote] = self.RPC().connect(remote)
+                    rpc[remote] = self.RPC().connect(globalVars, remote)
                     if rpc[remote]['success'] == False:
                         return rpc[remote]
 
@@ -57,7 +61,7 @@ class plugin(TestSuite.BaseClass):
             elif cmd == 'cleanup':
                 ''' Quick check to make sure we can connect to the remotes before we do anything else. '''
                 for remote in testData['cmd']['cleanup']:
-                    rpc[remote] = self.RPC().connect(remote)
+                    rpc[remote] = self.RPC().connect(globalVars, remote)
                     if rpc[remote]['success'] == False:
                         return rpc[remote]
 

commit f086d32e062d90d46799573ca8484216e0a2d3db
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:20:30 2011 -0500

    complete revamp of the failover plugin making it platform independent and *much* easier to use.

diff --git a/plugins/failover.py b/plugins/failover.py
index 4b2e430..7b278d4 100644
--- a/plugins/failover.py
+++ b/plugins/failover.py
@@ -18,46 +18,172 @@ class plugin(TestSuite.BaseClass):
     def main(self, testData, testPath, globalVars, pluginData):
 
         for cmd in testData['cmd']:
-            if cmd == 'assign':
-                if not 'active_testsuite_remote_host' in testData['cmd'] or not 'standby_testsuite_remote_host' in testData['cmd']:
-                    return {'success':False,'msg':'Both active and standby remote hosts must be specified.','shutdownExempt':True}
 
-                if not 'shared_ip_label' in testData['cmd']:
-                    return {'success':False,'msg':'A label must be specified to assign a shared ip.','shutdownExempt':True}
+            if not 'active_testsuite_remote_host' in testData['cmd'][cmd] or not 'standby_testsuite_remote_host' in testData['cmd'][cmd]:
+                return {'success':False,'msg':'Both active and standby remote hosts must be specified.','shutdownExempt':True}
 
-                sharedIP = testData['cmd']['shared_ip']
-                if self.ping(sharedIP):
-                    return {'success':False, 'msg':'The %s shared ip address is responding before cluster services have been started.' % sharedIP, 'shutdownList':shutdownList}
+            if not 'shared_ip_label' in testData['cmd'][cmd]:
+                return {'success':False,'msg':'A label must be specified to assign a shared ip.','shutdownExempt':True}
 
-                continue
+            if not testData['cmd'][cmd]['address_pool'] in pluginData['pluginConfigFile']['pools']:
+                return {'success':False,'msg':'The address pool specified, %s, does not exist in the failover config file.' % testData['cmd'][cmd]['address_pool']}
 
+            if not len(pluginData['pluginConfigFile']['pools'][testData['cmd'][cmd]['address_pool']]['ipv4']) == len(pluginData['pluginConfigFile']['pools'][testData['cmd'][cmd]['address_pool']]['ipv6']):
+                return {'success':False,'msg':'Address pools must have equal amounts of ipv4 and ipv6 addresses.'}
+   
+            if len(pluginData['pluginConfigFile']['pools'][testData['cmd'][cmd]['address_pool']]['ipv4']) < 1:
+                return {'success':False,'msg':'Address pools must have at least one ipv4 and one ipv6 ip address.'}
+   
+            if 'used' in pluginData['pluginConfigFile']:
+                if len(pluginData['pluginConfigFile']['used']['ipv4']) == len(pluginData['pluginConfigFile']['pools'][testData['cmd'][cmd]['address_pool']]['ipv4']):
+                    return {'success':False,'msg':'The ip addresses in the %s address pool have been exhausted. Please add more or specify a different address pool.' % testData['cmd'][cmd]['address_pool'], 'shutdownExempt':True}
+            else:
+                pluginData['pluginConfigFile']['used'] = {'ipv4':[], 'ipv6':[]}
+                pluginData['pluginConfigFile']['labels'] = {}
 
-                results = self.RPC().connect(testData['cmd']['testsuite_remote_active'])
-                if not results['success'] == True:
-                    return self._addShutdownList(results, shutdownList)
-                else:
-                    activeNode = results
-                    activeNode['nodeID'] = '0'
+            shutdownList = [testData['cmd'][cmd]['active_testsuite_remote_host'], testData['cmd'][cmd]['standby_testsuite_remote_host']]
 
-                results = self.RPC().connect(testData['cmd']['testsuite_remote_standby'])
-                if not results['success'] == True:
-                    return self._addShutdownList(results, shutdownList)
-                else:
-                    standbyNode = results
-                    standbyNode['nodeID'] = '1'
+            cluster = {}
+
+            cluster['active'] = self.RPC().connect(globalVars, testData['cmd'][cmd]['active_testsuite_remote_host'])
+            print cluster['active']
+            if cluster['active']['success'] == False:
+                return self._addShutdownList(results, shutdownList)
 
-        if not self.ping(sharedIP):
-            return {'success':False, 'msg':'The %s shared ip address is failing to respond.' % sharedIP, 'shutdownList':shutdownList}
+            cluster['standby'] = self.RPC().connect(globalVars, testData['cmd'][cmd]['standby_testsuite_remote_host'])
+            if cluster['standby']['success'] == False:
+               return self._addShutdownList(results, shutdownList)
 
-        return {'success':True,'shutdownList':shutdownList}
+            if cmd == 'assign':
 
+                ''' Cleanup the nodes and make sure *nothing* from the address pools are assigned to these nodes '''
+                for nodeType in ['active', 'standby']:
+                    if cluster[nodeType]['plat'] == 'Linux':
+                        results = platformCmds_Linux().remove(globalVars, nodeType, cluster, pluginData['pluginConfigFile']['pools'])
+                        if results['success'] == False:
+                            return self._addShutdownList(results, shutdownList)
+
+
+                ''' Assign IPs '''
+                ipv4addr, ipv4network, ipv4netmask, ipv4broadcast, ipv6addr, pluginData = self.assignIPs(pluginData, testData['cmd'][cmd])
+
+                if self.ping('ipv4', ipv4addr) or self.ping('ipv6', ipv6addr):
+                    return {'success':False, 'msg':'The shared IP addresses being assigned, %s and %s, are reachable on the network *before* being assigned.' % (ipv4addr, ipv6addr), 'shutdownExempt':True}
+
+                ''' Assign the ips to the active node '''
+                if cluster[nodeType]['plat'] == 'Linux':
+                    results = platformCmds_Linux().add(globalVars, 'active', cluster, ipv4addr, ipv4network, ipv4netmask, ipv6addr)
+                    if results['success'] == False:
+                        return self._addShutdownList(results, shutdownList)
+
+                pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']] = {\
+                    'active':testData['cmd'][cmd]['active_testsuite_remote_host'],
+                    'standby':testData['cmd'][cmd]['standby_testsuite_remote_host'],
+                    'ipv4addr':ipv4addr,
+                    'ipv4network':ipv4network,
+                    'ipv4netmask':ipv4netmask,
+                    'ipv6addr':ipv6addr
+                }
+
+                override = self.dictMerge(globalVars, {'overrides':{'RPC':{'connect':{testData['cmd'][cmd]['shared_ip_label']:{'ipv4':ipv4addr, 'ipv6':ipv6addr}}}}})
+   
+                return self.dictMerge(results, {'shutdownList':shutdownList, 'pluginData':pluginData, 'globalVars':override}) 
+
+            elif cmd == 'failover':
+
+                ipv4addr = pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['ipv4addr']
+                ipv4network = pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['ipv4network']
+                ipv4netmask = pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['ipv4netmask']
+                ipv6addr = pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['ipv6addr']
+
+                if cluster['standby']['plat'] == 'Linux':
+                    results = platformCmds_Linux().add(globalVars, 'standby', cluster, ipv4addr, ipv4network, ipv4netmask, ipv6addr)
+                    if results['success'] == False:
+                        return self._addShutdownList(results, shutdownList)
+                
+                if cluster['active']['plat'] == 'Linux':
+                    results = platformCmds_Linux().remove(globalVars, 'active', cluster, pluginData['pluginConfigFile']['pools'])
+                    if results['success'] == False:
+                        return self._addShutdownList(results, shutdownList)
+
+                tmpActive = pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['active']
+                tmpStandby = pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['standby']
+
+                pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['active'] = tmpStandby
+                pluginData['pluginConfigFile']['labels'][testData['cmd'][cmd]['shared_ip_label']]['standby'] = tmpActive
+
+                return self.dictMerge(results, {'shutdownList':shutdownList, 'pluginData':pluginData})
+
+            elif cmd == 'shutdown':
+                pass
+    
     def _addShutdownList(self, results, shutdownList):
         results['shutdownList'] = shutdownList
         return results
 
-    def platformAssignCmd(self, platform):
-        if platform == 'Linux':
-            pass
-        else:
-            return {'success':False, 'msg':'The %s platform is currently not supported within the failover plugin.'}
+    def assignIPs(self, pluginData, testData):
+        for ipv4info in pluginData['pluginConfigFile']['pools'][testData['address_pool']]['ipv4']:
+            for ipv4 in ipv4info:
+                if len(pluginData['pluginConfigFile']['used']['ipv4']) > 0:
+                    for usedipv4 in pluginData['pluginConfigFile']['used']['ipv4']:
+                        if usedipv4 == ipv4info:
+                            continue
+                        else:
+                            ipv4addr = ipv4
+                            ipv4network = ipv4info[ipv4]['network']
+                            ipv4netmask = ipv4info[ipv4]['netmask']
+                            ipv4broadcast = ipv4info[ipv4]['broadcast']
+                            ipv6addr = pluginData['pluginConfigFile']['pools'][testData['address_pool']]['ipv6'][pluginData['pluginConfigFile']['pools'][testData['address_pool']]['ipv4'].index(ipv4info)]
+                            pluginData['pluginConfigFile']['used']['ipv4'].append(ipv4info)
+                            return ipv4addr, ipv4network, ipv4netmask, ipv4broadcast, ipv6addr, pluginData
+                else:
+                    ipv4addr = ipv4
+                    ipv4network = ipv4info[ipv4]['network']
+                    ipv4netmask = ipv4info[ipv4]['netmask']
+                    ipv4broadcast = ipv4info[ipv4]['broadcast']
+                    ipv6addr = pluginData['pluginConfigFile']['pools'][testData['address_pool']]['ipv6'][0]
+                    pluginData['pluginConfigFile']['used']['ipv4'].append(ipv4info)
+                    return ipv4addr, ipv4network, ipv4netmask, ipv4broadcast, ipv6addr, pluginData
+
+class platformCmds_Linux:
+    def _cmd(self, globalVars, nodeType, cluster, cmd):
+        return cluster[nodeType]['rpc']('run', cluster[nodeType]['hostname'], globalVars, 'failover', nodeType, cmd, True)
+
+    def gratuitousArp(self, globalVars, nodeType, cluster, ipv4addr, ipv4network):
+        macaddr = cluster[nodeType]['macaddr'].replace(':', '')
+        results = self._cmd(globalVars, nodeType, cluster, ['send_arp', ipv4addr, macaddr, ipv4network, 'ffffffffffff'])
+        if results['success'] == False:
+            return results
+        return results
+
+    def add(self, globalVars, nodeType, cluster, ipv4addr, ipv4network, ipv4netmask, ipv6addr):
+        results = self._cmd(globalVars, nodeType, cluster, ['ifconfig', cluster[nodeType]['iface'], 'inet', 'add', ipv4addr, 'netmask', ipv4netmask])
+        if results['success'] == False:
+            return results
 
+        results = self.gratuitousArp(globalVars, nodeType, cluster, ipv4addr, ipv4network)
+        if results['success'] == False:
+            return results 
+           
+        results = self._cmd(globalVars, nodeType, cluster, ['ifconfig', cluster[nodeType]['iface'], 'inet6', 'add', ipv6addr])
+        if results['success'] == False:
+            return results
+
+        return results
+
+    def remove(self, globalVars, nodeType, cluster, pools):
+        for addressPool in pools:
+            for ipAddressPool in pools[addressPool]['ipv6']:
+                results = self._cmd(globalVars, nodeType, cluster, ['ifconfig', cluster[nodeType]['iface'], 'inet6', 'del', ipAddressPool])
+                if results['success'] == False:
+                    return results
+
+        results = self._cmd(globalVars, nodeType, cluster, ['ifconfig', '%s:0' % cluster[nodeType]['iface'], 'down'])
+        if results['success'] == False:
+            return results
+
+        #results = self._cmd(globalVars, nodeType, cluster, ['/etc/init.d/networking','restart'])
+        #if results['success'] == False:
+        #    return results
+
+        return results

commit d9094868d1551e598c3c6d5509e1938a0273db67
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:19:07 2011 -0500

    added override and plugin data support so that, in theory, any piece of the testsuite can have an override that can be set within any plugin. additionally, the pluginData variable was created so that a plugin could essentially talk to itself if it is subsequently called again within a test.

diff --git a/testsuite.py b/testsuite.py
index 957be00..a33b77d 100755
--- a/testsuite.py
+++ b/testsuite.py
@@ -43,7 +43,7 @@ class __main__:
         except:
             pass
 
-        self.globalVars = {'cwd':cwd, 'hostname':hostname, 'testInfo':{}, 'mode':'testing'}
+        self.globalVars = {'cwd':cwd, 'hostname':hostname, 'testInfo':{}, 'overrides':{}, 'mode':'testing'}
 
         if len(argv) >= 2:
             self.globalVars['mode'] = argv[1]
@@ -135,7 +135,11 @@ class __main__:
 
                                 ''' import plugins '''
                                 for plugin in [plugin for timeLine in subTestCase[testName]['timeline'] for plugin in timeLine]:
-                                    pluginData[plugin] = plugins.plugins().init(plugin, self.globalVars)
+                                    if plugin in pluginData:
+                                        pluginData[plugin] = self._dataMerge(plugins.plugins().init(plugin, self.globalVars), pluginData[plugin])
+                                    else:
+                                        pluginData[plugin] = plugins.plugins().init(plugin, self.globalVars)
+
                                     if pluginData[plugin]['success'] == False:
                                         errorMsgs.append(pluginData[plugin]['msg'])
                                         success = False
@@ -151,6 +155,10 @@ class __main__:
                                         self.globalVars['testInfo']['testPlugin'] = plugin
                                         runResults = plugins.plugins().execute(plugin, pluginData[plugin], timeLine[plugin], testData['path'], self.globalVars)
                                         if self.globalVars['mode'] == 'testing': 
+                                            if 'globalVars' in runResults:
+                                                self.globalVars = runResults['globalVars']
+                                            if 'pluginData' in runResults:
+                                                pluginData[plugin] = runResults['pluginData']
                                             if not 'shutdownList' in runResults:
                                                 if not 'shutdownExempt' in runResults:
                                                     if 'testsuite_remote_host' in timeLine[plugin]:
@@ -160,7 +168,10 @@ class __main__:
                                                     shutdownList.append({remote:plugin})
                                             if runResults['success'] == False and self.globalVars['testSuccess'] == True:
                                                 self.globalVars['testSuccess'] = False
-                                                self.globalVars['testMsg'] = runResults['msg'] = "'%s' plugin: %s" % (plugin, runResults['msg'])
+                                                if 'remote' in runResults:
+                                                    self.globalVars['testMsg'] = runResults['msg'] = "'%s' plugin on '%s': %s" % (plugin, runResults['remote'], runResults['msg'])
+                                                else:
+                                                    self.globalVars['testMsg'] = runResults['msg'] = "'%s' plugin: %s" % (plugin, runResults['msg'])
                                                 break
                                         if runResults['success'] == 'docs':
                                             docsPluginData[testCategory][testData['name']]['tests'][testName]['pluginData'].append({'pluginName':plugin,'results':runResults['docs']})
@@ -281,6 +292,11 @@ class __main__:
 
         return
 
+    def _dataMerge(self, FROM, TO):
+        for val in FROM:
+            TO[val] = FROM[val]
+        return TO
+
     def _banner(self):
         print >> sys.stderr, "\n--------------------------------------------------------"
         print >> sys.stderr, "+  Test-Suite                                          +"

commit 074c8a6252e94b331e352091d9b2d63ec0a428e3
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:17:02 2011 -0500

    updated the plugins to support the new override capability within the rpc class.

diff --git a/plugins/asteriskscf_configurator.py b/plugins/asteriskscf_configurator.py
index b3673bb..b370b63 100644
--- a/plugins/asteriskscf_configurator.py
+++ b/plugins/asteriskscf_configurator.py
@@ -21,7 +21,7 @@ import Ice
 class plugin(TestSuite.BaseClass):
     def main(self, testData, testPath, globalVars, pluginData):
         if globalVars['mode'] == 'docs':
-            rpc = self.RPC().connect('testsuite-remote-1.digium.internal')
+            rpc = self.RPC().connect(globalVars, 'testsuite-remote-1.digium.internal')
             for cmd in testData['cmd']:
                 if cmd == 'sip':
                     execCmd = ['./SipConfigurator.py', '--config=<path to sip config>', '--locator="LocatorService:tcp -p 4411 -h <service locator host"']
@@ -59,7 +59,7 @@ class plugin(TestSuite.BaseClass):
                 serviceLocatorParams.category = AsteriskSCF.Media.RTP.V1.ConfigurationDiscoveryCategory
             else:
                 return {'success':False,'shutdownExempt':'True','msg':'The %s command is invalid.' % cmd}
-            results = ConfiguratorApp(cmd, testData['service_locator_host'], testData['cmd'][cmd], AsteriskSCF, testData['configuration_wipe'], serviceLocatorParams).main([''])
+            results = ConfiguratorApp(globalVars, cmd, testData['service_locator_host'], testData['cmd'][cmd], AsteriskSCF, testData['configuration_wipe'], serviceLocatorParams).main([''])
             if 'msg' in results:
                 results['msg'] = "['%s' component] %s" % (cmd, results['msg'])
             if results['success'] == False:
@@ -132,11 +132,12 @@ class ConfiguratorApp(Ice.Application):
     any arguments as it will expect a file path and we're using a dict
     type instead.
     '''
-    def __init__(self, cmd, host, config, AsteriskSCF, configWipe=False, serviceLocatorParams=None):
+    def __init__(self, globalVars, cmd, host, config, AsteriskSCF, configWipe=False, serviceLocatorParams=None):
         self.cmd = cmd
         self.host = host
         self.config = config
         self.configWipe = configWipe
+        self.globalVars = globalVars
         self.AsteriskSCF = AsteriskSCF
         self.serviceLocatorParams = serviceLocatorParams
 
@@ -146,6 +147,7 @@ class ConfiguratorApp(Ice.Application):
         if self.cmd == 'rtp':
             visitor = RtpSectionVisitors()
 
+        visitor.globalVars = self.globalVars
         visitor.AsteriskSCF = self.AsteriskSCF
        
         proxy = 'LocatorService:tcp -p 4411 -h %s' % self.host
@@ -215,7 +217,7 @@ class SectionVisitors():
         except:
             return None
 
-    def getRemoteHost(self, section, config, host, port):
+    def getRemoteHost(self, globalVars, section, config, host, port):
         try:
             config[host]
         except:
@@ -231,7 +233,7 @@ class SectionVisitors():
         try:
             self.hosts[config[host]][config['ipv4oripv6']]
         except:
-            self.hosts[config[host]] = plugin().RPC().connect(config[host])
+            self.hosts[config[host]] = plugin().RPC().connect(globalVars, config[host])
         if self.hosts[config[host]]['success'] == False:
             return self.hosts[config[host]]
         try:
@@ -248,7 +250,7 @@ class SipSectionVisitors(SectionVisitors):
         return {'success':True}
 
     def visit_transport_udp(self, config, section):
-        remote = self.getRemoteHost(section, config, 'host', 'port')
+        remote = self.getRemoteHost(self.globalVars, section, config, 'host', 'port')
         if remote['success'] == False:
             return remote
 
@@ -272,7 +274,7 @@ class SipSectionVisitors(SectionVisitors):
         return {'success':True}
 
     def visit_transport_tcp(self, config, section):
-        remote = self.getRemoteHost(section, config, 'host', 'port')
+        remote = self.getRemoteHost(self.globalVars, section, config, 'host', 'port')
         if remote['success'] == False:
             return remote
 
@@ -296,7 +298,7 @@ class SipSectionVisitors(SectionVisitors):
         return {'success':True}
 
     def visit_transport_tls(self, config, section):
-        remote = self.getRemoteHost(section, config, 'host', 'port')
+        remote = self.getRemoteHost(self.globalVars, section, config, 'host', 'port')
         if remote['success'] == False:
             return remote
 
@@ -328,14 +330,14 @@ class SipSectionVisitors(SectionVisitors):
 
         mapper.map('routing', self.AsteriskSCF.SIP.V1.SipRoutingItem(), 'routingServiceName', 'routingService', config.get, None)
 
-        remote = self.getRemoteHost(section, config, 'sourcehost', 'sourceport')
+        remote = self.getRemoteHost(self.globalVars, section, config, 'sourcehost', 'sourceport')
         if remote['success'] == False:
             return remote
         item = self.AsteriskSCF.SIP.V1.SipSourceTransportAddressItem()
         mapper.map('sourcehost', item, 'host', 'sourceaddress', remote['sourcehost'], None)
         mapper.map('sourceport', item, 'port', 'sourceaddress', remote['sourceport'], 5060)
 
-        remote = self.getRemoteHost(section, config, 'targethost', 'targetport')
+        remote = self.getRemoteHost(self.globalVars, section, config, 'targethost', 'targetport')
         if remote['success'] == False:
             return remote
         item = self.AsteriskSCF.SIP.V1.SipTargetDestinationAddressItem()
diff --git a/plugins/protos.py b/plugins/protos.py
index 7a641d3..f15ab98 100644
--- a/plugins/protos.py
+++ b/plugins/protos.py
@@ -20,7 +20,7 @@ class plugin(TestSuite.RemoteBaseClass):
         if not 'targethost' in testData['cmd'] and not 'ipv4oripv6' in testData['cmd']:
             return {'success':False,'msg':'The target host and ipv4oripv6 options must be specified.'}
 
-        targetHost = plugin().RPC().connect(testData['cmd']['targethost'])
+        targetHost = plugin().RPC().connect(globalVars, testData['cmd']['targethost'])
         if targetHost['success'] == False:
             return targetHost
 
diff --git a/plugins/sipp.py b/plugins/sipp.py
index d86626d..2150745 100644
--- a/plugins/sipp.py
+++ b/plugins/sipp.py
@@ -31,13 +31,23 @@ class plugin(TestSuite.BaseClass):
             if not 'testsuite_remote_host' in testData:
                 return {'success':False,'msg':'No testsuite remote host specified.'}
 
-            remote = self.RPC().connect(testData['testsuite_remote_host'])
+            remote = self.RPC().connect(globalVars, testData['testsuite_remote_host'])
             if remote['success'] == False:
                 return remote
 
             for mode in modes:
                 if mode in config:
                     if mode == 'uas':
+                        results = remote['rpc']('listProcesses')
+                        if results['success'] == False:
+                            return results
+
+                        if 'sipp' in results['msg']:
+                            if 'uas' in results['msg']['sipp']:
+                                results = remote['rpc']('shutdown', 'sipp')
+                                if results['success'] == False:
+                                    return results
+
                         waitForPidToFinish = False
                     if mode == 'uac':
                         waitForPidToFinish = True
@@ -76,7 +86,7 @@ class plugin(TestSuite.BaseClass):
             rpc = {}
 
             for remoteHost in config['generate_injection_file']['redistribute_to_hosts']:
-                rpc[remoteHost] = self.RPC().connect(remoteHost)
+                rpc[remoteHost] = self.RPC().connect(globalVars, remoteHost)
                 if rpc[remoteHost]['success'] == False:
                     return rpc[remoteHost]
 
@@ -116,7 +126,7 @@ class plugin(TestSuite.BaseClass):
         else:
             execCmd = self._execBuilder(execCmd, '-sn %s' % mode) 
 
-        results = self.getRemoteHost(config, testsuite_remote_host)
+        results = self.getRemoteHost(globalVars, config, testsuite_remote_host)
         if results['success'] == False:
             return results
 
@@ -147,14 +157,14 @@ class plugin(TestSuite.BaseClass):
             if 'duration' in config:
                 execCmd = self._execBuilder(execCmd, '-d %s' % config['duration'])
             if 'targethost' in config:
-                results = self.getRemoteHost(config, config['targethost'])
+                results = self.getRemoteHost(globalVars, config, config['targethost'])
                 if results['success'] == False:
                     return results
                 execCmd = self._execBuilder(execCmd, '%s' % results['ip'])
     
         return {'success':True, 'execCmd':execCmd}
 
-    def getRemoteHost(self, config, host):
+    def getRemoteHost(self, globalVars, config, host):
         try:
             config['ipv4oripv6']
         except:
@@ -164,7 +174,7 @@ class plugin(TestSuite.BaseClass):
         try:
             self.hosts[host][config['ipv4oripv6']]
         except:
-            self.hosts[host] = self.RPC().connect(host)
+            self.hosts[host] = self.RPC().connect(globalVars, host)
         if self.hosts[host]['success'] == False:
             return self.hosts[host]
         return {'success':True, 'ip':self.hosts[host][config['ipv4oripv6']]}

commit e4ae470d24f2db7cd16dced914439a95999901c2
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:14:57 2011 -0500

    moved the load yaml files function into a seperate class so that it can be called by either the yaml parser base class or by the plugin config file class.

diff --git a/lib/python/yaml_parser.py b/lib/python/yaml_parser.py
index ba727e0..c027a9a 100755
--- a/lib/python/yaml_parser.py
+++ b/lib/python/yaml_parser.py
@@ -5,7 +5,19 @@ import sys
 import time
 import yaml
 
-class yamlBase:
+class yamlLoad:
+    def loadFiles(self, path, yaml_file):
+        try:
+            f = open("%s/%s" % (path, yaml_file), "r")
+        except IOError:
+            return {'success':False, 'msg':'Failed to open yaml file: %s/%s' % (path, yaml_file)}
+        except:
+            return {'success':False, 'msg':'Unexpected error: %s' % sys.exc_info()[0]}
+        data = yaml.load(f)
+        f.close()
+        return {'success':True, 'data':data}
+
+class yamlBase(yamlLoad):
     def __init__(self):
         self.testDir = 'tests'
         self.testsYaml = 'tests.yaml'
@@ -15,7 +27,12 @@ class yamlBase:
         self.load()
 
     def parse(self, searchPath, yamlFile, test=None):
-        testData = self.loadFiles(searchPath, self.testsYaml)
+        results = self.loadFiles(searchPath, self.testsYaml)
+        if results['success'] == False:
+            return results
+    
+        testData = results['data']
+
         for list in testData:
             for items in testData[list]:
                 path = "%s/%s" % (searchPath, items)
@@ -30,29 +47,25 @@ class yamlBase:
                     self.indResults[test]['docs'] = testData['docs']
                 elif list == 'testcase':
                     results = self.loadFiles(path, yamlFile)
-                    if 'docs' in results:
+                    if results['success'] == False:
+                        return results
+                    if 'docs' in results['data']:
                         self.indResults[test]['lastModDates'].append("%s" % os.path.getmtime("%s/%s" % (path, yamlFile)))
-                    results['path'] = path
-                    self.indResults[test]['tests'].append(results)
-
-    def loadFiles(self, path, yaml_file):
-        f = open("%s/%s" % (path, yaml_file), "r")
-        try:
-            f = open("%s/%s" % (path, yaml_file), "r")
-        except IOError:
-            self.__fatalError("Failed to open %s/%s" % (path, yaml_file))
-        except:
-            self.__fatalError("Unexpected error: %s" % sys.exc_info()[0])
-        data = yaml.load(f)
-        f.close()
-        return data
+                    results['data']['path'] = path
+                    self.indResults[test]['tests'].append(results['data'])
 
     def loadEvents(self, event):
         if event == 'testsuite_remote_startup':
-            test = self.loadFiles('events', 'startup.yaml')
+            results = self.loadFiles('events', 'startup.yaml')
+            if results['success'] == False:
+                return results
+            test = results['data']
             test['name'] = 'startup_init'
         elif event == 'testsuite_remote_shutdown':
-            test = self.loadFiles('events', 'shutdown.yaml')
+            results = self.loadFiles('events', 'shutdown.yaml')
+            if results['success'] == False:
+                return results
+            test = results['data']
             test['name'] = 'shutdown'
         else:
             return

commit b1895219f5f6229ad9592367112cac6d675e445b
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:13:46 2011 -0500

    added support for plugin config files. this is useful for things like the failover plugin where a block of ip addresses needs to be defined, but not placed in the individual test yaml files where after enough tests are created, would make editing each of the tests unbearable.

diff --git a/lib/python/plugins.py b/lib/python/plugins.py
index 8061674..46cff2d 100644
--- a/lib/python/plugins.py
+++ b/lib/python/plugins.py
@@ -14,7 +14,7 @@ import imp
 import sys
 import inspect
 
-import file
+import yaml_parser
 
 class plugins:
     def execute(self, name, pluginData, testData, testPath, globalVars):
@@ -48,10 +48,9 @@ class plugins:
         except ImportError:
             return {'success':False,'msg':'%s' % sys.exc_info()[1]}
         try:
-            pluginConfig = '%s/configs/%s.conf' % (globalVars['cwd'], name)
-            results = file.file().read(pluginConfig)
+            results = yaml_parser.yamlLoad().loadFiles('%s/configs' % globalVars['cwd'], '%s.conf' % name)
             if results['success'] == True:
-                pluginConfig = results['fd']
+                pluginConfig = results['data']
             return {'success':True, 'module':imp.load_module(name, fp, pathName, desc), 'pluginConfigFile':pluginConfig}
         finally:
             if fp:

commit b6deb04acc1a485add2f10133174332c0e142dc0
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 14:12:13 2011 -0500

    Added support into the testsuite and util base classes for overriding specific class data (in this case, the primary purposes was for virtual failover hosts). Added support to the rpc connect to obtain mac address, platform, and arch from the remote host. modified some of the error messages to be more specific in terms of the host that the error message is originating from. added support in the ping function for ipv6. added a timer on the rpc connections that will display a warning if the rpc connection goes beyond a specific limit.

diff --git a/lib/python/TestSuite.py b/lib/python/TestSuite.py
index b596936..420f237 100644
--- a/lib/python/TestSuite.py
+++ b/lib/python/TestSuite.py
@@ -23,10 +23,22 @@ class utils():
     def run(self, testData, testPath, globalVars, pluginData):
         self.RPC.globalVars = globalVars
         return self.baseClass(testData, testPath, globalVars, pluginData)
+
+    def dictMerge(self, fromDict, toDict):
+        merged = dict(fromDict)
+        for k,v in toDict.iteritems():
+            if k in merged:
+                merged[k] = self.dictMerge(merged[k], v)
+            else:
+                merged[k] = v
+        return merged
         
-    def ping(self, host):
+    def ping(self, ipVer, host):
+        pingStr = 'ping'
+        if ipVer == 'ipv6':
+            pingStr = '%s6' % pingStr
         process = subprocess.Popen(
-                'ping -c1 %s' % host,
+                '%s -c1 %s' % (pingStr, host),
                 stdin=subprocess.PIPE,
                 stdout=subprocess.PIPE,
                 stderr=subprocess.PIPE,
@@ -77,26 +89,37 @@ class utils():
             except:
                 self.docs = []
 
-        def connect(self, host):
+        def connect(self, globalVars, host):
+            override = False 
+            try: 
+                if host in globalVars['overrides']['RPC']['connect']:
+                    override = True
+            except:
+                pass
+
             self.host = host
-            self.rpc[self.host] = xmlrpclib.Server('http://%s:8000' % self.host)
 
-            try:
-                timerStart = datetime.datetime.now().second
-                self.rpc[self.host].reset()
-                timerDelta = datetime.datetime.now().second - timerStart
-            except:
-                return {'success':False,'msg':'Connection to %s was refused.' % self.host}
+            if override == False:
+                self.rpc[self.host] = xmlrpclib.Server('http://%s:8000' % self.host)
+
+                try:
+                    timerStart = datetime.datetime.now().second
+                    self.rpc[self.host].reset()
+                    timerDelta = datetime.datetime.now().second - timerStart
+                except:
+                    return {'success':False,'msg':'Connection to %s was refused. %s' % (self.host, sys.exc_info()[1])}
           
-            if timerDelta > 1:
-                print "\n!!WARNING!! - RPC connect times to '%s' are exceeding normal thresholds and may affect test times.\n" % self.host
-        
-            ipv4, ipv6 = self.rpc[self.host].whatAreMyIps()
+                if timerDelta > 1:
+                    print "\n!!WARNING!! - RPC connect times to '%s' are exceeding normal thresholds and may affect test times.\n" % self.host
+
+                ipv4, ipv6, plat, arch, iface, macaddr = self.rpc[self.host].getHostInfo()
 
-            if self.globalVars['mode'] == 'testing':
-                return {'success':True, 'rpc':self.testingCmd, 'ipv4':ipv4, 'ipv6':ipv6, 'hostname':self.host.split('.')[0], 'fqdn':self.host}
-            elif self.globalVars['mode'] == 'docs':
-                return {'success':True, 'rpc':self.docCmd, 'ipv4':ipv4, 'ipv6':ipv6, 'hostname':self.host.split('.')[0], 'fqdn':self.host}
+                if self.globalVars['mode'] == 'testing':
+                    return {'success':True, 'rpc':self.testingCmd, 'ipv4':ipv4, 'ipv6':ipv6, 'plat':plat, 'arch':arch, 'iface':iface, 'macaddr':macaddr, 'hostname':self.host.split('.')[0], 'fqdn':self.host}
+                elif self.globalVars['mode'] == 'docs':
+                    return {'success':True, 'rpc':self.docCmd, 'ipv4':ipv4, 'ipv6':ipv6, 'hostname':self.host.split('.')[0], 'fqdn':self.host}
+            else:
+                return {'success':True, 'rpc':None, 'ipv4':globalVars['overrides']['RPC']['connect'][host]['ipv4'], 'ipv6':globalVars['overrides']['RPC']['connect'][host]['ipv6'], 'hostname':self.host.split('.')[0], 'fqdn':self.host}
 
         def docCmd(self, cmd, *args):
             argList = []
@@ -106,16 +129,20 @@ class utils():
             return {'success':'docs','docs':self.docs}
 
         def testingCmd(self, cmd, *args):
+            msg = {}
             try:
                 func = getattr(self.rpc[self.host], cmd)
             except AttributeError:
-                return {'success':False,'msg':"Unable to execute '%s' on %s. %s" % (cmd, self.host, sys.exc_info()[1])}
+                msg = {'success':False,'msg':"Unable to execute '%s' on %s. %s" % (cmd, self.host, sys.exc_info()[1])}
             else:
                 try:
                     results = func(*args)
+                    results['remote'] = self.host
+                    return results
                 except:
-                    return {'success':False,'msg':"Unable to execute '%s' on %s. %s" % (cmd, self.host, sys.exc_info()[1])}
-            return results
+                    msg = {'success':False,'msg':"Unable to execute '%s' on %s. %s" % (cmd, self.host, sys.exc_info()[1])}
+            msg['remote'] = self.host 
+            return msg
 
     class file:
         def write(self, fn, fd):
@@ -175,7 +202,7 @@ class RemoteBaseClass(utils):
             return {'success':False,'msg':'No command specified.'}
         if not 'testsuite_remote_host' in testData:
             return {'success':False,'msg':'No testsuite remote host specified.'}
-        rpc = self.RPC().connect(testData['testsuite_remote_host'])
+        rpc = self.RPC().connect(globalVars, testData['testsuite_remote_host'])
         if rpc['success'] == False:
             return rpc
         return self.main(testData, testPath, globalVars, pluginData, rpc)

commit 294d1e829abba45da2dcd147fb86471f0871db79
Author: Darren Sessions <dsessions at digium.com>
Date:   Fri Jul 8 13:42:19 2011 -0500

    Modified the ubuntu testsuite-remote init script to sudo the sysctl command required for the non-local bind.

diff --git a/contrib/ubuntu/init.d/testsuite-remote b/contrib/ubuntu/init.d/testsuite-remote
index 0be097d..8119d2f 100755
--- a/contrib/ubuntu/init.d/testsuite-remote
+++ b/contrib/ubuntu/init.d/testsuite-remote
@@ -32,7 +32,7 @@ DAEMON_ARGS=$TESTSUITE_INSTALL_PATH/remote.py
 
 set -e 
 
-sysctl -w net.ipv4.ip_nonlocal_bind=1 > /dev/null
+sudo sysctl -w net.ipv4.ip_nonlocal_bind=1 > /dev/null
 
 do_start()
 {

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/testsuite.git



More information about the asterisk-scf-commits mailing list