This commit address the changes in CLI required to work with the
global forwarder.  A new CLI option (-G) has been added.

Change-Id: I9bef1af65d0a8078bdb9a75bc807a124a3063847
diff --git a/cli/alarm_filters.py b/cli/alarm_filters.py
index e607cf1..7ba1844 100644
--- a/cli/alarm_filters.py
+++ b/cli/alarm_filters.py
@@ -32,9 +32,9 @@
 
 
 class AlarmFiltersCli(Cmd):
-    def __init__(self, get_channel):
+    def __init__(self, get_stub):
         Cmd.__init__(self)
-        self.get_channel = get_channel
+        self.get_stub = get_stub
         self.prompt = '(' + self.colorize(
             self.colorize('alarm_filters', 'red'), 'bold') + ') '
 
@@ -57,7 +57,7 @@
         make_option('-i', '--filter-id', action="store", dest='filter_id')
     ])
     def do_show(self, line, opts):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
 
         if not opts.filter_id:
             result = stub.ListAlarmFilters(Empty())
@@ -145,7 +145,7 @@
     ])
     def do_create(self, line, opts):
         if opts.filter_rules:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             result = stub.CreateAlarmFilter(voltha_pb2.AlarmFilter(rules=opts.filter_rules))
             print_pb_list_as_table("Rules for Filter ID = {}:".format(result.id),
                                    result.rules, {}, self.poutput)
@@ -172,7 +172,7 @@
                                        'bold') + ' to update')
             return
 
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         stub.DeleteAlarmFilter(voltha_pb2.ID(id=opts.filter_id))
 
     def help_update(self):
@@ -230,7 +230,7 @@
             return
 
         if opts.filter_rules:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             result = stub.UpdateAlarmFilter(
                 voltha_pb2.AlarmFilter(id=opts.filter_id, rules=opts.filter_rules)
             )
diff --git a/cli/device.py b/cli/device.py
index c1e9ba6..6c7eea2 100644
--- a/cli/device.py
+++ b/cli/device.py
@@ -38,9 +38,9 @@
 
 class DeviceCli(Cmd):
 
-    def __init__(self, get_channel, device_id):
+    def __init__(self, device_id, get_stub):
         Cmd.__init__(self)
-        self.get_channel = get_channel
+        self.get_stub = get_stub
         self.device_id = device_id
         self.prompt = '(' + self.colorize(
             self.colorize('device {}'.format(device_id), 'red'), 'bold') + ') '
@@ -51,7 +51,7 @@
         self._cmdloop()
 
     def get_device(self, depth=0):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.GetDevice(voltha_pb2.ID(id=self.device_id),
                              metadata=(('get-depth', str(depth)), ))
         return res
@@ -286,7 +286,7 @@
             return
 
         elif line.strip() == "commit" and self.pm_config_dirty:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             stub.UpdateDevicePmConfigs(self.pm_config_last)
             self.pm_config_last = self.get_device(depth=-1).pm_configs
             self.pm_config_dirty = False
diff --git a/cli/logical_device.py b/cli/logical_device.py
index f3a3f7e..c1a9479 100644
--- a/cli/logical_device.py
+++ b/cli/logical_device.py
@@ -33,9 +33,9 @@
 
 class LogicalDeviceCli(Cmd):
 
-    def __init__(self, get_channel, logical_device_id):
+    def __init__(self, logical_device_id, get_stub):
         Cmd.__init__(self)
-        self.get_channel = get_channel
+        self.get_stub = get_stub
         self.logical_device_id = logical_device_id
         self.prompt = '(' + self.colorize(
             self.colorize('logical device {}'.format(logical_device_id), 'red'),
@@ -45,17 +45,17 @@
         self._cmdloop()
 
     def get_logical_device(self, depth=0):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.GetLogicalDevice(voltha_pb2.ID(id=self.logical_device_id),
                                     metadata=(('get-depth', str(depth)), ))
         return res
 
     def get_device(self, id):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         return stub.GetDevice(voltha_pb2.ID(id=id))
 
     def get_devices(self):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.ListDevices(Empty())
         return res.items
 
diff --git a/cli/main.py b/cli/main.py
index a05041a..c0dbef6 100755
--- a/cli/main.py
+++ b/cli/main.py
@@ -48,6 +48,7 @@
                                         'localhost:50055'),
     voltha_sim_rest_endpoint=os.environ.get('VOLTHA_SIM_REST_ENDPOINT',
                                             'localhost:18880'),
