1 # Copyright (c) 2011, 2012 Nicira, Inc.
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
19 from __future__ import print_function
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
36 class TestArena(xmlrpc.XMLRPC):
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).
44 xmlrpc.XMLRPC.__init__(self, allowNone=True)
52 def __acquire_handle(self, value):
54 Allocates new handle and assigns value object to it
56 handle = self.handle_id
57 self.handle_map[handle] = value
61 def __get_handle_resources(self, handle):
63 Return resources that were assigned to handle
65 return self.handle_map[handle]
67 def __delete_handle(self, handle):
69 Releases handle from handle_map
71 del self.handle_map[handle]
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.
79 for port in self.ports:
80 # Remove ports that were added to existing bridges
81 vswitch.ovs_vsctl_del_port_from_bridge(port)
83 for bridge in self.bridges:
84 # Remove bridges that were added for L3 tests
85 vswitch.ovs_vsctl_del_bridge(bridge)
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])
91 def render(self, request):
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
97 self.request = request
98 return xmlrpc.XMLRPC.render(self, request)
100 def xmlrpc_get_my_address(self):
102 Returns the RPC client's IP address.
104 return self.request.getClientIP()
106 def xmlrpc_get_my_address_from(self, his_ip, his_port):
108 Returns the ovs-test server IP address that the other ovs-test server
109 with the given ip will see.
111 server1 = xmlrpclib.Server("http://%s:%u/" % (his_ip, his_port))
112 return server1.get_my_address()
114 def xmlrpc_create_udp_listener(self, port):
116 Creates a UDP listener that will receive packets from UDP sender
119 listener = udp.UdpListener()
120 reactor.listenUDP(port, listener)
121 handle_id = self.__acquire_handle(listener)
122 except CannotListenError:
126 def xmlrpc_create_udp_sender(self, host, count, size, duration):
128 Send UDP datagrams to UDP listener
130 sender = udp.UdpSender(tuple(host), count, size, duration)
131 reactor.listenUDP(0, sender)
132 handle_id = self.__acquire_handle(sender)
135 def xmlrpc_get_udp_listener_results(self, handle):
137 Returns number of datagrams that were received
139 listener = self.__get_handle_resources(handle)
140 return listener.getResults()
142 def xmlrpc_get_udp_sender_results(self, handle):
144 Returns number of datagrams that were sent
146 sender = self.__get_handle_resources(handle)
147 return sender.getResults()
149 def xmlrpc_close_udp_listener(self, handle):
151 Releases UdpListener and all its resources
153 listener = self.__get_handle_resources(handle)
154 listener.transport.stopListening()
155 self.__delete_handle(handle)
158 def xmlrpc_close_udp_sender(self, handle):
160 Releases UdpSender and all its resources
162 sender = self.__get_handle_resources(handle)
163 sender.transport.stopListening()
164 self.__delete_handle(handle)
167 def xmlrpc_create_tcp_listener(self, port):
169 Creates a TcpListener that will accept connection from TcpSender
172 listener = tcp.TcpListenerFactory()
173 port = reactor.listenTCP(port, listener)
174 handle_id = self.__acquire_handle((listener, port))
176 except CannotListenError:
179 def xmlrpc_create_tcp_sender(self, his_ip, his_port, duration):
181 Creates a TcpSender that will connect to TcpListener
183 sender = tcp.TcpSenderFactory(duration)
184 connector = reactor.connectTCP(his_ip, his_port, sender)
185 handle_id = self.__acquire_handle((sender, connector))
188 def xmlrpc_get_tcp_listener_results(self, handle):
190 Returns number of bytes received
192 (listener, _) = self.__get_handle_resources(handle)
193 return listener.getResults()
195 def xmlrpc_get_tcp_sender_results(self, handle):
197 Returns number of bytes sent
199 (sender, _) = self.__get_handle_resources(handle)
200 return sender.getResults()
202 def xmlrpc_close_tcp_listener(self, handle):
204 Releases TcpListener and all its resources
207 (_, port) = self.__get_handle_resources(handle)
208 port.loseConnection()
209 self.__delete_handle(handle)
210 except exceptions.KeyError:
214 def xmlrpc_close_tcp_sender(self, handle):
216 Releases TcpSender and all its resources
219 (_, connector) = self.__get_handle_resources(handle)
220 connector.disconnect()
221 self.__delete_handle(handle)
222 except exceptions.KeyError:
226 def xmlrpc_create_test_bridge(self, bridge, iface):
228 This function creates a physical bridge from iface. It moves the
229 IP configuration from the physical interface to the bridge.
231 ret = vswitch.ovs_vsctl_add_bridge(bridge)
233 self.pbridges.add((bridge, iface))
234 util.interface_up(bridge)
235 (ip_addr, mask) = util.interface_get_ip(iface)
236 util.interface_assign_ip(bridge, ip_addr, mask)
237 util.move_routes(iface, bridge)
238 util.interface_assign_ip(iface, "0.0.0.0", "255.255.255.255")
239 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, iface)
241 self.ports.add(iface)
243 util.interface_assign_ip(iface, ip_addr, mask)
244 util.move_routes(bridge, iface)
245 vswitch.ovs_vsctl_del_bridge(bridge)
249 def xmlrpc_del_test_bridge(self, bridge, iface):
251 This function deletes the test bridge and moves its IP configuration
252 back to the physical interface.
254 ret = vswitch.ovs_vsctl_del_pbridge(bridge, iface)
255 self.pbridges.discard((bridge, iface))
258 def xmlrpc_get_iface_from_bridge(self, brname):
260 Tries to figure out physical interface from bridge.
262 return vswitch.ovs_get_physical_interface(brname)
264 def xmlrpc_create_bridge(self, brname):
266 Creates an OVS bridge.
268 ret = vswitch.ovs_vsctl_add_bridge(brname)
270 self.bridges.add(brname)
273 def xmlrpc_del_bridge(self, brname):
275 Deletes an OVS bridge.
277 ret = vswitch.ovs_vsctl_del_bridge(brname)
279 self.bridges.discard(brname)
282 def xmlrpc_is_ovs_bridge(self, bridge):
284 This function verifies whether given interface is an ovs bridge.
286 return vswitch.ovs_vsctl_is_ovs_bridge(bridge)
288 def xmlrpc_add_port_to_bridge(self, bridge, port):
290 Adds a port to the OVS bridge.
292 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, port)
297 def xmlrpc_del_port_from_bridge(self, port):
299 Removes a port from OVS bridge.
301 ret = vswitch.ovs_vsctl_del_port_from_bridge(port)
303 self.ports.discard(port)
306 def xmlrpc_ovs_vsctl_set(self, table, record, column, key, value):
308 This function allows to alter OVS database.
310 return vswitch.ovs_vsctl_set(table, record, column, key, value)
312 def xmlrpc_interface_up(self, iface):
314 This function brings up given interface.
316 return util.interface_up(iface)
318 def xmlrpc_interface_assign_ip(self, iface, ip_address, mask):
320 This function allows to assing ip address to the given interface.
322 return util.interface_assign_ip(iface, ip_address, mask)
324 def xmlrpc_get_interface(self, address):
326 Finds first interface that has given address
328 return util.get_interface(address)
330 def xmlrpc_get_interface_mtu(self, iface):
332 Returns MTU of the given interface
334 return util.get_interface_mtu(iface)
336 def xmlrpc_uname(self):
338 Return information about running kernel
342 def xmlrpc_get_driver(self, iface):
344 Returns driver version
346 return util.get_driver(iface)
348 def xmlrpc_get_interface_from_routing_decision(self, ip):
350 Returns driver version
352 return util.get_interface_from_routing_decision(ip)
355 def start_rpc_server(port):
357 This function creates a RPC server and adds it to the Twisted Reactor.
359 rpc_server = TestArena()
360 reactor.listenTCP(port, server.Site(rpc_server))
362 print("Starting RPC server\n")
364 # If this server was started from ovs-test client then we must flush
365 # STDOUT so that client would know that server is ready to accept
366 # XML RPC connections.