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