Python3: resources and libraries
[csit.git] / resources / libraries / python / NATUtil.py
1 # Copyright (c) 2019 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 """NAT utilities library."""
15
16 from pprint import pformat
17 from socket import AF_INET, inet_pton
18 from enum import IntEnum
19
20 from robot.api import logger
21
22 from resources.libraries.python.InterfaceUtil import InterfaceUtil
23 from resources.libraries.python.PapiExecutor import PapiSocketExecutor
24
25
26 class NATConfigFlags(IntEnum):
27     """Common NAT plugin APIs"""
28     NAT_IS_NONE = 0x00
29     NAT_IS_TWICE_NAT = 0x01
30     NAT_IS_SELF_TWICE_NAT = 0x02
31     NAT_IS_OUT2IN_ONLY = 0x04
32     NAT_IS_ADDR_ONLY = 0x08
33     NAT_IS_OUTSIDE = 0x10
34     NAT_IS_INSIDE = 0x20
35     NAT_IS_STATIC = 0x40
36     NAT_IS_EXT_HOST_VALID = 0x80
37
38
39 class NATUtil:
40     """This class defines the methods to set NAT."""
41
42     def __init__(self):
43         pass
44
45     @staticmethod
46     def set_nat44_interfaces(node, int_in, int_out):
47         """Set inside and outside interfaces for NAT44.
48
49         :param node: DUT node.
50         :param int_in: Inside interface.
51         :param int_out: Outside interface.
52         :type node: dict
53         :type int_in: str
54         :type int_out: str
55         """
56         cmd = u"nat44_interface_add_del_feature"
57
58         int_in_idx = InterfaceUtil.get_sw_if_index(node, int_in)
59         err_msg = f"Failed to set inside interface {int_in} for NAT44 " \
60             f"on host {node[u'host']}"
61         args_in = dict(
62             sw_if_index=int_in_idx,
63             is_add=1,
64             flags=getattr(NATConfigFlags, u"NAT_IS_INSIDE").value
65         )
66
67         with PapiSocketExecutor(node) as papi_exec:
68             papi_exec.add(cmd, **args_in).get_reply(err_msg)
69
70         int_out_idx = InterfaceUtil.get_sw_if_index(node, int_out)
71         err_msg = f"Failed to set outside interface {int_out} for NAT44 " \
72             f"on host {node[u'host']}"
73         args_in = dict(
74             sw_if_index=int_out_idx,
75             is_add=1,
76             flags=getattr(NATConfigFlags, u"NAT_IS_OUTSIDE").value
77         )
78
79         with PapiSocketExecutor(node) as papi_exec:
80             papi_exec.add(cmd, **args_in).get_reply(err_msg)
81
82     @staticmethod
83     def set_nat44_deterministic(node, ip_in, subnet_in, ip_out, subnet_out):
84         """Set deterministic behaviour of NAT44.
85
86         :param node: DUT node.
87         :param ip_in: Inside IP.
88         :param subnet_in: Inside IP subnet.
89         :param ip_out: Outside IP.
90         :param subnet_out: Outside IP subnet.
91         :type node: dict
92         :type ip_in: str
93         :type subnet_in: str or int
94         :type ip_out: str
95         :type subnet_out: str or int
96         """
97         cmd = u"nat_det_add_del_map"
98         err_msg = f"Failed to set deterministic behaviour of NAT " \
99             f"on host {node[u'host']}"
100         args_in = dict(
101             is_add=True,
102             in_addr=inet_pton(AF_INET, str(ip_in)),
103             in_plen=int(subnet_in),
104             out_addr=inet_pton(AF_INET, str(ip_out)),
105             out_plen=int(subnet_out)
106         )
107
108         with PapiSocketExecutor(node) as papi_exec:
109             papi_exec.add(cmd, **args_in).get_reply(err_msg)
110
111     @staticmethod
112     def show_nat(node):
113         """Show the NAT configuration and data.
114
115         Used data sources:
116
117             nat_show_config
118             nat_worker_dump
119             nat44_interface_addr_dump
120             nat44_address_dump
121             nat44_static_mapping_dump
122             nat44_user_dump
123             nat44_interface_dump
124             nat44_user_session_dump
125             nat_det_map_dump
126
127         :param node: DUT node.
128         :type node: dict
129         """
130         cmd = u"nat_show_config"
131         err_msg = f"Failed to get NAT configuration on host {node[u'host']}"
132
133         with PapiSocketExecutor(node) as papi_exec:
134             reply = papi_exec.add(cmd).get_reply(err_msg)
135
136         logger.debug(f"NAT Configuration:\n{pformat(reply)}")
137
138         cmds = [
139             u"nat_worker_dump",
140             u"nat44_interface_addr_dump",
141             u"nat44_address_dump",
142             u"nat44_static_mapping_dump",
143             u"nat44_user_dump",
144             u"nat44_interface_dump",
145             u"nat44_user_session_dump",
146             u"nat_det_map_dump"
147         ]
148         PapiSocketExecutor.dump_and_log(node, cmds)