1 # Copyright (c) 2011, 2012 Nicira Networks
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:
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
16 rpcserver is an XML RPC server that allows RPC client to initiate tests
23 from twisted.internet import reactor
24 from twisted.internet.error import CannotListenError
25 from twisted.web import xmlrpc
26 from twisted.web import server
34 class TestArena(xmlrpc.XMLRPC):
36 This class contains all the functions that ovs-test client will call
37 remotely. The caller is responsible to use designated handleIds
38 for designated methods (e.g. do not mix UDP and TCP handles).
42 xmlrpc.XMLRPC.__init__(self, allowNone=True)
50 def __acquire_handle(self, value):
52 Allocates new handle and assigns value object to it
54 handle = self.handle_id
55 self.handle_map[handle] = value
59 def __get_handle_resources(self, handle):
61 Return resources that were assigned to handle
63 return self.handle_map[handle]
65 def __delete_handle(self, handle):
67 Releases handle from handle_map
69 del self.handle_map[handle]
73 Delete all remaining bridges and ports if ovs-test client did not had
74 a chance to remove them. It is necessary to call this function if
75 ovs-test server is abruptly terminated when doing the tests.
77 for port in self.ports:
78 # Remove ports that were added to existing bridges
79 vswitch.ovs_vsctl_del_port_from_bridge(port)
81 for bridge in self.bridges:
82 # Remove bridges that were added for L3 tests
83 vswitch.ovs_vsctl_del_bridge(bridge)
85 for pbridge in self.pbridges:
86 # Remove bridges that were added for VLAN tests
87 vswitch.ovs_vsctl_del_pbridge(pbridge[0], pbridge[1])
89 def render(self, request):
91 This method overrides the original XMLRPC.render method so that it
92 would be possible to get the XML RPC client IP address from the
95 self.request = request
96 return xmlrpc.XMLRPC.render(self, request)
98 def xmlrpc_get_my_address(self):
100 Returns the RPC client's IP address.
102 return self.request.getClientIP()
104 def xmlrpc_get_my_address_from(self, his_ip, his_port):
106 Returns the ovs-test server IP address that the other ovs-test server
107 with the given ip will see.
109 server1 = xmlrpclib.Server("http://%s:%u/" % (his_ip, his_port))
110 return server1.get_my_address()
112 def xmlrpc_create_udp_listener(self, port):
114 Creates a UDP listener that will receive packets from UDP sender
117 listener = udp.UdpListener()
118 reactor.listenUDP(port, listener)
119 handle_id = self.__acquire_handle(listener)
120 except CannotListenError:
124 def xmlrpc_create_udp_sender(self, host, count, size, duration):
126 Send UDP datagrams to UDP listener
128 sender = udp.UdpSender(tuple(host), count, size, duration)
129 reactor.listenUDP(0, sender)
130 handle_id = self.__acquire_handle(sender)
133 def xmlrpc_get_udp_listener_results(self, handle):
135 Returns number of datagrams that were received
137 listener = self.__get_handle_resources(handle)
138 return listener.getResults()
140 def xmlrpc_get_udp_sender_results(self, handle):
142 Returns number of datagrams that were sent
144 sender = self.__get_handle_resources(handle)
145 return sender.getResults()
147 def xmlrpc_close_udp_listener(self, handle):
149 Releases UdpListener and all its resources
151 listener = self.__get_handle_resources(handle)
152 listener.transport.stopListening()
153 self.__delete_handle(handle)
156 def xmlrpc_close_udp_sender(self, handle):
158 Releases UdpSender and all its resources
160 sender = self.__get_handle_resources(handle)
161 sender.transport.stopListening()
162 self.__delete_handle(handle)
165 def xmlrpc_create_tcp_listener(self, port):
167 Creates a TcpListener that will accept connection from TcpSender
170 listener = tcp.TcpListenerFactory()
171 port = reactor.listenTCP(port, listener)
172 handle_id = self.__acquire_handle((listener, port))
174 except CannotListenError:
177 def xmlrpc_create_tcp_sender(self, his_ip, his_port, duration):
179 Creates a TcpSender that will connect to TcpListener
181 sender = tcp.TcpSenderFactory(duration)
182 connector = reactor.connectTCP(his_ip, his_port, sender)
183 handle_id = self.__acquire_handle((sender, connector))
186 def xmlrpc_get_tcp_listener_results(self, handle):
188 Returns number of bytes received
190 (listener, _) = self.__get_handle_resources(handle)
191 return listener.getResults()
193 def xmlrpc_get_tcp_sender_results(self, handle):
195 Returns number of bytes sent
197 (sender, _) = self.__get_handle_resources(handle)
198 return sender.getResults()
200 def xmlrpc_close_tcp_listener(self, handle):
202 Releases TcpListener and all its resources
205 (_, port) = self.__get_handle_resources(handle)
206 port.loseConnection()
207 self.__delete_handle(handle)
208 except exceptions.KeyError:
212 def xmlrpc_close_tcp_sender(self, handle):
214 Releases TcpSender and all its resources
217 (_, connector) = self.__get_handle_resources(handle)
218 connector.disconnect()
219 self.__delete_handle(handle)
220 except exceptions.KeyError:
224 def xmlrpc_create_test_bridge(self, bridge, iface):
226 This function creates a physical bridge from iface. It moves the
227 IP configuration from the physical interface to the bridge.
229 ret = vswitch.ovs_vsctl_add_bridge(bridge)
231 self.pbridges.add((bridge, iface))
232 util.interface_up(bridge)
233 (ip_addr, mask) = util.interface_get_ip(iface)
234 util.interface_assign_ip(bridge, ip_addr, mask)
235 util.move_routes(iface, bridge)
236 util.interface_assign_ip(iface, "0.0.0.0", "255.255.255.255")
237 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, iface)
239 self.ports.add(iface)
241 util.interface_assign_ip(iface, ip_addr, mask)
242 util.move_routes(bridge, iface)
243 vswitch.ovs_vsctl_del_bridge(bridge)
247 def xmlrpc_del_test_bridge(self, bridge, iface):
249 This function deletes the test bridge and moves its IP configuration
250 back to the physical interface.
252 ret = vswitch.ovs_vsctl_del_pbridge(bridge, iface)
253 self.pbridges.discard((bridge, iface))
256 def xmlrpc_get_iface_from_bridge(self, brname):
258 Tries to figure out physical interface from bridge.
260 return vswitch.ovs_get_physical_interface(brname)
262 def xmlrpc_create_bridge(self, brname):
264 Creates an OVS bridge.
266 ret = vswitch.ovs_vsctl_add_bridge(brname)
268 self.bridges.add(brname)
271 def xmlrpc_del_bridge(self, brname):
273 Deletes an OVS bridge.
275 ret = vswitch.ovs_vsctl_del_bridge(brname)
277 self.bridges.discard(brname)
280 def xmlrpc_is_ovs_bridge(self, bridge):
282 This function verifies whether given interface is an ovs bridge.
284 return vswitch.ovs_vsctl_is_ovs_bridge(bridge)
286 def xmlrpc_add_port_to_bridge(self, bridge, port):
288 Adds a port to the OVS bridge.
290 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, port)
295 def xmlrpc_del_port_from_bridge(self, port):
297 Removes a port from OVS bridge.
299 ret = vswitch.ovs_vsctl_del_port_from_bridge(port)
301 self.ports.discard(port)
304 def xmlrpc_ovs_vsctl_set(self, table, record, column, key, value):
306 This function allows to alter OVS database.
308 return vswitch.ovs_vsctl_set(table, record, column, key, value)
310 def xmlrpc_interface_up(self, iface):
312 This function brings up given interface.
314 return util.interface_up(iface)
316 def xmlrpc_interface_assign_ip(self, iface, ip_address, mask):
318 This function allows to assing ip address to the given interface.
320 return util.interface_assign_ip(iface, ip_address, mask)
322 def xmlrpc_get_interface(self, address):
324 Finds first interface that has given address
326 return util.get_interface(address)
328 def xmlrpc_get_interface_mtu(self, iface):
330 Returns MTU of the given interface
332 return util.get_interface_mtu(iface)
334 def xmlrpc_uname(self):
336 Return information about running kernel
340 def xmlrpc_get_driver(self, iface):
342 Returns driver version
344 return util.get_driver(iface)
347 def start_rpc_server(port):
349 This function creates a RPC server and adds it to the Twisted Reactor.
351 rpc_server = TestArena()
352 reactor.listenTCP(port, server.Site(rpc_server))
354 print "Starting RPC server\n"
356 # If this server was started from ovs-test client then we must flush
357 # STDOUT so that client would know that server is ready to accept
358 # XML RPC connections.