+    global_request=os.environ.get('GLOBAL_REQUEST', False)
 )
 
 banner = """\
@@ -66,6 +67,7 @@
     # Settable CLI parameters
     voltha_grpc = 'localhost:50055'
     voltha_sim_rest = 'localhost:18880'
+    global_request = False
     max_history_lines = 500
     default_device_id = None
     default_logical_device_id = None
@@ -86,13 +88,15 @@
     del Cmd.do_load
     del Cmd.do__relative_load
 
-    def __init__(self, voltha_grpc, voltha_sim_rest):
+    def __init__(self, voltha_grpc, voltha_sim_rest, global_request=False):
         VolthaCli.voltha_grpc = voltha_grpc
         VolthaCli.voltha_sim_rest = voltha_sim_rest
+        VolthaCli.global_request = global_request
         Cmd.__init__(self)
         self.prompt = '(' + self.colorize(
             self.colorize(self.prompt, 'blue'), 'bold') + ') '
         self.channel = None
+        self.stub = None
         self.device_ids_cache = None
         self.device_ids_cache_ts = time()
         self.logical_device_ids_cache = None
@@ -135,6 +139,14 @@
             self.channel = grpc.insecure_channel(self.voltha_grpc)
         return self.channel
 
+    def get_stub(self):
+        if self.stub is None:
+            self.stub = \
+                voltha_pb2.VolthaGlobalServiceStub(self.get_channel()) \
+                    if self.global_request else \
+                        voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        return self.stub
+
     # ~~~~~~~~~~~~~~~~~ ACTUAL COMMAND IMPLEMENTATIONS ~~~~~~~~~~~~~~~~~~~~~~~~
 
     def do_reset_history(self, line):
@@ -152,18 +164,18 @@
 
     def do_adapters(self, line):
         """List loaded adapter"""
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.ListAdapters(Empty())
         omit_fields = {'config.log_level', 'logical_device_ids'}
         print_pb_list_as_table('Adapters:', res.items, omit_fields, self.poutput)
 
     def get_devices(self):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.ListDevices(Empty())
         return res.items
 
     def get_logical_devices(self):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.ListLogicalDevices(Empty())
         return res.items
 
@@ -183,7 +195,7 @@
 
     def do_logical_devices(self, line):
         """List logical devices in Voltha"""
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.ListLogicalDevices(Empty())
         omit_fields = {
             'desc.mfr_desc',
@@ -201,7 +213,7 @@
         device_id = line.strip() or self.default_device_id
         if not device_id:
             raise Exception('<device-id> parameter needed')
-        sub = DeviceCli(self.get_channel, device_id)
+        sub = DeviceCli(device_id, self.get_stub)
         sub.cmdloop()
 
     def do_logical_device(self, line):
@@ -209,7 +221,7 @@
         logical_device_id = line.strip() or self.default_logical_device_id
         if not logical_device_id:
             raise Exception('<logical-device-id> parameter needed')
-        sub = LogicalDeviceCli(self.get_channel, logical_device_id)
+        sub = LogicalDeviceCli(logical_device_id, self.get_stub)
         sub.cmdloop()
 
     def device_ids(self, force_refresh=False):
@@ -273,7 +285,7 @@
     ])
     def do_preprovision_olt(self, line, opts):
         """Preprovision a new OLT with given device type"""
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         kw = dict(type=opts.device_type)
         if opts.host_and_port:
             kw['host_and_port'] = opts.host_and_port
@@ -299,7 +311,7 @@
         device_id = line or self.default_device_id
         self.poutput('enabling {}'.format(device_id))
         try:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             stub.EnableDevice(voltha_pb2.ID(id=device_id))
 
             while True:
@@ -328,7 +340,7 @@
         device_id = line or self.default_device_id
         self.poutput('rebooting {}'.format(device_id))
         try:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             stub.RebootDevice(voltha_pb2.ID(id=device_id))
             self.poutput('rebooted {}'.format(device_id))
         except Exception, e:
@@ -341,7 +353,7 @@
         device_id = line or self.default_device_id
         self.poutput('Self Testing {}'.format(device_id))
         try:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             res = stub.SelfTest(voltha_pb2.ID(id=device_id))
             self.poutput('Self Tested {}'.format(device_id))
             self.poutput(dumps(pb2dict(res), indent=4))
@@ -355,7 +367,7 @@
         device_id = line or self.default_device_id
         self.poutput('deleting {}'.format(device_id))
         try:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             stub.DeleteDevice(voltha_pb2.ID(id=device_id))
             self.poutput('deleted {}'.format(device_id))
         except Exception, e:
@@ -368,7 +380,7 @@
         device_id = line
         self.poutput('disabling {}'.format(device_id))
         try:
-            stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+            stub = self.get_stub()
             stub.DisableDevice(voltha_pb2.ID(id=device_id))
 
             # Do device query and verify that the device admin status is
@@ -387,25 +399,25 @@
 
     def do_test(self, line):
         """Enter test mode, which makes a bunch on new commands available"""
-        sub = TestCli(self.history, self.get_channel, self.voltha_grpc,
-                      self.voltha_sim_rest)
+        sub = TestCli(self.history, self.voltha_grpc,
+                      self.get_stub, self.voltha_sim_rest)
         sub.cmdloop()
 
     def do_alarm_filters(self, line):
-        sub = AlarmFiltersCli(self.get_channel)
+        sub = AlarmFiltersCli(self.get_stub)
         sub.cmdloop()
 
 
 class TestCli(VolthaCli):
-    def __init__(self, history, get_channel, voltha_grpc, voltha_sim_rest):
+    def __init__(self, history, voltha_grpc, get_stub, voltha_sim_rest):
         VolthaCli.__init__(self, voltha_grpc, voltha_sim_rest)
         self.history = history
-        self.get_channel = get_channel
+        self.get_stub = get_stub
         self.prompt = '(' + self.colorize(self.colorize('test', 'cyan'),
                                           'bold') + ') '
 
     def get_device(self, device_id, depth=0):
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         res = stub.GetDevice(voltha_pb2.ID(id=device_id),
                              metadata=(('get-depth', str(depth)),))
         return res
@@ -432,7 +444,7 @@
         Return the NNI port number and the first usable UNI port of logical
         device, and the vlan associated with the latter.
         """
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         ports = stub.ListLogicalDevicePorts(
             voltha_pb2.ID(id=logical_device_id)).items
         nni = None
