[ONOS-7216] Creating a test for onos-form-cluster functionality
Change-Id: I67a5a05c30465a56809148e5de5983d1d71045fe
diff --git a/TestON/JenkinsFile/FUNCJenkinsFile b/TestON/JenkinsFile/FUNCJenkinsFile
index 3555299..857ff54 100644
--- a/TestON/JenkinsFile/FUNCJenkinsFile
+++ b/TestON/JenkinsFile/FUNCJenkinsFile
@@ -15,7 +15,8 @@
"FUNCnetconf" : [wiki_link:prop["WikiPrefix"]+"-"+"FUNCnetconf", wiki_file:"FUNCnetconfWiki.txt"],
"FUNCgroup" : [wiki_link:prop["WikiPrefix"]+"-"+"FUNCgroup", wiki_file:"FUNCgroupWiki.txt"],
"FUNCintent" : [wiki_link:prop["WikiPrefix"]+"-"+"FUNCintent", wiki_file:"FUNCintentWiki.txt"],
-"FUNCintentRest" : [wiki_link:prop["WikiPrefix"]+"-"+"FUNCintentRest", wiki_file:"FUNCintentRestWiki.txt"]
+"FUNCintentRest" : [wiki_link:prop["WikiPrefix"]+"-"+"FUNCintentRest", wiki_file:"FUNCintentRestWiki.txt"],
+"FUNCformCluster" : [wiki_link:prop["WikiPrefix"]+"-"+"FUNCformCluster", wiki_file:"FUNCformClusterWiki.txt"]
]
table_name = "executed_test_tests"
result_name = "executed_test_results"
@@ -118,7 +119,7 @@
done
ls -al
cd '''
- if( prop["manualRun"] == "false" ){
+ if( prop["manualRun"] == "false" || prop["postResult"] == "true" ){
// Post Results
withCredentials([
string(credentialsId: 'db_pass', variable: 'pass'),
@@ -163,7 +164,7 @@
}
}
- if( prop["manualRun"] == "false" ){
+ if( prop["manualRun"] == "false" || prop["postResult"] == "true" ){
def post = build job: "Pipeline_postjob_VM", propagate: false,
parameters: [
string(name: 'Wiki_Contents', value: fileContents),
diff --git a/TestON/JenkinsFile/JenkinsfileTrigger b/TestON/JenkinsFile/JenkinsfileTrigger
index d0ce382..6b1da7b 100644
--- a/TestON/JenkinsFile/JenkinsfileTrigger
+++ b/TestON/JenkinsFile/JenkinsfileTrigger
@@ -6,15 +6,16 @@
AllTheTests=
[
"FUNC":[
- "FUNCipv6Intent" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCoptical" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCflow" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCnetCfg": ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCovsdbtest" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCnetconf" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCgroup" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
- "FUNCintent" : ["basic":false, "extra_A":true, "extra_B":false, "day":""],
- "FUNCintentRest" : ["basic":false, "extra_A":false, "extra_B":true, "day":""]
+ "FUNCipv6Intent" : ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCoptical" : ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCflow" : ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCnetCfg": ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCovsdbtest" : ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCnetconf" : ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCgroup" : ["basic":true, "extra_A":false, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCformCluster" :["basic":false, "extra_A":false, "extra_B":false, "new_Test":true, "day":""],
+ "FUNCintent" : ["basic":false, "extra_A":true, "extra_B":false, "new_Test":false, "day":""],
+ "FUNCintentRest" : ["basic":false, "extra_A":false, "extra_B":true, "new_Test":false, "day":""],
],
"HA":[
"HAsanity" : ["basic":true, "extra_A":false, "extra_B":false, "day":""],
@@ -197,6 +198,7 @@
}
def monday( getResult ){
FUNC_choices += adder( "FUNC", "basic", true, "M", getResult )
+ FUNC_choices += adder( "FUNC", "new_Test", true, "M", getResult )
FUNC_choices += adder( "FUNC", "extra_A", true, "M", getResult )
HA_choices += adder( "HA", "basic", true, "M", getResult )
HA_choices += adder( "HA", "extra_A", true, "M", getResult )
@@ -205,6 +207,7 @@
}
def tuesday( getDay, getResult ){
FUNC_choices += adder( "FUNC", "basic", getDay, "T", getResult )
+ FUNC_choices += adder( "FUNC", "new_Test", getDay, "T", getResult )
FUNC_choices += adder( "FUNC", "extra_B", getDay, "T", getResult )
HA_choices += adder( "HA", "basic", getDay, "T", getResult )
HA_choices += adder( "HA", "extra_B", getDay, "T", getResult )
@@ -216,6 +219,7 @@
}
def wednesday( getDay, getResult ){
FUNC_choices += adder( "FUNC", "basic", getDay, "W", getResult )
+ FUNC_choices += adder( "FUNC", "new_Test", getDay, "W", getResult )
FUNC_choices += adder( "FUNC", "extra_A", getDay, "W", getResult )
HA_choices += adder( "HA", "basic", getDay, "W", getResult )
HA_choices += adder( "HA", "extra_A", getDay, "W", getResult )
@@ -225,6 +229,7 @@
}
def thursday( getDay, getResult ){
FUNC_choices += adder( "FUNC", "basic", getDay, "Th", getResult )
+ FUNC_choices += adder( "FUNC", "new_Test", getDay, "Th", getResult )
FUNC_choices += adder( "FUNC", "extra_B", getDay, "Th", getResult )
HA_choices += adder( "HA", "basic", getDay, "Th", getResult )
HA_choices += adder( "HA", "extra_B", getDay, "Th", getResult )
@@ -233,6 +238,7 @@
}
def friday( getDay, getResult ){
FUNC_choices += adder( "FUNC", "basic", getDay, "F", getResult )
+ FUNC_choices += adder( "FUNC", "new_Test", getDay, "F", getResult )
FUNC_choices += adder( "FUNC", "extra_A", getDay, "F", getResult )
HA_choices += adder( "HA", "basic", getDay, "F", getResult )
HA_choices += adder( "HA", "extra_A", getDay, "F", getResult )
@@ -422,7 +428,7 @@
}
def oldFlowCheck( jobOn, onos_branch ){
result = ""
- if( isOldFlow && jobOn == "SCPF" && onos_branch="master" )
+ if( isOldFlow && jobOn == "SCPF" && onos_branch== "master" )
result = '''sed -i -e 's/@Component(immediate = true)/@Component(enabled = false)/g' ~/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
sed -i -e 's/@Component(enabled = false)/@Component(immediate = true)/g' ~/onos/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ECFlowRuleStore.java'''
return result
diff --git a/TestON/drivers/common/cli/onosdriver.py b/TestON/drivers/common/cli/onosdriver.py
index 73b1755..31f26d5 100755
--- a/TestON/drivers/common/cli/onosdriver.py
+++ b/TestON/drivers/common/cli/onosdriver.py
@@ -2437,3 +2437,37 @@
except Exception:
main.log.exception( self.name + ": Uncaught exception!" )
main.cleanAndExit()
+
+ def formCluster( self, onosIPs ):
+ """
+ From ONOS cluster for IP addresses in onosIPs list
+ """
+ try:
+ onosIPs = " ".join( onosIPs )
+ command = "onos-form-cluster {}".format( onosIPs )
+ main.log.info( "Sending: " + command )
+ self.handle.sendline( "" )
+ self.handle.expect( self.prompt )
+ self.handle.sendline( command )
+ self.handle.expect( self.prompt )
+ handle = self.handle.before
+ main.log.debug( handle )
+ assert handle is not None, "Error in sendline"
+ assert "Command not found:" not in handle, handle
+ assert "Error" not in handle, handle
+ assert "Exception:" not in handle, handle
+ assert "curl:" not in handle, handle
+ return main.TRUE
+ except AssertionError:
+ main.log.exception( "{} Error in onos-form-cluster output:".format( self.name ) )
+ return main.FALSE
+ except TypeError:
+ main.log.exception( self.name + ": Object not as expected" )
+ return main.FALSE
+ except pexpect.EOF:
+ main.log.error( self.name + ": EOF exception found" )
+ main.log.error( self.name + ": " + self.handle.before )
+ main.cleanAndExit()
+ except Exception:
+ main.log.exception( self.name + ": Uncaught exception!" )
+ main.cleanAndExit()
diff --git a/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.params b/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.params
new file mode 100644
index 0000000..b8da936
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.params
@@ -0,0 +1,44 @@
+<PARAMS>
+ # CASE - Description
+ # 0 - Variable initialization and optional pull and build ONOS package
+ # 1 - install ONOS with single node
+ # 2 - Starting ONOS with forming clusters.
+ # 3 - Checking the ONOS configuration with single node
+ # 4 - Checking the ONOS configuration with cluster formed
+ # 5 - Starting Mininet and verifying topology
+
+ <testcases>0,1,3,2,4,5</testcases>
+
+ <DEPENDENCY>
+ <path>/tests/FUNC/FUNCformCluster/dependencies/</path>
+ <file>formClusterFuncs</file>
+ </DEPENDENCY>
+ <GRAPH>
+ <nodeCluster>BM</nodeCluster>
+ <builds>20</builds>
+ </GRAPH>
+ <ENV>
+ <cellApps>drivers,openflow</cellApps>
+ <additionalApp>org.onosproject.fwd</additionalApp>
+ <cellBasicName>singleTemp</cellBasicName>
+ </ENV>
+ <GIT>
+ <pull>False</pull>
+ <branch>master</branch>
+ </GIT>
+ <TEST>
+ <numNodes>7</numNodes>
+ </TEST>
+ <RETRY>
+ <pingall>2</pingall>
+ <topoCheck>2</topoCheck>
+ </RETRY>
+ <SLEEP>
+ <afterONOSStart>15</afterONOSStart>
+ <pingall>3</pingall>
+ </SLEEP>
+ <MININET>
+ <topo>mn --topo tree,2,2</topo>
+ </MININET>
+
+</PARAMS>
diff --git a/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.py b/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.py
new file mode 100644
index 0000000..55b6e41
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.py
@@ -0,0 +1,261 @@
+"""
+Copyright 2017 Open Networking Foundation ( ONF )
+
+Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
+the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
+or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
+
+ TestON is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ ( at your option ) any later version.
+
+ TestON is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TestON. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+
+class FUNCformCluster:
+
+ def __init__( self ):
+ self.default = ''
+
+ def CASE0( self, main ):
+ import imp
+ import re
+
+ try:
+ from tests.dependencies.ONOSSetup import ONOSSetup
+ main.testSetUp = ONOSSetup()
+ except ImportError:
+ main.log.error( "ONOSSetup not found. exiting the test" )
+ main.cleanAndExit()
+ main.testSetUp.envSetupDescription()
+ stepResult = main.TRUE
+ try:
+ main.apps = main.params[ 'ENV' ][ 'cellApps' ]
+ main.additionalApp = main.params[ 'ENV' ][ 'additionalApp' ]
+ main.cellBasicName = main.params[ 'ENV' ][ 'cellBasicName' ]
+ main.mnTopo = main.params[ 'MININET' ][ 'topo' ]
+ main.startSleep = int( main.params[ 'SLEEP' ][ 'afterONOSStart' ] )
+ dependencyPath = main.testOnDirectory + \
+ main.params[ 'DEPENDENCY' ][ 'path' ]
+ dependencyFile = main.params[ 'DEPENDENCY' ][ 'file' ]
+ main.numNodes = int( main.params[ 'TEST' ][ 'numNodes' ] )
+ main.funcs = imp.load_source( dependencyFile,
+ dependencyPath +
+ dependencyFile +
+ ".py" )
+ main.pingallRetry = int( main.params[ 'RETRY' ][ 'pingall' ] )
+ main.topoCheckRetry = int( main.params[ 'RETRY' ][ 'topoCheck' ] )
+ main.pingallSleep = int( main.params[ 'SLEEP' ][ 'pingall' ] )
+
+ except Exception as e:
+ main.testSetUp.envSetupException( e )
+ if len( main.Cluster.runningNodes ) != main.numNodes:
+ main.log.error( "The number of the nodes needs to be " + str( main.numNodes ) +
+ "\nExiting Test..." )
+ main.cleanAndExit()
+ main.testSetUp.evnSetupConclusion( stepResult )
+
+ def CASE1( self, main ):
+ """
+ - Create cells with single node
+ - apply each cell to each cluster
+ - install ONOS
+ - ssh-secure
+ - start the ONOS
+ - activate org.onosproject.fwd to cluster 1 only.
+ """
+ main.case( "Starting ONOS with indepenent configuration" )
+ main.caseExplanation = "Starting ONOS with one node itself."
+ main.testSetUp.killingAllOnos( main.Cluster, True, False )
+ threads = []
+ i = 0
+ for cluster in main.Cluster.runningNodes:
+ i += 1
+ t = main.Thread( target=cluster.Bench.createCellFile,
+ name="create-cell",
+ args=[ main.ONOSbench.ip_address,
+ main.cellBasicName + str( i ),
+ main.Mininet1.ip_address,
+ main.apps,
+ cluster.ip_address,
+ main.ONOScell.karafUser,
+ True ] )
+ threads.append( t )
+ t.start()
+ cellResult = main.TRUE
+ for t in threads:
+ t.join()
+ cellResult = cellResult and t.result
+
+ threads = []
+ i = 0
+ for cluster in main.Cluster.runningNodes:
+ i += 1
+ t = main.Thread( target=cluster.Bench.setCell,
+ name="set-cell",
+ args=[ main.cellBasicName + str( i ) ] )
+ threads.append( t )
+ t.start()
+ for t in threads:
+ t.join()
+ cellResult = cellResult and t.result
+
+ threads = []
+ i = 0
+ for cluster in main.Cluster.runningNodes:
+ i += 1
+ t = main.Thread( target=cluster.Bench.verifyCell,
+ name="verify-cell" )
+ threads.append( t )
+ t.start()
+ for t in threads:
+ t.join()
+ cellResult = cellResult and t.result
+
+ uninstallResult = main.testSetUp.uninstallOnos( main.Cluster, True )
+ buildResult = main.testSetUp.buildOnos( main.Cluster )
+ installResult = main.testSetUp.installOnos( main.Cluster, True, True )
+ secureSshResult = main.testSetUp.setupSsh( main.Cluster )
+ onosServiceResult = main.testSetUp.checkOnosService( main.Cluster )
+ onosCliResult = main.testSetUp.startOnosClis( main.Cluster )
+ activateResult = main.Cluster.active( 0 ).CLI.activateApp( main.additionalApp )
+
+ result = cellResult and uninstallResult and buildResult and installResult and \
+ secureSshResult and onosServiceResult and onosCliResult and activateResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=result,
+ onpass="Successfully started the ONOS",
+ onfail="Failed to start the ONOS" )
+
+ def CASE2( self, main ):
+ """
+ - Execute onos-form-cluster to all the nodes.
+ - start the ONOS.
+ - activate org.onosproject.fwd to cluster 1.
+ """
+ main.case( "Starting ONOS with form cluster." )
+ main.caseExplanation = "This will connect all the clusters of the ONOS."
+ main.step( "Executing onos-form-cluster" )
+ formClusterResult = main.ONOSbench.formCluster( main.Cluster.getIps( True, True ) )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=result,
+ onpass="Successfully formed clusters to ONOS",
+ onfail="Failed to form clusters to ONOS" )
+ onosServiceResult = main.testSetUp.checkOnosService( main.Cluster )
+ onosCliResult = main.testSetUp.startOnosClis( main.Cluster )
+ activateResult = main.Cluster.active( 0 ).CLI.activateApp( main.additionalApp )
+ result = formClusterResult and onosServiceResult and onosCliResult and activateResult
+ utilities.assert_equals( expect=main.TRUE,
+ actual=result,
+ onpass="Successfully formed clusters to ONOS and started",
+ onfail="Failed to form clusters to ONOS and started" )
+
+ def CASE3( self, main ):
+ """
+ Checking the configuration of the ONOS with single-node ONOS.
+ It will check :
+ - the number of the node : They should only have 1 node.
+ - App status : Only the first node should have additional app installed.
+ """
+ import time
+ main.case( "Checking the configuration of the ONOS" )
+ main.caseExplanation = "Checking the number of the nodes and apps"
+ main.step( "Checking the number of the nodes" )
+ main.log.info( "Sleep for " + str( main.startSleep ) + " to give enough time to ONOS")
+ time.sleep( main.startSleep )
+ result = main.funcs.checkingNumNodes( main, 1 )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=result,
+ onpass="Successfully checking the nodes numbers of the ONOS",
+ onfail="Failed to checking the nodes numbers of the ONOS" )
+ main.step( "Checking the app status. Only the first node should have " +
+ main.additionalApp + " installed." )
+ i = 0
+ appResult = main.TRUE
+ for cluster in main.Cluster.active():
+ appResult = appResult and main.funcs.checkingApp( main, main.additionalApp, cluster, True if i == 0 else False )
+ i += 1
+ main.Cluster.active( 0 ).CLI.deactivateApp( main.additionalApp )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=appResult,
+ onpass="Successfully checking the app status of the ONOS",
+ onfail="Failed to checking the app status of the ONOS" )
+
+ def CASE4( self, main ):
+ """
+ Checking the configuration of the ONOS with form-cluster.
+ It will check :
+ - the number of the node : They should only have 7 nodes.
+ - state of the node.
+ - App status : All the nodes should have additional app.
+ """
+ import time
+ main.case( "Checking the configuration of the ONOS after form-cluster" )
+ main.caseExplanation = "Checking the number of the nodes and apps"
+ main.step( "Checking the number of the nodes" )
+ main.log.info( "Sleep for " + str( main.startSleep ) + " to give enough time to ONOS")
+ time.sleep( main.startSleep )
+ result = main.funcs.checkingNumNodes( main, main.numNodes )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=result,
+ onpass="Successfully checking the nodes numbers of the ONOS",
+ onfail="Failed to checking the nodes numbers of the ONOS" )
+ main.step( "Checking the status of the nodes" )
+ nodeStatusResult = main.TRUE if main.Cluster.nodesCheck() else main.FALSE
+ utilities.assert_equals( expect=main.TRUE,
+ actual=nodeStatusResult,
+ onpass="The status of the nodes were in READY as expected",
+ onfail="The status of the nodes were NOT in READY as expected" )
+ main.step( "Checking the app status. All nodes should have " +
+ main.additionalApp + " installed." )
+ appResult = main.TRUE
+ for cluster in main.Cluster.active():
+ appResult = appResult and main.funcs.checkingApp( main, main.additionalApp, cluster, True )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=appResult,
+ onpass="Successfully checking the app status of the ONOS",
+ onfail="Failed to checking the app status of the ONOS" )
+
+ def CASE5( self, main ):
+ """
+ Run simple mininet to check connectivity of ONOS clusters.
+ - It will do ping all
+ - It will compare topos between mininet and ONOS.
+ """
+ try:
+ from tests.dependencies.topology import Topology
+ except ImportError:
+ main.log.error( "Topology not found exiting the test" )
+ main.cleanAndExit()
+ try:
+ main.Topology
+ except ( NameError, AttributeError ):
+ main.Topology = Topology()
+ main.case( "Starting 2x2 Tree Mininet and compare the Topology" )
+ main.caseExplanation = "Starting 2x2 Mininet and assign ONOS controllers to switches."
+ main.step( "Starting Mininet" )
+ for ctrl in main.Cluster.runningNodes:
+ main.mnTopo += " --controller remote,ip=" + ctrl.ipAddress
+ startMnResult = main.Mininet1.startNet( mnCmd=main.mnTopo )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=startMnResult,
+ onpass="Successfully started Mininet",
+ onfail="Failed to start Mininet" )
+ main.step( "Pingall hosts to confirm ONOS discovery" )
+ pingResult = utilities.retry( f=main.Mininet1.pingall,
+ retValue=main.FALSE,
+ attempts=main.pingallRetry,
+ sleep=main.pingallSleep )
+ utilities.assert_equals( expect=main.TRUE,
+ actual=pingResult,
+ onpass="Successfully discovered hosts",
+ onfail="Failed to discover hosts" )
+ main.Topology.compareTopos( main.Mininet1, main.topoCheckRetry )
diff --git a/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.topo b/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.topo
new file mode 100644
index 0000000..c96b419
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCformCluster/FUNCformCluster.topo
@@ -0,0 +1,36 @@
+<TOPOLOGY>
+ <COMPONENT>
+
+ <ONOScell>
+ <host>localhost</host> # ONOS "bench" machine
+ <user>sdn</user>
+ <password>rocks</password>
+ <type>OnosClusterDriver</type>
+ <connect_order>1</connect_order>
+ <COMPONENTS>
+ <cluster_name></cluster_name> # Used as a prefix for cluster components. Defaults to 'ONOS'
+ <diff_clihost></diff_clihost> # if it has different host other than localhost for CLI. True or empty. OC# will be used for True.
+ <karaf_username></karaf_username>
+ <karaf_password></karaf_password>
+ <web_user></web_user>
+ <web_pass></web_pass>
+ <rest_port></rest_port>
+ <prompt></prompt> # TODO: we technically need a few of these, one per component
+ <onos_home></onos_home> # defines where onos home is
+ <nodes> 7 </nodes> # number of nodes in the cluster
+ </COMPONENTS>
+ </ONOScell>
+
+ <Mininet1>
+ <host>OCN</host>
+ <user>sdn</user>
+ <password>rocks</password>
+ <type>MininetCliDriver</type>
+ <connect_order>2</connect_order>
+ <COMPONENTS>
+ <prompt></prompt>
+ </COMPONENTS>
+ </Mininet1>
+
+ </COMPONENT>
+</TOPOLOGY>
diff --git a/TestON/tests/FUNC/FUNCformCluster/README b/TestON/tests/FUNC/FUNCformCluster/README
new file mode 100644
index 0000000..4ab2cc6
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCformCluster/README
@@ -0,0 +1,13 @@
+Summary:
+ This test is checking the functionality of onos-form-cluster.
+ It will first run 7 single node of ONOS and check the number of the node and app.
+ Since it is single node, each of them should have 1 node.
+ Then, it will form 7 clusters to the ONOS and re-check the number of the nodes, status of nodes,
+ and app.
+ This time, it should have 7 nodes and installing app from one node should affect the other nodes.
+ The status of the Nodes should be "READY"
+ Lastly, it will run the Mininet with controllers of 7 nodes to pingall and compare topology
+ of ONOS and Mininet.
+
+Required:
+ Since it is fixed with 7 nodes, test will be forced to exit unless it has 7 clusters.
\ No newline at end of file
diff --git a/TestON/tests/FUNC/FUNCformCluster/__init__.py b/TestON/tests/FUNC/FUNCformCluster/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCformCluster/__init__.py
diff --git a/TestON/tests/FUNC/FUNCformCluster/dependencies/formClusterFuncs.py b/TestON/tests/FUNC/FUNCformCluster/dependencies/formClusterFuncs.py
new file mode 100644
index 0000000..044c8a3
--- /dev/null
+++ b/TestON/tests/FUNC/FUNCformCluster/dependencies/formClusterFuncs.py
@@ -0,0 +1,64 @@
+"""
+Copyright 2017 Open Networking Foundation ( ONF )
+
+Please refer questions to either the onos test mailing list at <onos-test@onosproject.org>,
+the System Testing Plans and Results wiki page at <https://wiki.onosproject.org/x/voMg>,
+or the System Testing Guide page at <https://wiki.onosproject.org/x/WYQg>
+
+ TestON is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ ( at your option ) any later version.
+
+ TestON is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TestON. If not, see <http://www.gnu.org/licenses/>.
+"""
+import json
+
+def checkingNumNodes( main, expected ):
+ """
+ check the number of nodes
+ :param expected:
+ Expected number of nodes
+ :return:
+ main.TRUE if all the number of the nodes are matched
+ main.FALSE if not.
+ """
+ result = main.TRUE
+ for cluster in main.Cluster.active():
+ actual = json.loads( cluster.CLI.summary() ).get( 'nodes' )
+ thisResult = main.TRUE if expected == actual else main.FALSE
+ if not thisResult:
+ main.log.error( "Number of the nodes not matched." +
+ "\nExpected nodes: " + str( expected ) +
+ "\nActual nodes: " + str( actual ) )
+ return result
+
+def checkingApp( main, appToBeChecked, cluster, expectedToBeThere ):
+ """
+ check the existence of app
+ :param appToBeChecked:
+ Name of the apps to be checked
+ :param cluster:
+ nth cluster to be checked
+ :param expectedToBeThere:
+ True if it is expected to be installed. False if it is expected not to be installed.
+ :return:
+ main.TRUE if they are all matched. Otherwise main.FALSE
+ """
+ result = False
+ appStatus = cluster.CLI.appStatus( appToBeChecked )
+ if appStatus == "ACTIVE" if expectedToBeThere else "UNINSTALL":
+ result = True
+ if result:
+ main.log.info( "App is " + ( "not " if not expectedToBeThere else "" ) + "there as expected" )
+ return main.TRUE
+ else:
+ main.log.error("App is " + ( "" if not expectedToBeThere else "not " ) + "there which should" +
+ ( "n't" if not expectedToBeThere else "" ) + " be there.")
+ return main.FALSE
diff --git a/TestON/tests/HA/HAcontinuousStopNodes/HAcontinuousStopNodes.py b/TestON/tests/HA/HAcontinuousStopNodes/HAcontinuousStopNodes.py
index 811e04f..537ab1b 100644
--- a/TestON/tests/HA/HAcontinuousStopNodes/HAcontinuousStopNodes.py
+++ b/TestON/tests/HA/HAcontinuousStopNodes/HAcontinuousStopNodes.py
@@ -171,9 +171,8 @@
onfail="ONOS nodes NOT successfully stopped" )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
sleep=15,
attempts=5 )
diff --git a/TestON/tests/HA/HAfullNetPartition/HAfullNetPartition.py b/TestON/tests/HA/HAfullNetPartition/HAfullNetPartition.py
index cf7fe73..c72cafa 100644
--- a/TestON/tests/HA/HAfullNetPartition/HAfullNetPartition.py
+++ b/TestON/tests/HA/HAfullNetPartition/HAfullNetPartition.py
@@ -244,9 +244,8 @@
main.cleanAndExit()
"""
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
sleep=15,
attempts=5 )
diff --git a/TestON/tests/HA/HAkillNodes/HAkillNodes.py b/TestON/tests/HA/HAkillNodes/HAkillNodes.py
index 01ebe38..7f18a3a 100644
--- a/TestON/tests/HA/HAkillNodes/HAkillNodes.py
+++ b/TestON/tests/HA/HAkillNodes/HAkillNodes.py
@@ -161,9 +161,8 @@
onfail="ONOS nodes NOT successfully killed" )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
sleep=15,
attempts=5 )
diff --git a/TestON/tests/HA/HAscaling/HAscaling.py b/TestON/tests/HA/HAscaling/HAscaling.py
index 63aa1e5..e405351 100644
--- a/TestON/tests/HA/HAscaling/HAscaling.py
+++ b/TestON/tests/HA/HAscaling/HAscaling.py
@@ -203,9 +203,8 @@
main.Cluster.startCLIs()
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
attempts=5 )
utilities.assert_equals( expect=True, actual=nodeResults,
onpass="Nodes check successful",
diff --git a/TestON/tests/HA/HAsingleInstanceRestart/HAsingleInstanceRestart.py b/TestON/tests/HA/HAsingleInstanceRestart/HAsingleInstanceRestart.py
index 584232a..9c8d923 100644
--- a/TestON/tests/HA/HAsingleInstanceRestart/HAsingleInstanceRestart.py
+++ b/TestON/tests/HA/HAsingleInstanceRestart/HAsingleInstanceRestart.py
@@ -716,9 +716,8 @@
onpass="Topology Check Test successful",
onfail="Topology Check Test NOT successful" )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
attempts=5 )
utilities.assert_equals( expect=True, actual=nodeResults,
diff --git a/TestON/tests/HA/HAstopNodes/HAstopNodes.py b/TestON/tests/HA/HAstopNodes/HAstopNodes.py
index 7b57730..e84d011 100644
--- a/TestON/tests/HA/HAstopNodes/HAstopNodes.py
+++ b/TestON/tests/HA/HAstopNodes/HAstopNodes.py
@@ -160,9 +160,8 @@
onfail="ONOS nodes NOT successfully stopped" )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
sleep=15,
attempts=5 )
diff --git a/TestON/tests/HA/HAswapNodes/HAswapNodes.py b/TestON/tests/HA/HAswapNodes/HAswapNodes.py
index e0751f6..b7da7bc 100644
--- a/TestON/tests/HA/HAswapNodes/HAswapNodes.py
+++ b/TestON/tests/HA/HAswapNodes/HAswapNodes.py
@@ -201,9 +201,8 @@
main.testSetUp.startOnosClis( main.Cluster )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
attempts=5 )
utilities.assert_equals( expect=True, actual=nodeResults,
onpass="Nodes check successful",
diff --git a/TestON/tests/HA/dependencies/HA.py b/TestON/tests/HA/dependencies/HA.py
index 2227146..68f19d6 100644
--- a/TestON/tests/HA/dependencies/HA.py
+++ b/TestON/tests/HA/dependencies/HA.py
@@ -271,39 +271,6 @@
main.log.error( "Inconsistent leaderboards:" + str( leaderList ) )
return ( result, leaderList )
- def nodesCheck( self, nodes ):
- nodesOutput = []
- results = True
- threads = []
- for node in nodes:
- t = main.Thread( target=node.nodes,
- name="nodes-" + str( node ),
- args=[] )
- threads.append( t )
- t.start()
-
- for t in threads:
- t.join()
- nodesOutput.append( t.result )
- ips = sorted( main.Cluster.getIps( activeOnly=True ) )
- for i in nodesOutput:
- try:
- current = json.loads( i )
- activeIps = []
- currentResult = False
- for node in current:
- if node[ 'state' ] == 'READY':
- activeIps.append( node[ 'ip' ] )
- activeIps.sort()
- if ips == activeIps:
- currentResult = True
- except ( ValueError, TypeError ):
- main.log.error( "Error parsing nodes output" )
- main.log.warn( repr( i ) )
- currentResult = False
- results = results and currentResult
- return results
-
def generateGraph( self, testName, plotName="Plot-HA", index=2 ):
# GRAPHS
# NOTE: important params here:
@@ -342,9 +309,8 @@
main.ONOSbench.handle.expect( "\$" )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( self.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
attempts=5 )
utilities.assert_equals( expect=True, actual=nodeResults,
@@ -2759,9 +2725,8 @@
main.log.debug( "Restart time: " + str( main.restartTime ) )
# TODO: MAke this configurable. Also, we are breaking the above timer
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( self.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
sleep=15,
attempts=5 )
@@ -3378,9 +3343,8 @@
# FIXME: move this to an ONOS state case
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( self.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
attempts=5 )
utilities.assert_equals( expect=True, actual=nodeResults,
onpass="Nodes check successful",
diff --git a/TestON/tests/SCPF/SCPFmastershipFailoverLat/SCPFmastershipFailoverLat.py b/TestON/tests/SCPF/SCPFmastershipFailoverLat/SCPFmastershipFailoverLat.py
index c534841..e591381 100644
--- a/TestON/tests/SCPF/SCPFmastershipFailoverLat/SCPFmastershipFailoverLat.py
+++ b/TestON/tests/SCPF/SCPFmastershipFailoverLat/SCPFmastershipFailoverLat.py
@@ -261,9 +261,8 @@
criticalError = True
main.log.info( "Checking ONOS nodes." )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.active() ],
sleep=1,
attempts=3 )
diff --git a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
index f542554..07b0188 100644
--- a/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
+++ b/TestON/tests/USECASE/SegmentRouting/dependencies/Testcaselib.py
@@ -422,7 +422,7 @@
if len( nodes ) < main.Cluster.numCtrls:
- nodeResults = utilities.retry( Testcaselib.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
attempts=5,
sleep=10 )
@@ -478,9 +478,8 @@
onfail="ONOS CLI is not ready" )
main.step( "Checking ONOS nodes" )
- nodeResults = utilities.retry( Testcaselib.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ nodes ],
attempts=5,
sleep=10 )
utilities.assert_equals( expect=True, actual=nodeResults,
@@ -587,28 +586,3 @@
main.Cluster.active( 0 ).REST.removeNetCfg( subjectClass="apps",
subjectKey="org.onosproject.segmentrouting",
configKey="xconnect" )
-
- @staticmethod
- def nodesCheck( nodes ):
- results = True
- nodesOutput = main.Cluster.command( "nodes", specificDriver=2 )
- ips = sorted( main.Cluster.getIps( activeOnly=True ) )
- for i in nodesOutput:
- try:
- current = json.loads( i )
- activeIps = []
- currentResult = False
- for node in current:
- if node[ 'state' ] == 'READY':
- activeIps.append( node[ 'ip' ] )
- currentResult = True
- for ip in ips:
- if ip not in activeIps:
- currentResult = False
- break
- except ( ValueError, TypeError ):
- main.log.error( "Error parsing nodes output" )
- main.log.warn( repr( i ) )
- currentResult = False
- results = results and currentResult
- return results
diff --git a/TestON/tests/USECASE/VPLS/VPLSfailsafe/VPLSfailsafe.py b/TestON/tests/USECASE/VPLS/VPLSfailsafe/VPLSfailsafe.py
index a7dfa3b..9778b68 100644
--- a/TestON/tests/USECASE/VPLS/VPLSfailsafe/VPLSfailsafe.py
+++ b/TestON/tests/USECASE/VPLS/VPLSfailsafe/VPLSfailsafe.py
@@ -421,9 +421,8 @@
# Checking if all nodes appear with status READY using 'nodes' command
main.step( "Checking ONOS nodes." )
- nodeResults = utilities.retry( main.HA.nodesCheck,
+ nodeResults = utilities.retry( main.Cluster.nodesCheck,
False,
- args=[ main.Cluster.runningNodes ],
sleep=main.timeSleep,
attempts=main.numAttempts )
diff --git a/TestON/tests/dependencies/Cluster.py b/TestON/tests/dependencies/Cluster.py
index 210134f..b0af55e 100644
--- a/TestON/tests/dependencies/Cluster.py
+++ b/TestON/tests/dependencies/Cluster.py
@@ -18,6 +18,7 @@
You should have received a copy of the GNU General Public License
along with TestON. If not, see <http://www.gnu.org/licenses/>.
"""
+import json
class Cluster():
def __str__( self ):
@@ -339,6 +340,28 @@
self.controllers[ i ].active = True
return result
+ def nodesCheck( self ):
+ results = True
+ nodesOutput = self.command( "nodes", specificDriver=2 )
+ ips = sorted( self.getIps( activeOnly=True ) )
+ for i in nodesOutput:
+ try:
+ current = json.loads( i )
+ activeIps = []
+ currentResult = False
+ for node in current:
+ if node[ 'state' ] == 'READY':
+ activeIps.append( node[ 'ip' ] )
+ activeIps.sort()
+ if ips == activeIps:
+ currentResult = True
+ except ( ValueError, TypeError ):
+ main.log.error( "Error parsing nodes output" )
+ main.log.warn( repr( i ) )
+ currentResult = False
+ results = results and currentResult
+ return results
+
def printResult( self, results, activeList, logLevel="debug" ):
"""
Description: