VOL-270: Investigate and support clustering support for xPON protos

Ensuring global-scope for:
 * ChannelgroupConfig
 * ChannelpairConfig
 * ChannelpartitionConfig
 * ChannelterminationConfig
 * VOntani
 * Ontani
 * VEnets

Making relevant changes into itests for xPON

Adding xPON test cases for test_dispatcher and global rest apis

Change-Id: I8b1ed1cb314810886cd25bee82ffc741f7fe6fcf
diff --git a/common/utils/id_generation.py b/common/utils/id_generation.py
index eedf434..59535b8 100644
--- a/common/utils/id_generation.py
+++ b/common/utils/id_generation.py
@@ -50,6 +50,14 @@
     assert id and len(id) == 16
     return id[:4] == BROADCAST_CORE_ID
 
+def create_empty_broadcast_id():
+    """
+    Returns an empty broadcast id (ffff000000000000). The id is used to
+    dispatch xPON objects across all the Voltha instances.
+    :return: An empty broadcast id
+    """
+    return '{}{}'.format(BROADCAST_CORE_ID, '0'*12)
+
 def create_cluster_id():
     """
     Returns an id that is common across all voltha instances.  The id  
diff --git a/tests/itests/voltha/test_dispatcher.py b/tests/itests/voltha/test_dispatcher.py
index 3c58f07..e70f111 100644
--- a/tests/itests/voltha/test_dispatcher.py
+++ b/tests/itests/voltha/test_dispatcher.py
@@ -19,6 +19,7 @@
 from voltha.core.flow_decomposer import *
 from voltha.protos.openflow_13_pb2 import FlowTableUpdate
 from voltha.protos import bbf_fiber_base_pb2 as fb
+from tests.itests.voltha.test_voltha_xpon import scenario as xpon_scenario
 
 LOCAL_CONSUL = "localhost:8500"
 DOCKER_COMPOSE_FILE = "compose/docker-compose-system-test.yml"
@@ -42,28 +43,22 @@
     kafka_kpis="kafkacat -o end -b {} -C -t voltha.kpis -c 5"
 )
 
-xpon_scenario = [
-    {'cterm-add': {
-        'pb2': fb.ChannelterminationConfig(),
-        'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "PON port",
-                    "description": "Channel Termination for Freedom Tower"
-                    },
-                "data": {
-                    "channelpair_ref": "",
-                    "location": "AT&T WTC OLT"
-                    },
-                "name": "PON port"
-                }
-            }
-        },
-    {'cterm-del': {
-        'pb2': fb.ChannelterminationConfig(),
-        'rpc': {"name": "PON port"}}
-    }
-]
+obj_type_config = {
+    'cg':     {'type':'channel_groups',
+               'config':'channelgroup_config'},
+    'cpart':  {'type':'channel_partitions',
+               'config':'channelpartition_config'},
+    'cpair':  {'type':'channel_pairs',
+               'config':'channelpair_config'},
+    'cterm':  {'type':'channel_terminations',
+               'config':'channeltermination_config'},
+    'vontani':{'type':'v_ont_anis',
+               'config':'v_ontani_config'},
+    'ontani': {'type':'ont_anis',
+               'config':'ontani_config'},
+    'venet':  {'type':'v_enets',
+               'config':'v_enet_config'}
+}
 
 
 class DispatcherTest(RestBase):
@@ -129,8 +124,24 @@
         self._get_device_type_rest(dtypes['items'][0]['id'])
         alarm_filter = self._create_device_filter_rest(olt_id)
         self._remove_device_filter_rest(alarm_filter['id'])
-        channel_termination = self._create_channel_termination_rest(olt_id)
-        self._delete_channel_termination_rest(olt_id)
+        #for xPON objects
+        for item in xpon_scenario:
+            for key,value in item.items():
+                _device_id = None
+                _obj_action = [val for val in key.split('-')]
+                _type_config = obj_type_config[_obj_action[0]]
+                if _obj_action[0] == "cterm":
+                    _device_id = olt_id
+                if _obj_action[1] == "mod":
+                    continue
+                elif _obj_action[1] == "add":
+                    _xpon_obj = self._create_xpon_object_rest(_type_config,
+                                                              value,
+                                                              _device_id)
+                elif _obj_action[1] == "del":
+                    self._delete_xpon_object_rest(_type_config,
+                                                  value,
+                                                  _device_id)
         # TODO: PM APIs test
 
     def test_02_cross_instances_dispatch(self):
@@ -261,46 +272,58 @@
                                        ponsim_logical_device_id)
 
         # Test 8:
-        # A. Create Channel Termination on particular device instance using REST
-        # B. Ensuring that it is present on that specific instance
-        # C. Retrieve Channel Termination from global grpc using empty
-        #    voltha instance
-        channel_termination = self._create_channel_termination_rest(
-            ponsim_olt.id)
-        global_cterm = self._get_channel_terminations_rest(ponsim_olt.id)
-        cterm = self._get_channel_terminations_grpc(
-            self.ponsim_voltha_stub_global, ponsim_olt.id)
-        assert global_cterm == MessageToDict(cterm,
-            including_default_value_fields = True,
-            preserving_proto_field_name = True)
-        cterm = self._get_channel_terminations_grpc(
-            self.ponsim_voltha_stub_local, ponsim_olt.id)
-        assert global_cterm == MessageToDict(cterm,
-            including_default_value_fields = True,
-            preserving_proto_field_name = True)
-        #Checking with empty instance
-        cterm = self._get_channel_terminations_grpc(
-            self.empty_voltha_stub_global, ponsim_olt.id)
-        assert global_cterm == MessageToDict(cterm,
-            including_default_value_fields = True,
-            preserving_proto_field_name = True)
-        #Simulated OLT
-        channel_termination = self._create_channel_termination_rest(
-            simulated_olt.id)
-        global_cterm = self._get_channel_terminations_rest(simulated_olt.id)
-        cterm = self._get_channel_terminations_grpc(
-            self.simulated_voltha_stub_global, simulated_olt.id)
-        assert global_cterm == MessageToDict(cterm,
-            including_default_value_fields = True,
-            preserving_proto_field_name = True)
-        cterm = self._get_channel_terminations_grpc(
-            self.simulated_voltha_stub_local, simulated_olt.id)
-        assert global_cterm == MessageToDict(cterm,
-            including_default_value_fields = True,
-            preserving_proto_field_name = True)
-        #Deleting Channel Termination
-        self._delete_channel_termination_rest(ponsim_olt.id)
-        self._delete_channel_termination_rest(simulated_olt.id)
+        # A. Create xPON objects instance using REST
+        # B. Ensuring that Channeltermination is present on specific instances
+        # C. Ensuring that other xPON objects are present in all instances
+        for item in xpon_scenario:
+            for key,value in item.items():
+                _obj_action = [val for val in key.split('-')]
+                _type_config = obj_type_config[_obj_action[0]]
+                if _obj_action[1] == "mod":
+                    continue
+                if _obj_action[0] == "cterm":
+                    if _obj_action[1] == "add":
+                        #Ponsim OLT
+                        self._create_xpon_object_rest(_type_config,
+                                                      value,
+                                                      ponsim_olt.id)
+                        self._verify_xpon_object_on_device(
+                            _type_config,
+                            self.ponsim_voltha_stub_global,
+                            ponsim_olt.id)
+                        self._delete_xpon_object_rest(_type_config,
+                                                      value,
+                                                      ponsim_olt.id)
+                        #Simulated OLT
+                        self._create_xpon_object_rest(_type_config,
+                                                      value,
+                                                      simulated_olt.id)
+                        self._verify_xpon_object_on_device(
+                            _type_config,
+                            self.simulated_voltha_stub_global,
+                            simulated_olt.id)
+                        self._delete_xpon_object_rest(_type_config,
+                                                      value,
+                                                      simulated_olt.id)
+                    elif _obj_action[1] == "del":
+                        continue
+                else:
+                    if _obj_action[1] == "add":
+                        self._create_xpon_object_rest(_type_config, value)
+                        #Checking with Ponsim OLT
+                        self._verify_xpon_object_on_device(
+                            _type_config,
+                            self.ponsim_voltha_stub_global)
+                        #Checking with empty instance
+                        self._verify_xpon_object_on_device(
+                            _type_config,
+                            self.empty_voltha_stub_global)
+                        #Checking with Simulated OLT
+                        self._verify_xpon_object_on_device(
+                            _type_config,
+                            self.simulated_voltha_stub_global)
+                    elif _obj_action[1] == "del":
+                        self._delete_xpon_object_rest(_type_config, value)
 
         # TODO:  More tests to be added as new features are added
 
@@ -769,31 +792,58 @@
         res = stub.ListLogicalDeviceFlows(voltha_pb2.ID(id=logical_device_id))
         return res
 
-    #For xPon objects
-    def _get_channel_terminations_rest(self, device_id):
-        res = self.get('/api/v1/devices/{}/channel_terminations'.format(
-            device_id))
+    #For xPON objects
+    def _get_path(self, type, name, operation, device_id=None):
+        if(type == 'channel_terminations'):
+            return '/api/v1/devices/{}/{}/{}{}'.format(device_id, type, name,
+                                                       operation)
+        return '/api/v1/{}/{}{}'.format(type, name, operation)
+
+    def _get_xpon_object_rest(self, obj_type, device_id=None):
+        if obj_type["type"] == "channel_terminations":
+            res = self.get('/api/v1/devices/{}/{}'.format(device_id,
+                                                          obj_type["type"]))
+        else:
+            res = self.get('/api/v1/{}'.format(obj_type["type"]))
         return res
 
-    def _get_channel_terminations_grpc(self, stub, device_id):
-        res = stub.GetAllChannelterminationConfig(voltha_pb2.ID(id=device_id))
+    def _get_xpon_object_grpc(self, stub, obj_type, device_id=None):
+        if obj_type["type"] == "channel_groups":
+            res = stub.GetAllChannelgroupConfig(Empty())
+        elif obj_type["type"] == "channel_partitions":
+            res = stub.GetAllChannelpartitionConfig(Empty())
+        elif obj_type["type"] == "channel_pairs":
+            res = stub.GetAllChannelpairConfig(Empty())
+        elif obj_type["type"] == "channel_terminations":
+            res = stub.GetAllChannelterminationConfig(
+                voltha_pb2.ID(id=device_id))
+        elif obj_type["type"] == "v_ont_anis":
+            res = stub.GetAllVOntaniConfig(Empty())
+        elif obj_type["type"] == "ont_anis":
+            res = stub.GetAllOntaniConfig(Empty())
+        elif obj_type["type"] == "v_enets":
+            res = stub.GetAllVEnetConfig(Empty())
         return res
 
-    def _create_channel_termination_rest(self, device_id):
-        value = xpon_scenario[0]['cterm-add']
+    def _create_xpon_object_rest(self, obj_type, value, device_id=None):
         ParseDict(value['rpc'], value['pb2'])
         request = value['pb2']
-        self.post('/api/v1/devices/{}/channel_terminations/{}'.format(
-            device_id, value['rpc']['name']),
+        self.post(self._get_path(obj_type["type"], value['rpc']['name'], "",
+                                 device_id),
                   MessageToDict(request, preserving_proto_field_name = True),
                   expected_code = 200)
         return request
 
-    def _delete_channel_termination_rest(self, device_id):
-        value = xpon_scenario[1]['cterm-del']
-        self.delete('/api/v1/devices/{}/channel_terminations/{}/delete'.format(
-            device_id, value['rpc']['name']),
-                  expected_code = 200)
+    def _delete_xpon_object_rest(self, obj_type, value, device_id=None):
+        self.delete(self._get_path(obj_type["type"], value['rpc']['name'],
+                                   "/delete", device_id), expected_code = 200)
+
+    def _verify_xpon_object_on_device(self, type_config, stub, device_id=None):
+        global_xpon_obj = self._get_xpon_object_rest(type_config, device_id)
+        xpon_obj = self._get_xpon_object_grpc(stub, type_config, device_id)
+        assert global_xpon_obj == MessageToDict(xpon_obj,
+            including_default_value_fields = True,
+            preserving_proto_field_name = True)
 
 if __name__ == '__main__':
     main()
diff --git a/tests/itests/voltha/test_voltha_xpon.py b/tests/itests/voltha/test_voltha_xpon.py
index af1cabf..201eb54 100644
--- a/tests/itests/voltha/test_voltha_xpon.py
+++ b/tests/itests/voltha/test_voltha_xpon.py
@@ -8,9 +8,10 @@
 from common.utils.consulhelpers import get_endpoint_from_consul
 
 '''
-These tests uses the ponsim OLT to verfiy addition, modification and deletion
-of channelgroups, channelpartition, channelpair, channeltermination, vOntAni,
-OntAni and VEnets for xpon
+These tests use the Ponsim OLT to verify create, update, and delete
+functionalities of ChannelgroupConfig, ChannelpartitionConfig,
+ChannelpairConfig, ChannelterminationConfig, VOntAni, OntAni, and VEnets
+for xPON
 The prerequisite for this test are:
  1. voltha ensemble is running
       docker-compose -f compose/docker-compose-system-test.yml up -d
@@ -23,175 +24,174 @@
 device_type = 'ponsim_olt'
 host_and_port = '172.17.0.1:50060'
 scenario = [
-        {'cg-add': {
-            'pb2': fb.ChannelgroupConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "Manhattan",
-                    "description": "Channel Group for Manhattan.."
-                    },
-                "data": {
-                    "polling_period": 100,
-                    "system_id": "000000",
-                    "raman_mitigation": "RAMAN_NONE"
-                    },
-                "name": "Manhattan"
-                }
+    {'cg-add': {
+        'pb2': fb.ChannelgroupConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "Manhattan",
+                "description": "Channel Group for Manhattan.."
+                },
+            "data": {
+                "polling_period": 100,
+                "system_id": "000000",
+                "raman_mitigation": "RAMAN_NONE"
+                },
+            "name": "Manhattan"
             }
-        },
-        {'cpart-add': {
-            'pb2': fb.ChannelpartitionConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "WTC",
-                    "description": "Channel Partition for World Trade \
-Center in Manhattan"
-                    },
-                "data": {
-                    "differential_fiber_distance": 20,
-                    "closest_ont_distance": 0,
-                    "fec_downstream": False,
-                    "multicast_aes_indicator": False,
-                    "authentication_method": "SERIAL_NUMBER",
-                    "channelgroup_ref": "Manhattan"
-                    },
-                "name": "WTC"
-                }
-            }
-        },
-        {'cpair-add': {
-            'pb2': fb.ChannelpairConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "PON port",
-                    "description": "Channel Pair for Freedom Tower in WTC"
-                    },
-                "data": {
-                    "channelpair_linerate": "down_10_up_10",
-                    "channelpair_type": "channelpair",
-                    "channelgroup_ref": "Manhattan",
-                    "gpon_ponid_interval": 0,
-                    "channelpartition_ref": "WTC",
-                    "gpon_ponid_odn_class": "CLASS_A"
-                    },
-                "name": "PON port"
-                }
-            }
-        },
-        {'cterm-add': {
-            'pb2': fb.ChannelterminationConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "PON port",
-                    "description": "Channel Termination for Freedom Tower"
-                    },
-                "data": {
-                    "channelpair_ref": "PON port",
-                    "location": "AT&T WTC OLT"
-                    },
-                "name": "PON port"
-                }
-            }
-        },
-        {'vontani-add': {
-            'pb2': fb.VOntaniConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "ATT Golden User",
-                    "description": "ATT Golden User in Freedom Tower"
-                    },
-                "data": {
-                    "preferred_chanpair": "PON port",
-                    "expected_serial_number": "ALCL00000000",
-                    "parent_ref": "WTC",
-                    "onu_id": 1
-                    },
-                "name": "ATT Golden User"
-                }
-            }
-        },
-        {'ontani-add': {
-            'pb2': fb.OntaniConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "ATT Golden User",
-                    "description": "ATT Golden User in Freedom Tower"
-                    },
-                "data": {
-                    "upstream_fec_indicator": True,
-                    "mgnt_gemport_aes_indicator": False
-                    },
-                "name": "ATT Golden User"
-                }
-            }
-        },
-        {'venet-add': {
-            'pb2': fb.VEnetConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "ATT SU Enet UNI-1-1",
-                    "description": "Ethernet port - 1"
-                    },
-                "data": {
-                    "v_ontani_ref": "ATT Golden User"
-                    },
-                "name": "ATT SU Enet UNI-1-1"
-                }
-            }
-        },
-        {'cg-mod': {
-            'pb2': fb.ChannelgroupConfig(),
-            'rpc': {
-                "interface": {
-                    "enabled": True,
-                    "name": "Manhattan",
-                    "description": "Channel Group for Manhattan"
-                    },
-                "data": {
-                    "polling_period": 100,
-                    "system_id": "000000",
-                    "raman_mitigation": "RAMAN_NONE"
-                    },
-                "name": "Manhattan"
-                }
-            }
-        },
-        {'venet-del': {
-            'pb2': fb.VEnetConfig(),
-            'rpc': {"name": "ATT SU Enet UNI-1-1"}}
-        },
-        {'ontani-del': {
-            'pb2': fb.OntaniConfig(),
-            'rpc': {"name": "ATT Golden User"}}
-        },
-        {'vontani-del': {
-            'pb2': fb.VOntaniConfig(),
-            'rpc': {"name": "ATT Golden User"}}
-        },
-        {'cterm-del': {
-            'pb2': fb.ChannelterminationConfig(),
-            'rpc': {"name": "PON port"}}
-        },
-        {'cpair-del': {
-            'pb2': fb.ChannelpairConfig(),
-            'rpc': {"name": "PON port"}}
-        },
-        {'cpart-del': {
-            'pb2': fb.ChannelpartitionConfig(),
-            'rpc': {"name": "WTC"}}
-        },
-        {'cg-del': {
-            'pb2': fb.ChannelgroupConfig(),
-            'rpc': {"name": "Manhattan"}}
         }
-    ]
+    },
+    {'cpart-add': {
+        'pb2': fb.ChannelpartitionConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "Freedom Tower",
+                "description":"Channel Partition for Freedom Tower in Manhattan"
+                },
+            "data": {
+                "differential_fiber_distance": 20,
+                "closest_ont_distance": 0,
+                "fec_downstream": False,
+                "multicast_aes_indicator": False,
+                "authentication_method": "SERIAL_NUMBER",
+                "channelgroup_ref": "Manhattan"
+                },
+            "name": "Freedom Tower"
+            }
+        }
+    },
+    {'cpair-add': {
+        'pb2': fb.ChannelpairConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "PON port",
+                "description": "Channel Pair for Freedom Tower"
+                },
+            "data": {
+                "channelpair_linerate": "down_10_up_10",
+                "channelpair_type": "channelpair",
+                "channelgroup_ref": "Manhattan",
+                "gpon_ponid_interval": 0,
+                "channelpartition_ref": "Freedom Tower",
+                "gpon_ponid_odn_class": "CLASS_A"
+                },
+            "name": "PON port"
+            }
+        }
+    },
+    {'cterm-add': {
+        'pb2': fb.ChannelterminationConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "PON port",
+                "description": "Channel Termination for Freedom Tower"
+                },
+            "data": {
+                "channelpair_ref": "PON port",
+                "location": "Freedom Tower OLT"
+                },
+            "name": "PON port"
+            }
+        }
+    },
+    {'vontani-add': {
+        'pb2': fb.VOntaniConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "Golden User",
+                "description": "Golden User in Freedom Tower"
+                },
+            "data": {
+                "preferred_chanpair": "PON port",
+                "expected_serial_number": "PSMO00000001",
+                "parent_ref": "Freedom Tower",
+                "onu_id": 1
+                },
+            "name": "Golden User"
+            }
+        }
+    },
+    {'ontani-add': {
+        'pb2': fb.OntaniConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "Golden User",
+                "description": "Golden User in Freedom Tower"
+                },
+            "data": {
+                "upstream_fec_indicator": True,
+                "mgnt_gemport_aes_indicator": False
+                },
+            "name": "Golden User"
+            }
+        }
+    },
+    {'venet-add': {
+        'pb2': fb.VEnetConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "Enet UNI 1",
+                "description": "Ethernet port - 1"
+                },
+            "data": {
+                "v_ontani_ref": "Golden User"
+                },
+            "name": "Enet UNI 1"
+            }
+        }
+    },
+    {'cg-mod': {
+        'pb2': fb.ChannelgroupConfig(),
+        'rpc': {
+            "interface": {
+                "enabled": True,
+                "name": "Manhattan",
+                "description": "Channel Group for Manhattan"
+                },
+            "data": {
+                "polling_period": 100,
+                "system_id": "000000",
+                "raman_mitigation": "RAMAN_NONE"
+                },
+            "name": "Manhattan"
+            }
+        }
+    },
+    {'venet-del': {
+        'pb2': fb.VEnetConfig(),
+        'rpc': {"name": "Enet UNI 1"}}
+    },
+    {'ontani-del': {
+        'pb2': fb.OntaniConfig(),
+        'rpc': {"name": "Golden User"}}
+    },
+    {'vontani-del': {
+        'pb2': fb.VOntaniConfig(),
+        'rpc': {"name": "Golden User"}}
+    },
+    {'cterm-del': {
+        'pb2': fb.ChannelterminationConfig(),
+        'rpc': {"name": "PON port"}}
+    },
+    {'cpair-del': {
+        'pb2': fb.ChannelpairConfig(),
+        'rpc': {"name": "PON port"}}
+    },
+    {'cpart-del': {
+        'pb2': fb.ChannelpartitionConfig(),
+        'rpc': {"name": "Freedom Tower"}}
+    },
+    {'cg-del': {
+        'pb2': fb.ChannelgroupConfig(),
+        'rpc': {"name": "Manhattan"}}
+    }
+]
 
 #for ordering the test cases
 id = 3
@@ -224,7 +224,7 @@
     #~~~~~~~~~~~~~~~~~~~~~~ Helper Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     # Create a new simulated device
     def add_device(self):
-        return self.post('/api/v1/local/devices',
+        return self.post('/api/v1/devices',
                            MessageToDict(Device(
                                 type=device_type,
                                 host_and_port=host_and_port
@@ -234,7 +234,7 @@
     def verify_device_preprovisioned_state(self, olt_id):
         # we also check that so far what we read back is same as what we get
         # back on create
-        device = self.get('/api/v1/local/devices/{}'.format(olt_id))
+        device = self.get('/api/v1/devices/{}'.format(olt_id))
         self.assertNotEqual(device['id'], '')
         self.assertEqual(device['adapter'], 'ponsim_olt')
         self.assertEqual(device['admin_state'], 'PREPROVISIONED')
@@ -243,19 +243,19 @@
     # Active the simulated device.
     # This will trigger the simulation of random alarms
     def activate_device(self, device_id):
-        path = '/api/v1/local/devices/{}'.format(device_id)
+        path = '/api/v1/devices/{}'.format(device_id)
         self.post(path + '/enable', expected_code=200)
         device = self.get(path)
         self.assertEqual(device['admin_state'], 'ENABLED')
 
     def deactivate_device(self, device_id):
-        path = '/api/v1/local/devices/{}'.format(device_id)
+        path = '/api/v1/devices/{}'.format(device_id)
         self.post(path + '/disable', expected_code=200)
         device = self.get(path)
         self.assertEqual(device['admin_state'], 'DISABLED')
 
     def delete_device(self, device_id):
-        path = '/api/v1/local/devices/{}'.format(device_id)
+        path = '/api/v1/devices/{}'.format(device_id)
         self.delete(path + '/delete', expected_code=200)
         device = self.get(path, expected_code=404)
         self.assertIsNone(device)
@@ -288,13 +288,13 @@
     def verify(self, type):
         if(type == 'channel_terminations'):
             return self.get('/api/v1/devices/{}/{}'.format(device['id'], type))
-        return self.get('/api/v1/local/{}'.format(type))
+        return self.get('/api/v1/{}'.format(type))
 
     def get_path(self, type, name, operation):
         if(type == 'channel_terminations'):
-            return 'api/v1/devices/{}/{}/{}{}'.format(device['id'],
+            return '/api/v1/devices/{}/{}/{}{}'.format(device['id'],
                 type, name, operation)
-        return 'api/v1/local/{}/{}{}'.format(type, name, operation)
+        return '/api/v1/{}/{}{}'.format(type, name, operation)
 
     # Method to check if the result is same as the change requested
     def search(self, req, result):
@@ -316,15 +316,20 @@
 #~~~~~~~~~~~~~~ Function to create test cases on the fly ~~~~~~~~~~~~~~~~
 def create_dynamic_method(key, value):
     obj_type_config = {
-        'cg':{'type':'channel_groups','config':'channelgroup_config'},
-        'cpart':{'type':'channel_partitions',
-                 'config':'channelpartition_config'},
-        'cpair':{'type':'channel_pairs','config':'channelpair_config'},
-        'cterm':{'type':'channel_terminations',
-                 'config':'channeltermination_config'},
-        'vontani':{'type':'v_ont_anis','config':'v_ontani_config'},
-        'ontani':{'type':'ont_anis','config':'ontani_config'},
-        'venet':{'type':'v_enets','config':'v_enet_config'}
+        'cg':     {'type':'channel_groups',
+                   'config':'channelgroup_config'},
+        'cpart':  {'type':'channel_partitions',
+                   'config':'channelpartition_config'},
+        'cpair':  {'type':'channel_pairs',
+                   'config':'channelpair_config'},
+        'cterm':  {'type':'channel_terminations',
+                   'config':'channeltermination_config'},
+        'vontani':{'type':'v_ont_anis',
+                   'config':'v_ontani_config'},
+        'ontani': {'type':'ont_anis',
+                   'config':'ontani_config'},
+        'venet':  {'type':'v_enets',
+                   'config':'v_enet_config'}
     }
 
     def _add(self, type, config, req, name):
@@ -361,13 +366,15 @@
 
     return dynamic_test_method
 
-#read the set instructions for tests and dynamically create test cases in desired sequence
+#read the set instructions for tests
+#dynamically create test cases in desired sequence
 for item in scenario:
     id = id + 1
     if(isinstance(item, dict)):
         for k,v in item.items():
             dynamic_method = create_dynamic_method(k, v)
-            dynamic_method.__name__ = 'test_{:3d}_{}'.format(id, k).replace(' ', '0')
+            dynamic_method.__name__ = 'test_{:3d}_{}'.format(id, k).replace(
+                ' ', '0')
             setattr(TestXPon, dynamic_method.__name__, dynamic_method)
             del dynamic_method
 
diff --git a/voltha/core/global_handler.py b/voltha/core/global_handler.py
index 08da69f..f75358f 100644
--- a/voltha/core/global_handler.py
+++ b/voltha/core/global_handler.py
@@ -18,7 +18,8 @@
 from twisted.internet.defer import returnValue
 
 from common.utils.grpc_utils import twisted_async
-from common.utils.id_generation import create_cluster_id
+from common.utils.id_generation import \
+    create_cluster_id, create_empty_broadcast_id
 from voltha.core.config.config_root import ConfigRoot
 from voltha.protos.device_pb2 import PmConfigs, Images
 from voltha.protos.voltha_pb2 import \
@@ -30,6 +31,7 @@
 from voltha.registry import registry
 from google.protobuf.empty_pb2 import Empty
 from dispatcher import DispatchError
+from voltha.protos import bbf_fiber_base_pb2 as fb
 
 log = structlog.get_logger()
 
@@ -515,136 +517,295 @@
 
     # bbf_fiber rpcs start
     @twisted_async
+    @inlineCallbacks
     def GetAllChannelgroupConfig(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        response = yield self.dispatcher.dispatch(
             'GetAllChannelgroupConfig',
-            request,
-            context)
+            Empty(),
+            context,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelgroup error')
+            context.set_code(response.error_code)
+            returnValue(Empty())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def CreateChannelgroup(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelgroupConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelgroupConfig())
+        response = yield self.dispatcher.dispatch(
             'CreateChannelgroup',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelgroup\'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelgroupConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def UpdateChannelgroup(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelgroupConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelgroupConfig())
+        response = yield self.dispatcher.dispatch(
             'UpdateChannelgroup',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelgroup\'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelgroupConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def DeleteChannelgroup(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelgroupConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelgroupConfig())
+        response = yield self.dispatcher.dispatch(
             'DeleteChannelgroup',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelgroup\'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelgroupConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def GetAllChannelpartitionConfig(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        response = yield self.dispatcher.dispatch(
             'GetAllChannelpartitionConfig',
-            request,
-            context)
+            Empty(),
+            context,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpartition error')
+            context.set_code(response.error_code)
+            returnValue(Empty())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def CreateChannelpartition(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelpartitionConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelpartitionConfig())
+        response = yield self.dispatcher.dispatch(
             'CreateChannelpartition',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpartition\'{}\' error'.format(
+                request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelpartitionConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def UpdateChannelpartition(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelpartitionConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelpartitionConfig())
+        response = yield self.dispatcher.dispatch(
             'UpdateChannelpartition',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpartition\'{}\' error'.format(
+                request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelpartitionConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def DeleteChannelpartition(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelpartitionConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelpartitionConfig())
+        response = yield self.dispatcher.dispatch(
             'DeleteChannelpartition',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpartition\'{}\' error'.format(
+                request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelpartitionConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def GetAllChannelpairConfig(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        response = yield self.dispatcher.dispatch(
             'GetAllChannelpairConfig',
-            request,
-            context)
+            Empty(),
+            context,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpair error')
+            context.set_code(response.error_code)
+            returnValue(Empty())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def CreateChannelpair(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelpairConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelpairConfig())
+        response = yield self.dispatcher.dispatch(
             'CreateChannelpair',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpair\'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelpairConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def UpdateChannelpair(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelpairConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelpairConfig())
+        response = yield self.dispatcher.dispatch(
             'UpdateChannelpair',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpair\'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelpairConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def DeleteChannelpair(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.ChannelpairConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.ChannelpairConfig())
+        response = yield self.dispatcher.dispatch(
             'DeleteChannelpair',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Channelpair\'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.ChannelpairConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
     @inlineCallbacks
@@ -661,7 +822,7 @@
             context.set_details('Channeltermination \'{}\' error'.format(
                 request.id))
             context.set_code(response.error_code)
-            returnValue(Empty())
+            returnValue(fb.ChannelterminationConfig())
         else:
             log.info('grpc-success-response', response=response)
             returnValue(response)
@@ -681,7 +842,7 @@
             context.set_details('Channeltermination \'{}\' error'.format(
                 request.id))
             context.set_code(response.error_code)
-            returnValue(Empty())
+            returnValue(fb.ChannelterminationConfig())
         else:
             log.info('grpc-success-response', response=response)
             returnValue(response)
@@ -701,7 +862,7 @@
             context.set_details('Channeltermination \'{}\' error'.format(
                 request.id))
             context.set_code(response.error_code)
-            returnValue(Empty())
+            returnValue(fb.ChannelterminationConfig())
         else:
             log.info('grpc-success-response', response=response)
             returnValue(response)
@@ -721,142 +882,298 @@
             context.set_details('Channeltermination \'{}\' error'.format(
                 request.id))
             context.set_code(response.error_code)
+            returnValue(fb.ChannelterminationConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
+
+    @twisted_async
+    @inlineCallbacks
+    def GetAllOntaniConfig(self, request, context):
+        log.info('grpc-request', request=request)
+        response = yield self.dispatcher.dispatch(
+            'GetAllOntaniConfig',
+            Empty(),
+            context,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Ontani error')
+            context.set_code(response.error_code)
             returnValue(Empty())
         else:
             log.info('grpc-success-response', response=response)
             returnValue(response)
 
     @twisted_async
-    def GetAllOntaniConfig(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
-            'GetAllOntaniConfig',
-            request,
-            context)
-
-    @twisted_async
+    @inlineCallbacks
     def CreateOntani(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.OntaniConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.OntaniConfig())
+        response = yield self.dispatcher.dispatch(
             'CreateOntani',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Ontani \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.OntaniConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def UpdateOntani(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.OntaniConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.OntaniConfig())
+        response = yield self.dispatcher.dispatch(
             'UpdateOntani',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Ontani \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.OntaniConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def DeleteOntani(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.OntaniConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.OntaniConfig())
+        response = yield self.dispatcher.dispatch(
             'DeleteOntani',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('Ontani \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.OntaniConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def GetAllVOntaniConfig(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        response = yield self.dispatcher.dispatch(
             'GetAllVOntaniConfig',
-            request,
-            context)
+            Empty(),
+            context,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VOntani error')
+            context.set_code(response.error_code)
+            returnValue(Empty())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def CreateVOntani(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.VOntaniConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.VOntaniConfig())
+        response = yield self.dispatcher.dispatch(
             'CreateVOntani',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VOntani \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.VOntaniConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def UpdateVOntani(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.VOntaniConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.VOntaniConfig())
+        response = yield self.dispatcher.dispatch(
             'UpdateVOntani',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VOntani \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.VOntaniConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def DeleteVOntani(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.VOntaniConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.VOntaniConfig())
+        response = yield self.dispatcher.dispatch(
             'DeleteVOntani',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VOntani \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.VOntaniConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def GetAllVEnetConfig(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        response = yield self.dispatcher.dispatch(
             'GetAllVEnetConfig',
             request,
-            context)
+            context,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VEnet error')
+            context.set_code(response.error_code)
+            returnValue(Empty())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def CreateVEnet(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.VEnetConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.VEnetConfig())
+        response = yield self.dispatcher.dispatch(
             'CreateVEnet',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VEnet \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.VEnetConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def UpdateVEnet(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.VEnetConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.VEnetConfig())
+        response = yield self.dispatcher.dispatch(
             'UpdateVEnet',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VEnet \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.VEnetConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
 
     @twisted_async
+    @inlineCallbacks
     def DeleteVEnet(self, request, context):
-        log.warning('temp-limited-implementation')
-        # TODO dispatching to local instead of collecting all
-        return self.dispatcher.dispatch(
-            self.instance_id,
-            VolthaLocalServiceStub,
+        log.info('grpc-request', request=request)
+        try:
+            assert isinstance(request, fb.VEnetConfig)
+            request.id = create_empty_broadcast_id()
+        except AssertionError, e:
+            context.set_details(e.message)
+            context.set_code(StatusCode.INVALID_ARGUMENT)
+            returnValue(fb.VEnetConfig())
+        response = yield self.dispatcher.dispatch(
             'DeleteVEnet',
             request,
-            context)
+            context,
+            id=request.id,
+            broadcast=True)
+        if isinstance(response, DispatchError):
+            log.info('grpc-error-response', error=response.error_code)
+            context.set_details('VEnet \'{}\' error'.format(request.id))
+            context.set_code(response.error_code)
+            returnValue(fb.VEnetConfig())
+        else:
+            log.info('grpc-success-response', response=response)
+            returnValue(response)
     # bbf_fiber rpcs end
 
     @twisted_async
diff --git a/voltha/protos/bbf_fiber_base.proto b/voltha/protos/bbf_fiber_base.proto
index 2c02171..c8cc400 100644
--- a/voltha/protos/bbf_fiber_base.proto
+++ b/voltha/protos/bbf_fiber_base.proto
@@ -13,24 +13,26 @@
 
 message ChannelgroupConfig
 {
-	ietf_interfaces.Interface interface = 1;
-	ChannelgroupConfigData data = 2;
-	string name = 3;
-
+	string id = 1 [(voltha.access) = READ_ONLY];
+	ietf_interfaces.Interface interface = 2;
+	ChannelgroupConfigData data = 3;
+	string name = 4;
 }
 
 message ChannelpartitionConfig
 {
-	ietf_interfaces.Interface interface = 1;
-	ChannelpartitionConfigData data = 2;
-	string name = 3;
+	string id = 1 [(voltha.access) = READ_ONLY];
+	ietf_interfaces.Interface interface = 2;
+	ChannelpartitionConfigData data = 3;
+	string name = 4;
 }
 
 message ChannelpairConfig
 {
-	ietf_interfaces.Interface interface = 1;
-	ChannelpairConfigData data = 2;
-	string name = 3;
+	string id = 1 [(voltha.access) = READ_ONLY];
+	ietf_interfaces.Interface interface = 2;
+	ChannelpairConfigData data = 3;
+	string name = 4;
 }
 message ChannelpairOper
 {
@@ -56,9 +58,10 @@
 
 message OntaniConfig
 {
-	ietf_interfaces.Interface interface = 1;
-	OntaniConfigData data = 2;
-	string name = 3;
+	string id = 1 [(voltha.access) = READ_ONLY];
+	ietf_interfaces.Interface interface = 2;
+	OntaniConfigData data = 3;
+	string name = 4;
 }
 message OntaniOper
 {
@@ -69,16 +72,18 @@
 
 message VOntaniConfig
 {
-	ietf_interfaces.Interface interface = 1;
-	VOntaniConfigData data = 2;
-	string name = 3;
+	string id = 1 [(voltha.access) = READ_ONLY];
+	ietf_interfaces.Interface interface = 2;
+	VOntaniConfigData data = 3;
+	string name = 4;
 }
 
 message VEnetConfig
 {
-	ietf_interfaces.Interface interface = 1;
-	VEnetConfigData data = 2;
-	string name = 3;
+	string id = 1 [(voltha.access) = READ_ONLY];
+	ietf_interfaces.Interface interface = 2;
+	VEnetConfigData data = 3;
+	string name = 4;
 }
 
 message AllChannelgroupConfig