ad0b83e95299065a2cfee1886503046f9337f655
[nepi.git] / src / nepi / resources / planetlab / vroute.py
1 #
2 #    NEPI, a framework to manage network experiments
3 #    Copyright (C) 2013 INRIA
4 #
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.
9 #
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.
14 #
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/>.
17 #
18 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
19
20 from nepi.execution.attribute import Attribute, Flags, Types
21 from nepi.execution.resource import clsinit_copy, ResourceState, \
22         reschedule_delay
23 from nepi.resources.linux.application import LinuxApplication
24 from nepi.resources.planetlab.node import PlanetlabNode
25 from nepi.resources.planetlab.tap import PlanetlabTap
26 from nepi.util.timefuncs import tnow, tdiffsec
27
28 import os
29 import time
30
31 PYTHON_VSYS_VERSION = "1.0"
32
33 @clsinit_copy
34 class PlanetlabVroute(LinuxApplication):
35     _rtype = "PlanetlabVroute"
36     _help = "Creates a Vroute on a PlanetLab host"
37     _backend = "planetlab"
38
39     @classmethod
40     def _register_attributes(cls):
41         action = Attribute("action", "Either add or del",
42               allowed = ["add", "del"],
43               flags = Flags.Design)
44
45         network = Attribute("network", "IPv4 Network Address",
46               flags = Flags.Design)
47
48         cls._register_attribute(action)
49         cls._register_attribute(network)
50
51     def __init__(self, ec, guid):
52         super(PlanetlabVroute, self).__init__(ec, guid)
53         self._home = "vroute-%s" % self.guid
54
55     @property
56     def tap(self):
57         tap = self.get_connected(PlanetlabTap.get_rtype())
58         if tap: return tap[0]
59         return None
60
61     @property
62     def node(self):
63         node = self.tap.get_connected(PlanetlabNode.get_rtype())
64         if node: return node[0]
65         return None
66
67     def upload_sources(self):
68         # upload vif-creation python script
69         pl_vroute = os.path.join(os.path.dirname(__file__), "scripts",
70                 "pl-vroute.py")
71
72         self.node.upload(pl_vroute,
73                 os.path.join(self.node.src_dir, "pl-vroute.py"),
74                 overwrite = False)
75
76         # upload stop.sh script
77         stop_command = self.replace_paths(self._stop_command)
78         self.node.upload(stop_command,
79                 os.path.join(self.app_home, "stop.sh"),
80                 text = True,
81                 # Overwrite file every time. 
82                 # The stop.sh has the path to the socket, wich should change
83                 # on every experiment run.
84                 overwrite = True)
85
86     def upload_start_command(self):
87         # Overwrite file every time. 
88         # The stop.sh has the path to the socket, wich should change
89         # on every experiment run.
90         super(PlanetlabVroute, self).upload_start_command(overwrite = True)
91
92         (out, err), proc = self.execute_command(self.get("command"), blocking = True)
93  
94     def do_deploy(self):
95         if not self.tap or self.tap.state < ResourceState.PROVISIONED:
96             self.ec.schedule(reschedule_delay, self.deploy)
97         else:
98             if not self.get("command"):
99                 self.set("command", self._start_command)
100
101             self.do_discover()
102             self.do_provision()
103
104             self.debug("----- READY ---- ")
105             self.set_ready()
106
107     def do_start(self):
108         if self.state == ResourceState.READY:
109             command = self.get("command")
110             self.info("Starting command '%s'" % command)
111
112             # Vroute started during deployment
113             self.set_started()
114         else:
115             msg = " Failed to execute command '%s'" % command
116             self.error(msg, out, err)
117             raise RuntimeError, msg
118
119     def do_stop(self):
120
121         command = self.get('command') or ''
122
123         if self.state == ResourceState.STARTED:
124             self.info("Stopping command '%s'" % self._stop_command)
125
126             command = "bash %s" % os.path.join(self.app_home, "stop.sh")
127             (out, err), proc = self.execute_command(command,
128                     blocking = True)
129
130             self.set_stopped()
131
132     def do_release(self):
133         # Node needs to wait until all associated RMs are released
134         # to be released
135         if not self.get("tearDown"):
136             self.set("tearDown", self._tear_down_command())
137
138         super(PlanetlabVroute, self).do_release()
139
140     def _tear_down_command(self):
141         if self.get("action") == "del":
142             return
143
144         return self._stop_command
145
146     @property
147     def _start_command(self):
148         command = ["sudo -S python ${SRC}/pl-vroute.py"]
149         command.append("-a %s" % self.get("action"))
150         command.append("-n %s" % self.get("network"))
151         command.append("-p %d" % self.tap.get("endpoint_prefix"))
152         command.append("-g %s" % self.tap.get("pointopoint"))
153         command.append("-f %s" % self.tap.get("deviceName"))
154         return " ".join(command)
155
156     @property
157     def _stop_command(self):
158         command = ["sudo -S python ${SRC}/pl-vroute.py"]
159         command.append("-a %s" % "del")
160         command.append("-n %s" % self.get("network"))
161         command.append("-p %d" % self.tap.get("endpoint_prefix"))
162         command.append("-g %s" % self.tap.get("pointopoint"))
163         command.append("-f %s" % self.tap.get("deviceName"))
164         return " ".join(command)
165
166     def valid_connection(self, guid):
167         # TODO: Validate!
168         return True
169