Zack Williams | 41513bf | 2018-07-07 20:08:35 -0700 | [diff] [blame] | 1 | # Copyright 2017-present Open Networking Foundation |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 14 | from tests.itests.voltha.rest_base import RestBase |
| 15 | |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 16 | from google.protobuf.json_format import MessageToDict, ParseDict |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 17 | import unittest |
| 18 | |
| 19 | from voltha.protos import bbf_fiber_base_pb2 as fb |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 20 | from voltha.protos.device_pb2 import Device |
Nikolay Titov | 176f1db | 2017-08-10 12:38:43 -0400 | [diff] [blame] | 21 | from voltha.protos import bbf_fiber_gemport_body_pb2 as gemport |
| 22 | from voltha.protos import bbf_fiber_tcont_body_pb2 as tcont |
| 23 | from voltha.protos import bbf_fiber_traffic_descriptor_profile_body_pb2 as tdp |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 24 | from common.utils.consulhelpers import get_endpoint_from_consul |
Richard Jankowski | 461cb97 | 2018-04-11 15:36:27 -0400 | [diff] [blame] | 25 | from tests.itests.voltha.xpon_scenario import scenario as xpon_scenario |
Richard Jankowski | 8728934 | 2018-04-19 13:59:10 -0400 | [diff] [blame] | 26 | from tests.itests.test_utils import get_pod_ip |
| 27 | from testconfig import config |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 28 | |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 29 | ''' |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 30 | These tests use the Ponsim OLT to verify create, update, and delete |
| 31 | functionalities of ChannelgroupConfig, ChannelpartitionConfig, |
| 32 | ChannelpairConfig, ChannelterminationConfig, VOntAni, OntAni, and VEnets |
| 33 | for xPON |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 34 | The prerequisite for this test are: |
| 35 | 1. voltha ensemble is running |
| 36 | docker-compose -f compose/docker-compose-system-test.yml up -d |
| 37 | 2. ponsim olt is running with PONSIM-OLT |
| 38 | sudo -s |
| 39 | . ./env.sh |
| 40 | ./ponsim/main.py -v |
| 41 | ''' |
| 42 | |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 43 | device_type = 'ponsim_olt' |
| 44 | host_and_port = '172.17.0.1:50060' |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 45 | |
Rachit Shrivastava | 8f4f9bf | 2017-07-20 11:59:30 -0400 | [diff] [blame] | 46 | #for ordering the test cases |
| 47 | id = 3 |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 48 | LOCAL_CONSUL = "localhost:8500" |
Richard Jankowski | 8728934 | 2018-04-19 13:59:10 -0400 | [diff] [blame] | 49 | |
| 50 | orch_env = 'docker-compose' |
| 51 | if 'test_parameters' in config and 'orch_env' in config['test_parameters']: |
| 52 | orch_env = config['test_parameters']['orch_env'] |
| 53 | print 'orchestration-environment: %s' % orch_env |
| 54 | |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 55 | # Retrieve details of the REST entry point |
Richard Jankowski | 8728934 | 2018-04-19 13:59:10 -0400 | [diff] [blame] | 56 | if orch_env == 'k8s-single-node': |
| 57 | rest_endpoint = get_pod_ip('voltha') + ':8443' |
| 58 | else: |
| 59 | rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'voltha-envoy-8443') |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 60 | # Construct the base_url |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 61 | BASE_URL = 'https://' + rest_endpoint |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 62 | |
| 63 | class GlobalPreChecks(RestBase): |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 64 | base_url = BASE_URL |
| 65 | |
| 66 | # def test_000_get_root(self): |
| 67 | # res = self.get('/#!/', expected_content_type='text/html') |
| 68 | # self.assertGreaterEqual(res.find('swagger'), 0) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 69 | |
| 70 | def test_001_get_health(self): |
| 71 | res = self.get('/health') |
| 72 | self.assertEqual(res['state'], 'HEALTHY') |
| 73 | |
| 74 | class TestXPon(RestBase): |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 75 | base_url = BASE_URL |
| 76 | |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 77 | def test_002_setup_device(self): |
| 78 | global device |
| 79 | device = self.add_device() |
| 80 | self.verify_device_preprovisioned_state(device['id']) |
| 81 | self.activate_device(device['id']) |
| 82 | |
Nikolay Titov | 7253ff2 | 2017-08-14 18:24:17 -0400 | [diff] [blame] | 83 | def _remove_device(self): |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 84 | self.deactivate_device(device['id']) |
| 85 | self.delete_device(device['id']) |
| 86 | |
| 87 | #~~~~~~~~~~~~~~~~~~~~~~ Helper Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 88 | # Create a new simulated device |
| 89 | def add_device(self): |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 90 | return self.post('/api/v1/devices', |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 91 | MessageToDict(Device( |
| 92 | type=device_type, |
| 93 | host_and_port=host_and_port |
| 94 | )), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 95 | expected_http_code=200) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 96 | |
| 97 | def verify_device_preprovisioned_state(self, olt_id): |
| 98 | # we also check that so far what we read back is same as what we get |
| 99 | # back on create |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 100 | device = self.get('/api/v1/devices/{}'.format(olt_id)) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 101 | self.assertNotEqual(device['id'], '') |
| 102 | self.assertEqual(device['adapter'], 'ponsim_olt') |
| 103 | self.assertEqual(device['admin_state'], 'PREPROVISIONED') |
| 104 | self.assertEqual(device['oper_status'], 'UNKNOWN') |
| 105 | |
| 106 | # Active the simulated device. |
| 107 | # This will trigger the simulation of random alarms |
| 108 | def activate_device(self, device_id): |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 109 | path = '/api/v1/devices/{}'.format(device_id) |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 110 | self.post(path + '/enable', expected_http_code=200) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 111 | device = self.get(path) |
| 112 | self.assertEqual(device['admin_state'], 'ENABLED') |
| 113 | |
| 114 | def deactivate_device(self, device_id): |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 115 | path = '/api/v1/devices/{}'.format(device_id) |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 116 | self.post(path + '/disable', expected_http_code=200) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 117 | device = self.get(path) |
| 118 | self.assertEqual(device['admin_state'], 'DISABLED') |
| 119 | |
| 120 | def delete_device(self, device_id): |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 121 | path = '/api/v1/devices/{}'.format(device_id) |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 122 | self.delete(path + '/delete', expected_http_code=200) |
| 123 | device = self.get(path, expected_http_code=404) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 124 | self.assertIsNone(device) |
| 125 | |
| 126 | # Add cg, cpair, cpart |
| 127 | def add(self, type, config, req, name): |
| 128 | res = self.verify(type) |
| 129 | prev_len = len(res[config]) |
| 130 | self.post(self.get_path(type, name, ''), |
| 131 | MessageToDict(req, preserving_proto_field_name = True), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 132 | expected_http_code = 200) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 133 | return self.verify(type), prev_len |
| 134 | |
| 135 | # Modify the existing cg, cpair, cpart |
| 136 | def modify(self, type, req, name): |
| 137 | self.post(self.get_path(type, name, '/modify'), |
| 138 | MessageToDict(req, preserving_proto_field_name = True), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 139 | expected_http_code = 200) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 140 | return self.verify(type) |
| 141 | |
| 142 | # Delete cg, cpair, cpart |
| 143 | def remove(self, type, config, name): |
| 144 | res = self.verify(type) |
| 145 | prev_len = len(res[config]) |
| 146 | self.delete(self.get_path(type, name, '/delete'), |
Stephane Barbarie | cd51f99 | 2017-09-07 16:37:02 -0400 | [diff] [blame] | 147 | expected_http_code = 200) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 148 | return self.verify(type), prev_len |
| 149 | |
| 150 | # Retrieve the desired item upon Post message |
| 151 | def verify(self, type): |
| 152 | if(type == 'channel_terminations'): |
Rachit Shrivastava | 8f4f9bf | 2017-07-20 11:59:30 -0400 | [diff] [blame] | 153 | return self.get('/api/v1/devices/{}/{}'.format(device['id'], type)) |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 154 | return self.get('/api/v1/{}'.format(type)) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 155 | |
| 156 | def get_path(self, type, name, operation): |
| 157 | if(type == 'channel_terminations'): |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 158 | return '/api/v1/devices/{}/{}/{}{}'.format(device['id'], |
Rachit Shrivastava | 8f4f9bf | 2017-07-20 11:59:30 -0400 | [diff] [blame] | 159 | type, name, operation) |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 160 | return '/api/v1/{}/{}{}'.format(type, name, operation) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 161 | |
| 162 | # Method to check if the result is same as the change requested |
| 163 | def search(self, req, result): |
Nikolay Titov | 176f1db | 2017-08-10 12:38:43 -0400 | [diff] [blame] | 164 | dict1 = MessageToDict(req, |
| 165 | including_default_value_fields = True, |
| 166 | preserving_proto_field_name = True) |
Nikolay Titov | 7253ff2 | 2017-08-14 18:24:17 -0400 | [diff] [blame] | 167 | #skip comparison of READ-ONLY fields |
Nikolay Titov | 176f1db | 2017-08-10 12:38:43 -0400 | [diff] [blame] | 168 | result['id'] = '' |
Nikolay Titov | 7253ff2 | 2017-08-14 18:24:17 -0400 | [diff] [blame] | 169 | if isinstance(req, fb.ChannelgroupConfig): |
| 170 | result['cg_index'] = 0 |
| 171 | elif isinstance(req, tcont.TcontsConfigData): |
Rachit Shrivastava | 1b2478e | 2018-03-01 11:53:49 -0500 | [diff] [blame] | 172 | if not dict1['alloc_id']: |
| 173 | result['alloc_id'] = 0 |
Nikolay Titov | 7253ff2 | 2017-08-14 18:24:17 -0400 | [diff] [blame] | 174 | elif isinstance(req, gemport.GemportsConfigData): |
Rachit Shrivastava | 1b2478e | 2018-03-01 11:53:49 -0500 | [diff] [blame] | 175 | if not dict1['gemport_id']: |
| 176 | result['gemport_id'] = 0 |
Nikolay Titov | 176f1db | 2017-08-10 12:38:43 -0400 | [diff] [blame] | 177 | return dict1 == result |
| 178 | |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 179 | |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 180 | #~~~~~~~~~~~~~~ Function to create test cases on the fly ~~~~~~~~~~~~~~~~ |
| 181 | def create_dynamic_method(key, value): |
| 182 | obj_type_config = { |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 183 | 'cg': {'type':'channel_groups', |
| 184 | 'config':'channelgroup_config'}, |
| 185 | 'cpart': {'type':'channel_partitions', |
| 186 | 'config':'channelpartition_config'}, |
| 187 | 'cpair': {'type':'channel_pairs', |
| 188 | 'config':'channelpair_config'}, |
| 189 | 'cterm': {'type':'channel_terminations', |
| 190 | 'config':'channeltermination_config'}, |
| 191 | 'vontani':{'type':'v_ont_anis', |
| 192 | 'config':'v_ontani_config'}, |
| 193 | 'ontani': {'type':'ont_anis', |
| 194 | 'config':'ontani_config'}, |
| 195 | 'venet': {'type':'v_enets', |
Nikolay Titov | 176f1db | 2017-08-10 12:38:43 -0400 | [diff] [blame] | 196 | 'config':'v_enet_config'}, |
| 197 | 'gemport':{'type':'gemports', |
| 198 | 'config':'gemports_config'}, |
| 199 | 'tcont': {'type':'tconts', |
| 200 | 'config':'tconts_config'}, |
| 201 | 'tdp': {'type':'traffic_descriptor_profiles', |
| 202 | 'config':'traffic_descriptor_profiles'} |
Rachit Shrivastava | 8f4f9bf | 2017-07-20 11:59:30 -0400 | [diff] [blame] | 203 | } |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 204 | |
| 205 | def _add(self, type, config, req, name): |
| 206 | result, prev_len = self.add(type, config, req, name) |
| 207 | self.assertEqual(result[config][prev_len]['name'], name) |
| 208 | self.assertEqual(len(result[config]), prev_len+1) |
Rachit Shrivastava | 1b2478e | 2018-03-01 11:53:49 -0500 | [diff] [blame] | 209 | self.assertEqual(self.search(req, result[config][prev_len]), True) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 210 | |
| 211 | def _mod(self, type, config, req, name): |
| 212 | result = self.modify(type, req, name) |
Nikolay Titov | 176f1db | 2017-08-10 12:38:43 -0400 | [diff] [blame] | 213 | self.assertEqual(self.search(req, result[config][0]), True) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 214 | |
| 215 | def _del(self, type, config, req, name): |
| 216 | result, prev_len = self.remove(type, config, name) |
| 217 | self.assertEqual(len(result[config]), prev_len-1) |
| 218 | |
| 219 | def _operate(self, obj_action, type_config, req, name): |
| 220 | if obj_action == 'add': |
| 221 | _add(self, type_config['type'], type_config['config'], req, name) |
| 222 | elif obj_action == 'mod': |
| 223 | _mod(self, type_config['type'], type_config['config'], req, name) |
| 224 | elif obj_action == 'del': |
| 225 | _del(self, type_config['type'], type_config['config'], req, name) |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 226 | |
| 227 | def _config(self): |
| 228 | ParseDict(value['rpc'], value['pb2']) |
| 229 | return value['pb2'] |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 230 | |
| 231 | def dynamic_test_method(self): |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 232 | _obj_action = [val for val in key.split('-')] |
| 233 | _type_config = obj_type_config[_obj_action[0]] |
| 234 | _req = _config(self) |
| 235 | _operate(self, _obj_action[1], _type_config, _req, value['rpc']['name']) |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 236 | |
| 237 | return dynamic_test_method |
| 238 | |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 239 | #read the set instructions for tests |
| 240 | #dynamically create test cases in desired sequence |
Richard Jankowski | 461cb97 | 2018-04-11 15:36:27 -0400 | [diff] [blame] | 241 | for item in xpon_scenario: |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 242 | id = id + 1 |
| 243 | if(isinstance(item, dict)): |
| 244 | for k,v in item.items(): |
| 245 | dynamic_method = create_dynamic_method(k, v) |
Rachit Shrivastava | a182e91 | 2017-07-28 15:18:34 -0400 | [diff] [blame] | 246 | dynamic_method.__name__ = 'test_{:3d}_{}'.format(id, k).replace( |
| 247 | ' ', '0') |
Rachit Shrivastava | b9809da | 2017-07-12 11:09:10 -0400 | [diff] [blame] | 248 | setattr(TestXPon, dynamic_method.__name__, dynamic_method) |
| 249 | del dynamic_method |
| 250 | |
| 251 | if __name__ == '__main__': |
Rachit Shrivastava | 5a2d569 | 2017-07-17 10:29:20 -0400 | [diff] [blame] | 252 | unittest.main() |