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