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
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
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 = six.moves.xmlrpc_client.Server("http://%s:%u/" %
113 return server1.get_my_address()
115 def xmlrpc_create_udp_listener(self, port):
117 Creates a UDP listener that will receive packets from UDP sender
120 listener = udp.UdpListener()
121 reactor.listenUDP(port, listener)
122 handle_id = self.__acquire_handle(listener)
123 except CannotListenError:
127 def xmlrpc_create_udp_sender(self, host, count, size, duration):
129 Send UDP datagrams to UDP listener
131 sender = udp.UdpSender(tuple(host), count, size, duration)
132 reactor.listenUDP(0, sender)
133 handle_id = self.__acquire_handle(sender)
136 def xmlrpc_get_udp_listener_results(self, handle):
138 Returns number of datagrams that were received
140 listener = self.__get_handle_resources(handle)
141 return listener.getResults()
143 def xmlrpc_get_udp_sender_results(self, handle):
145 Returns number of datagrams that were sent
147 sender = self.__get_handle_resources(handle)
148 return sender.getResults()
150 def xmlrpc_close_udp_listener(self, handle):
152 Releases UdpListener and all its resources
154 listener = self.__get_handle_resources(handle)
155 listener.transport.stopListening()
156 self.__delete_handle(handle)
159 def xmlrpc_close_udp_sender(self, handle):
161 Releases UdpSender and all its resources
163 sender = self.__get_handle_resources(handle)
164 sender.transport.stopListening()
165 self.__delete_handle(handle)
168 def xmlrpc_create_tcp_listener(self, port):
170 Creates a TcpListener that will accept connection from TcpSender
173 listener = tcp.TcpListenerFactory()
174 port = reactor.listenTCP(port, listener)
175 handle_id = self.__acquire_handle((listener, port))
177 except CannotListenError:
180 def xmlrpc_create_tcp_sender(self, his_ip, his_port, duration):
182 Creates a TcpSender that will connect to TcpListener
184 sender = tcp.TcpSenderFactory(duration)
185 connector = reactor.connectTCP(his_ip, his_port, sender)
186 handle_id = self.__acquire_handle((sender, connector))
189 def xmlrpc_get_tcp_listener_results(self, handle):
191 Returns number of bytes received
193 (listener, _) = self.__get_handle_resources(handle)
194 return listener.getResults()
196 def xmlrpc_get_tcp_sender_results(self, handle):
198 Returns number of bytes sent
200 (sender, _) = self.__get_handle_resources(handle)
201 return sender.getResults()
203 def xmlrpc_close_tcp_listener(self, handle):
205 Releases TcpListener and all its resources
208 (_, port) = self.__get_handle_resources(handle)
209 port.loseConnection()
210 self.__delete_handle(handle)
211 except exceptions.KeyError:
215 def xmlrpc_close_tcp_sender(self, handle):
217 Releases TcpSender and all its resources
220 (_, connector) = self.__get_handle_resources(handle)
221 connector.disconnect()
222 self.__delete_handle(handle)
223 except exceptions.KeyError:
227 def xmlrpc_create_test_bridge(self, bridge, iface):
229 This function creates a physical bridge from iface. It moves the
230 IP configuration from the physical interface to the bridge.
232 ret = vswitch.ovs_vsctl_add_bridge(bridge)
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)
242 self.ports.add(iface)
244 util.interface_assign_ip(iface, ip_addr, mask)
245 util.move_routes(bridge, iface)
246 vswitch.ovs_vsctl_del_bridge(bridge)
250 def xmlrpc_del_test_bridge(self, bridge, iface):
252 This function deletes the test bridge and moves its IP configuration
253 back to the physical interface.
255 ret = vswitch.ovs_vsctl_del_pbridge(bridge, iface)
256 self.pbridges.discard((bridge, iface))
259 def xmlrpc_get_iface_from_bridge(self, brname):
261 Tries to figure out physical interface from bridge.
263 return vswitch.ovs_get_physical_interface(brname)
265 def xmlrpc_create_bridge(self, brname):
267 Creates an OVS bridge.
269 ret = vswitch.ovs_vsctl_add_bridge(brname)
271 self.bridges.add(brname)
274 def xmlrpc_del_bridge(self, brname):
276 Deletes an OVS bridge.
278 ret = vswitch.ovs_vsctl_del_bridge(brname)
280 self.bridges.discard(brname)
283 def xmlrpc_is_ovs_bridge(self, bridge):
285 This function verifies whether given interface is an ovs bridge.
287 return vswitch.ovs_vsctl_is_ovs_bridge(bridge)
289 def xmlrpc_add_port_to_bridge(self, bridge, port):
291 Adds a port to the OVS bridge.
293 ret = vswitch.ovs_vsctl_add_port_to_bridge(bridge, port)
298 def xmlrpc_del_port_from_bridge(self, port):
300 Removes a port from OVS bridge.
302 ret = vswitch.ovs_vsctl_del_port_from_bridge(port)
304 self.ports.discard(port)
307 def xmlrpc_ovs_vsctl_set(self, table, record, column, key, value):
309 This function allows to alter OVS database.
311 return vswitch.ovs_vsctl_set(table, record, column, key, value)
313 def xmlrpc_interface_up(self, iface):
315 This function brings up given interface.
317 return util.interface_up(iface)
319 def xmlrpc_interface_assign_ip(self, iface, ip_address, mask):
321 This function allows to assing ip address to the given interface.
323 return util.interface_assign_ip(iface, ip_address, mask)
325 def xmlrpc_get_interface(self, address):
327 Finds first interface that has given address
329 return util.get_interface(address)
331 def xmlrpc_get_interface_mtu(self, iface):
333 Returns MTU of the given interface
335 return util.get_interface_mtu(iface)
337 def xmlrpc_uname(self):
339 Return information about running kernel
343 def xmlrpc_get_driver(self, iface):
345 Returns driver version
347 return util.get_driver(iface)
349 def xmlrpc_get_interface_from_routing_decision(self, ip):
351 Returns driver version
353 return util.get_interface_from_routing_decision(ip)
356 def start_rpc_server(port):
358 This function creates a RPC server and adds it to the Twisted Reactor.
360 rpc_server = TestArena()
361 reactor.listenTCP(port, server.Site(rpc_server))
363 print("Starting RPC server\n")
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.