Fix Tap failing tests
[csit.git] / resources / libraries / python / VatJsonUtil.py
1 # Copyright (c) 2018 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 """Utilities to work with JSON data format from VAT."""
15
16 from robot.api import logger
17
18 from resources.libraries.python.parsers.JsonParser import JsonParser
19
20
21 class VatJsonUtil(object):
22     """Utilities to work with JSON data format from VAT."""
23
24     @staticmethod
25     def _convert_mac_to_number_list(mac_address):
26         """Convert MAC address string to list of decimal numbers.
27
28         Converts a ":" separated MAC address to decimal number list as used
29         in JSON interface dump.
30
31         :param mac_address: MAC address.
32         :type mac_address: str
33         :returns: List representation of MAC address.
34         :rtype: list
35         """
36         list_mac = []
37         for num in mac_address.split(":"):
38             list_mac.append(int(num, 16))
39         return list_mac
40
41     @staticmethod
42     def get_vpp_interface_by_mac(interfaces_list, mac_address):
43         """Return interface dictionary from interface_list by MAC address.
44
45         Extracts interface dictionary from all of the interfaces in interfaces
46         list parsed from JSON according to mac_address of the interface.
47
48         :param interfaces_list: Interfaces parsed from JSON.
49         :param mac_address: MAC address of interface we are looking for.
50         :type interfaces_list: dict
51         :type mac_address: str
52         :returns: Interface from JSON.
53         :rtype: dict
54         """
55         interface_dict = {}
56         list_mac_address = VatJsonUtil._convert_mac_to_number_list(mac_address)
57         logger.trace("MAC address {0} converted to list {1}."
58                      .format(mac_address, list_mac_address))
59         for interface in interfaces_list:
60             # TODO: create vat json integrity checking and move there
61             if "l2_address" not in interface:
62                 raise KeyError(
63                     "key l2_address not found in interface dict."
64                     "Probably input list is not parsed from correct VAT "
65                     "json output.")
66             if "l2_address_length" not in interface:
67                 raise KeyError(
68                     "key l2_address_length not found in interface "
69                     "dict. Probably input list is not parsed from correct "
70                     "VAT json output.")
71             mac_from_json = interface["l2_address"][:6]
72             if mac_from_json == list_mac_address:
73                 if interface["l2_address_length"] != 6:
74                     raise ValueError("l2_address_length value is not 6.")
75                 interface_dict = interface
76                 break
77         return interface_dict
78
79     @staticmethod
80     def update_vpp_interface_data_from_json(node, interface_dump_json):
81         """Update vpp node data in node__DICT from JSON interface dump.
82
83         This method updates vpp interface names and sw if indexes according to
84         interface MAC addresses found in interface_dump_json.
85
86         :param node: Node dictionary.
87         :param interface_dump_json: JSON output from dump_interface_list VAT
88             command.
89         :type node: dict
90         :type interface_dump_json: str
91         """
92         interface_list = JsonParser().parse_data(interface_dump_json)
93         for ifc in node['interfaces'].values():
94             if_mac = ifc['mac_address']
95             interface_dict = VatJsonUtil.get_vpp_interface_by_mac(
96                 interface_list, if_mac)
97             if not interface_dict:
98                 logger.trace('Interface {0} not found by MAC {1}'
99                              .format(ifc, if_mac))
100                 ifc['vpp_sw_index'] = None
101                 continue
102             ifc['name'] = interface_dict["interface_name"]
103             ifc['vpp_sw_index'] = interface_dict["sw_if_index"]
104             ifc['mtu'] = interface_dict["mtu"]
105
106     @staticmethod
107     def get_interface_sw_index_from_json(interface_dump_json, interface_name):
108         """Get sw_if_index from given JSON output by interface name.
109
110         :param interface_dump_json: JSON output from dump_interface_list VAT
111             command.
112         :param interface_name: Interface name.
113         :type interface_dump_json: str
114         :type interface_name: str
115         :returns: SW interface index.
116         :rtype: int
117         :raises ValueError: If interface not found in interface_dump_json.
118         """
119         logger.trace(interface_dump_json)
120         interface_list = JsonParser().parse_data(interface_dump_json)
121         for interface in interface_list:
122             try:
123                 if interface['interface_name'] == interface_name:
124                     index = interface['sw_if_index']
125                     logger.debug('Interface with name {} has sw_if_index {}.'
126                                  .format(interface_name, index))
127                     return index
128             except KeyError:
129                 pass
130         raise ValueError('Interface with name {} not found.'
131                          .format(interface_name))
132
133     @staticmethod
134     def get_interface_name_from_json(interface_dump_json, sw_if_index):
135         """Get interface name from given JSON output by sw_if_index.
136
137         :param interface_dump_json: JSON output from dump_interface_list VAT
138             command.
139         :param sw_if_index: SW interface index.
140         :type interface_dump_json: str
141         :type sw_if_index: int
142         :returns: Interface name.
143         :rtype: str
144         :raises ValueError: If interface not found in interface_dump_json.
145         """
146         logger.trace(interface_dump_json)
147         interface_list = JsonParser().parse_data(interface_dump_json)
148         for interface in interface_list:
149             try:
150                 if interface['sw_if_index'] == sw_if_index:
151                     interface_name = interface['interface_name']
152                     logger.debug('Interface with sw_if_index {idx} has name'
153                                  ' {name}.'.format(idx=sw_if_index,
154                                                    name=interface_name))
155                     return interface_name
156             except KeyError:
157                 pass
158         raise ValueError('Interface with sw_if_index {} not found.'
159                          .format(sw_if_index))
160
161     @staticmethod
162     def get_interface_mac_from_json(interface_dump_json, sw_if_index):
163         """Get interface MAC address from given JSON output by sw_if_index.
164
165         :param interface_dump_json: JSON output from dump_interface_list VAT
166             command.
167         :param sw_if_index: SW interface index.
168         :type interface_dump_json: str
169         :type sw_if_index: int
170         :returns: Interface MAC address.
171         :rtype: str
172         :raises ValueError: If interface not found in interface_dump_json.
173         """
174         logger.trace(interface_dump_json)
175         interface_list = JsonParser().parse_data(interface_dump_json)
176         for interface in interface_list:
177             try:
178                 if interface['sw_if_index'] == sw_if_index:
179                     mac_from_json = interface['l2_address'][:6] \
180                         if 'l2_address' in interface.keys() else ''
181                     mac_address = ':'.join('{:02x}'.format(item)
182                                            for item in mac_from_json)
183                     logger.debug('Interface with sw_if_index {idx} has MAC'
184                                  ' address {addr}.'.format(idx=sw_if_index,
185                                                            addr=mac_address))
186                     return mac_address
187             except KeyError:
188                 pass
189         raise ValueError('Interface with sw_if_index {idx} not found.'
190                          .format(idx=sw_if_index))
191
192     @staticmethod
193     def verify_vat_retval(vat_out, exp_retval=0, err_msg='VAT cmd failed'):
194         """Verify return value of VAT command.
195
196         VAT command JSON output should be object (dict in python) or array. We
197         are looking for something like this: { "retval": 0 }. Verification is
198         skipped if VAT output does not contain return value element or root
199         elemet is array.
200
201         :param vat_out: VAT command output in python representation of JSON.
202         :param exp_retval: Expected return value (default 0).
203         :err_msg: Message to be displayed in case of error (optional).
204         :type vat_out: dict or list
205         :type exp_retval: int
206         :type err_msg: str
207         :raises RuntimeError: If VAT command return value is incorrect.
208         """
209         if isinstance(vat_out, dict):
210             retval = vat_out.get('retval')
211             if retval is not None:
212                 if retval != exp_retval:
213                     raise RuntimeError(err_msg)