Test Failed
Pull Request — master (#104)
by Vinicius
01:48
created

test_flow_builder_failover   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 948
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
eloc 682
dl 0
loc 948
rs 9.9179
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
B test_handle_failover_old_path_diff_svlan() 0 402 3
B test_handle_failover_link_down() 0 286 3
B test_handle_failover_old_path_same_svlan() 0 244 3
1
"""Test flowbuilder failover flows."""
2
import json
3
4
from unittest.mock import AsyncMock, MagicMock
5
from napps.kytos.telemetry_int.managers.int import INTManager
6
from napps.kytos.telemetry_int.proxy_port import ProxyPort
7
from kytos.lib.helpers import get_controller_mock, get_switch_mock, get_interface_mock
8
from kytos.core.common import EntityStatus
9
10
11
async def test_handle_failover_link_down() -> None:
12
    """Test handle failover_link_down.
13
14
               +----+                                              +----+
15
              5|    |6                                            5|    |6
16
           +---+----v---+            +------------+           +----+----v---+
17
        1  |            |            |            |           |             |1
18
    -------+            |3         2 |            |3        2 |             +-------
19
     vlan  |     s1     +------------+    s2      +-----------+    s3       | vlan
20
     100   |            |            |            |           |             | 100
21
           |            |            |            |           |             |
22
           +------------+            +------------+           +-------------+
23
                |4                                                   3|
24
                |_____________________________________________________|
25
    """
26
27
    controller = get_controller_mock()
28
    int_manager = INTManager(controller)
29
    get_proxy_port_or_raise = MagicMock()
30
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
31
32
    dpid_a = "00:00:00:00:00:00:00:01"
33
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
34
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
35
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
36
    mock_interface_a5 = get_interface_mock("s1-eth5", 5, mock_switch_a)
37
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a5.port_number}
38
    mock_interface_a5.status = EntityStatus.UP
39
    mock_interface_a6 = get_interface_mock("s1-eth6", 6, mock_switch_a)
40
    mock_interface_a6.status = EntityStatus.UP
41
    mock_interface_a5.metadata = {
42
        "looped": {
43
            "port_numbers": [
44
                mock_interface_a5.port_number,
45
                mock_interface_a6.port_number,
46
            ]
47
        }
48
    }
49
50
    dpid_z = "00:00:00:00:00:00:00:03"
51
    mock_switch_z = get_switch_mock(dpid_z, 0x04)
52
    mock_interface_z1 = get_interface_mock("s1-eth1", 1, mock_switch_z)
53
    mock_interface_z1.status = EntityStatus.UP
54
    mock_interface_z1.id = f"{dpid_z}:{mock_interface_z1.port_number}"
55
    mock_interface_z5 = get_interface_mock("s1-eth5", 5, mock_switch_z)
56
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z5.port_number}
57
    mock_interface_z5.status = EntityStatus.UP
58
    mock_interface_z6 = get_interface_mock("s1-eth6", 6, mock_switch_z)
59
    mock_interface_z6.status = EntityStatus.UP
60
    mock_interface_z5.metadata = {
61
        "looped": {
62
            "port_numbers": [
63
                mock_interface_z5.port_number,
64
                mock_interface_z6.port_number,
65
            ]
66
        }
67
    }
68
69
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
70
        mock_interface_a5.port_number: mock_interface_a5,
71
        mock_interface_a6.port_number: mock_interface_a6,
72
    }[port_no]
73
74
    mock_switch_z.get_interface_by_port_no = lambda port_no: {
75
        mock_interface_z5.port_number: mock_interface_z5,
76
        mock_interface_z6.port_number: mock_interface_z6,
77
    }[port_no]
78
79
    pp_a = ProxyPort(controller, source=mock_interface_a5)
80
    assert pp_a.source == mock_interface_a5
81
    assert pp_a.destination == mock_interface_a6
82
    pp_z = ProxyPort(controller, source=mock_interface_z5)
83
    assert pp_z.source == mock_interface_z5
84
    assert pp_z.destination == mock_interface_z6
