Adding a control class for app configuration/activation.
Change dhcp/igmp to use this interface for app configuration
diff --git a/src/test/builder/buildFsm.sh b/src/test/builder/buildFsm.sh
index 51fd8d3..87bc14f 100644
--- a/src/test/builder/buildFsm.sh
+++ b/src/test/builder/buildFsm.sh
@@ -14,3 +14,7 @@
 ##Generate DNS test state machine
 python yamlFsm.py -p DnsHolder -f noseDnsTest.yaml > ${odir}/noseDnsHolder.py
 
+#Generate EAP MD5 authentication state machine
+python yamlFsm.py -p Md5AuthHolder -f noseMd5AuthTest.yaml > ${odir}/noseMd5AuthHolder.py
+
+
diff --git a/src/test/dhcp/dhcpTest.py b/src/test/dhcp/dhcpTest.py
index 52788fc..5be99b7 100644
--- a/src/test/dhcp/dhcpTest.py
+++ b/src/test/dhcp/dhcpTest.py
@@ -6,11 +6,11 @@
 import time
 import os, sys
 import copy
-import json
 CORD_TEST_UTILS = 'utils'
 test_root = os.getenv('CORD_TEST_ROOT') or './'
 sys.path.append(test_root + CORD_TEST_UTILS)
 from DHCP import DHCPTest
+from OnosCtrl import OnosCtrl
 
 log.setLevel('INFO')
 
@@ -24,25 +24,30 @@
         "router": "10.1.8.1",
         "domain": "8.8.8.8",
         "ttl": "63",
-        "lease": "300",
-        "renew": "150",
-        "rebind": "200",
         "delay": "2",
-        "timeout": "150",
         "startip": "10.1.11.51",
         "endip": "10.1.11.100"
     }
     
+    app = 'org.onosproject.dhcp'
+
+    def setUp(self):
+        ''' Activate the dhcp app'''
+        self.onos_ctrl = OnosCtrl(self.app)
+        status, _ = self.onos_ctrl.activate()
+        assert_equal(status, True)
+        time.sleep(3)
+
+    def teardown(self):
+        '''Deactivate the dhcp app'''
+        self.onos_ctrl.deactivate()
+
     def onos_load_config(self, config):
-          json_dict = json.JSONEncoder().encode(config)
-          with tempfile.NamedTemporaryFile(delete=False) as temp:
-                temp.write(json_dict)
-                temp.flush()
-                temp.close()
-          log.info('Loading DHCP config in file %s to ONOS.' %temp.name)
-          os.system('./dhcp_config_load.sh %s' %temp.name)
-          os.unlink(temp.name)
-          time.sleep(2)
+        status, code = self.onos_ctrl.config(config)
+        if status is False:
+            log.info('JSON request returned status %d' %code)
+            assert_equal(status, True)
+        time.sleep(2)
 
     def onos_dhcp_table_load(self, config = None):
           dhcp_dict = {'apps' : { 'org.onosproject.dhcp' : { 'dhcp' : copy.copy(self.dhcp_server_config) } } }
@@ -62,15 +67,15 @@
         return cip,sip
 
     def test_dhcp_1request(self, iface = 'veth0'):
