Add stratum bmv2 for SROnosFailure and SRLinkFailure

- Add running stratum switches to these tests
- Add support for docker in SROnosFailure functions
- Add xconnect to cfgtranslator
- Rework switch roles in cfgtranslator

Change-Id: Ic0b386107a7813810de9bf7c34bdf2d869eafa84
(cherry picked from commit d2c84e79dd2257cba150dcde5c089b9d0bf81140)
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index 68072a7..e20e31a 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -720,20 +720,23 @@
         main.step( "Kill link between %s and %s" % ( end1, end2 ) )
         linkDown = main.Network.link( END1=end1, END2=end2, OPTION="down" )
         linkDown = linkDown and main.Network.link( END2=end1, END1=end2, OPTION="down" )
+        utilities.assert_equals( expect=main.TRUE, actual=linkDown,
+                                 onpass="Link down successful",
+                                 onfail="Failed to turn off link?" )
         # TODO: Can remove this, since in the retry we will wait anyways if topology is incorrect
         main.log.info(
                 "Waiting %s seconds for link down to be discovered" % sleep )
         time.sleep( sleep )
+        main.step( "Checking topology after link down" )
         topology = utilities.retry( main.Cluster.active( 0 ).CLI.checkStatus,
                                     main.FALSE,
                                     kwargs={ 'numoswitch': switches,
                                              'numolink': links },
                                     attempts=10,
                                     sleep=sleep )
-        result = topology and linkDown
-        utilities.assert_equals( expect=main.TRUE, actual=result,
-                                 onpass="Link down successful",
-                                 onfail="Failed to turn off link?" )
+        utilities.assert_equals( expect=main.TRUE, actual=topology,
+                                 onpass="Topology after link down is correct",
+                                 onfail="Topology after link down is incorrect" )
 
     @staticmethod
     def killLinkBatch( main, links, linksAfter, switches, sleep=None ):
@@ -1092,12 +1095,18 @@
         else:
             sleep = float( sleep )
 
+        stepResult = main.TRUE
         for i in nodes:
-            killResult = main.ONOSbench.onosDie( main.Cluster.runningNodes[ i ].ipAddress )
-            utilities.assert_equals( expect=main.TRUE, actual=killResult,
-                                     onpass="ONOS instance Killed",
-                                     onfail="Error killing ONOS instance" )
+            node = main.Cluster.runningNodes[ i ]
+            if node.inDocker:
+                killResult = node.server.dockerStop( node.name )
+            else:
+                killResult = main.ONOSbench.onosDie( node.ipAddress )
+            stepResult = stepResult and killResult
             main.Cluster.runningNodes[ i ].active = False
+        utilities.assert_equals( expect=main.TRUE, actual=stepResult,
+                                 onpass="ONOS instance Killed",
+                                 onfail="Error killing ONOS instance" )
         main.Cluster.reset()
         main.log.debug( "sleeping %i seconds" % ( sleep ) )
         time.sleep( sleep )
@@ -1118,11 +1127,22 @@
             sleep = float( main.params[ 'timers' ][ 'OnosDiscovery' ] )
         else:
             sleep = float( sleep )
-        [ main.ONOSbench.onosStart( main.Cluster.runningNodes[ i ].ipAddress ) for i in nodes ]
+        for i in nodes:
+            node = main.Cluster.runningNodes[ i ]
+            if node.inDocker:
+                main.Cluster.startONOSDockerNode( i )
+            else:
+                main.ONOSbench.onosStart( node.ipAddress )
         main.log.debug( "sleeping %i seconds" % ( sleep ) )
         time.sleep( sleep )
         for i in nodes:
-            isUp = main.ONOSbench.isup( main.Cluster.runningNodes[ i ].ipAddress )
+            node =  main.Cluster.runningNodes[ i ]
+            if node.inDocker:
+                isUp = node.CLI.dockerExec( node.name, dockerPrompt=node.dockerPrompt )
+                isUp = isUp and node.CLI.prepareForCLI()
+                isUp = isUp and node.CLI.onosSecureSSH( userName=node.karafUser, userPWD=node.karafPass )
+            else:
+                isUp = main.ONOSbench.isup( node.ipAddress )
             utilities.assert_equals( expect=main.TRUE, actual=isUp,
                                      onpass="ONOS service is ready",
                                      onfail="ONOS service did not start properly" )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py b/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py