85
86
    evcs_data = {
87
        "ceaf53b16c3a40": {
88
            "flows": {
89
                "00:00:00:00:00:00:00:01": [
90
                    {
91
                        "match": {"in_port": 1, "dl_vlan": 100},
92
                        "cookie": 12307967605643950656,
93
                        "actions": [
94
                            {"action_type": "push_vlan", "tag_type": "s"},
95
                            {"action_type": "set_vlan", "vlan_id": 1},
96
                            {"action_type": "output", "port": 3},
97
                        ],
98
                        "owner": "mef_eline",
99
                        "table_group": "evpl",
100
                        "table_id": 0,
101
                        "priority": 20000,
102
                    }
103
                ],
104
                "00:00:00:00:00:00:00:03": [
105
                    {
106
                        "match": {"in_port": 1, "dl_vlan": 100},
107
                        "cookie": 12307967605643950656,
108
                        "actions": [
109
                            {"action_type": "push_vlan", "tag_type": "s"},
110
                            {"action_type": "set_vlan", "vlan_id": 1},
111
                            {"action_type": "output", "port": 2},
112
                        ],
113
                        "owner": "mef_eline",
114
                        "table_group": "evpl",
115
                        "table_id": 0,
116
                        "priority": 20000,
117
                    }
118
                ],
119
            },
120
            "evc_id": "ceaf53b16c3a40",
121
            "id": "ceaf53b16c3a40",
122
            "name": "inter_evpl",
123
            "metadata": {
124
                "telemetry_request": {},
125
                "telemetry": {
126
                    "enabled": True,
127
                    "status": "UP",
128
                    "status_reason": [],
129
                    "status_updated_at": "2024-06-11T16:56:29",
130
                },
131
            },
132
            "active": True,
133
            "enabled": True,
134
            "uni_a": {
135
                "interface_id": "00:00:00:00:00:00:00:01:1",
136
                "tag": {"tag_type": "vlan", "value": 100},
137
            },
138
            "uni_z": {
139
                "interface_id": "00:00:00:00:00:00:00:03:1",
140
                "tag": {"tag_type": "vlan", "value": 100},
141
            },
142
        }
143
    }
144
145
    int_manager._send_flows = AsyncMock()
146
    int_manager._install_int_flows = AsyncMock()
147
    int_manager._remove_int_flows = AsyncMock()
148
    int_manager.remove_int_flows = AsyncMock()
149
    await int_manager.handle_failover_flows(evcs_data, "failover_link_down")
150
    assert int_manager._install_int_flows.call_count == 1
151
    assert int_manager._remove_int_flows.call_count == 0
152
    assert int_manager.remove_int_flows.call_count == 0
153
154
    expected_built_flows = {
155
        "12307967605643950656": [
156
            {
157
                "flow": {
158
                    "match": {
159
                        "in_port": 1,
160
                        "dl_vlan": 100,
161
                        "dl_type": 2048,
162
                        "nw_proto": 6,
163
                    },
164
                    "cookie": 12163852417568094784,
165
                    "owner": "telemetry_int",
166
                    "table_group": "evpl",
167
                    "table_id": 0,
168
                    "priority": 20100,
169
                    "instructions": [
170
                        {
171
                            "instruction_type": "apply_actions",
172
                            "actions": [{"action_type": "push_int"}],
173
                        },
174
                        {"instruction_type": "goto_table", "table_id": 2},
175
                    ],
176
                },
177
                "switch": "00:00:00:00:00:00:00:01",
178
            },
179
            {
180
                "flow": {
181
                    "match": {
182
                        "in_port": 1,
183
                        "dl_vlan": 100,
184
                        "dl_type": 2048,
185
                        "nw_proto": 17,
186
                    },
187
                    "cookie": 12163852417568094784,
188
                    "owner": "telemetry_int",
189
                    "table_group": "evpl",
190
                    "table_id": 0,
191
                    "priority": 20100,
192
                    "instructions": [
193
                        {
194
                            "instruction_type": "apply_actions",
195
                            "actions": [{"action_type": "push_int"}],
196
                        },
197
                        {"instruction_type": "goto_table", "table_id": 2},
198
                    ],
199
                },
200
                "switch": "00:00:00:00:00:00:00:01",
201
            },
202
            {
203
                "flow": {
204
                    "match": {"in_port": 1, "dl_vlan": 100},
205
                    "cookie": 12163852417568094784,
206
                    "owner": "telemetry_int",
207
                    "table_group": "evpl",
208
                    "table_id": 2,
209
                    "priority": 20000,
210
                    "instructions": [
211
                        {
212
                            "instruction_type": "apply_actions",
213
                            "actions": [
214
                                {"action_type": "add_int_metadata"},
215
                                {"action_type": "push_vlan", "tag_type": "s"},
216
                                {"action_type": "set_vlan", "vlan_id": 1},
217
                                {"action_type": "output", "port": 3},
218
                            ],
219
                        }
220
                    ],
221
                },
222
                "switch": "00:00:00:00:00:00:00:01",
223
            },
224
            {
225
                "flow": {
226
                    "match": {
227
                        "in_port": 1,
228
                        "dl_vlan": 100,
229
                        "dl_type": 2048,
230
                        "nw_proto": 6,
231
                    },
232
                    "cookie": 12163852417568094784,
233
                    "owner": "telemetry_int",
234
                    "table_group": "evpl",
235
                    "table_id": 0,
236
                    "priority": 20100,
237
                    "instructions": [
238
                        {
239
                            "instruction_type": "apply_actions",
240
                            "actions": [{"action_type": "push_int"}],
241
                        },
242
                        {"instruction_type": "goto_table", "table_id": 2},
243
                    ],
244
                },
245
                "switch": "00:00:00:00:00:00:00:03",
246
            },
247
            {
248
                "flow": {
249
                    "match": {
250
                        "in_port": 1,
251
                        "dl_vlan": 100,
252
                        "dl_type": 2048,
253
                        "nw_proto": 17,
254
                    },
255
                    "cookie": 12163852417568094784,
256
                    "owner": "telemetry_int",
257
                    "table_group": "evpl",
258
                    "table_id": 0,
259
                    "priority": 20100,
260
                    "instructions": [
261
                        {
262
                            "instruction_type": "apply_actions",
263
                            "actions": [{"action_type": "push_int"}],
264
                        },
265
                        {"instruction_type": "goto_table", "table_id": 2},
266
                    ],
267
                },
268
                "switch": "00:00:00:00:00:00:00:03",
269
            },
270
            {
271
                "flow": {
272
                    "match": {"in_port": 1, "dl_vlan": 100},
273
                    "cookie": 12163852417568094784,
274
                    "owner": "telemetry_int",
275
                    "table_group": "evpl",
276
                    "table_id": 2,
277
                    "priority": 20000,
278
                    "instructions": [
279
                        {
280
                            "instruction_type": "apply_actions",
281
                            "actions": [
282
                                {"action_type": "add_int_metadata"},
283
                                {"action_type": "push_vlan", "tag_type": "s"},
284
                                {"action_type": "set_vlan", "vlan_id": 1},
285
                                {"action_type": "output", "port": 2},
286
                            ],
287
                        }
288
                    ],
289
                },
290
                "switch": "00:00:00:00:00:00:00:03",
291
            },
292
        ]
293
    }
