Support for exposing ports to host to allow external access to cord-tester ONOS.
Just set:
"expose_port" : true
in manifest file to enable host port bindings for external access to cord-tester ONOS containers.

Change-Id: I155b8669b39ad4de5075738ec49ba2af76a53f7c
diff --git a/src/test/setup/cord-test.py b/src/test/setup/cord-test.py
index d414735..f2c4600 100755
--- a/src/test/setup/cord-test.py
+++ b/src/test/setup/cord-test.py
@@ -585,6 +585,7 @@
 
     onos_cord = None
     Onos.update_data_dir(test_manifest.karaf_version)
+    Onos.set_expose_port(test_manifest.expose_port)
     if onos_cord_loc:
         if onos_cord_loc.find(os.path.sep) < 0:
             onos_cord_loc = os.path.join(os.getenv('HOME'), onos_cord_loc)
@@ -657,7 +658,7 @@
             quagga_config = Onos.get_quagga_config(i)
             onos = Onos(name = name, image = Onos.IMAGE, tag = Onos.TAG, boot_delay = 60, cluster = cluster_mode,
                         data_volume = data_volume, async = async_mode,
-                        quagga_config = quagga_config, network = test_manifest.docker_network)
+                        quagga_config = quagga_config, network = test_manifest.docker_network, instance = i)
             onos_instances.append(onos)
             if onos.running:
                 onos_ips.append(onos.ipaddr)
@@ -864,6 +865,7 @@
     onos_cord = None
     onos_cord_loc = test_manifest.onos_cord
     Onos.update_data_dir(test_manifest.karaf_version)
+    Onos.set_expose_port(test_manifest.expose_port)
     olt_config_file = test_manifest.olt_config
     if not os.access(olt_config_file, os.F_OK):
         olt_config_file = os.path.join(CordTester.tester_base, 'olt_config.json')
@@ -946,7 +948,7 @@
             quagga_config = Onos.get_quagga_config(i)
             onos = Onos(name = name, image = Onos.IMAGE, tag = Onos.TAG, boot_delay = 60, cluster = cluster_mode,
                         data_volume = data_volume, async = async_mode,
-                        quagga_config = quagga_config, network = test_manifest.docker_network)
+                        quagga_config = quagga_config, network = test_manifest.docker_network, instance = i)
             onos_instances.append(onos)
             if onos.running:
                 onos_ips.append(onos.ipaddr)
@@ -1340,6 +1342,9 @@
                             help='Specify the voltha interface for voltha to listen')
     parser_run.add_argument('-voltha-enable', '--voltha-enable', action='store_true',
                             help='Run the tests with voltha environment enabled')
+    parser_run.add_argument('-expose-port', '--expose-port', action='store_true',
+                            help='Start ONOS by exposing the controller ports to the host.'
+                            'Add +1 for every other onos/cluster instance when running more than 1 ONOS instances')
     parser_run.set_defaults(func=runTest)
 
     parser_setup = subparser.add_parser('setup', help='Setup cord tester environment')
@@ -1389,6 +1394,9 @@
                               help='Specify the voltha interface for voltha to listen')
     parser_setup.add_argument('-voltha-enable', '--voltha-enable', action='store_true',
                               help='Run the tests with voltha environment enabled')
+    parser_setup.add_argument('-expose-port', '--expose-port', action='store_true',
+                              help='Start ONOS by exposing the controller ports to the host.'
+                              'Add +1 for every other onos/cluster instance when running more than 1 ONOS instances')
     parser_setup.set_defaults(func=setupCordTester)
 
     parser_xos = subparser.add_parser('xos', help='Building xos into cord tester environment')
diff --git a/src/test/utils/CordContainer.py b/src/test/utils/CordContainer.py
index ab49cb5..841fcd0 100644
--- a/src/test/utils/CordContainer.py
+++ b/src/test/utils/CordContainer.py
@@ -96,7 +96,10 @@
         if port_list:
             port_bindings = {}
             for p in port_list:
-                port_bindings[str(p)] = str(p)
+                if type(p) is tuple:
+                    port_bindings[str(p[0])] = str(p[1])
+                else:
+                    port_bindings[str(p)] = str(p)
 
         if host_guest_map:
             binds = []
