Initial implementation of test suite for ONOS NETCONF
functionality using OF-Config
    -for more information please check the README

Change-Id: I631ae8b5de24553899c44a465a604283602a6f27
diff --git a/TestON/tests/FUNCnetconf/Dependency/netconf.py b/TestON/tests/FUNCnetconf/Dependency/netconf.py
new file mode 100644
index 0000000..5ebbea5
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/netconf.py
@@ -0,0 +1,141 @@
+"""
+    Wrapper functions for FUNCnetconf
+    This functions include Onosclidriver and Mininetclidriver driver functions
+    Author: Jeremy Songster, jeremy@onlab.us
+"""
+import time
+import json
+
+def __init__( self ):
+    self.default = ''
+
+def startApp( main ):
+    """
+        This function starts the netconf app in all onos nodes and ensures that
+        the OF-Config server is running on the node to be configured
+    """
+
+    startResult = main.FALSE
+    startResult = main.CLIs[ 0 ].activateApp( appName="org.onosproject.netconf" )
+    return startResult
+
+def startOFC( main ):
+    """
+        This function uses pexpect pxssh class to activate the ofc-server daemon on OC2
+    """
+
+    startResult = main.FALSE
+    try:
+        main.ONOSbench.handle.sendline( "" )
+        main.ONOSbench.handle.expect( "\$" )
+        main.ONOSbench.handle.sendline( "ifconfig eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1 }'" )
+        main.ONOSbench.handle.expect( "\$1 }'" )
+        main.ONOSbench.handle.expect( "\$" )
+        main.configDeviceIp = main.ONOSbench.handle.before
+        main.configDeviceIp = main.configDeviceIp.split()
+        main.configDeviceIp = main.configDeviceIp[ 0 ]
+        main.log.info( "Device to be configured: " + str( main.configDeviceIp ) )
+        main.ONOSbench.handle.sendline( "sudo ofc-server" )
+        main.ONOSbench.handle.expect( "\$" )
+        startResult = main.TRUE
+        return startResult
+    except pexpect.ExceptionPexpect as e:
+        main.log.exception( self.name + ": Pexpect exception found: " )
+        main.log.error( self.name + ":    " + self.handle.before )
+        main.cleanup()
+        main.exit()
+
+def createConfig( main ):
+    """
+        This function writes a configuration file that can later be sent to the
+        REST API to configure a device.
+        The controller device is assumed to be OC1
+        The device to be configured is assumed to be OC2
+    """
+    createCfgResult = main.FALSE
+    # TODO, add ability to set Manufacturer, Hardware and Software versions
+    main.cfgJson = '{ "devices":{ "netconf:'+ main.configDeviceIp + ":" +\
+                    main.configDevicePort + '":' + '{ "basic":{ "driver":"'+\
+                    main.configDriver + '" } } }, "apps": { "' +\
+                    main.configApps + '":{ "devices":[ { "name":' +\
+                    main.configName + ', "password":' + main.configPass +\
+                    ', "ip":"' + main.configDeviceIp + '", "port":' +\
+                    main.configPort + '} ] } } }'
+    try:
+        file = open( "/home/admin/OnosSystemTest/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json", 'w' )
+        main.cfgJson = json.loads( main.cfgJson )
+        main.cfgJson = json.dumps( main.cfgJson, sort_keys=True,
+                               indent=4, separators=(',', ': '))
+        print main.cfgJson
+        file.write( main.cfgJson )
+        if file:
+            createCfgResult = main.TRUE
+            file.close()
+            return createCfgResult
+        else:
+            main.log.error( "There was an error opening the file")
+            return createCfgResult
+    except:
+        main.log.exception( "There was an error opening the file")
+        return createCfgResult
+
+def sendConfig( main ):
+    """
+        This function prepares the command needed to upload the configuration
+        file to the REST API
+    """
+    ip = main.ONOSip[0]
+    port = 8181
+    url = "/network/configuration"
+    method = "POST"
+    data = main.cfgJson
+    configResult = main.FALSE
+    sendResult = main.CLIs[ 0 ].send( ip=ip, port=port, url=url, method=method, data=data )
+    main.log.info( "Device configuration request response code: " + str( sendResult[ 0 ] ) )
+    if ( 200 <= sendResult[ 0 ] <= 299):
+        configResult = main.TRUE
+    else:
+        configResult = main.FALSE
+
+    return configResult
+
+def devices( main ):
+    """
+        This function get the list of devices from the REST API, the ONOS CLI, and
+        the device-controllers command and check to see that each recognizes the
+        device is configured according to the configuration uploaded above.
+    """
+    availResult = main.FALSE
+    typeResult = main.FALSE
+    addressResult = main.FALSE
+    driverResult = main.FALSE
+    try:
+        apiResult = main.CLIs[ 0 ].devices()
+        cliResult = main.CLIs2[ 0 ].devices()
+
+        apiDict = json.loads( apiResult )
+        cliDict = json.loads( cliResult )
+        apiAnnotations = apiDict[ 0 ].get( "annotations" )
+        cliAnnotations = cliDict[ 0 ].get( "annotations" )
+
+        main.log.info( "API device availability result: " + str( apiDict[ 0 ].get( "available" ) ) )
+        main.log.info( "CLI device availability result: " + str( cliDict[ 0 ].get( "available" ) ) )
+        if apiDict[ 0 ].get( "available" ) == True and cliDict[ 0 ].get( "available" ) == True:
+            availResult = main.TRUE
+        main.log.info( "API device type result: " + apiDict[ 0 ].get( "type" ) )
+        main.log.info( "CLI device type result: " + cliDict[ 0 ].get( "type" ) )
+        if apiDict[ 0 ].get( "type" ) == "SWITCH" and cliDict[ 0 ].get( "type" ) == "SWITCH":
+            typeResult = main.TRUE
+        main.log.info( "API device ipaddress: " + apiAnnotations.get( "ipaddress" ) )
+        main.log.info( "CLI device ipaddress: " + apiAnnotations.get( "ipaddress" ) )
+        if str( apiAnnotations.get( "ipaddress" ) ) == main.configDeviceIp and str( cliAnnotations.get( "ipaddress" ) ) == main.configDeviceIp:
+            addressResult = main.TRUE
+        main.log.info( "API device driver: " + apiAnnotations.get( "driver" ) )
+        main.log.info( "CLI device driver: " + cliAnnotations.get( "driver" ) )
+        if apiAnnotations.get( "driver" ) == main.configDriver and cliAnnotations.get( "driver" ) == main.configDriver:
+            driverResult = main.TRUE
+
+        return availResult and typeResult and addressResult and driverResult
+    except TypeError:
+        main.log.error( "Device was not configured correctly" )
+        return main.FALSE
\ No newline at end of file
diff --git a/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json b/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json
new file mode 100644
index 0000000..fc5a231
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/netconfConfig.json
@@ -0,0 +1,21 @@
+{
+    "apps": {
+        "org.onosproject.netconf": {
+            "devices": [
+                {
+                    "ip": "10.128.50.10",
+                    "name": "sdn",
+                    "password": "rocks",
+                    "port": 830
+                }
+            ]
+        }
+    },
+    "devices": {
+        "netconf:10.128.50.10:830": {
+            "basic": {
+                "driver": "ovs-netconf"
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/TestON/tests/FUNCnetconf/Dependency/startUp.py b/TestON/tests/FUNCnetconf/Dependency/startUp.py
new file mode 100644
index 0000000..bf2a2b6
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/startUp.py
@@ -0,0 +1,38 @@
+"""
+    This wrapper function is use for starting up onos instance
+"""
+
+import time
+import os
+import json
+
+def onosBuild( main, gitBranch ):
+    """
+        This includes pulling ONOS and building it using maven install
+    """
+
+    buildResult = main.FALSE
+
+    # Git checkout a branch of ONOS
+    checkOutResult = main.ONOSbench.gitCheckout( gitBranch )
+    # Does the git pull on the branch that was checked out
+    if not checkOutResult:
+        main.log.warn( "Failed to checked out " + gitBranch +
+                                           " branch")
+    else:
+        main.log.info( "Successfully checked out " + gitBranch +
+                                           " branch")
+    gitPullResult = main.ONOSbench.gitPull()
+    if gitPullResult == main.ERROR:
+        main.log.error( "Error pulling git branch" )
+    else:
+        main.log.info( "Successfully pulled " + gitBranch + " branch" )
+
+    # Maven clean install
+    buildResult = main.ONOSbench.cleanInstall()
+
+    return buildResult
+
+
+
+
diff --git a/TestON/tests/FUNCnetconf/Dependency/topo.py b/TestON/tests/FUNCnetconf/Dependency/topo.py
new file mode 100644
index 0000000..b44e3fc
--- /dev/null
+++ b/TestON/tests/FUNCnetconf/Dependency/topo.py
@@ -0,0 +1,100 @@
+"""
+    These functions can be used for topology comparisons
+"""
+
+import time
+import os
+import json
+
+def getAllDevices( main ):
+    """
+        Return a list containing the devices output from each ONOS node
+    """
+    devices = []
+    threads = []
+    for i in range( main.numCtrls ):
+        t = main.Thread( target=main.CLIs[i].devices,
+                         name="devices-" + str( i ),
+                         args=[ ] )
+        threads.append( t )
+        t.start()
+
+    for t in threads:
+        t.join()
+        devices.append( t.result )
+    return devices
+
+def getAllHosts( main ):
+    """
+        Return a list containing the hosts output from each ONOS node
+    """
+    hosts = []
+    ipResult = main.TRUE
+    threads = []
+    for i in range( main.numCtrls ):
+        t = main.Thread( target=main.CLIs[i].hosts,
+                         name="hosts-" + str( i ),
+                         args=[ ] )
+        threads.append( t )
+        t.start()
+
+    for t in threads:
+        t.join()
+        hosts.append( t.result )
+    return hosts
+
+def getAllPorts( main ):
+    """
+        Return a list containing the ports output from each ONOS node
+    """
+    ports = []
+    threads = []
+    for i in range( main.numCtrls ):
+        t = main.Thread( target=main.CLIs[i].ports,
+                         name="ports-" + str( i ),
+                         args=[ ] )
+        threads.append( t )
+        t.start()
+
+    for t in threads:
+        t.join()
+        ports.append( t.result )
+    return ports
+
+def getAllLinks( main ):
+    """
+        Return a list containing the links output from each ONOS node
+    """
+    links = []
+    threads = []
+    for i in range( main.numCtrls ):
+        t = main.Thread( target=main.CLIs[i].links,
+                         name="links-" + str( i ),
+                         args=[ ] )
+        threads.append( t )
+        t.start()
+
+    for t in threads:
+        t.join()
+        links.append( t.result )
+    return links
+
+def getAllClusters( main ):
+    """
+        Return a list containing the clusters output from each ONOS node
+    """
+    clusters = []
+    threads = []
+    for i in range( main.numCtrls ):
+        t = main.Thread( target=main.CLIs[i].clusters,
+                         name="clusters-" + str( i ),
+                         args=[ ] )
+        threads.append( t )
+        t.start()
+
+    for t in threads:
+        t.join()
+        clusters.append( t.result )
+    return clusters
+
+