294
295
    serd = json.dumps(expected_built_flows)
296
    assert json.dumps(int_manager._install_int_flows.call_args[0][0]) == serd
297
298
299
async def test_handle_failover_old_path_same_svlan() -> None:
300
    """Test handle failover_old_path_same_svlan.
301
302
               +----+                                              +----+
303
              5|    |6                                            5|    |6
304
           +---+----v---+            +------------+           +----+----v---+
305
        1  |            |            |            |           |             |1
306
    -------+            |3         2 |            |3        2 |             +-------
307
     vlan  |     s1     +------------+    s2      +-----------+    s3       | vlan
308
     100   |            |            |            |           |             | 100
309
           |            |            |            |           |             |
310
           +------------+            +------------+           +-------------+
311
                |4                                                   3|
312
                |_____________________________________________________|
313
    """
314
315
    controller = get_controller_mock()
316
    int_manager = INTManager(controller)
317
    get_proxy_port_or_raise = MagicMock()
318
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
319
320
    dpid_a = "00:00:00:00:00:00:00:01"
321
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
322
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
323
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
324
    mock_interface_a5 = get_interface_mock("s1-eth5", 5, mock_switch_a)
325
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a5.port_number}
326
    mock_interface_a5.status = EntityStatus.UP
327
    mock_interface_a6 = get_interface_mock("s1-eth6", 6, mock_switch_a)
328
    mock_interface_a6.status = EntityStatus.UP
329
    mock_interface_a5.metadata = {
330
        "looped": {
331
            "port_numbers": [
332
                mock_interface_a5.port_number,
333
                mock_interface_a6.port_number,
334
            ]
335
        }
336
    }
337
338
    dpid_z = "00:00:00:00:00:00:00:03"
339
    mock_switch_z = get_switch_mock(dpid_z, 0x04)
340
    mock_interface_z1 = get_interface_mock("s1-eth1", 1, mock_switch_z)
341
    mock_interface_z1.status = EntityStatus.UP
342
    mock_interface_z1.id = f"{dpid_z}:{mock_interface_z1.port_number}"
343
    mock_interface_z5 = get_interface_mock("s1-eth5", 5, mock_switch_z)
344
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z5.port_number}
345
    mock_interface_z5.status = EntityStatus.UP
346
    mock_interface_z6 = get_interface_mock("s1-eth6", 6, mock_switch_z)
347
    mock_interface_z6.status = EntityStatus.UP