@@ -586,7 +589,9 @@
                        ['igmp', '1.2-SNAPSHOT'],
                        )
     cord_apps_version_updated = False
-    ports = [] #[ 8181, 8101, 9876, 6653, 6633, 2000, 2620, 5005 ]
+    expose_port = False
+    expose_ports = [ 8181, 8101, 9876, 6653, 6633, 2000, 2620, 5005 ]
+    ports = []
     setup_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', 'setup')
     host_config_dir = os.path.join(setup_dir, 'onos-config')
     guest_config_dir = '/root/onos/config'
@@ -662,6 +667,15 @@
                 cls.ssl_key = os.path.join(cls.host_config_dir, os.path.basename(key))
             except:pass
 
+    @classmethod
+    def set_expose_port(cls, flag):
+        cls.expose_port = flag
+
+    def get_port_map(self, instance=0):
+        if self.expose_port is False:
+            return self.ports
+        return map(lambda p: (p, p + instance), self.expose_ports)
+
     def remove_data_volume(self):
         if self.data_map is not None:
             self.remove_data_map(*self.data_map)
@@ -669,7 +683,7 @@
     def __init__(self, name = NAME, image = IMAGE, prefix = PREFIX, tag = TAG,
                  boot_delay = 20, restart = False, network_cfg = None,
                  cluster = False, data_volume = None, async = False, quagga_config = None,
-                 network = None):
+                 network = None, instance = 0):
         if restart is True:
             ##Find the right image to restart
             running_image = filter(lambda c: c['Names'][0] == '/{}'.format(name), self.dckr.containers())
@@ -687,11 +701,11 @@
         self.data_map = None
         instance_memory = (get_mem(jvm_heap_size = Onos.JVM_HEAP_SIZE, instances = Onos.MAX_INSTANCES),) * 2
         self.env['JAVA_OPTS'] = self.JAVA_OPTS_FORMAT.format(*instance_memory)
+        self.ports = self.get_port_map(instance = instance)
         if self.ssl_key:
             key_files = ( os.path.join(self.guest_config_dir, os.path.basename(self.ssl_key)), ) * 2
             self.env['JAVA_OPTS'] += ' -DenableOFTLS=true -Djavax.net.ssl.keyStore={} -Djavax.net.ssl.keyStorePassword=222222 -Djavax.net.ssl.trustStore={} -Djavax.net.ssl.trustStorePassword=222222'.format(*key_files)
         if cluster is True:
-            self.ports = []
             if data_volume is not None:
                 self.data_map = self.get_data_map(data_volume, self.guest_data_dir)
                 self.host_guest_map = self.host_guest_map + self.data_map
@@ -853,9 +867,10 @@
         if not cls.cluster_instances or Onos.cluster_mode is False:
             return
         for i in range(count):
-            name = '{}-{}'.format(Onos.NAME, len(cls.cluster_instances)+1)
+            instance = len(cls.cluster_instances)
+            name = '{}-{}'.format(Onos.NAME, instance+1)
             onos = cls(name = name, image = Onos.IMAGE, tag = Onos.TAG, prefix = Container.IMAGE_PREFIX,
-                       cluster = True, network_cfg = network_cfg)
+                       cluster = True, network_cfg = network_cfg, instance = instance)
             cls.cluster_instances.append(onos)
 
         cls.setup_cluster(cls.cluster_instances)
diff --git a/src/test/utils/TestManifest.py b/src/test/utils/TestManifest.py
index 9d4825b..17de424 100644
--- a/src/test/utils/TestManifest.py
+++ b/src/test/utils/TestManifest.py
@@ -53,6 +53,7 @@
             self.voltha_loc = args.voltha_loc
             self.voltha_intf = args.voltha_intf
             self.voltha_enable = args.voltha_enable
+            self.expose_port = args.expose_port
         else:
             with open(self.manifest, 'r') as fd:
                 data = json.load(fd)
@@ -85,3 +86,4 @@
             if self.voltha_loc:
                 voltha_enable = True
             self.voltha_enable = data.get('voltha_enable', voltha_enable)
+            self.expose_port = data.get('expose_port', False)