-        config = {'startip':'10.10.10.20', 'endip':'10.10.10.100', 
-                  'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:cb:fe",
+        config = {'startip':'10.10.10.20', 'endip':'10.10.10.69', 
+                  'ip':'10.10.10.2', 'mac': "ca:fe:ca:fe:ca:fe",
                   'subnet': '255.255.255.0', 'broadcast':'10.10.10.255', 'router':'10.10.10.1'}
         self.onos_dhcp_table_load(config)
         self.dhcp = DHCPTest(seed_ip = '10.10.10.1', iface = iface)
         self.send_recv()
 
     def test_dhcp_Nrequest(self, iface = 'veth0'):
-        config = {'startip':'192.168.1.20', 'endip':'192.168.1.100', 
+        config = {'startip':'192.168.1.20', 'endip':'192.168.1.69', 
                   'ip':'192.168.1.2', 'mac': "ca:fe:ca:fe:cc:fe",
                   'subnet': '255.255.255.0', 'broadcast':'192.168.1.255', 'router': '192.168.1.1'}
         self.onos_dhcp_table_load(config)
diff --git a/src/test/dhcp/dhcp_config_load.sh b/src/test/dhcp/dhcp_config_load.sh
deleted file mode 100755
index cbed6d8..0000000
--- a/src/test/dhcp/dhcp_config_load.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-json="$1"
-controller="$2"
-if [ x"$json" = "x" ]; then
-  echo "No json file specified. Exiting"
-  exit 127
-fi
-if [ x"$controller" = "x" ]; then
-    controller=`ovs-vsctl show | egrep "Controller|tcp" | grep -v ptcp | sed 's,Controller,,g' | sed 's,\",,g' | tr -s ' '|awk -F":" '{print $2}'`
-    echo "Controller at $controller"
-fi
-echo "Loading dhcp config json file $json to controller at $controller"
-curl --fail -sSL --user karaf:karaf \
-    -X POST -H 'Content-Type:application/json' \
-    http://$controller:8181/onos/v1/network/configuration/ -d@$json
-
-
diff --git a/src/test/igmp/igmpTest.py b/src/test/igmp/igmpTest.py
index 28c243a..bc3463b 100644
--- a/src/test/igmp/igmpTest.py
+++ b/src/test/igmp/igmpTest.py
@@ -6,7 +6,6 @@
 import time, monotonic
 import os, sys
 import tempfile
-import json
 import random
 import threading
 
@@ -16,6 +15,7 @@
 from IGMP import *
 from McastTraffic import *
 from Stats import Stats
+from OnosCtrl import OnosCtrl
 log.setLevel('INFO')
 
 IGMP_DST_MAC = "01:00:5e:00:01:01"
@@ -52,7 +52,26 @@
     IGMP_TEST_TIMEOUT = 5
     MCAST_TRAFFIC_TIMEOUT = 10
     max_packets = 100
-    
+    app = 'org.onosproject.igmp'
+
+    def setUp(self):
+        ''' Activate the dhcp app'''
+        self.onos_ctrl = OnosCtrl(self.app)
+        status, _ = self.onos_ctrl.activate()
+        assert_equal(status, True)
+        time.sleep(3)
+
+    def teardown(self):
+        '''Deactivate the dhcp app'''
+        self.onos_ctrl.deactivate()
+
+    def onos_load_config(self, config):
+        status, code = self.onos_ctrl.config(config)
+        if status is False:
+            log.info('JSON request returned status %d' %code)
+            assert_equal(status, True)
+        time.sleep(2)
+          
     def onos_ssm_table_load(self, groups, src_list):
           ssm_dict = {'apps' : { 'org.onosproject.igmp' : { 'ssmTranslate' : [] } } }
           ssm_xlate_list = ssm_dict['apps']['org.onosproject.igmp']['ssmTranslate']
@@ -62,15 +81,7 @@
                       d['source'] = s
                       d['group'] = g
                       ssm_xlate_list.append(d)
-          json_dict = json.JSONEncoder().encode(ssm_dict)
-          with tempfile.NamedTemporaryFile(delete=False) as temp:
-                temp.write(json_dict)
-                temp.flush()
-                temp.close()
-          log.debug('Loading SSM config in file %s to ONOS.' %temp.name)
-          os.system('./igmp_ssm_load.sh %s' %temp.name)
-          os.unlink(temp.name)
-          ##Wait for ONOS to populate the SSM map before sending join.Huh
+          self.onos_load_config(ssm_dict)
           time.sleep(2)
 
     def igmp_verify_join(self, igmpStateList):
diff --git a/src/test/igmp/igmp_ssm_load.sh b/src/test/igmp/igmp_ssm_load.sh
deleted file mode 100755
index b2e9623..0000000
--- a/src/test/igmp/igmp_ssm_load.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/usr/bin/env bash
-json="$1"
-controller="$2"
-if [ x"$json" = "x" ]; then
-  echo "No json file specified. Exiting"
-  exit 127
-fi
-if [ x"$controller" = "x" ]; then
-    controller=`ovs-vsctl show | egrep "Controller|tcp" | grep -v ptcp | sed 's,Controller,,g' | sed 's,\",,g' | tr -s ' '|awk -F":" '{print $2}'`
-    #echo "Controller at $controller"
-fi
-#echo "Loading ssm translate json file $json to controller at $controller"
-curl --fail -sSL --user karaf:karaf \
-    -X POST -H 'Content-Type:application/json' \
-    http://$controller:8181/onos/v1/network/configuration/ -d@$json
-
-
diff --git a/src/test/utils/EapTLS.py b/src/test/utils/EapTLS.py
index 575fb20..d6b6b7e 100644
--- a/src/test/utils/EapTLS.py
+++ b/src/test/utils/EapTLS.py
@@ -11,6 +11,7 @@
 import scapy
 from nose.tools import *
 from CordTestBase import CordTester
+import re
 
 class TLSAuthTest(EapolPacket, CordTester):
 
@@ -89,4 +90,75 @@
         print 'Inside EAP TLS Cert Req'
         p = self.eapol_recv()
         print 'Got TLS Cert Req with payload len: %d' %len(p)
+        code, pkt_id, eaplen = unpack("!BBH", p[0:4])
+        print "Code %d, id %d, len %d" %(code, pkt_id, eaplen)
+        assert_equal(code, EAP_REQUEST)
+        reqtype = unpack("!B", p[4:5])[0]
+        assert_equal(reqtype, EAP_TYPE_TLS)
+        rex_pem = re.compile(r'\-+BEGIN[^\-]+\-+(.*?)\-+END[^\-]+\-+', re.DOTALL)
+        self.pem_cert="""-----BEGIN CERTIFICATE-----
+MIIE4TCCA8mgAwIBAgIJANhJTS6x4B0iMA0GCSqGSIb3DQEBCwUAMIGTMQswCQYD
+VQQGEwJGUjEPMA0GA1UECBMGUmFkaXVzMRIwEAYDVQQHEwlTb21ld2hlcmUxFTAT
+BgNVBAoTDEV4YW1wbGUgSW5jLjEgMB4GCSqGSIb3DQEJARYRYWRtaW5AZXhhbXBs
+ZS5jb20xJjAkBgNVBAMTHUV4YW1wbGUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4X
+DTE0MDUyMDExNTkzNloXDTE0MDcxOTExNTkzNlowgZMxCzAJBgNVBAYTAkZSMQ8w
+DQYDVQQIEwZSYWRpdXMxEjAQBgNVBAcTCVNvbWV3aGVyZTEVMBMGA1UEChMMRXhh
+bXBsZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQG
+A1UEAxMdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC/KUyltP0BS5A/sYg/XJOZMSHDIUiW+D8s1JgJ
+9Q/FIAnlMpevjPQtlmWi+hpgOUGgTryV+rTlzcUNw/gjmMs1Z4bAakFIc2vCPybw
+5hgKMU2E9SMgLr1aMVzwN3BH/njt1eWQ5Q9ajyu3JzmXZwOg/tV03L7BYpjLajhT
+iln4pvO/nq9YHVGurE5qCwyyrleYmtEXPi8MxrgudaKShrr7KgXbhlSwEaGGapSD
+JFhKvyQ4UZ56qiDFXD/AIXE9o8Soouv+8ufsCOyf/xKp1QkUaZ17Fe6YHqvQYdNM
+ovwnXnX+vRW0cZVui7ufxHncb9sJSAlovxzDy/GeL0SHtdH9AgMBAAGjggE0MIIB
+MDAdBgNVHQ4EFgQUHjtJ/Mjl+dcwmT5UI37N74qh2YUwgcgGA1UdIwSBwDCBvYAU
+HjtJ/Mjl+dcwmT5UI37N74qh2YWhgZmkgZYwgZMxCzAJBgNVBAYTAkZSMQ8wDQYD
+VQQIEwZSYWRpdXMxEjAQBgNVBAcTCVNvbWV3aGVyZTEVMBMGA1UEChMMRXhhbXBs
+ZSBJbmMuMSAwHgYJKoZIhvcNAQkBFhFhZG1pbkBleGFtcGxlLmNvbTEmMCQGA1UE
+AxMdRXhhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCCQDYSU0useAdIjAMBgNV
+HRMEBTADAQH/MDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly93d3cuZXhhbXBsZS5j
+b20vZXhhbXBsZV9jYS5jcmwwDQYJKoZIhvcNAQELBQADggEBAEbkq17kbT7X/oiy
+E2DOV7g1W8Au+TQR0GKzjXPgmYVGixN8l/9dQZ9WVDmCetBy71UHgTxPp20My2zr
+uA7hy9FYNGtZ2jmu0p019fH+CSCL7RHHgKsY63UsldT1qPYiWiyqbWy5GvJX778N
+GxVo7oN33se1c4KEmMOLVqQqX5dDWjN2r27l0GFh1ssx4RHqOc57G5Txq861i6UT
+KlrN0xpyu7LjcQGMwKbfzCXfwys5i4rrAVX1spILTIihUKpD6FYxp6oj+d4ELZOh
+br3zfhKrkbvPCG0gEziBLnwd11ZJELQfm89IYBhmoOYkk5+ZOszDsXKGWzfV6XSW
+ZRv+LU0=
+-----END CERTIFICATE-----"""
+        self.der_cert = rex_pem.findall(self.pem_cert)[0].decode("base64")
+        self.pem_priv_key = """-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEA84TzkjbcskbKZnrlKcXzSSgi07n+4N7kOM7uIhzpkTuU0HIv
+h4VZS2axxfV6hV3CD9MuKVg2zEhroqK1Js5n4ke230nSP/qiELfCl0R+hzRtbfKL
+tFUr1iHeU0uQ6v3q+Tg1K/Tmmg72uxKrhyHDL7z0BriPjhAHJ5XlQsvR1RCMkqzu
+D9wjSInJxpMMIgLndOclAKv4D1wQtYU7ZpTw+01XBlUhIiXb86qpYL9NqnnRq5JI
+uhmOEuxo2ca63+xaHNhD/udSyc8C0Md/yX6wlONTRFgLLv0pdLUGm1xEjfsydaQ6
+qGd7hzIKUI3hohNKJa/mHLElv7SZolPTogK/EQIDAQABAoIBAADq9FwNtuE5IRQn
+zGtO4q7Y5uCzZ8GDNYr9RKp+P2cbuWDbvVAecYq2NV9QoIiWJOAYZKklOvekIju3
+r0UZLA0PRiIrTg6NrESx3JrjWDK8QNlUO7CPTZ39/K+FrmMkV9lem9yxjJjyC34D
+AQB+YRTx+l14HppjdxNwHjAVQpIx/uO2F5xAMuk32+3K+pq9CZUtrofe1q4Agj9R
+5s8mSy9pbRo9kW9wl5xdEotz1LivFOEiqPUJTUq5J5PeMKao3vdK726XI4Z455Nm
+W2/MA0YV0ug2FYinHcZdvKM6dimH8GLfa3X8xKRfzjGjTiMSwsdjgMa4awY3tEHH
+674jhAECgYEA/zqMrc0zsbNk83sjgaYIug5kzEpN4ic020rSZsmQxSCerJTgNhmg
+utKSCt0Re09Jt3LqG48msahX8ycqDsHNvlEGPQSbMu9IYeO3Wr3fAm75GEtFWePY
+BhM73I7gkRt4s8bUiUepMG/wY45c5tRF23xi8foReHFFe9MDzh8fJFECgYEA9EFX
+4qAik1pOJGNei9BMwmx0I0gfVEIgu0tzeVqT45vcxbxr7RkTEaDoAG6PlbWP6D9a
+WQNLp4gsgRM90ZXOJ4up5DsAWDluvaF4/omabMA+MJJ5kGZ0gCj5rbZbKqUws7x8
+bp+6iBfUPJUbcqNqFmi/08Yt7vrDnMnyMw2A/sECgYEAiiuRMxnuzVm34hQcsbhH
+6ymVqf7j0PW2qK0F4H1ocT9qhzWFd+RB3kHWrCjnqODQoI6GbGr/4JepHUpre1ex
+4UEN5oSS3G0ru0rC3U4C59dZ5KwDHFm7ffZ1pr52ljfQDUsrjjIMRtuiwNK2OoRa
+WSsqiaL+SDzSB+nBmpnAizECgYBdt/y6rerWUx4MhDwwtTnel7JwHyo2MDFS6/5g
+n8qC2Lj6/fMDRE22w+CA2esp7EJNQJGv+b27iFpbJEDh+/Lf5YzIT4MwVskQ5bYB
+JFcmRxUVmf4e09D7o705U/DjCgMH09iCsbLmqQ38ONIRSHZaJtMDtNTHD1yi+jF+
+OT43gQKBgQC/2OHZoko6iRlNOAQ/tMVFNq7fL81GivoQ9F1U0Qr+DH3ZfaH8eIkX
+xT0ToMPJUzWAn8pZv0snA0um6SIgvkCuxO84OkANCVbttzXImIsL7pFzfcwV/ERK
+UM6j0ZuSMFOCr/lGPAoOQU0fskidGEHi1/kW+suSr28TqsyYZpwBDQ==
+-----END RSA PRIVATE KEY-----
+        """
+        self.der_priv_key = rex_pem.findall(self.pem_priv_key)[0].decode("base64")
+        reqdata = TLSRecord(version="TLS_1_0")/TLSHandshake()/TLSCertificateList(
+            certificates=[TLSCertificate(data=x509.X509Cert(self.der_cert))])
+        #reqdata.show()
+        print "------> Sending Client Hello TLS Certificate payload of len %d ----------->" %len(reqdata)
+        eap_payload = self.eapTLS(EAP_RESPONSE, pkt_id, TLS_LENGTH_INCLUDED, str(reqdata))
+        self.eapol_send(EAPOL_EAPPACKET, eap_payload)
         self.nextEvent = None
diff --git a/src/test/utils/EapolAAA.py b/src/test/utils/EapolAAA.py
index f7a8a2d..6c477f0 100644
--- a/src/test/utils/EapolAAA.py
+++ b/src/test/utils/EapolAAA.py
@@ -84,3 +84,26 @@
         eap_payload = self.eap(EAP_RESPONSE, pkt_id, EAP_TYPE_ID, user)
         return self.eapol_send(EAPOL_EAPPACKET, eap_payload)
 
+    def eap_md5_challenge_recv(self,rad_pwd):
+        PASS = rad_pwd
+        print 'Inside EAP MD5 Challenge Exchange'
+        p = self.s.recv(self.max_payload_size)[14:]
+        vers,pkt_type,eapollen  = unpack("!BBH",p[:4])
+        print "EAPOL Version %d, type %d, len %d" %(vers, pkt_type, eapollen)
+        code, pkt_id, eaplen = unpack("!BBH", p[4:8])
+        print "EAP Code %d, id %d, len %d" %(code, pkt_id, eaplen)
+        assert_equal(code, EAP_REQUEST)
+        reqtype = unpack("!B", p[8:9])[0]
+        reqdata = p[9:4+eaplen]
+        print 'Request type is %d' %(reqtype)
+        assert_equal(reqtype, EAP_TYPE_MD5)
+        challenge=pack("!B",pkt_id)+PASS+reqdata[1:]
+        print "Generating md5 challenge for %s" % challenge
+        return (challenge,pkt_id)
+
+    def eap_Status(self):
+        print 'Inside EAP Status'
+        p = self.s.recv(self.max_payload_size)[14:]
+        code, id, eaplen = unpack("!BBH", p[4:8])
+        return code
+
diff --git a/src/test/utils/OnosCtrl.py b/src/test/utils/OnosCtrl.py
new file mode 100644
index 0000000..043438f
--- /dev/null
+++ b/src/test/utils/OnosCtrl.py
@@ -0,0 +1,32 @@
+import json
+import requests
+import os,sys,time
+
+class OnosCtrl:
+    
+    def __init__(self, app, controller = None):
+        self.app = app
+        if controller is None:
+            self.controller = os.getenv('ONOS_CONTROLLER_IP') or 'localhost'
+        else:
+            self.controller = controller
+        self.app_url = 'http://%s:8181/onos/v1/applications/%s' %(self.controller, self.app)
+        self.cfg_url = 'http://%s:8181/onos/v1/network/configuration/' %(self.controller)
+        self.auth = ('karaf', 'karaf')
+
+    def config(self, config):
+        if config:
+            json_data = json.dumps(config)
+            resp = requests.post(self.cfg_url, auth = self.auth, data = json_data)
+            return resp.ok, resp.status_code
+        return False, 400
+
+    def activate(self):
+        resp = requests.post(self.app_url + '/active', auth = self.auth)
+        return resp.ok, resp.status_code
+
+    def deactivate(self):
+        resp = requests.delete(self.app_url + '/active', auth = self.auth)
+        return resp.ok, resp.status_code
+
+