733: Insert the description of the change.Need to support Error Checking for consistency – if Meter Reference made then need Meter to exist first before reference.

If Flow Table ID does not resolve to a Technology Profile in KV Store generate an error – initial approach to simplify implementation - the Technology for the Profile will not be used to qualify the lookup.

Initially just do OF agent checks which do not need knowledge available in the adapter i.e. Meter Band Reference requires Meter Band definition first. Any Forward References need error checks (OF Error messages).

OF Agent needs to pass through the Meter/Meter Band programming and the Flow Table ID used to reference the Technology Profile.

The VOLTHA core needs to be able to receive meters from the OFAgent and store them in the appropriate logical device. A new northbound API needs to be added to the core to support this.

Change-Id: Ide776dbcbc04232c1d929a85707fec09e3dedf6f
diff --git a/tests/utests/ofagent/test_of_protocol_handler.py b/tests/utests/ofagent/test_of_protocol_handler.py
index ca4392d..fbcc654 100644
--- a/tests/utests/ofagent/test_of_protocol_handler.py
+++ b/tests/utests/ofagent/test_of_protocol_handler.py
@@ -40,7 +40,7 @@
         req.role = ofp.OFPCR_ROLE_MASTER
         return req
 
-    def test_handle_flow_mod_request_role_salve(self):
+    def test_handle_flow_mod_request_role_slave(self):
         generic_obj = self.gen_generic_obj()
         device = self.gen_device()
         of_proto_handler = OpenFlowProtocolHandler(device.datapath_id, device.id, generic_obj, generic_obj, generic_obj)
@@ -57,6 +57,23 @@
         of_proto_handler.role = ofp.OFPCR_ROLE_MASTER
         of_proto_handler.handle_flow_mod_request(generic_obj)
 
+    def test_handle_meter_mod_request_role_slave(self):
+        generic_obj = self.gen_generic_obj()
+        device = self.gen_device()
+        of_proto_handler = OpenFlowProtocolHandler(device.datapath_id, device.id, generic_obj, generic_obj, generic_obj)
+        of_proto_handler.role = ofp.OFPCR_ROLE_SLAVE
+        with self.assertRaises(Exception) as context:
+            of_proto_handler.handle_meter_mod_request(generic_obj)
+        print context.exception
+        self.assertTrue('\'function\' object has no attribute \'send\'' in str(context.exception))
+
+    def test_handle_meter_mod_request_role_master(self):
+        generic_obj = self.gen_generic_obj()
+        device = self.gen_device()
+        of_proto_handler = OpenFlowProtocolHandler(device.datapath_id, device.id, generic_obj, generic_obj, generic_obj)
+        of_proto_handler.role = ofp.OFPCR_ROLE_MASTER
+        of_proto_handler.handle_meter_mod_request(generic_obj)
+
     def test_handle_role_request(self):
         generic_obj = self.gen_generic_obj()
         req = self.gen_role_req()
diff --git a/tests/utests/ofagent/test_ofagent_meter_mod_converter.py b/tests/utests/ofagent/test_ofagent_meter_mod_converter.py
new file mode 100644
index 0000000..899953a
--- /dev/null
+++ b/tests/utests/ofagent/test_ofagent_meter_mod_converter.py
@@ -0,0 +1,76 @@
+#
+# Copyright 2017 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+from unittest import main, TestCase
+import structlog
+from loxi.of13.message import meter_mod
+from ofagent.converter import to_grpc
+from ofagent.loxi.of13 import const
+from random import randint
+from protobuf_to_dict import protobuf_to_dict
+from ofagent.loxi.of13.message import meter_mod
+
+log = structlog.get_logger()
+
+
+class test_of_agent_vcore_connection(TestCase):
+
+    def test_meter_mod_loxi_to_grpc_converter(self):
+        from ofagent.loxi.of13 import meter_band
+
+        assertion_check_keys = dict()
+        meter_bands = list()
+
+        command_list = [const.OFPMC_ADD, const.OFPMC_MODIFY, const.OFPMC_DELETE]
+        flag_list = [const.OFPMF_KBPS, const.OFPMF_PKTPS, const.OFPMF_BURST, const.OFPMF_STATS]
+        meter_band_constructs = [meter_band.dscp_remark, meter_band.drop, meter_band.experimenter]
+
+        assertion_check_keys['meter_band_entry_cnt'] = randint(0, 20)
+        assertion_check_keys['xid_instance'] = randint(0, 0xFFFFFFFF)
+        assertion_check_keys['command_instance'] = command_list[randint(0, len(command_list) - 1)]
+        assertion_check_keys['flag_instance'] = flag_list[randint(0, len(flag_list) - 1)]
+
+        for i in range(0, assertion_check_keys['meter_band_entry_cnt']):
+            meter_band = meter_band_constructs[randint(0, len(meter_band_constructs)-1)]()
+            assertion_check_keys['meter_band_type_' + str(i)] = meter_band.type
+            meter_bands.append(meter_band)
+
+        of_meter_mod_req = meter_mod(xid=assertion_check_keys['xid_instance'],
+                                     command=assertion_check_keys['command_instance'],
+                                     flags=assertion_check_keys['flag_instance'],
+                                     meters=meter_bands)
+
+        req = to_grpc(of_meter_mod_req)
+        request = protobuf_to_dict(req)
+
+        if request.has_key('flags'):
+            self.assertEqual(request['flags'], assertion_check_keys['flag_instance'])
+
+        if request.has_key('command'):
+            self.assertEqual(request['command'], assertion_check_keys['command_instance'])
+
+        if request.has_key('bands'):
+            self.assertEqual(assertion_check_keys['meter_band_entry_cnt'], len(request['bands']))
+
+            name_suffix = 0
+            for i in request['bands']:
+                self.assertEqual(i['type'], assertion_check_keys['meter_band_type_' + str(name_suffix)])
+                name_suffix = name_suffix+1
+
+
+if __name__ == '__main__':
+    main()