348
    mock_interface_z5.metadata = {
349
        "looped": {
350
            "port_numbers": [
351
                mock_interface_z5.port_number,
352
                mock_interface_z6.port_number,
353
            ]
354
        }
355
    }
356
357
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
358
        mock_interface_a5.port_number: mock_interface_a5,
359
        mock_interface_a6.port_number: mock_interface_a6,
360
    }[port_no]
361
362
    mock_switch_z.get_interface_by_port_no = lambda port_no: {
363
        mock_interface_z5.port_number: mock_interface_z5,
364
        mock_interface_z6.port_number: mock_interface_z6,
365
    }[port_no]
366
367
    pp_a = ProxyPort(controller, source=mock_interface_a5)
368
    assert pp_a.source == mock_interface_a5
369
    assert pp_a.destination == mock_interface_a6
370
    pp_z = ProxyPort(controller, source=mock_interface_z5)
371
    assert pp_z.source == mock_interface_z5
372
    assert pp_z.destination == mock_interface_z6
373
374
    evcs_data = {
375
        "ceaf53b16c3a40": {
376
            "removed_flows": {
377
                "00:00:00:00:00:00:00:01": [
378
                    {
379
                        "cookie": 12307967605643950656,
380
                        "match": {"in_port": 4, "dl_vlan": 1},
381
                        "cookie_mask": 18446744073709551615,
382
                    }
383
                ],
384
                "00:00:00:00:00:00:00:03": [
385
                    {
386
                        "cookie": 12307967605643950656,
387
                        "match": {"in_port": 3, "dl_vlan": 1},
388
                        "cookie_mask": 18446744073709551615,
389
                    }
390
                ],
391
            },
392
            "current_path": [
393
                {
394
                    "id": "78282c4d5",
395
                    "endpoint_a": {
396
                        "id": "00: 00:00:00:00:00:00:01:3",
397
                        "name": "s1-eth3",
398
                        "port_number": 3,
399
                        "mac": "b2:ac:2b:ac:87:bb",
400
                        "switch": "00:00:00:00:00:00:00:01",
401
                        "type": "interface",
402
                        "nni": True,
403
                        "uni": False,
404
                        "speed": 1250000000.0,
405
                        "metadata": {},
406
                        "lldp": True,
407
                        "active": True,
408
                        "enabled": True,
409
                        "status": "UP",
410
                        "status_reason": [],
411
                        "link": "78282c4d5",
412
                    },
413
                    "endpoint_b": {
414
                        "id": "00:00:00:00:00:00:00:02:2",
415
                        "name": "s2-eth2",
416
                        "port_number": 2,
417
                        "mac": "62:50:49:d7:79:8a",
418
                        "switch": "00:00:00:00:00:00:00:02",
419
                        "type": "interface",
420
                        "nni": True,
421
                        "uni": False,
422
                        "speed": 1250000000.0,
423
                        "metadata": {},
424
                        "lldp": True,
425
                        "active": True,
426
                        "enabled": True,
427
                        "status": "UP",
428
                        "status_reason": [],
429
                        "link": "78282c4d5",
430
                    },
431
                    "metadata": {"s_vlan": {"tag_type": "vlan", "value": 1}},
432
                    "active": True,
433
                    "enabled": True,
434
                    "status": "UP",
435
                    "status_reason": [],
436
                },
437
                {
438
                    "id": "4d42dc085",
439
                    "endpoint_a": {
440
                        "id": "00:00:00:00:00:00:00:02:3",
441
                        "name": "s2-eth3",
442
                        "port_number": 3,
443
                        "mac": "76:82:ef:6e:d2:9d",
444
                        "switch": "00:00:00:00:00:00:00:02",
445
                        "type": "interface",
446
                        "nni": True,
447
                        "uni": False,
448
                        "speed": 1250000000.0,
449
                        "metadata": {},
450
                        "lldp": True,
451
                        "active": True,
452
                        "enabled": True,
453
                        "status": "UP",
454
                        "status_reason ": [],
455
                        "link": "4d42dc085",
456
                    },
457
                    "endpoint_b": {
458
                        "id": "00:00:00:00:00:00:00:03:2",
459
                        "name": "s3-eth2",
460
                        "port_number": 2,
461
                        "mac": "6a:c1:51:b1:a9:8a",
462
                        "switch": "00:00:00:00:00:00:00:03",
463
                        "type": "interface",
464
                        "nni": True,
465
                        "uni": False,
466
                        "speed": 1250000000.0,
467
                        "metadata": {},
468
                        "lldp": True,
469
                        "active": True,
470
                        "enabled": True,
471
                        "status": "UP",
472
                        "status_reason": [],
473
                        "link": "4d42dc085",
474
                    },
475
                    "metadata": {"s_vlan": {"tag_type": "vlan", "value": 1}},
476
                    "active": True,
477
                    "enabled": True,
478
                    "status": "UP",
479
                    "status_reason": [],
480
                },
481
            ],
482
            "evc_id": "ceaf53b16c3a40",
483
            "id": "ceaf53b16c3a40",
484
            "name": "inter_evpl",
485
            "metadata": {
486
                "telemetry_request": {},
487
                "telemetry": {
488
                    "enabled": True,
489
                    "status": "UP",
490
                    "status_reason": [],
491
                    "status_updated_at": "2024-06-11T16:56:29",
492
                },
493
            },
494
            "active": True,
495
            "enabled": True,
496
            "uni_a": {
497
                "interface_id": "00:00:00:00:00:00:00:01:1",
498
                "tag": {"tag_type": "vlan", "value": 100},
499
            },
500
            "uni_z": {
501
                "interface_id": "00:00:00:00:00:00:00:03:1",
502
                "tag": {"tag_type": "vlan", "value": 100},
503
            },
504
        }
505
    }
506
507
    get_proxy_port_or_raise.side_effect = [pp_a, pp_z]
508
    int_manager._send_flows = AsyncMock()
509
    int_manager._install_int_flows = AsyncMock()
510
    int_manager._remove_int_flows = AsyncMock()
511
    int_manager.remove_int_flows = AsyncMock()
512
    await int_manager.handle_failover_flows(evcs_data, "failover_old_path")
513
    assert int_manager._install_int_flows.call_count == 0
514
    assert int_manager._remove_int_flows.call_count == 1
515
    assert int_manager.remove_int_flows.call_count == 0
516
517
    expected_built_flows = {
518
        "12307967605643950656": [
519
            {
520
                "flow": {
521
                    "cookie": 12163852417568094784,
522
                    "match": {"in_port": 4, "dl_vlan": 1},
523
                    "cookie_mask": 18446744073709551615,
524
                    "priority": 21000,
525
                    "table_group": "evpl",
526
                },
527
                "switch": "00:00:00:00:00:00:00:01",
528
            },
529
            {
530
                "flow": {
531
                    "cookie": 12163852417568094784,
532
                    "match": {"in_port": 3, "dl_vlan": 1},
533
                    "cookie_mask": 18446744073709551615,
534
                    "priority": 21000,
535
                    "table_group": "evpl",
536
                },
537
                "switch": "00:00:00:00:00:00:00:03",
538
            },
539
        ]
540
    }
541
    serd = json.dumps(expected_built_flows)
542
    assert json.dumps(int_manager._remove_int_flows.call_args[0][0]) == serd
543
544
545
# pylint: disable=too-many-statements
546
async def test_handle_failover_old_path_diff_svlan() -> None:
547
    """Test handle failover_old_path_diff_svlan.
548
549
               +----+                                              +----+
550
              5|    |6                                            5|    |6
551
           +---+----v---+            +------------+           +----+----v---+
552
        1  |            |            |            |           |             |1
553
    -------+            |3         2 |            |3        2 |             +-------
554
     vlan  |     s1     +------------+    s2      +-----------+    s3       | vlan
555
     100   |            |            |            |           |             | 100
556
           |            |            |            |           |             |
557
           +------------+            +------------+           +-------------+
558
                |4                                                   3|
559
                |_____________________________________________________|
560
    """
561
562
    controller = get_controller_mock()
563
    int_manager = INTManager(controller)
564
    get_proxy_port_or_raise = MagicMock()
565
    int_manager.get_proxy_port_or_raise = get_proxy_port_or_raise
566
567
    dpid_a = "00:00:00:00:00:00:00:01"
568
    mock_switch_a = get_switch_mock(dpid_a, 0x04)
569
    mock_interface_a1 = get_interface_mock("s1-eth1", 1, mock_switch_a)
570
    mock_interface_a1.id = f"{dpid_a}:{mock_interface_a1.port_number}"
571
    mock_interface_a4 = get_interface_mock("s1-eth4", 4, mock_switch_a)
572
    mock_interface_a4.id = f"{dpid_a}:{mock_interface_a4.port_number}"
573
    mock_interface_a5 = get_interface_mock("s1-eth5", 5, mock_switch_a)
574
    mock_interface_a1.metadata = {"proxy_port": mock_interface_a5.port_number}
575
    mock_interface_a4.status = EntityStatus.UP
576
    mock_interface_a5.status = EntityStatus.UP
577
    mock_interface_a6 = get_interface_mock("s1-eth6", 6, mock_switch_a)