index 5e95efe..b978b73 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/cfgtranslator.py
@@ -27,8 +27,8 @@
 DHCP_APP_ID = ONOS_GROUP_ID + '.' + DHCP_APP
 
 # Translate configuration JSON file from BMv2 driver to OFDPA-OVS driver.
-def bmv2ToOfdpa( main, cfgFile="" ):
-    didRE = r"device:(?P<swType>bmv2|tofino):(?P<swRole>leaf|spine)(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
+def bmv2ToOfdpa( main, cfgFile="", rolesRE=r'spine|leaf' ):
+    didRE = r"device:(?P<swType>bmv2|tofino):(?P<swRole>" + rolesRE + ")(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
     if not cfgFile:
         cfgFile = "%s%s.json" % ( main.configPath + main.forJson,
                                   main.cfgName )
@@ -84,12 +84,21 @@
                         netcfg[ 'apps' ][ DHCP_APP_ID ][ 'default' ][ i ][ 'dhcpServerConnectPoint' ] = \
                             'of:' + searchObj.group( 'swNum' ).zfill(16) + '/' + searchObj.group( 'portNum' )
 
+    if 'xconnects' in netcfg.keys():
+        new_xconnects = []
+        for xconnect in netcfg[ 'xconnects' ]:
+            searchObj = re.search( didRE, xconnect.get( "deviceId" ) )
+            if searchObj:
+                new_device = 'of:' + searchObj.group( 'swNum' ).zfill( 16 )
+                xconnect[ 'deviceId' ] = new_device
+            new_xconnects.append( xconnect )
+        netcfg[ 'xconnects' ] = new_xconnects
+
     with open( cfgFile, 'w' ) as cfg:
         cfg.write( json.dumps( netcfg, indent=4, separators=( ',', ':' ), sort_keys=True ) )
 
 # Translate configuration JSON file from OFDPA-OVS driver to BMv2 driver.
