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