blob: 71e0696289f02b3ff3144cca5028cc72b3c8592a [file] [log] [blame]
Zsolt Haraszti66862032016-11-28 14:28:39 -08001from time import time, sleep
2
3from google.protobuf.json_format import MessageToDict
4
5from voltha.core.flow_decomposer import *
6from voltha.protos.device_pb2 import Device
7from voltha.protos.common_pb2 import AdminState, OperStatus
8from voltha.protos import openflow_13_pb2 as ofp
9from tests.itests.voltha.rest_base import RestBase
khenaidoob96ee0a2017-06-28 15:39:16 -040010from common.utils.consulhelpers import get_endpoint_from_consul
Zsolt Haraszti66862032016-11-28 14:28:39 -080011
khenaidoob96ee0a2017-06-28 15:39:16 -040012LOCAL_CONSUL = "localhost:8500"
Zsolt Haraszti66862032016-11-28 14:28:39 -080013
14class TestColdActivationSequence(RestBase):
15
khenaidoob96ee0a2017-06-28 15:39:16 -040016 # Retrieve details of the REST entry point
Stephane Barbariecd51f992017-09-07 16:37:02 -040017 rest_endpoint = get_endpoint_from_consul(LOCAL_CONSUL, 'envoy-8443')
khenaidoob96ee0a2017-06-28 15:39:16 -040018
19 # Construct the base_url
ubuntuc5c83d72017-07-01 17:57:19 -070020 base_url = 'https://' + rest_endpoint
khenaidoob96ee0a2017-06-28 15:39:16 -040021
Zsolt Haraszti66862032016-11-28 14:28:39 -080022 def wait_till(self, msg, predicate, interval=0.1, timeout=5.0):
23 deadline = time() + timeout
24 while time() < deadline:
25 if predicate():
26 return
27 sleep(interval)
28 self.fail('Timed out while waiting for condition: {}'.format(msg))
29
30 def test_cold_activation_sequence(self):
31 """Complex test-case to cover device activation sequence"""
32
33 self.verify_prerequisites()
34 olt_id = self.add_olt_device()
35 self.verify_device_preprovisioned_state(olt_id)
36 self.activate_device(olt_id)
37 ldev_id = self.wait_for_logical_device(olt_id)
38 onu_ids = self.wait_for_onu_discovery(olt_id)
39 self.verify_logical_ports(ldev_id)
40 self.simulate_eapol_flow_install(ldev_id, olt_id, onu_ids)
41 self.verify_olt_eapol_flow(olt_id)
42 self.verify_onu_forwarding_flows(onu_ids)
43 self.simulate_eapol_start()
44 self.simulate_eapol_request_identity()
45 self.simulate_eapol_response_identity()
46 self.simulate_eapol_request()
47 self.simulate_eapol_response()
48 self.simulate_eapol_success()
49 self.install_and_verify_dhcp_flows()
50 self.install_and_verify_igmp_flows()
51 self.install_and_verifyunicast_flows()
52
53 def verify_prerequisites(self):
54 # all we care is that Voltha is available via REST using the base uri
55 self.get('/api/v1')
56
57 def add_olt_device(self):
58 device = Device(
59 type='simulated_olt',
60 mac_address='00:00:00:00:00:01'
61 )
62 device = self.post('/api/v1/devices', MessageToDict(device),
Stephane Barbariecd51f992017-09-07 16:37:02 -040063 expected_http_code=200)
Zsolt Haraszti66862032016-11-28 14:28:39 -080064 return device['id']
65
66 def verify_device_preprovisioned_state(self, olt_id):
67 # we also check that so far what we read back is same as what we get
68 # back on create
69 device = self.get('/api/v1/devices/{}'.format(olt_id))
70 self.assertNotEqual(device['id'], '')
71 self.assertEqual(device['adapter'], 'simulated_olt')
72 self.assertEqual(device['admin_state'], 'PREPROVISIONED')
73 self.assertEqual(device['oper_status'], 'UNKNOWN')
74
75 def activate_device(self, olt_id):
76 path = '/api/v1/devices/{}'.format(olt_id)
Stephane Barbariecd51f992017-09-07 16:37:02 -040077 self.post(path + '/enable', expected_http_code=200)
Zsolt Haraszti66862032016-11-28 14:28:39 -080078 device = self.get(path)
79 self.assertEqual(device['admin_state'], 'ENABLED')
80
81 self.wait_till(
82 'admin state moves to ACTIVATING or ACTIVE',
83 lambda: self.get(path)['oper_status'] in ('ACTIVATING', 'ACTIVE'),
84 timeout=0.5)
85
86 # eventually, it shall move to active state and by then we shall have
87 # device details filled, connect_state set, and device ports created
88 self.wait_till(
89 'admin state ACTIVE',
90 lambda: self.get(path)['oper_status'] == 'ACTIVE',
91 timeout=0.5)
92 device = self.get(path)
ggowdru236bd952017-06-20 20:32:55 -070093 images = device['images']
94 image = images['image']
95 image_1 = image[0]
96 version = image_1['version']
97 self.assertNotEqual(version, '')
Zsolt Haraszti66862032016-11-28 14:28:39 -080098 self.assertEqual(device['connect_status'], 'REACHABLE')
99
100 ports = self.get(path + '/ports')['items']
101 self.assertEqual(len(ports), 2)
102
103 def wait_for_logical_device(self, olt_id):
104 # we shall find the logical device id from the parent_id of the olt
105 # (root) device
106 device = self.get(
107 '/api/v1/devices/{}'.format(olt_id))
108 self.assertNotEqual(device['parent_id'], '')
109 logical_device = self.get(
110 '/api/v1/logical_devices/{}'.format(device['parent_id']))
111
112 # the logical device shall be linked back to the hard device,
113 # its ports too
114 self.assertEqual(logical_device['root_device_id'], device['id'])
115
116 logical_ports = self.get(
117 '/api/v1/logical_devices/{}/ports'.format(
118 logical_device['id'])
119 )['items']
120 self.assertGreaterEqual(len(logical_ports), 1)
121 logical_port = logical_ports[0]
122 self.assertEqual(logical_port['id'], 'nni')
123 self.assertEqual(logical_port['ofp_port']['name'], 'nni')
124 self.assertEqual(logical_port['ofp_port']['port_no'], 129)
125 self.assertEqual(logical_port['device_id'], device['id'])
126 self.assertEqual(logical_port['device_port_no'], 2)
127 return logical_device['id']
128
129 def wait_for_onu_discovery(self, olt_id):
130 # shortly after we shall see the discovery of four new onus, linked to
131 # the olt device
132 def find_our_onus():
133 devices = self.get('/api/v1/devices')['items']
134 return [
135 d for d in devices
136 if d['parent_id'] == olt_id
137 ]
138 self.wait_till(
khenaidoob96ee0a2017-06-28 15:39:16 -0400139 'find ONUs linked to the olt device',
140 lambda: len(find_our_onus()) >= 1,
Zsolt Haraszti66862032016-11-28 14:28:39 -0800141 2
142 )
143
144 # verify that they are properly set
145 onus = find_our_onus()
146 for onu in onus:
147 self.assertEqual(onu['admin_state'], 'ENABLED')
148 self.assertEqual(onu['oper_status'], 'ACTIVE')
149
150 return [onu['id'] for onu in onus]
151
152 def verify_logical_ports(self, ldev_id):
153
154 # at this point we shall see at least 5 logical ports on the
155 # logical device
156 logical_ports = self.get(
157 '/api/v1/logical_devices/{}/ports'.format(ldev_id)
158 )['items']
159 self.assertGreaterEqual(len(logical_ports), 5)
160
161 # verify that all logical ports are LIVE (state=4)
162 for lport in logical_ports:
163 self.assertEqual(lport['ofp_port']['state'], 4)
164
165 def simulate_eapol_flow_install(self, ldev_id, olt_id, onu_ids):
166
167 # emulate the flow mod requests that shall arrive from the SDN
168 # controller, one for each ONU
169 lports = self.get(
170 '/api/v1/logical_devices/{}/ports'.format(ldev_id)
171 )['items']
172
173 # device_id -> logical port map, which we will use to construct
174 # our flows
175 lport_map = dict((lp['device_id'], lp) for lp in lports)
176 for onu_id in onu_ids:
177 # if eth_type == 0x888e => send to controller
178 _in_port = lport_map[onu_id]['ofp_port']['port_no']
179 req = ofp.FlowTableUpdate(
Stephane Barbariecd51f992017-09-07 16:37:02 -0400180 id=ldev_id,
Zsolt Haraszti66862032016-11-28 14:28:39 -0800181 flow_mod=mk_simple_flow_mod(
182 match_fields=[
183 in_port(_in_port),
184 vlan_vid(ofp.OFPVID_PRESENT | 0),
185 eth_type(0x888e)],
186 actions=[
187 output(ofp.OFPP_CONTROLLER)
188 ],
189 priority=1000
190 )
191 )
192 res = self.post('/api/v1/logical_devices/{}/flows'.format(ldev_id),
193 MessageToDict(req,
194 preserving_proto_field_name=True),
Stephane Barbariecd51f992017-09-07 16:37:02 -0400195 expected_http_code=200)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800196
197 # for sanity, verify that flows are in flow table of logical device
198 flows = self.get(
199 '/api/v1/logical_devices/{}/flows'.format(ldev_id))['items']
200 self.assertGreaterEqual(len(flows), 4)
201
202 def verify_olt_eapol_flow(self, olt_id):
203 # olt shall have two flow rules, one is the default and the
204 # second is the result of eapol forwarding with rule:
205 # if eth_type == 0x888e => push vlan(1000); out_port=nni_port
206 flows = self.get('/api/v1/devices/{}/flows'.format(olt_id))['items']
207 self.assertEqual(len(flows), 2)
208 flow = flows[1]
209 self.assertEqual(flow['table_id'], 0)
210 self.assertEqual(flow['priority'], 1000)
211
212 # TODO refine this
213 # self.assertEqual(flow['match'], {})
214 # self.assertEqual(flow['instructions'], [])
215
216 def verify_onu_forwarding_flows(self, onu_ids):
217 pass
218
219 def simulate_eapol_start(self):
220 pass
221
222 def simulate_eapol_request_identity(self):
223 pass
224
225 def simulate_eapol_response_identity(self):
226 pass
227
228 def simulate_eapol_request(self):
229 pass
230
231 def simulate_eapol_response(self):
232 pass
233
234 def simulate_eapol_success(self):
235 pass
236
237 def install_and_verify_dhcp_flows(self):
238 pass
239
240 def install_and_verify_igmp_flows(self):
241 pass
242
243 def install_and_verifyunicast_flows(self):
244 pass
245