]> git.proxmox.com Git - ovs.git/blame - python/ovstest/rpcserver.py
Remove dependency on python3-six
[ovs.git] / python / ovstest / rpcserver.py
CommitLineData
e0edde6f 1# Copyright (c) 2011, 2012 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"""
16rpcserver is an XML RPC server that allows RPC client to initiate tests
17"""
18
8d25d9a2 19import sys
8d25d9a2 20
6c7050b5 21import exceptions
22
0c4d144a 23import xmlrpc.client
6c7050b5 24
25import tcp
26
0be6140a 27from twisted.internet import reactor
0be6140a 28from twisted.internet.error import CannotListenError
8d25d9a2 29from twisted.web import server
6c7050b5 30from twisted.web import xmlrpc
8d25d9a2 31
8d25d9a2 32import udp
6c7050b5 33
0be6140a 34import util
6c7050b5 35
8d25d9a2 36import vswitch
0be6140a
AA
37
38
39class TestArena(xmlrpc.XMLRPC):
40 """
8d25d9a2 41 This class contains all the functions that ovs-test client will call
0be6140a
AA
42 remotely. The caller is responsible to use designated handleIds
43 for designated methods (e.g. do not mix UDP and TCP handles).
44 """
45
46 def __init__(self):
8d25d9a2 47 xmlrpc.XMLRPC.__init__(self, allowNone=True)
0be6140a
AA
48 self.handle_id = 1
49 self.handle_map = {}
8d25d9a2
AA
50 self.bridges = set()
51 self.pbridges = set()
52 self.ports = set()
53 self.request = None
0be6140a
AA
54
55 def __acquire_handle(self, value):
56 """
57 Allocates new handle and assigns value object to it
58 """
59 handle = self.handle_id
60 self.handle_map[handle] = value
61 self.handle_id += 1
62 return handle
63
64 def __get_handle_resources(self, handle):
65 """
66 Return resources that were assigned to handle
67 """
68 return self.handle_map[handle]
69
70 def __delete_handle(self, handle):
71 """
72 Releases handle from handle_map
73 """
74 del self.handle_map[handle]
75
8d25d9a2
AA
76 def cleanup(self):
77 """
78 Delete all remaining bridges and ports if ovs-test client did not had
79 a chance to remove them. It is necessary to call this function if
80 ovs-test server is abruptly terminated when doing the tests.
81 """
82 for port in self.ports:
83 # Remove ports that were added to existing bridges
84 vswitch.ovs_vsctl_del_port_from_bridge(port)
85
86 for bridge in self.bridges:
87 # Remove bridges that were added for L3 tests
88 vswitch.ovs_vsctl_del_bridge(bridge)
89
90 for pbridge in self.pbridges:
91 # Remove bridges that were added for VLAN tests
92 vswitch.ovs_vsctl_del_pbridge(pbridge[0], pbridge[1])
93
94 def render(self, request):
95 """
96 This method overrides the original XMLRPC.render method so that it
97 would be possible to get the XML RPC client IP address from the
98 request object.
99 """
100 self.request = request
101 return xmlrpc.XMLRPC.render(self, request)
102
103 def xmlrpc_get_my_address(self):
104 """
105 Returns the RPC client's IP address.
106 """
107 return self.request.getClientIP()
108
109 def xmlrpc_get_my_address_from(self, his_ip, his_port):
110 """
111 Returns the ovs-test server IP address that the other ovs-test server
112 with the given ip will see.
113 """
0c4d144a 114 server1 = xmlrpc.client.Server("http://%s:%u/" % (his_ip, his_port))
8d25d9a2 115 return server1.get_my_address()
0be6140a
AA
116
117 def xmlrpc_create_udp_listener(self, port):
118 """
119 Creates a UDP listener that will receive packets from UDP sender
120 """
121 try:
122 listener = udp.UdpListener()
123 reactor.listenUDP(port, listener)
124 handle_id = self.__acquire_handle(listener)
125 except CannotListenError:
126 return -1
127 return handle_id
128
129 def xmlrpc_create_udp_sender(self, host, count, size, duration):
130 """
131 Send UDP datagrams to UDP listener
132 """
133 sender = udp.UdpSender(tuple(host), count, size, duration)
134 reactor.listenUDP(0, sender)
135 handle_id = self.__acquire_handle(sender)
136 return handle_id
137
138 def xmlrpc_get_udp_listener_results(self, handle):
139 """
140 Returns number of datagrams that were received
141 """
142 listener = self.__get_handle_resources(handle)
143 return listener.getResults()
144
145 def xmlrpc_get_udp_sender_results(self, handle):
146 """
147 Returns number of datagrams that were sent
148 """
149 sender = self.__get_handle_resources(handle)
150 return sender.getResults()
151
152 def xmlrpc_close_udp_listener(self, handle):
153 """
154 Releases UdpListener and all its resources
155 """
156 listener = self.__get_handle_resources(handle)
157 listener.transport.stopListening()
158 self.__delete_handle(handle)
159 return 0
160
161 def xmlrpc_close_udp_sender(self, handle):
162 """
163 Releases UdpSender and all its resources
164 """
165 sender = self.__get_handle_resources(handle)
166 sender.transport.stopListening()
167 self.__delete_handle(handle)
168 return 0
169
170 def xmlrpc_create_tcp_listener(self, port):
171 """
172 Creates a TcpListener that will accept connection from TcpSender
173 """
174 try:
175 listener = tcp.TcpListenerFactory()
176 port = reactor.listenTCP(port, listener)
177 handle_id = self.__acquire_handle((listener, port))
178 return handle_id
179 except CannotListenError:
180 return -1
181
182 def xmlrpc_create_tcp_sender(self, his_ip, his_port, duration):
183 """
184 Creates a TcpSender that will connect to TcpListener
185 """
186 sender = tcp.TcpSenderFactory(duration)
187 connector = reactor.connectTCP(his_ip, his_port, sender)
188 handle_id = self.__acquire_handle((sender, connector))
189 return handle_id
190
191 def xmlrpc_get_tcp_listener_results(self, handle):
192 """
193 Returns number of bytes received
194 """
195 (listener, _) = self.__get_handle_resources(handle)
196 return listener.getResults()
197
198 def xmlrpc_get_tcp_sender_results(self, handle):
199 """
200 Returns number of bytes sent
201 """
202 (sender, _) = self.__get_handle_resources(handle)
203 return sender.getResults()
204
205 def xmlrpc_close_tcp_listener(self, handle):
206 """
207 Releases TcpListener and all its resources
208 """
209 try:
210 (_, port) = self.__get_handle_resources(handle)
211 port.loseConnection()
212 self.__delete_handle(handle)
213 except exceptions.KeyError:
214 return -1
215 return 0
216
217 def xmlrpc_close_tcp_sender(self, handle):
218 """
219 Releases TcpSender and all its resources
220 """
221 try:
222 (_, connector) = self.__get_handle_resources(handle)
223 connector.disconnect()
224 self.__delete_handle(handle)
225 except exceptions.KeyError:
226 return -1
227 return 0
228
8d25d9a2
AA
229 def xmlrpc_create_test_bridge(self, bridge, iface):
230 """
231 This function creates a physical bridge from iface. It moves the
232 IP configuration from the physical interface to the bridge.
233 """
234 ret = vswitch.ovs_vsctl_add_bridge(bridge)
235 if ret == 0:
236 self.pbridges.add((bridge, iface))
237 util.interface_up(bridge)
238 (ip_addr, mask) = util.interface_get_ip(iface)
239 util.interface_assign_ip(bridge, ip_addr, mask)
0b2c7e69 240 util.interface_up(bridge)
8d25d9a2 241 util.move_routes(iface, bridge)
0b2c7e69 242 util.interface_remove_ip(iface, ip_addr, mask)
8d25d9a2
AA
243 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, iface)
244 if ret == 0:
245 self.ports.add(iface)
246 else:
247 util.interface_assign_ip(iface, ip_addr, mask)
0b2c7e69 248 util.interface_up(iface)
8d25d9a2
AA
249 util.move_routes(bridge, iface)
250 vswitch.ovs_vsctl_del_bridge(bridge)
251
252 return ret
253
254 def xmlrpc_del_test_bridge(self, bridge, iface):
255 """
256 This function deletes the test bridge and moves its IP configuration
257 back to the physical interface.
258 """
259 ret = vswitch.ovs_vsctl_del_pbridge(bridge, iface)
260 self.pbridges.discard((bridge, iface))
261 return ret
262
263 def xmlrpc_get_iface_from_bridge(self, brname):
264 """
265 Tries to figure out physical interface from bridge.
266 """
267 return vswitch.ovs_get_physical_interface(brname)
268
269 def xmlrpc_create_bridge(self, brname):
270 """
271 Creates an OVS bridge.
272 """
273 ret = vswitch.ovs_vsctl_add_bridge(brname)
274 if ret == 0:
275 self.bridges.add(brname)
276 return ret
277
278 def xmlrpc_del_bridge(self, brname):
279 """
280 Deletes an OVS bridge.
281 """
282 ret = vswitch.ovs_vsctl_del_bridge(brname)
283 if ret == 0:
284 self.bridges.discard(brname)
285 return ret
286
287 def xmlrpc_is_ovs_bridge(self, bridge):
288 """
289 This function verifies whether given interface is an ovs bridge.
290 """
291 return vswitch.ovs_vsctl_is_ovs_bridge(bridge)
292
293 def xmlrpc_add_port_to_bridge(self, bridge, port):
294 """
295 Adds a port to the OVS bridge.
296 """
297 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, port)
298 if ret == 0:
299 self.ports.add(port)
300 return ret
301
302 def xmlrpc_del_port_from_bridge(self, port):
303 """
304 Removes a port from OVS bridge.
305 """
306 ret = vswitch.ovs_vsctl_del_port_from_bridge(port)
307 if ret == 0:
308 self.ports.discard(port)
309 return ret
310
311 def xmlrpc_ovs_vsctl_set(self, table, record, column, key, value):
312 """
313 This function allows to alter OVS database.
314 """
315 return vswitch.ovs_vsctl_set(table, record, column, key, value)
316
317 def xmlrpc_interface_up(self, iface):
318 """
319 This function brings up given interface.
320 """
321 return util.interface_up(iface)
322
323 def xmlrpc_interface_assign_ip(self, iface, ip_address, mask):
324 """
325 This function allows to assing ip address to the given interface.
326 """
327 return util.interface_assign_ip(iface, ip_address, mask)
0be6140a 328
0b2c7e69
BP
329 def xmlrpc_interface_remove_ip(self, iface, ip_address, mask):
330 """
331 This function allows to assing ip address to the given interface.
332 """
333 return util.interface_remove_ip(iface, ip_address, mask)
334
0be6140a
AA
335 def xmlrpc_get_interface(self, address):
336 """
337 Finds first interface that has given address
338 """
339 return util.get_interface(address)
340
341 def xmlrpc_get_interface_mtu(self, iface):
342 """
343 Returns MTU of the given interface
344 """
345 return util.get_interface_mtu(iface)
346
347 def xmlrpc_uname(self):
348 """
349 Return information about running kernel
350 """
351 return util.uname()
352
353 def xmlrpc_get_driver(self, iface):
354 """
355 Returns driver version
356 """
357 return util.get_driver(iface)
358
2d8bdd8f
AA
359 def xmlrpc_get_interface_from_routing_decision(self, ip):
360 """
361 Returns driver version
362 """
363 return util.get_interface_from_routing_decision(ip)
364
0be6140a
AA
365
366def start_rpc_server(port):
8d25d9a2
AA
367 """
368 This function creates a RPC server and adds it to the Twisted Reactor.
369 """
370 rpc_server = TestArena()
371 reactor.listenTCP(port, server.Site(rpc_server))
372 try:
8ea171ab 373 print("Starting RPC server\n")
8d25d9a2 374 sys.stdout.flush()
eda26d40
RB
375 # If this server was started from ovs-test client then we must flush
376 # STDOUT so that client would know that server is ready to accept
377 # XML RPC connections.
8d25d9a2
AA
378 reactor.run()
379 finally:
380 rpc_server.cleanup()