CSIT-424: HC Test: JSON comparison function rework
[csit.git] / resources / libraries / python / IPv4Util.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 """Implements IPv4 RobotFramework keywords"""
15
16 from robot.api import logger as log
17 from robot.api.deco import keyword
18
19 from resources.libraries.python.topology import Topology
20 from resources.libraries.python.IPv4Setup import get_node
21 from resources.libraries.python.ssh import exec_cmd
22
23
24 class IPv4Util(object):
25     """Implements keywords for IPv4 tests."""
26
27     @staticmethod
28     @keyword('From node "${node}" interface "${port}" ARP-ping '
29              'IPv4 address "${ip_address}"')
30     def arp_ping(node, interface, ip_address):
31         """Send an ARP ping from the specified node.
32
33         :param node: Node in topology.
34         :param ip_address: Destination IP address for the ARP packet.
35         :param interface: Name of an interface to send the ARP packet from.
36         :type node: dict
37         :type ip_address: str
38         :type interface: str
39         """
40         log.debug('From node {} interface {} ARP-ping IPv4 address {}'.
41                   format(Topology.get_node_hostname(node),
42                          interface, ip_address))
43         get_node(node).arp_ping(ip_address, interface)
44
45     @staticmethod
46     def set_interface_address(node, interface, address, prefix_length):
47         """See IPv4Node.set_ip for more information.
48
49         :param node: Node where IP address should be set to.
50         :param interface: Interface name.
51         :param address: IP address.
52         :param prefix_length: Prefix length.
53         :type node: dict
54         :type interface: str
55         :type address: str
56         :type prefix_length: int
57         """
58         log.debug('Node {} interface {} has IPv4 address {} with prefix '
59                   'length {}'.format(Topology.get_node_hostname(node),
60                                      interface, address, prefix_length))
61         get_node(node).set_ip(interface, address, int(prefix_length))
62
63     @staticmethod
64     def set_route(node, network, prefix_length, interface, gateway):
65         """See IPv4Node.set_route for more information.
66
67         :param node: Node where IP address should be set to.
68         :param network: IP network.
69         :param prefix_length: Prefix length.
70         :param interface: Interface name.
71         :param gateway: Gateway.
72         :type node: dict
73         :type network: str
74         :type prefix_length: int
75         :type interface: str
76         :type gateway: str
77         """
78         log.debug('Node {} routes to network {} with prefix length {} '
79                   'via {} interface {}'.format(Topology.get_node_hostname(node),
80                                                network, prefix_length,
81                                                gateway, interface))
82         get_node(node).set_route(network, int(prefix_length),
83                                  gateway, interface)
84
85     @staticmethod
86     @keyword('Get IPv4 address prefix of node "${node}" interface "${port}" '
87              'from "${nodes_addr}"')
88     def get_ip_addr_prefix_length(node, port, nodes_addr):
89         """ Get IPv4 address prefix for specified interface.
90
91         :param node: Node dictionary.
92         :param port: Interface name.
93         :param nodes_addr: Available nodes IPv4 addresses.
94         :type node: dict
95         :type port: str
96         :type nodes_addr: dict
97         :return: IPv4 prefix length.
98         :rtype: int
99         """
100         for net in nodes_addr.values():
101             for net_port in net['ports'].values():
102                 if net_port['node'] == node['host'] and net_port['if'] == port:
103                     return net['prefix']
104
105         raise Exception('Subnet not found for node {n} port {p}'.
106                         format(n=node['host'], p=port))
107
108     @staticmethod
109     @keyword('Get IPv4 subnet of node "${node}" interface "${port}" from '
110              '"${nodes_addr}"')
111     def get_ip_addr_subnet(node, port, nodes_addr):
112         """ Get IPv4 subnet of specified interface.
113
114         :param node: Node dictionary.
115         :param port: Interface name.
116         :param nodes_addr: Available nodes IPv4 addresses.
117         :type node: dict
118         :type port: int
119         :type nodes_addr: dict
120         :return: IPv4 subnet.
121         :rtype: str
122         """
123         for net in nodes_addr.values():
124             for net_port in net['ports'].values():
125                 if net_port['node'] == node['host'] and net_port['if'] == port:
126                     return net['net_addr']
127
128         raise Exception('Subnet not found for node {n} port {p}'.
129                         format(n=node['host'], p=port))
130
131     @staticmethod
132     @keyword('Flush IPv4 addresses "${port}" "${node}"')
133     def flush_ip_addresses(port, node):
134         """See IPv4Node.flush_ip_addresses for more information.
135
136         :param port:
137         :param node:
138         :return:
139         """
140         get_node(node).flush_ip_addresses(port)
141
142     @staticmethod
143     def get_link_address(link, nodes_addr):
144         """Get link IPv4 address.
145
146         :param link: Link name.
147         :param nodes_addr: Available nodes IPv4 addresses.
148         :type link: str
149         :type nodes_addr: dict
150         :return: Link IPv4 address.
151         :rtype: str
152         """
153         net = nodes_addr.get(link)
154         if net is None:
155             raise ValueError('Link "{0}" not found'.format(link))
156         return net.get('net_addr')
157
158     @staticmethod
159     def get_link_prefix(link, nodes_addr):
160         """Get link IPv4 address prefix.
161
162         :param link: Link name.
163         :param nodes_addr: Available nodes IPv4 addresses.
164         :type link: str
165         :type nodes_addr: dict
166         :return: Link IPv4 address prefix.
167         :rtype: int
168         """
169         net = nodes_addr.get(link)
170         if net is None:
171             raise ValueError('Link "{0}" not found'.format(link))
172         return net.get('prefix')
173
174     @staticmethod
175     def send_ping_from_node_to_dst(node, destination, namespace=None,
176                                    ping_count=3, interface=None):
177         """Send a ping from node to destination. Optionally, you can define a
178         namespace and interface from where to send a ping.
179
180         :param node: Node to start ping on.
181         :param destination: IPv4 address where to send ping.
182         :param namespace: Namespace to send ping from. Optional
183         :param ping_count: Number of pings to send. Default 3
184         :param interface: Interface from where to send ping. Optional
185         :type node: dict
186         :type destination: str
187         :type namespace: str
188         :type ping_count: int
189         :type interface: str
190         :raises RuntimeError: If no response for ping, raise error
191         """
192         cmd = ''
193         if namespace is not None:
194             cmd = 'ip netns exec {0} ping -c{1} {2}'.format(
195                 namespace, ping_count, destination)
196         elif interface is not None:
197             cmd = 'ping -I {0} -c{1} {2}'.format(
198                 interface, ping_count, destination)
199         else:
200             cmd = 'ping -c{0} {1}'.format(ping_count, destination)
201         ret_code, _, _ = exec_cmd(node, cmd, sudo=True)
202         if ret_code != 0:
203             raise RuntimeError("Ping Not Successful")
204
205     @staticmethod
206     def set_linux_interface_arp(node, interface, ip_addr, mac, namespace=None):
207         """Set arp on interface in linux.
208
209         :param node: Node where to execute command.
210         :param interface: Interface in namespace.
211         :param ip_addr: IP address for ARP entry.
212         :param mac: MAC address.
213         :param namespace: Execute command in namespace. Optional
214         :type node: dict
215         :type interface: str
216         :type ip_addr: str
217         :type mac: str
218         :type namespace: str
219         :raises RuntimeError: Could not set ARP properly.
220         """
221         if namespace is not None:
222             cmd = 'ip netns exec {} arp -i {} -s {} {}'.format(
223                 namespace, interface, ip_addr, mac)
224         else:
225             cmd = 'arp -i {} -s {} {}'.format(interface, ip_addr, mac)
226         ret_code, _, stderr = exec_cmd(node, cmd, sudo=True)
227         if ret_code != 0:
228             raise RuntimeError("Arp set not successful, reason:{}".
229                                format(stderr))