Adding PlanetLabGRETunnel
[nepi.git] / src / nepi / resources / linux / gretunnel.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.tunnel import LinuxTunnel
24 from nepi.util.sshfuncs import ProcStatus
25 from nepi.util.timefuncs import tnow, tdiffsec
26
27 import re
28 import socket
29 import time
30 import os
31
32 @clsinit_copy
33 class LinuxGRETunnel(LinuxTunnel):
34     _rtype = "LinuxGRETunnel"
35     _help = "Constructs a tunnel between two Linux endpoints using a UDP connection "
36     _backend = "linux"
37
38     def log_message(self, msg):
39         return " guid %d - GRE tunnel %s - %s - %s " % (self.guid, 
40                 self.endpoint1.node.get("hostname"), 
41                 self.endpoint2.node.get("hostname"), 
42                 msg)
43
44     def get_endpoints(self):
45         """ Returns the list of RM that are endpoints to the tunnel 
46         """
47         connected = []
48         for guid in self.connections:
49             rm = self.ec.get_resource(guid)
50             if hasattr(rm, "gre_connect_command"):
51                 connected.append(rm)
52         return connected
53
54     def initiate_connection(self, endpoint, remote_endpoint):
55         # Return the command to execute to initiate the connection to the
56         # other endpoint
57         connection_run_home = self.run_home(endpoint)
58         gre_connect_command = endpoint.gre_connect_command(
59                 remote_endpoint, connection_run_home)
60
61         # upload command to connect.sh script
62         shfile = os.path.join(self.app_home(endpoint), "gre-connect.sh")
63         endpoint.node.upload(gre_connect_command,
64                 shfile,
65                 text = True, 
66                 overwrite = False)
67
68         # invoke connect script
69         cmd = "bash %s" % shfile
70         (out, err), proc = endpoint.node.run(cmd, self.run_home(endpoint)) 
71              
72         # check if execution errors occurred
73         msg = " Failed to connect endpoints "
74         
75         if proc.poll() or err:
76             self.error(msg, out, err)
77             raise RuntimeError, msg
78     
79         # Wait for pid file to be generated
80         pid, ppid = endpoint.node.wait_pid(self.run_home(endpoint))
81         
82         # If the process is not running, check for error information
83         # on the remote machine
84         if not pid or not ppid:
85             (out, err), proc = endpoint.node.check_errors(self.run_home(endpoint))
86             # Out is what was written in the stderr file
87             if err:
88                 msg = " Failed to start command '%s' " % command
89                 self.error(msg, out, err)
90                 raise RuntimeError, msg
91         
92         # After creating the TAP, the pl-vif-create.py script
93         # will write the name of the TAP to a file. We wait until
94         # we can read the interface name from the file.
95         vif_name = endpoint.wait_vif_name()
96         endpoint.set("deviceName", vif_name) 
97
98         # Wait if name
99         return True
100
101     def establish_connection(self, endpoint, remote_endpoint, data):
102         pass
103
104     def verify_connection(self, endpoint, remote_endpoint):
105         remote_ip = socket.gethostbyname(remote_endpoint.node.get("hostname"))
106
107         command = "ping -c 4 %s" % remote_ip
108         (out, err), proc = endpoint.node.execute(command,
109                 blocking = True)
110
111         m = re.search("(\d+)% packet loss", str(out))
112         if not m or int(m.groups()[0]) == 100:
113              msg = " Erroro establishing GRE Tunnel"
114              self.error(msg, out, err)
115              raise RuntimeError, msg
116
117     def terminate_connection(self, endpoint, remote_endpoint):
118         pass
119
120     def check_state_connection(self):
121         pass
122
123     def valid_connection(self, guid):
124         # TODO: Validate!
125         return True
126