578
    mock_interface_a6.status = EntityStatus.UP
579
    mock_interface_a5.metadata = {
580
        "looped": {
581
            "port_numbers": [
582
                mock_interface_a5.port_number,
583
                mock_interface_a6.port_number,
584
            ]
585
        }
586
    }
587
588
    dpid_z = "00:00:00:00:00:00:00:03"
589
    mock_switch_z = get_switch_mock(dpid_z, 0x04)
590
    mock_interface_z1 = get_interface_mock("s1-eth1", 1, mock_switch_z)
591
    mock_interface_z1.status = EntityStatus.UP
592
    mock_interface_z1.id = f"{dpid_z}:{mock_interface_z1.port_number}"
593
    mock_interface_z3 = get_interface_mock("s1-eth3", 3, mock_switch_z)
594
    mock_interface_z3.status = EntityStatus.UP
595
    mock_interface_z3.id = f"{dpid_z}:{mock_interface_z3.port_number}"
596
    mock_interface_z5 = get_interface_mock("s1-eth5", 5, mock_switch_z)
597
    mock_interface_z1.metadata = {"proxy_port": mock_interface_z5.port_number}
598
    mock_interface_z5.status = EntityStatus.UP
599
    mock_interface_z6 = get_interface_mock("s1-eth6", 6, mock_switch_z)
600
    mock_interface_z6.status = EntityStatus.UP
601
    mock_interface_z5.metadata = {
602
        "looped": {
603
            "port_numbers": [
604
                mock_interface_z5.port_number,
605
                mock_interface_z6.port_number,
606
            ]
607
        }
608
    }
609
610
    mock_switch_a.get_interface_by_port_no = lambda port_no: {
611
        mock_interface_a5.port_number: mock_interface_a5,
612
        mock_interface_a6.port_number: mock_interface_a6,
613
    }[port_no]
614
615
    mock_switch_z.get_interface_by_port_no = lambda port_no: {
616
        mock_interface_z5.port_number: mock_interface_z5,
617
        mock_interface_z6.port_number: mock_interface_z6,
618
    }[port_no]
619
620
    pp_a = ProxyPort(controller, source=mock_interface_a5)
621
    assert pp_a.source == mock_interface_a5
622
    assert pp_a.destination == mock_interface_a6
623
    pp_z = ProxyPort(controller, source=mock_interface_z5)
624
    assert pp_z.source == mock_interface_z5
625
    assert pp_z.destination == mock_interface_z6
