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