-def ofdpaToBmv2( main, switchPrefix="bmv2", cfgFile="" ):
-    didRE= r"device:(?P<swType>bmv2|tofino):(?P<swRole>leaf|spine)(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
+def ofdpaToBmv2( main, switchPrefix="bmv2", cfgFile="", roleMap={r'0*[1-9]([0-9]){2}': 'spine', r'0{15}[1-9]': "leaf"} ):
     didRE = r"of:0*(?P<swNum>[1-9][0-9]*)(/(?P<portNum>[0-9]+))?"
     if not cfgFile:
         cfgFile = "%s%s.json" % ( main.configPath + main.forJson,
@@ -101,7 +110,14 @@
         for port in netcfg[ 'ports' ].keys():
             searchObj = re.search( didRE, port )
             if searchObj:
-                new_port = 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
+                # search  for a match between keys of roleMap and device id and set role to value of key
+                role = "leaf"
+                for roleRE, roleValue in roleMap.items():
+                    roleMatch = re.search( roleRE, searchObj.group( 'swNum' ) )
+                    if roleMatch:
+                        role = roleValue
+                        break
+                new_port = 'device:' + switchPrefix + ':' + role + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
                 netcfg[ 'ports' ][ new_port ] = netcfg[ 'ports' ].pop( port )
 
     if 'hosts' in netcfg.keys():
@@ -111,7 +127,14 @@
                 for location in hostCfg[ 'basic' ][ 'locations' ]:
                     searchObj = re.search( didRE, location )
                     if searchObj:
-                        new_locations.append( 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' ) )
+                        # search  for a match between keys of roleMap and device id and set role to value of key
+                        role = "leaf"
+                        for roleRE, roleValue in roleMap.items():
+                            roleMatch = re.search( roleRE, searchObj.group( 'swNum' ) )
+                            if roleMatch:
+                                role = roleValue
+                                break
+                        new_locations.append( 'device:' + switchPrefix + ':' + role + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' ) )
                     else:
                         new_locations.append( location )
                 netcfg[ 'hosts' ][ host ][ 'basic' ][ 'locations' ] = new_locations
@@ -119,7 +142,14 @@
                 location = hostCfg[ 'basic' ][ 'locations' ]
                 searchObj = re.search( didRE, location )
                 if searchObj:
-                    new_location = 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
+                    # search  for a match between keys of roleMap and device id and set role to value of key
+                    role = "leaf"
+                    for roleRE, roleValue in roleMap.items():
+                        roleMatch = re.search( roleRE, searchObj.group( 'swNum' ) )
+                        if roleMatch:
+                            role = roleValue
+                            break
+                    new_location = 'device:' + switchPrefix + ':' + role + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
                     netcfg[ 'hosts' ][ host ][ 'basic' ][ 'locations' ] = new_location
 
     if 'devices' in netcfg.keys():
@@ -127,6 +157,7 @@
             searchObj = re.search( didRE, device )
             new_device = device
             if searchObj:
+                #TODO This or roleMap? maybe use this to populate role Map?
                 isLeaf = netcfg[ 'devices' ][ device ][ SR_APP ][ 'isEdgeRouter' ]
                 if isLeaf is True:
                     new_device = 'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' )
@@ -137,7 +168,14 @@
                 searchObj = re.search( didRE,
                                        netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ])
                 if searchObj:
-                    netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ] = 'device:' + switchPrefix + ':leaf' + \
+                    # search  for a match between keys of roleMap and device id and set role to value of key
+                    role = "leaf"
+                    for roleRE, roleValue in roleMap.items():
+                        roleMatch = re.search( roleRE, searchObj.group( 'swNum' ) )
+                        if roleMatch:
+                            role = roleValue
+                            break
+                    netcfg[ 'devices' ][ new_device ][ SR_APP ][ 'pairDeviceId' ] = 'device:' + switchPrefix + ':' + role + \
                                                                                     searchObj.group( 'swNum' )
             if 'basic' in netcfg[ 'devices' ][ new_device ].keys():
                 if 'driver' in netcfg[ 'devices' ][ new_device ][ 'basic' ].keys():
@@ -150,8 +188,32 @@
                     searchObj = re.search( didRE,
                                            dhcpcfg[ 'dhcpServerConnectPoint' ] )
                     if searchObj:
+                        # search  for a match between keys of roleMap and device id and set role to value of key
+                        role = "leaf"
+                        for roleRE, roleValue in roleMap.items():
+                            roleMatch = re.search( roleRE, searchObj.group( 'swNum' ) )
+                            if roleMatch:
+                                role = roleValue
+                                break
                         netcfg[ 'apps' ][ DHCP_APP_ID ][ 'default' ][ i ][ 'dhcpServerConnectPoint' ] = \
-                            'device:' + switchPrefix + ':leaf' + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
+                            'device:' + switchPrefix + ':' + role + searchObj.group( 'swNum' ) + '/' + searchObj.group( 'portNum' )
+
+    if 'xconnects' in netcfg.keys():
+        new_xconnects = []
+        for xconnect in netcfg[ 'xconnects' ]:
+            searchObj = re.search( didRE, xconnect.get( "deviceId" ) )
+            if searchObj:
+                # search  for a match between keys of roleMap and device id and set role to value of key
+                role = "leaf"
+                for roleRE, roleValue in roleMap.items():
+                    roleMatch = re.search( roleRE, searchObj.group( 'swNum' ) )
+                    if roleMatch:
+                        role = roleValue
+                        break
+                new_device = 'device:' + switchPrefix + ':' + role + searchObj.group( 'swNum' )
+                xconnect[ 'deviceId' ] = new_device
+            new_xconnects.append( xconnect )
+        netcfg[ 'xconnects' ] = new_xconnects
 
     with open( cfgFile, 'w' ) as cfg:
         cfg.write( json.dumps( netcfg, indent=4, separators=( ',', ':' ), sort_keys=True ) )