# Copyright (C) 2013 INRIA
#
# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation;
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# Author: Alina Quereilhac <alina.quereilhac@inria.fr>
from nepi.execution.attribute import Attribute, Flags, Types
-from nepi.execution.resource import clsinit_copy, ResourceState, \
- reschedule_delay
+from nepi.execution.resource import clsinit_copy, ResourceState
from nepi.resources.linux.tunnel import LinuxTunnel
from nepi.util.sshfuncs import ProcStatus
from nepi.util.timefuncs import tnow, tdiffsec
@clsinit_copy
class LinuxUdpTunnel(LinuxTunnel):
- _rtype = "LinuxUdpTunnel"
+ _rtype = "linux::UdpTunnel"
_help = "Constructs a tunnel between two Linux endpoints using a UDP connection "
- _backend = "linux"
+ _platform = "linux"
@classmethod
def _register_attributes(cls):
self.endpoint2.node.get("hostname"),
msg)
+ def get_endpoints(self):
+ """ Returns the list of RM that are endpoints to the tunnel
+ """
+ connected = []
+ for guid in self.connections:
+ rm = self.ec.get_resource(guid)
+ if hasattr(rm, "initiate_udp_connection"):
+ connected.append(rm)
+ return connected
+
def initiate_connection(self, endpoint, remote_endpoint):
cipher = self.get("cipher")
cipher_key = self.get("cipherKey")
bwlimit = self.get("bwLimit")
txqueuelen = self.get("txQueueLen")
-
- # Return the command to execute to initiate the connection to the
- # other endpoint
+ connection_app_home = self.app_home(endpoint)
connection_run_home = self.run_home(endpoint)
- udp_connect_command = endpoint.udp_connect_command(
- remote_endpoint, connection_run_home,
- cipher, cipher_key, bwlimit, txqueuelen)
- # upload command to connect.sh script
- shfile = os.path.join(self.app_home(endpoint), "udp-connect.sh")
- endpoint.node.upload(udp_connect_command,
- shfile,
- text = True,
- overwrite = False)
-
- # invoke connect script
- cmd = "bash %s" % shfile
- (out, err), proc = endpoint.node.run(cmd, self.run_home(endpoint))
-
- # check if execution errors occurred
- msg = " Failed to connect endpoints "
-
- if proc.poll():
- self.error(msg, out, err)
- raise RuntimeError, msg
-
- # Wait for pid file to be generated
- pid, ppid = endpoint.node.wait_pid(self.run_home(endpoint))
-
- # If the process is not running, check for error information
- # on the remote machine
- if not pid or not ppid:
- (out, err), proc = endpoint.node.check_errors(self.run_home(endpoint))
- # Out is what was written in the stderr file
- if err:
- msg = " Failed to start command '%s' " % command
- self.error(msg, out, err)
- raise RuntimeError, msg
-
- # wait until port is written to file
- port = self.wait_local_port(endpoint)
-
- self._pids[endpoint] = (pid, ppid)
+ port = endpoint.initiate_udp_connection(
+ remote_endpoint,
+ connection_app_home,
+ connection_run_home,
+ cipher, cipher_key, bwlimit, txqueuelen)
return port
def establish_connection(self, endpoint, remote_endpoint, port):
- self.upload_remote_port(endpoint, port)
+ connection_app_home = self.app_home(endpoint)
+ connection_run_home = self.run_home(endpoint)
+
+ endpoint.establish_udp_connection(remote_endpoint,
+ connection_app_home,
+ connection_run_home,
+ port)
def verify_connection(self, endpoint, remote_endpoint):
- self.wait_result(endpoint)
+ connection_app_home = self.app_home(endpoint)
+ connection_run_home = self.run_home(endpoint)
- def terminate_connection(self, endpoint, remote_endpoint):
- pid, ppid = self._pids[endpoint]
+ endpoint.verify_connection(remote_endpoint,
+ connection_app_home,
+ connection_run_home)
- if pid and ppid:
- (out, err), proc = endpoint.node.kill(pid, ppid,
- sudo = True)
+ def terminate_connection(self, endpoint, remote_endpoint):
+ connection_app_home = self.app_home(endpoint)
+ connection_run_home = self.run_home(endpoint)
- # check if execution errors occurred
- if proc.poll() and err:
- msg = " Failed to STOP tunnel"
- self.error(msg, out, err)
- raise RuntimeError, msg
+ endpoint.terminate_connection(remote_endpoint,
+ connection_app_home,
+ connection_run_home)
def check_state_connection(self):
# Make sure the process is still running in background
# No execution errors occurred. Make sure the background
# process with the recorded pid is still running.
- pid1, ppid1 = self._pids[self.endpoint1]
- pid2, ppid2 = self._pids[self.endpoint2]
- status1 = self.endpoint1.node.status(pid1, ppid1)
- status2 = self.endpoint2.node.status(pid2, ppid2)
+ status1 = self.endpoint1.check_status()
+ status2 = self.endpoint2.check_status()
if status1 == ProcStatus.FINISHED and \
status2 == ProcStatus.FINISHED:
else:
self.set_stopped()
- def wait_local_port(self, endpoint):
- """ Waits until the local_port file for the endpoint is generated,
- and returns the port number
-
- """
- return self.wait_file(endpoint, "local_port")
-
- def wait_result(self, endpoint):
- """ Waits until the return code file for the endpoint is generated
-
- """
- return self.wait_file(endpoint, "ret_file")
-
- def wait_file(self, endpoint, filename):
- """ Waits until file on endpoint is generated """
- result = None
- delay = 1.0
-
- for i in xrange(20):
- (out, err), proc = endpoint.node.check_output(
- self.run_home(endpoint), filename)
-
- if out:
- result = out.strip()
- break
- else:
- time.sleep(delay)
- delay = delay * 1.5
- else:
- msg = "Couldn't retrieve %s" % filename
- self.error(msg, out, err)
- raise RuntimeError, msg
-
- return result
-
- def upload_remote_port(self, endpoint, port):
- # upload remote port number to file
- port = "%s\n" % port
- endpoint.node.upload(port,
- os.path.join(self.run_home(endpoint), "remote_port"),
- text = True,
- overwrite = False)
-