2 # NEPI, a framework to manage network experiments
3 # Copyright (C) 2013 INRIA
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19 # Alexandros Kouvakas <alexandros.kouvakas@gmail.com>
21 from nepi.execution.attribute import Attribute, Flags, Types
22 from nepi.execution.resource import ResourceManager, clsinit_copy, ResourceState
23 from nepi.resources.planetlab.openvswitch.ovs import OVSWitch
24 from nepi.resources.planetlab.node import PlanetlabNode
25 from nepi.resources.linux.application import LinuxApplication
27 reschedule_delay = "0.5s"
30 class OVSPort(LinuxApplication):
32 .. class:: Class Args :
34 :param ec: The Experiment controller
35 :type ec: ExperimentController
36 :param guid: guid of the RM
38 :param creds: Credentials to communicate with the rm
44 _authorized_connections = ["OVSWitch", "Tunnel"]
47 def _register_attributes(cls):
48 """ Register the attributes of OVSPort RM
51 port_name = Attribute("port_name", "Name of the port",
52 flags = Flags.ExecReadOnly)
54 cls._register_attribute(port_name)
56 def __init__(self, ec, guid):
58 :param ec: The Experiment controller
59 :type ec: ExperimentController
60 :param guid: guid of the RM
64 super(OVSPort, self).__init__(ec, guid)
65 self._port_number = None
70 rm_list = self.get_connected(OVSWitch.rtype())
73 node = elt.get_connected(PlanetlabNode.rtype())
74 if node: return node[0]
79 ovswitch = self.get_connected(OVSWitch.rtype())
80 if ovswitch: return ovswitch[0]
84 def port_number(self):
85 return self._port_number
87 def valid_connection(self, guid):
91 # def valid_connection(self, guid):
92 # """ Check if the connection is available.
94 # :param guid: Guid of the current RM
99 # rm = self.ec.get_resource(guid)
100 # if rm.rtype() in self._authorized_connections:
101 # msg = "Connection between %s %s and %s %s accepted" % (self.rtype(), self._guid, rm.rtype(), guid)
104 # msg = "Connection between %s %s and %s %s refused" % (self.rtype(), self._guid, rm.rtype(), guid)
107 def get_host_ip(self):
108 """ Get the hostname of the node that
109 the port belongs to. We use it for tunnel.
111 get_host_ip = self.node
113 msg = "info_list is empty"
115 raise RuntimeError, msg
117 self.port_info.append(get_host_ip.get('hostname'))
118 self.port_info.append(socket.gethostbyname(self.port_info[0]))
120 def create_port(self):
121 """ Create the desired port
123 port_name = self.get('port_name')
124 if not (port_name or self.ovswitch):
125 msg = "The rm_list is empty or the port name is not assigned\n Failed to create port"
127 self.debug("ovswitch_list = %s and port_name = %s" % (self.ovswitch, port_name) )
128 raise AttributeError, msg
130 self.info("Create the port %s on switch %s" % (port_name, self.ovswitch.get('bridge_name')))
131 self.port_info.append(port_name)
132 self.port_info.append(self.ovswitch.get('virtual_ip_pref'))
133 cmd = "sliver-ovs create-port %s %s" % (self.ovswitch.get('bridge_name'), port_name)
134 self.node.run(cmd, self.ovswitch.ovs_checks,
135 stderr = "stdout-%s" % port_name,
136 stdout = "stderr-%s" % port_name,
139 def get_local_end(self):
140 """ Get the local_endpoint of the port
142 msg = "Discovering the number of the port %s"\
143 % self.get('port_name')
146 command = "sliver-ovs get-local-endpoint %s"\
147 % self.get('port_name')
149 (out, err), proc = self.node.run_and_wait(command, self.ovswitch.ovs_checks,
150 shfile = "port_number-%s.sh" % self.get('port_name'),
151 pidfile = "port_number_pidfile-%s" % self.get('port_name'),
152 ecodefile = "port_number_exitcode-%s" % self.get('port_name'),
154 stdout = "stdout-%s" % self.get('port_name'),
155 stderr = "stderr-%s" % self.get('port_name'))
158 msg = "No assignment in attribute port_name"
160 self.debug("You are in the method get_local_end and the port_name = %s" % self.get('port_name'))
161 raise AttributeError, msg
162 self._port_number = None
163 self._port_number = int(out)
164 self.port_info.append(self._port_number)
165 self.info("The number of the %s is %s" % (self.get('port_name'), self._port_number))
167 def switch_connect_command(self, local_port_name,
168 remote_ip, remote_port_num):
169 """ Script for switch links
171 command = ["sliver-ovs"]
172 command.append("set-remote-endpoint ")
173 command.append("%s " % local_port_name)
174 command.append("%s " % remote_ip)
175 command.append("%s " % remote_port_num)
176 command = " ".join(command)
177 command = self.replace_paths(command)
181 """ Provision the ports.No meaning.
186 """ Discover the ports.No meaning
191 """ Wait until ovswitch is started
193 ovswitch = self.ovswitch
194 if not ovswitch or ovswitch.state < ResourceState.READY:
195 self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.ovswitch.state )
196 self.ec.schedule(reschedule_delay, self.deploy)
205 self.ovswitch.ovs_status()
206 self._state = ResourceState.READY
208 self._state = ResourceState.FAILED
212 """ Start the RM. It means nothing special for
218 """ Stop the RM. It means nothing special for
224 """ Release the port RM means delete the ports
226 # OVS needs to wait until all associated RMs are released
228 from nepi.resources.planetlab.openvswitch.tunnel import Tunnel
229 rm = self.get_connected(Tunnel.rtype())
230 if rm[0].state < ResourceState.FINISHED:
231 self.ec.schedule(reschedule_delay, self.release)
234 msg = "Deleting the port %s" % self.get('port_name')
236 cmd = "sliver-ovs del_port %s" % self.get('port_name')
237 (out, err), proc = self.node.run(cmd, self.ovswitch.ovs_checks,
242 self.error(msg, out, err)
243 raise RuntimeError, msg
245 self._state = ResourceState.RELEASED