Support to enable VOLTHA in cord-tester.
VOLTHA can now be started by cord-tester by specifying voltha_loc in manifest file.
voltha_intf specifies the interface for voltha to listen.
A sample manifest-voltha.json can be modified accordingly before starting cord-tester.
Changed the default olt_type to simulated_olt in volthaTest configuration json.
This would enable testing of voltha tests.
Fix indentation broken in voltha tests earlier.

Change-Id: Ia18b870c83dcb60c15c07f8602579494f32457c9
diff --git a/src/test/utils/TestManifest.py b/src/test/utils/TestManifest.py
index bdd66c7..26c5130 100644
--- a/src/test/utils/TestManifest.py
+++ b/src/test/utils/TestManifest.py
@@ -50,6 +50,8 @@
             self.server = args.server
             self.jvm_heap_size = args.jvm_heap_size if args.jvm_heap_size else None
             self.karaf_version = args.karaf
+            self.voltha_loc = args.voltha_loc
+            self.voltha_intf = args.voltha_intf
         else:
             with open(self.manifest, 'r') as fd:
                 data = json.load(fd)
@@ -76,3 +78,5 @@
             self.iterations = data.get('iterations', None)
             self.jvm_heap_size = data.get('jvm_heap_size', None)
             self.karaf_version = data.get('karaf_version', '3.0.8')
+            self.voltha_loc = data.get('voltha_loc', '')
+            self.voltha_intf = data.get('voltha_intf', 'eth0')
diff --git a/src/test/utils/VolthaCtrl.py b/src/test/utils/VolthaCtrl.py
index b23aefa..19e246c 100644
--- a/src/test/utils/VolthaCtrl.py
+++ b/src/test/utils/VolthaCtrl.py
@@ -1,7 +1,93 @@
 import requests
 import json
 import time
-from CordTestUtils import log_test as log
+import os
+import signal
+from CordTestUtils import log_test as log, getstatusoutput
+from CordContainer import Container
+
+class VolthaService(object):
+    services = ('consul', 'kafka', 'zookeeper', 'registrator', 'fluentd')
+    compose_file = 'docker-compose-system-test.yml'
+    service_map = {}
+
+    def __init__(self, voltha_loc, controller, interface = 'eth0'):
+        if not os.access(voltha_loc, os.F_OK):
+            raise Exception('Voltha location %s not found' %voltha_loc)
+        compose_file_loc = os.path.join(voltha_loc, 'compose', self.compose_file)
+        if not os.access(compose_file_loc, os.F_OK):
+            raise Exception('Voltha compose file %s not found' %compose_file_loc)
+        self.voltha_loc = voltha_loc
+        self.controller = controller
+        self.interface = interface
+        self.compose_file_loc = compose_file_loc
+
+    def start(self):
+        start_cmd = 'docker-compose -f {} up -d {} {} {} {} {}'.format(self.compose_file_loc,
+                                                                       *self.services)
+        ret = os.system(start_cmd)
+        if ret != 0:
+            raise Exception('Failed to start voltha services. Failed with code %d' %ret)
+
+        for service in self.services:
+            name = 'compose_{}_1'.format(service)
+            network = 'compose_default'
+            cnt = Container(name, name)
+            ip = cnt.ip(network = network)
+            if not ip:
+                raise Exception('IP not found for container %s' %name)
+            print('IP %s for service %s' %(ip, service))
+            self.service_map[service] = dict(name = name, network = network, ip = ip)
+
+        #first start chameleon
+        chameleon_start_cmd = "cd {} && sh -c '. ./env.sh && \
+        nohup python chameleon/main.py -v --consul=localhost:8500 \
+        --fluentd={}:24224 --grpc-endpoint=localhost:50555 \
+        >/tmp/chameleon.log 2>&1 &'".format(self.voltha_loc,
+                                            self.service_map['fluentd']['ip'])
+        ret = os.system(chameleon_start_cmd)
+        if ret != 0:
+            raise Exception('VOLTHA chameleon service not started. Failed with return code %d' %ret)
+
+        #now start voltha and ofagent
+        voltha_start_cmd = "cd {} && sh -c '. ./env.sh && \
+        nohup python voltha/main.py -v --consul=localhost:8500 --kafka={}:9092 -I {} \
+        --fluentd={}:24224 --rest-port=8880 --grpc-port=50555 \
+        >/tmp/voltha.log 2>&1 &'".format(self.voltha_loc,
+                                         self.service_map['kafka']['ip'],
+                                         self.interface,
+                                         self.service_map['fluentd']['ip'])
+        ret = os.system(voltha_start_cmd)
+        if ret != 0:
+            raise Exception('Failed to start VOLTHA. Return code %d' %ret)
+
+
+        ofagent_start_cmd = "cd {} && sh -c '. ./env.sh && \
+        nohup python ofagent/main.py -v --consul=localhost:8500 \
+        --fluentd={}:24224 --controller={}:6653 --grpc-endpoint=localhost:50555 \
+        >/tmp/ofagent.log 2>&1 &'".format(self.voltha_loc,
+                                          self.service_map['fluentd']['ip'],
+                                          self.controller)
+        ret = os.system(ofagent_start_cmd)
+        if ret != 0:
+            raise Exception('VOLTHA ofagent not started. Failed with return code %d' %ret)
+
+    def kill_service(self, pattern):
+        st, output = getstatusoutput('pgrep -f "{}"'.format(pattern))
+        if st == 0 and output:
+            pids = output.strip().splitlines()
+            for pid in pids:
+                try:
+                    os.kill(int(pid), signal.SIGKILL)
+                except:
+                    pass
+
+    def stop(self):
+        self.kill_service('python voltha/main.py')
+        self.kill_service('python ofagent/main.py')
+        self.kill_service('python chameleon/main.py')
+        service_stop_cmd = 'docker-compose -f {} down'.format(self.compose_file_loc)
+        os.system(service_stop_cmd)
 
 class VolthaCtrl(object):