Initial implementation of ONOS cluster driver
- Create CLI, REST, and "Bench" components for a cluster
- Return driver object when it is created
- Add __str__ and __repr__ implementations for drivers
- Add first pass at a cluster class
- Prototype with clustered Sample test
- Prototype with HAsanity test
- Add new Exception class for SkipCase
Change-Id: I32ee7cf655ab9a2a5cfccf5f891ca71a6a70c1ee
diff --git a/TestON/tests/dependencies/Cluster.py b/TestON/tests/dependencies/Cluster.py
new file mode 100644
index 0000000..01dc767
--- /dev/null
+++ b/TestON/tests/dependencies/Cluster.py
@@ -0,0 +1,131 @@
+"""
+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 Cluster():
+
+ def __str__( self ):
+ return self.name
+ def __repr__( self ):
+ #TODO use repr of cli's?
+ controllers = []
+ for ctrl in self.controllers:
+ controllers.append( str( ctrl ) )
+ return "%s[%s]" % ( self.name, ", ".join( controllers ) )
+
+
+ def __init__( self, ctrlList=[], name="Cluster" ):
+ #assert isInstance( ctrlList, Controller ), "ctrlList should be a list of ONOS Controllers"
+ self.controllers = ctrlList
+ self.name = str( name )
+ self.iterator = iter( self.active() )
+
+ def getIps( self, activeOnly=False):
+ ips = []
+ if activeOnly:
+ nodeList = self.active()
+ else:
+ nodeList = self.controllers
+ for ctrl in nodeList:
+ ips.append( ctrl.ipAddress )
+ return ips
+
+ def active( self ):
+ """
+ Return a list of active controllers in the cluster
+ """
+ return [ ctrl for ctrl in self.controllers
+ if ctrl.active ]
+
+ def next( self ):
+ """
+ An iterator for the cluster's controllers that
+ resets when there are no more elements.
+
+ Returns the next controller in the cluster
+ """
+ try:
+ return self.iterator.next()
+ except StopIteration:
+ self.reset()
+ try:
+ return self.iterator.next()
+ except StopIteration:
+ raise RuntimeError( "There are no active nodes in the cluster" )
+
+ def reset( self ):
+ """
+ Resets the cluster iterator.
+
+ This should be used whenever a node's active state is changed
+ and is also used internally when the iterator has been exhausted.
+ """
+ self.iterator = iter( self.active() )
+
+ def install( self ):
+ """
+ Install ONOS on all controller nodes in the cluster
+ """
+ result = main.TRUE
+ # FIXME: use the correct onosdriver function
+ # TODO: Use threads to install in parallel, maybe have an option for sequential installs
+ for ctrl in self.controllers:
+ result &= ctrl.installOnos( ctrl.ipAddress )
+ return result
+
+ def startCLIs( self ):
+ """
+ Start the ONOS cli on all controller nodes in the cluster
+ """
+ cliResults = main.TRUE
+ threads = []
+ for ctrl in self.controllers:
+ t = main.Thread( target=ctrl.CLI.startOnosCli,
+ name="startCli-" + ctrl.name,
+ args=[ ctrl.ipAddress ] )
+ threads.append( t )
+ t.start()
+ ctrl.active = True
+
+ for t in threads:
+ t.join()
+ cliResults = cliResults and t.result
+ return cliResults
+
+ def command( self, function, args=(), kwargs={} ):
+ """
+ Send a command to all ONOS nodes and return the results as a list
+ """
+ threads = []
+ results = []
+ for ctrl in self.active():
+ f = getattr( ctrl, function )
+ t = main.Thread( target=f,
+ name=function + "-" + ctrl.name,
+ args=args,
+ kwargs=kwargs )
+ threads.append( t )
+ t.start()
+
+ for t in threads:
+ t.join()
+ results.append( t.result )
+ return results