626
627
    evcs_data = {
628
        "ceaf53b16c3a40": {
629
            "removed_flows": {
630
                "00:00:00:00:00:00:00:01": [
631
                    {
632
                        "cookie": 12307967605643950656,
633
                        "match": {"in_port": 4, "dl_vlan": 2},
634
                        "cookie_mask": 18446744073709551615,
635
                    }
636
                ],
637
                "00:00:00:00:00:00:00:03": [
638
                    {
639
                        "cookie": 12307967605643950656,
640
                        "match": {"in_port": 3, "dl_vlan": 2},
641
                        "cookie_mask": 18446744073709551615,
642
                    }
643
                ],
644
            },
645
            "current_path": [
646
                {
647
                    "id": "78282c4d5",
648
                    "endpoint_a": {
649
                        "id": "00:00:00:00:00:00:00:01:3",
650
                        "name": "s1-eth3",
651
                        "port_number": 3,
652
                        "mac": "b2:ac:2b:ac:87:bb",
653
                        "switch": "00:00:00:00:00:00:00:01",
654
                        "type": "interface",
655
                        "nni": True,
656
                        "uni": False,
657
                        "speed": 1250000000.0,
658
                        "metadata": {},
659
                        "lldp": True,
660
                        "active": True,
661
                        "enabled": True,
662
                        "status": "UP",
663
                        "status_reason": [],
664
                        "link": "78282c4d5",
665
                    },
666
                    "endpoint_b": {
667
                        "id": "00:00:00:00:00:00:00:02:2",
668
                        "name": "s2-eth2",
669
                        "port_number": 2,
670
                        "mac": "62:50:49:d7:79:8a",
671
                        "switch": "00:00:00:00:00:00:00:02",
672
                        "type": "interface",
673
                        "nni": True,
674
                        "uni": False,
675
                        "speed": 1250000000.0,
676
                        "metadata": {},
677
                        "lldp": True,
678
                        "active": True,
679
                        "enabled": True,
680
                        "status": "UP",
681
                        "status_reason": [],
682
                        "link": "78282c4d5",
683
                    },
684
                    "metadata": {"s_vlan": {"tag_type": "vlan", "value": 1}},
685
                    "active": True,
686
                    "enabled": True,
687
                    "status": "UP",
688
                    "status_reason": [],
689
                },
690
                {
691
                    "id": "4d42dc085",
692
                    "endpoint_a": {
693
                        "id": "00:00:00:00:00:00:00:02:3",
694
                        "name": "s2-eth3",
695
                        "port_number": 3,
696
                        "mac": "76:82:ef:6e:d2:9d",
697
                        "switch": "00:00:00:00:00:00:00:02",
698
                        "type": "interface",
699
                        "nni": True,
700
                        "uni": False,
701
                        "speed": 1250000000.0,
702
                        "metadata": {},
703
                        "lldp": True,
704
                        "active": True,
705
                        "enabled": True,
706
                        "status": "UP",
707
                        "status_reason ": [],
708
                        "link": "4d42dc085",
709
                    },
710
                    "endpoint_b": {
711
                        "id": "00:00:00:00:00:00:00:03:2",
712
                        "name": "s3-eth2",
713
                        "port_number": 2,
714
                        "mac": "6a:c1: 51:b1:a9:8a",
715
                        "switch": "00:00:00:00:00:00:00:03",
716
                        "type": "interface",
717
                        "nni": True,
718
                        "uni": False,
719
                        "speed": 1250000000.0,
720
                        "metadata": {},
721
                        "lldp": True,
722
                        "active": True,
723
                        "enabled": True,
724
                        "status": "UP",
725
                        "status_reason": [],
726
                        "link": "4d42dc085",
727
                    },
728
                    "metadata": {"s_vlan": {"tag_type": "vlan", "value": 1}},
729
                    "active": True,
730
                    "enabled": True,
731
                    "status": "UP",
732
                    "status_reason": [],
733
                },
734
            ],
735
            "evc_id": "ceaf53b16c3a40",
736
            "id": "ceaf53b16c3a40",
737
            "name": "inter_evpl",
738
            "metadata": {
739
                "telemetry_request": {},
740
                "telemetry": {
741
                    "enabled": True,
742
                    "status": "UP",
743
                    "status_reason": [],
744
                    "status_updated_at": "2024-06-11T16:56:29",
745
                },
746
            },
747
            "active": True,
748
            "enabled": True,
749
            "uni_a": {
750
                "interface_id": "00:00:00:00:00:00:00:01:1",
751
                "tag": {"tag_type": "vlan", "value": 100},
752
            },
753
            "uni_z": {
754
                "interface_id": "00:00:00:00:00:00:00:03:1",
755
                "tag": {"tag_type": "vlan", "value": 100},
756
            },
757
        }
758
    }
759
760
    get_proxy_port_or_raise.side_effect = [pp_a, pp_z]
761
    int_manager._send_flows = AsyncMock()
762
    int_manager._install_int_flows = AsyncMock()
763
    int_manager._remove_int_flows = AsyncMock()
764
    int_manager.remove_int_flows = AsyncMock()
765
    await int_manager.handle_failover_flows(evcs_data, "failover_deployed")
766
    assert int_manager._install_int_flows.call_count == 0
767
    assert int_manager._remove_int_flows.call_count == 1
768
    assert int_manager.remove_int_flows.call_count == 0
