]> git.proxmox.com Git - ovs.git/blame - python/ovstest/util.py
Remove dependency on python3-six
[ovs.git] / python / ovstest / util.py
CommitLineData
0b2c7e69 1# Copyright (c) 2011, 2012, 2017 Nicira, Inc.
0be6140a
AA
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at:
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""
16util module contains some helper function
17"""
8d25d9a2 18import array
8d25d9a2 19import fcntl
6c7050b5 20
8d25d9a2 21import os
6c7050b5 22import re
2d8bdd8f 23import select
6c7050b5 24import signal
8d25d9a2
AA
25import socket
26import struct
27import subprocess
73eb682e 28
6c7050b5 29import exceptions
30
0c4d144a 31import xmlrpc.client
0be6140a 32
8d25d9a2
AA
33
34def str_ip(ip_address):
35 """
36 Converts an IP address from binary format to a string.
37 """
38 (x1, x2, x3, x4) = struct.unpack("BBBB", ip_address)
0be6140a
AA
39 return ("%u.%u.%u.%u") % (x1, x2, x3, x4)
40
8d25d9a2 41
0be6140a 42def get_interface_mtu(iface):
8d25d9a2
AA
43 """
44 Returns MTU of the given interface.
45 """
0be6140a
AA
46 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
47 indata = iface + ('\0' * (32 - len(iface)))
48 try:
a0631d92 49 outdata = fcntl.ioctl(s.fileno(), 0x8921, indata) # socket.SIOCGIFMTU
0be6140a
AA
50 mtu = struct.unpack("16si12x", outdata)[1]
51 except:
52 return 0
53
54 return mtu
55
8d25d9a2 56
0be6140a
AA
57def get_interface(address):
58 """
59 Finds first interface that has given address
60 """
61 bytes = 256 * 32
62 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
63 names = array.array('B', '\0' * bytes)
64 outbytes = struct.unpack('iL', fcntl.ioctl(
65 s.fileno(),
a0631d92 66 0x8912, # SIOCGIFCONF
0be6140a
AA
67 struct.pack('iL', bytes, names.buffer_info()[0])
68 ))[0]
69 namestr = names.tostring()
70
71 for i in range(0, outbytes, 40):
72 name = namestr[i:i + 16].split('\0', 1)[0]
73 if address == str_ip(namestr[i + 20:i + 24]):
74 return name
8d25d9a2
AA
75 return None # did not find interface we were looking for
76
0be6140a
AA
77
78def uname():
79 os_info = os.uname()
8d25d9a2 80 return os_info[2] # return only the kernel version number
0be6140a 81
8d25d9a2
AA
82
83def start_process(args):
0be6140a 84 try:
8d25d9a2 85 p = subprocess.Popen(args,
a0631d92
RB
86 stdin=subprocess.PIPE,
87 stdout=subprocess.PIPE,
88 stderr=subprocess.PIPE)
0be6140a 89 out, err = p.communicate()
8d25d9a2 90 return (p.returncode, out, err)
0be6140a 91 except exceptions.OSError:
8d25d9a2
AA
92 return (-1, None, None)
93
94
95def get_driver(iface):
96 ret, out, _err = start_process(["ethtool", "-i", iface])
97 if ret == 0:
98 lines = out.splitlines()
99 driver = "%s(%s)" % (lines[0], lines[1]) # driver name + version
100 else:
101 driver = None
0be6140a 102 return driver
8d25d9a2
AA
103
104
105def interface_up(iface):
106 """
107 This function brings given iface up.
108 """
0b2c7e69 109 ret, _out, _err = start_process(["ip", "link", "set", iface, "up"])
8d25d9a2
AA
110 return ret
111
112
113def interface_assign_ip(iface, ip_addr, mask):
114 """
0b2c7e69
BP
115 This function adds an IP address to an interface. If mask is None
116 then a mask will be selected automatically. In case of success
117 this function returns 0.
8d25d9a2 118 """
0b2c7e69
BP
119 interface_ip_op(iface, ip_addr, mask, "add")
120
121
122def interface_remove_ip(iface, ip_addr, mask):
123 """
124 This function removes an IP address from an interface. If mask is
125 None then a mask will be selected automatically. In case of
126 success this function returns 0.
127 """
128 interface_ip_op(iface, ip_addr, mask, "del")
129
130
131def interface_ip_op(iface, ip_addr, mask, op):
8d25d9a2 132 if mask is not None:
0b2c7e69
BP
133 arg = "%s/%s" % (ip_addr, mask)
134 elif '/' in ip_addr:
135 arg = ip_addr
136 else:
137 (x1, x2, x3, x4) = struct.unpack("BBBB", socket.inet_aton(ip_addr))
138 if x1 < 128:
139 arg = "%s/8" % ip_addr
140 elif x1 < 192:
141 arg = "%s/16" % ip_addr
142 else:
143 arg = "%s/24" % ip_addr
144 ret, _out, _err = start_process(["ip", "addr", op, arg, "dev", iface])
8d25d9a2
AA
145 return ret
146
147
148def interface_get_ip(iface):
149 """
150 This function returns tuple - ip and mask that was assigned to the
151 interface.
152 """
0b2c7e69 153 args = ["ip", "addr", "show", iface]
8d25d9a2
AA
154 ret, out, _err = start_process(args)
155
156 if ret == 0:
0b2c7e69
BP
157 ip = re.search(r'inet (\S+)/(\S+)', out)
158 if ip is not None:
159 return (ip.group(1), ip.group(2))
8d25d9a2
AA
160 else:
161 return ret
162
163
164def move_routes(iface1, iface2):
165 """
166 This function moves routes from iface1 to iface2.
167 """
168 args = ["ip", "route", "show", "dev", iface1]
169 ret, out, _err = start_process(args)
170 if ret == 0:
171 for route in out.splitlines():
172 args = ["ip", "route", "replace", "dev", iface2] + route.split()
173 start_process(args)
2d8bdd8f
AA
174
175
176def get_interface_from_routing_decision(ip):
177 """
178 This function returns the interface through which the given ip address
179 is reachable.
180 """
181 args = ["ip", "route", "get", ip]
182 ret, out, _err = start_process(args)
183 if ret == 0:
184 iface = re.search(r'dev (\S+)', out)
185 if iface:
186 return iface.group(1)
187 return None
188
189
190def rpc_client(ip, port):
0c4d144a 191 return xmlrpc.client.Server("http://%s:%u/" % (ip, port), allow_none=True)
2d8bdd8f
AA
192
193
194def sigint_intercept():
195 """
196 Intercept SIGINT from child (the local ovs-test server process).
197 """
198 signal.signal(signal.SIGINT, signal.SIG_IGN)
199
200
201def start_local_server(port):
202 """
203 This function spawns an ovs-test server that listens on specified port
204 and blocks till the spawned ovs-test server is ready to accept XML RPC
205 connections.
206 """
207 p = subprocess.Popen(["ovs-test", "-s", str(port)],
208 stdout=subprocess.PIPE, stderr=subprocess.PIPE,
209 preexec_fn=sigint_intercept)
a0631d92 210 fcntl.fcntl(p.stdout.fileno(), fcntl.F_SETFL,
2d8bdd8f
AA
211 fcntl.fcntl(p.stdout.fileno(), fcntl.F_GETFL) | os.O_NONBLOCK)
212
213 while p.poll() is None:
214 fd = select.select([p.stdout.fileno()], [], [])[0]
215 if fd:
216 out = p.stdout.readline()
217 if out.startswith("Starting RPC server"):
218 break
219 if p.poll() is not None:
220 raise RuntimeError("Couldn't start local instance of ovs-test server")
221 return p
222
223
224def get_datagram_sizes(mtu1, mtu2):
225 """
226 This function calculates all the "interesting" datagram sizes so that
227 we test both - receive and send side with different packets sizes.
228 """
229 s1 = set([8, mtu1 - 100, mtu1 - 28, mtu1])
230 s2 = set([8, mtu2 - 100, mtu2 - 28, mtu2])
231 return sorted(s1.union(s2))
232
233
234def ip_from_cidr(string):
235 """
236 This function removes the netmask (if present) from the given string and
237 returns the IP address.
238 """
239 token = string.split("/")
240 return token[0]
241
242
243def bandwidth_to_string(bwidth):
244 """Convert bandwidth from long to string and add units."""
245 bwidth = bwidth * 8 # Convert back to bits/second
246 if bwidth >= 10000000:
247 return str(int(bwidth / 1000000)) + "Mbps"
248 elif bwidth > 10000:
249 return str(int(bwidth / 1000)) + "Kbps"
250 else:
251 return str(int(bwidth)) + "bps"