@@ -464,7 +476,7 @@
         nni_port_no, unis = self.get_logical_ports(logical_device_id)
 
         # construct and push flow rule
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         for uni_port_no, _ in unis:
             update = FlowTableUpdate(
                 id=logical_device_id,
@@ -495,7 +507,7 @@
         nni_port_no, unis = self.get_logical_ports(logical_device_id)
 
         # construct and push flow rules
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
 
         for uni_port_no, _ in unis:
             stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
@@ -550,7 +562,7 @@
         nni_port_no, unis = self.get_logical_ports(logical_device_id)
 
         # construct and push flow rules
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
 
         for uni_port_no, c_vid in unis:
             # Controller-bound flows
@@ -733,7 +745,7 @@
         nni_port_no, unis = self.get_logical_ports(logical_device_id)
 
         # construct and push flow rules
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
 
         # Controller-bound flows
         for uni_port_no, _ in unis:
@@ -760,7 +772,7 @@
         Remove all flows and flow groups from given logical device
         """
         logical_device_id = line or self.default_logical_device_id
-        stub = voltha_pb2.VolthaLocalServiceStub(self.get_channel())
+        stub = self.get_stub()
         stub.UpdateLogicalDeviceFlowTable(FlowTableUpdate(
             id=logical_device_id,
             flow_mod=ofp.ofp_flow_mod(
@@ -812,6 +824,10 @@
     parser.add_argument(
         '-L', '--lookup', action='store_true', help=_help)
 
+    _help = 'All requests to the Voltha gRPC service are global'
+    parser.add_argument(
+        '-G', '--global_request', action='store_true', help=_help)
+
     _help = '<hostname>:<port> of Voltha gRPC service (default={})'.format(
         defs['voltha_grpc_endpoint'])
     parser.add_argument('-g', '--grpc-endpoint', action='store',
@@ -844,7 +860,8 @@
         args.sim_rest_endpoint = '{}:{}'.format(services[0]['ServiceAddress'],
                                                 services[0]['ServicePort'])
 
-    c = VolthaCli(args.grpc_endpoint, args.sim_rest_endpoint)
+    c = VolthaCli(args.grpc_endpoint, args.sim_rest_endpoint,
+                  args.global_request)
     c.poutput(banner)
     c.load_history()
     c.cmdloop()
diff --git a/cli/setup.sh b/cli/setup.sh
index ee0a643..218a270 100755
--- a/cli/setup.sh
+++ b/cli/setup.sh
@@ -1,10 +1,11 @@
 #!/bin/bash
 
-while getopts LC:g:s: option
+while getopts LGC:g:s: option
 do
     case "${option}"
     in
 	L) LOOKUP_OPT="-L";;
+	G) GLOBAL_REQUEST_OPT="-G";;
 	C) CONSUL_OPT="-C ${OPTARG}";;
 	g) GRPC_OPT="-g ${OPTARG}";;
 	s) SIM_OPT="-s ${OPTARG}";;
@@ -22,7 +23,7 @@
 echo "export DOCKER_HOST_IP=$DOCKER_HOST_IP" > /home/voltha/.bash_profile
 echo "export PYTHONPATH=/cli" >> /home/voltha/.bash_profile
 echo "export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> /home/voltha/.bash_profile
-echo "/cli/cli/main.py $LOOKUP_OPT $CONSUL_OPT $GRPC_OPT $SIM_OPT" >> /home/voltha/.bash_profile
+echo "/cli/cli/main.py $LOOKUP_OPT $GLOBAL_REQUEST_OPT $CONSUL_OPT $GRPC_OPT $SIM_OPT" >> /home/voltha/.bash_profile
 echo "logout" >> /home/voltha/.bash_profile
 chown voltha.voltha /home/voltha/.bash_profile
 /usr/sbin/sshd -D