Add keywords for Honeycomb tests
[csit.git] / resources / libraries / python / L2Util.py
1 # Copyright (c) 2016 Cisco and/or its affiliates.
2 # Licensed under the Apache License, Version 2.0 (the "License");
3 # you may not use this file except in compliance with the License.
4 # You may obtain a copy of the License at:
5 #
6 #     http://www.apache.org/licenses/LICENSE-2.0
7 #
8 # Unless required by applicable law or agreed to in writing, software
9 # distributed under the License is distributed on an "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 # See the License for the specific language governing permissions and
12 # limitations under the License.
13
14 """L2 Utilities Library."""
15
16 from robot.api.deco import keyword
17 from resources.libraries.python.topology import Topology
18 from resources.libraries.python.VatExecutor import VatExecutor, VatTerminal
19 from resources.libraries.python.ssh import exec_cmd_no_error
20
21
22 class L2Util(object):
23     """Utilities for l2 configuration"""
24
25     @staticmethod
26     def vpp_add_l2fib_entry(node, mac, interface, bd_id):
27         """ Create a static L2FIB entry on a vpp node.
28
29         :param node: Node to add L2FIB entry on.
30         :param mac: Destination mac address.
31         :param interface: Interface name or sw_if_index.
32         :param bd_id: Bridge domain id.
33         :type node: dict
34         :type mac: str
35         :type interface: str or int
36         :type bd_id: int
37         """
38         if isinstance(interface, basestring):
39             sw_if_index = Topology.get_interface_sw_index(node, interface)
40         else:
41             sw_if_index = interface
42         VatExecutor.cmd_from_template(node, "add_l2_fib_entry.vat",
43                                       mac=mac, bd=bd_id,
44                                       interface=sw_if_index)
45
46     @staticmethod
47     def create_l2_bd(node, bd_id, flood=1, uu_flood=1, forward=1, learn=1,
48                      arp_term=0):
49         """Create a l2 bridge domain on the chosen VPP node
50
51         Execute "bridge_domain_add_del bd_id {bd_id} flood {flood} uu-flood 1
52         forward {forward} learn {learn} arp-term {arp_term}" VAT command on
53         the node.
54
55         :param node: node where we wish to crate the l2 bridge domain
56         :param bd_id: bridge domain index number
57         :param flood: enable flooding
58         :param uu_flood: enable uu_flood
59         :param forward: enable forwarding
60         :param learn: enable mac address learning to fib
61         :param arp_term: enable arp_termination
62         :type node: dict
63         :type bd_id: int
64         :type flood: bool
65         :type uu_flood: bool
66         :type forward: bool
67         :type learn: bool
68         :type arp_term:bool
69         """
70         VatExecutor.cmd_from_template(node, "l2_bd_create.vat",
71                                       bd_id=bd_id, flood=flood,
72                                       uu_flood=uu_flood, forward=forward,
73                                       learn=learn, arp_term=arp_term)
74
75     @staticmethod
76     def add_interface_to_l2_bd(node, interface, bd_id, shg=0):
77         """Add a interface to the l2 bridge domain.
78
79         Get SW IF ID and add it to the bridge domain.
80
81         :param node: node where we want to execute the command that does this
82         :param interface: interface name
83         :param bd_id: bridge domain index number to add Interface name to
84         :param shg: split horizon group
85         :type node: dict
86         :type interface: str
87         :type bd_id: int
88         :type shg: int
89         """
90         sw_if_index = Topology.get_interface_sw_index(node, interface)
91         L2Util.add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg)
92
93     @staticmethod
94     def add_sw_if_index_to_l2_bd(node, sw_if_index, bd_id, shg=0):
95         """Add interface with sw_if_index to l2 bridge domain.
96
97         Execute the "sw_interface_set_l2_bridge sw_if_index {sw_if_index}
98         bd_id {bd_id} shg {shg} enable" VAT command on the given node.
99
100         :param node: node where we want to execute the command that does this
101         :param sw_if_index: interface index
102         :param bd_id: bridge domain index number to add SW IF ID to
103         :param shg: split horizon group
104         :type node: dict
105         :type sw_if_index: int
106         :type bd_id: int
107         :type shg: int
108         :return:
109         """
110         VatExecutor.cmd_from_template(node, "l2_bd_add_sw_if_index.vat",
111                                       bd_id=bd_id, sw_if_index=sw_if_index,
112                                       shg=shg)
113
114     @staticmethod
115     @keyword('Create dict used in bridge domain template file for node '
116              '"${node}" with links "${link_names}" and bd_id "${bd_id}"')
117     def create_bridge_domain_vat_dict(node, link_names, bd_id):
118         """Create dictionary that can be used in l2 bridge domain template.
119
120         :param node: node data dictionary
121         :param link_names: list of names of links the bridge domain should be
122         connecting
123         :param bd_id: bridge domain index number
124         :type node: dict
125         :type link_names: list
126         :return: dictionary used to generate l2 bridge domain VAT configuration
127         from template file
128         The resulting dictionary looks like this:
129         'interface1': interface name of first interface
130         'interface2': interface name of second interface
131         'bd_id': bridge domain index
132         """
133         bd_dict = Topology().get_interfaces_by_link_names(node, link_names)
134         bd_dict['bd_id'] = bd_id
135         return bd_dict
136
137     @staticmethod
138     def vpp_add_l2_bridge_domain(node, bd_id, port_1, port_2, learn=True):
139         """Add L2 bridge domain with 2 interfaces to the VPP node.
140
141         :param node: Node to add L2BD on.
142         :param bd_id: Bridge domain ID.
143         :param port_1: First interface name added to L2BD.
144         :param port_2: Second interface name added to L2BD.
145         :param learn: Enable/disable MAC learn.
146         :type node: dict
147         :type bd_id: int
148         :type port_1: str
149         :type port_2: str
150         :type learn: bool
151         """
152         sw_if_index1 = Topology.get_interface_sw_index(node, port_1)
153         sw_if_index2 = Topology.get_interface_sw_index(node, port_2)
154         VatExecutor.cmd_from_template(node,
155                                       'l2_bridge_domain.vat',
156                                       sw_if_id1=sw_if_index1,
157                                       sw_if_id2=sw_if_index2,
158                                       bd_id=bd_id,
159                                       learn=int(learn))
160
161     @staticmethod
162     def vpp_setup_bidirectional_cross_connect(node, interface1, interface2):
163         """Create bidirectional cross-connect between 2 interfaces on vpp node.
164
165         :param node: Node to add bidirectional cross-connect
166         :param interface1: first interface name or sw_if_index
167         :param interface2: second interface name or sw_if_index
168         :type node: dict
169         :type interface1: str or int
170         :type interface2: str or int
171         """
172
173         if isinstance(interface1, basestring):
174             sw_iface1 = Topology().get_interface_sw_index(node, interface1)
175         else:
176             sw_iface1 = interface1
177
178         if isinstance(interface2, basestring):
179             sw_iface2 = Topology().get_interface_sw_index(node, interface2)
180         else:
181             sw_iface2 = interface2
182
183         with VatTerminal(node) as vat:
184             vat.vat_terminal_exec_cmd_from_template('l2_xconnect.vat',
185                                                     interface1=sw_iface1,
186                                                     interface2=sw_iface2)
187             vat.vat_terminal_exec_cmd_from_template('l2_xconnect.vat',
188                                                     interface1=sw_iface2,
189                                                     interface2=sw_iface1)
190
191     @staticmethod
192     def linux_add_bridge(node, br_name, if_1, if_2):
193         """Bridge two interfaces on linux node.
194
195         :param node: Node to add bridge on.
196         :param br_name: Bridge name.
197         :param if_1: First interface to be added to the bridge.
198         :param if_2: Second interface to be added to the bridge.
199         :type node: dict
200         :type br_name: str
201         :type if_1: str
202         :type if_2: str
203         """
204         cmd = 'brctl addbr {0}'.format(br_name)
205         exec_cmd_no_error(node, cmd, sudo=True)
206         cmd = 'brctl addif {0} {1}'.format(br_name, if_1)
207         exec_cmd_no_error(node, cmd, sudo=True)
208         cmd = 'brctl addif {0} {1}'.format(br_name, if_2)
209         exec_cmd_no_error(node, cmd, sudo=True)
210
211     @staticmethod
212     def linux_del_bridge(node, br_name):
213         """Delete bridge from linux node.
214
215         :param node: Node to delete bridge from.
216         :param br_name: Bridge name.
217         .. note:: The network interface corresponding to the bridge must be
218         down before it can be deleted!
219         """
220         cmd = 'brctl delbr {0}'.format(br_name)
221         exec_cmd_no_error(node, cmd, sudo=True)
222
223     @staticmethod
224     def vpp_get_bridge_domain_data(node, bd_id=None):
225         """Get all bridge domain data from a VPP node. If a domain ID number is
226         provided, return only data for the matching bridge domain.
227
228         :param node: VPP node to get bridge domain data from.
229         :param bd_id: Numeric ID of a specific bridge domain.
230         :type node: dict
231         :type bd_id: int
232         :return: List of dictionaries containing data for each bridge domain, or
233          a single dictionary for the specified bridge domain.
234         :rtype: list or dict
235         """
236         with VatTerminal(node) as vat:
237             response = vat.vat_terminal_exec_cmd_from_template("l2_bd_dump.vat")
238
239         data = response[0]
240
241         if bd_id is not None:
242             for bridge_domain in data:
243                 if bridge_domain["bd_id"] == bd_id:
244
245                     return bridge_domain
246
247         return data