blob: 0f6911c2838b4304ce5a8b25aae1bb45f6ac7b79 [file] [log] [blame]
Zack Williams41513bf2018-07-07 20:08:35 -07001# 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 Shrivastavab9809da2017-07-12 11:09:10 -040014from tests.itests.voltha.rest_base import RestBase
15
Rachit Shrivastava5a2d5692017-07-17 10:29:20 -040016from google.protobuf.json_format import MessageToDict, ParseDict
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040017import unittest
18
19from voltha.protos import bbf_fiber_base_pb2 as fb
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040020from voltha.protos.device_pb2 import Device
Nikolay Titov176f1db2017-08-10 12:38:43 -040021from voltha.protos import bbf_fiber_gemport_body_pb2 as gemport
22from voltha.protos import bbf_fiber_tcont_body_pb2 as tcont
23from voltha.protos import bbf_fiber_traffic_descriptor_profile_body_pb2 as tdp
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040024from common.utils.consulhelpers import get_endpoint_from_consul
Richard Jankowski461cb972018-04-11 15:36:27 -040025from tests.itests.voltha.xpon_scenario import scenario as xpon_scenario
Richard Jankowski87289342018-04-19 13:59:10 -040026from tests.itests.test_utils import get_pod_ip
27from testconfig import config
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040028
Rachit Shrivastava5a2d5692017-07-17 10:29:20 -040029'''
Rachit Shrivastavaa182e912017-07-28 15:18:34 -040030These tests use the Ponsim OLT to verify create, update, and delete
31functionalities of ChannelgroupConfig, ChannelpartitionConfig,
32ChannelpairConfig, ChannelterminationConfig, VOntAni, OntAni, and VEnets
33for xPON
Rachit Shrivastava5a2d5692017-07-17 10:29:20 -040034The 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 Shrivastavab9809da2017-07-12 11:09:10 -040043device_type = 'ponsim_olt'
44host_and_port = '172.17.0.1:50060'
Rachit Shrivastava5a2d5692017-07-17 10:29:20 -040045
Rachit Shrivastava8f4f9bf2017-07-20 11:59:30 -040046#for ordering the test cases
47id = 3
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040048LOCAL_CONSUL = "localhost:8500"
Richard Jankowski87289342018-04-19 13:59:10 -040049
50orch_env = 'docker-compose'
51if 'test_parameters' in config and 'orch_env' in config['test_parameters']:
52 orch_env = config['test_parameters']['orch_env']
53print 'orchestration-environment: %s' % orch_env
54
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040055# Retrieve details of the REST entry point
Richard Jankowski87289342018-04-19 13:59:10 -040056if orch_env == 'k8s-single-node':
57 rest_endpoint = get_pod_ip('voltha') + ':8443'
58else:
59 rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'voltha-envoy-8443')
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040060# Construct the base_url
Stephane Barbariecd51f992017-09-07 16:37:02 -040061BASE_URL = 'https://' + rest_endpoint
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040062
63class GlobalPreChecks(RestBase):
Stephane Barbariecd51f992017-09-07 16:37:02 -040064 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 Shrivastavab9809da2017-07-12 11:09:10 -040069
70 def test_001_get_health(self):
71 res = self.get('/health')
72 self.assertEqual(res['state'], 'HEALTHY')
73
74class TestXPon(RestBase):
Stephane Barbariecd51f992017-09-07 16:37:02 -040075 base_url = BASE_URL
76
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040077 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 Titov7253ff22017-08-14 18:24:17 -040083 def _remove_device(self):
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040084 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 Shrivastavaa182e912017-07-28 15:18:34 -040090 return self.post('/api/v1/devices',
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040091 MessageToDict(Device(
92 type=device_type,
93 host_and_port=host_and_port
94 )),
Stephane Barbariecd51f992017-09-07 16:37:02 -040095 expected_http_code=200)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -040096
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 Shrivastavaa182e912017-07-28 15:18:34 -0400100 device = self.get('/api/v1/devices/{}'.format(olt_id))
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400101 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 Shrivastavaa182e912017-07-28 15:18:34 -0400109 path = '/api/v1/devices/{}'.format(device_id)
Stephane Barbariecd51f992017-09-07 16:37:02 -0400110 self.post(path + '/enable', expected_http_code=200)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400111 device = self.get(path)
112 self.assertEqual(device['admin_state'], 'ENABLED')
113
114 def deactivate_device(self, device_id):
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400115 path = '/api/v1/devices/{}'.format(device_id)
Stephane Barbariecd51f992017-09-07 16:37:02 -0400116 self.post(path + '/disable', expected_http_code=200)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400117 device = self.get(path)
118 self.assertEqual(device['admin_state'], 'DISABLED')
119
120 def delete_device(self, device_id):
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400121 path = '/api/v1/devices/{}'.format(device_id)
Stephane Barbariecd51f992017-09-07 16:37:02 -0400122 self.delete(path + '/delete', expected_http_code=200)
123 device = self.get(path, expected_http_code=404)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400124 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 Barbariecd51f992017-09-07 16:37:02 -0400132 expected_http_code = 200)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400133 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 Barbariecd51f992017-09-07 16:37:02 -0400139 expected_http_code = 200)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400140 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 Barbariecd51f992017-09-07 16:37:02 -0400147 expected_http_code = 200)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400148 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 Shrivastava8f4f9bf2017-07-20 11:59:30 -0400153 return self.get('/api/v1/devices/{}/{}'.format(device['id'], type))
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400154 return self.get('/api/v1/{}'.format(type))
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400155
156 def get_path(self, type, name, operation):
157 if(type == 'channel_terminations'):
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400158 return '/api/v1/devices/{}/{}/{}{}'.format(device['id'],
Rachit Shrivastava8f4f9bf2017-07-20 11:59:30 -0400159 type, name, operation)
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400160 return '/api/v1/{}/{}{}'.format(type, name, operation)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400161
162 # Method to check if the result is same as the change requested
163 def search(self, req, result):
Nikolay Titov176f1db2017-08-10 12:38:43 -0400164 dict1 = MessageToDict(req,
165 including_default_value_fields = True,
166 preserving_proto_field_name = True)
Nikolay Titov7253ff22017-08-14 18:24:17 -0400167 #skip comparison of READ-ONLY fields
Nikolay Titov176f1db2017-08-10 12:38:43 -0400168 result['id'] = ''
Nikolay Titov7253ff22017-08-14 18:24:17 -0400169 if isinstance(req, fb.ChannelgroupConfig):
170 result['cg_index'] = 0
171 elif isinstance(req, tcont.TcontsConfigData):
Rachit Shrivastava1b2478e2018-03-01 11:53:49 -0500172 if not dict1['alloc_id']:
173 result['alloc_id'] = 0
Nikolay Titov7253ff22017-08-14 18:24:17 -0400174 elif isinstance(req, gemport.GemportsConfigData):
Rachit Shrivastava1b2478e2018-03-01 11:53:49 -0500175 if not dict1['gemport_id']:
176 result['gemport_id'] = 0
Nikolay Titov176f1db2017-08-10 12:38:43 -0400177 return dict1 == result
178
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400179
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400180#~~~~~~~~~~~~~~ Function to create test cases on the fly ~~~~~~~~~~~~~~~~
181def create_dynamic_method(key, value):
182 obj_type_config = {
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400183 '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 Titov176f1db2017-08-10 12:38:43 -0400196 '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 Shrivastava8f4f9bf2017-07-20 11:59:30 -0400203 }
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400204
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 Shrivastava1b2478e2018-03-01 11:53:49 -0500209 self.assertEqual(self.search(req, result[config][prev_len]), True)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400210
211 def _mod(self, type, config, req, name):
212 result = self.modify(type, req, name)
Nikolay Titov176f1db2017-08-10 12:38:43 -0400213 self.assertEqual(self.search(req, result[config][0]), True)
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400214
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 Shrivastava5a2d5692017-07-17 10:29:20 -0400226
227 def _config(self):
228 ParseDict(value['rpc'], value['pb2'])
229 return value['pb2']
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400230
231 def dynamic_test_method(self):
Rachit Shrivastava5a2d5692017-07-17 10:29:20 -0400232 _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 Shrivastavab9809da2017-07-12 11:09:10 -0400236
237 return dynamic_test_method
238
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400239#read the set instructions for tests
240#dynamically create test cases in desired sequence
Richard Jankowski461cb972018-04-11 15:36:27 -0400241for item in xpon_scenario:
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400242 id = id + 1
243 if(isinstance(item, dict)):
244 for k,v in item.items():
245 dynamic_method = create_dynamic_method(k, v)
Rachit Shrivastavaa182e912017-07-28 15:18:34 -0400246 dynamic_method.__name__ = 'test_{:3d}_{}'.format(id, k).replace(
247 ' ', '0')
Rachit Shrivastavab9809da2017-07-12 11:09:10 -0400248 setattr(TestXPon, dynamic_method.__name__, dynamic_method)
249 del dynamic_method
250
251if __name__ == '__main__':
Rachit Shrivastava5a2d5692017-07-17 10:29:20 -0400252 unittest.main()