769
770
    expected_built_flows = {
771
        "12307967605643950656": [
772
            {
773
                "flow": {
774
                    "cookie": 12163852417568094784,
775
                    "match": {
776
                        "in_port": 4,
777
                        "dl_vlan": 2,
778
                        "dl_type": 2048,
779
                        "nw_proto": 6,
780
                    },
781
                    "cookie_mask": 18446744073709551615,
782
                    "priority": 21100,
783
                    "table_group": "evpl",
784
                    "owner": "telemetry_int",
785
                    "instructions": [
786
                        {
787
                            "instruction_type": "apply_actions",
788
                            "actions": [
789
                                {"action_type": "add_int_metadata"},
790
                                {"action_type": "output", "port": 5},
791
                            ],
792
                        }
793
                    ],
794
                },
795
                "switch": "00:00:00:00:00:00:00:01",
796
            },
797
            {
798
                "flow": {
799
                    "cookie": 12163852417568094784,
800
                    "match": {
801
                        "in_port": 4,
802
                        "dl_vlan": 2,
803
                        "dl_type": 2048,
804
                        "nw_proto": 17,
805
                    },
806
                    "cookie_mask": 18446744073709551615,
807
                    "priority": 21100,
808
                    "table_group": "evpl",
809
                    "owner": "telemetry_int",
810
                    "instructions": [
811
                        {
812
                            "instruction_type": "apply_actions",
813
                            "actions": [
814
                                {"action_type": "add_int_metadata"},
815
                                {"action_type": "output", "port": 5},
816
                            ],
817
                        }
818
                    ],
819
                },
820
                "switch": "00:00:00:00:00:00:00:01",
821
            },
822
            {
823
                "flow": {
824
                    "cookie": 12163852417568094784,
825
                    "match": {"in_port": 6, "dl_vlan": 2},
826
                    "cookie_mask": 18446744073709551615,
827
                    "priority": 21000,
828
                    "table_group": "evpl",
829
                    "owner": "telemetry_int",
830
                    "instructions": [
831
                        {
832
                            "instruction_type": "apply_actions",
833
                            "actions": [{"action_type": "send_report"}],
834
                        },
835
                        {"instruction_type": "goto_table", "table_id": 2},
836
                    ],
837
                },
838
                "switch": "00:00:00:00:00:00:00:01",
839
            },
840
            {
841
                "flow": {
842
                    "cookie": 12163852417568094784,
843
                    "match": {"in_port": 6, "dl_vlan": 2},
844
                    "cookie_mask": 18446744073709551615,
845
                    "priority": 21000,
846
                    "table_group": "evpl",
847
                    "owner": "telemetry_int",
848
                    "instructions": [
849
                        {
850
                            "instruction_type": "apply_actions",
851
                            "actions": [{"action_type": "pop_int"}],
852
                        }
853
                    ],
854
                    "table_id": 2,
855
                },
856
                "switch": "00:00:00:00:00:00:00:01",
857
            },
858
            {
859
                "flow": {
860
                    "cookie": 12163852417568094784,
861
                    "match": {
862
                        "in_port": 3,
863
                        "dl_vlan": 2,
864
                        "dl_type": 2048,
865
                        "nw_proto": 6,
866
                    },
867
                    "cookie_mask": 18446744073709551615,
868
                    "priority": 21100,
869
                    "table_group": "evpl",
870
                    "owner": "telemetry_int",
871
                    "instructions": [
872
                        {
873
                            "instruction_type": "apply_actions",
874
                            "actions": [
875
                                {"action_type": "add_int_metadata"},
876
                                {"action_type": "output", "port": 5},
877
                            ],
878
                        }
879
                    ],
880
                },
881
                "switch": "00:00:00:00:00:00:00:03",
882
            },
883
            {
884
                "flow": {
885
                    "cookie": 12163852417568094784,
886
                    "match": {
887
                        "in_port": 3,
888
                        "dl_vlan": 2,
889
                        "dl_type": 2048,
890
                        "nw_proto": 17,
891
                    },
892
                    "cookie_mask": 18446744073709551615,
893
                    "priority": 21100,
894
                    "table_group": "evpl",
895
                    "owner": "telemetry_int",
896
                    "instructions": [
897
                        {
898
                            "instruction_type": "apply_actions",
899
                            "actions": [
900
                                {"action_type": "add_int_metadata"},
901
                                {"action_type": "output", "port": 5},
902
                            ],
903
                        }
904
                    ],
905
                },
906
                "switch": "00:00:00:00:00:00:00:03",
907
            },
908
            {
909
                "flow": {
910
                    "cookie": 12163852417568094784,
911
                    "match": {"in_port": 6, "dl_vlan": 2},
912
                    "cookie_mask": 18446744073709551615,
913
                    "priority": 21000,
914
                    "table_group": "evpl",
915
                    "owner": "telemetry_int",
916
                    "instructions": [
917
                        {
918
                            "instruction_type": "apply_actions",
919
                            "actions": [{"action_type": "send_report"}],
920
                        },
921
                        {"instruction_type": "goto_table", "table_id": 2},
922
                    ],
923
                },
924
                "switch": "00:00:00:00:00:00:00:03",
925
            },
926
            {
927
                "flow": {
928
                    "cookie": 12163852417568094784,
929
                    "match": {"in_port": 6, "dl_vlan": 2},
930
                    "cookie_mask": 18446744073709551615,
931
                    "priority": 21000,
932
                    "table_group": "evpl",
933
                    "owner": "telemetry_int",
934
                    "instructions": [
935
                        {
936
                            "instruction_type": "apply_actions",
937
                            "actions": [{"action_type": "pop_int"}],
938
                        }
939
                    ],
940
                    "table_id": 2,
941
                },
942
                "switch": "00:00:00:00:00:00:00:03",
943
            },
944
        ]
945
    }
946
    serd = json.dumps(expected_built_flows)
947
    assert json.dumps(int_manager._remove_int_flows.call_args[0][0]) == serd
948