from nepi.execution.attribute import Attribute, Flags, Types
from nepi.execution.resource import ResourceManager, clsinit_copy, \
- ResourceState, reschedule_delay
+ ResourceState
from nepi.resources.linux import rpmfuncs, debfuncs
from nepi.util import sshfuncs, execfuncs
from nepi.util.sshfuncs import ProcStatus
import os
import random
import re
+import socket
import tempfile
import time
import threading
source compilation, file download, etc)
"""
- _rtype = "LinuxNode"
+ _rtype = "linux::Node"
_help = "Controls Linux host machines ( either localhost or a host " \
"that can be accessed using a SSH key)"
- _backend_type = "linux"
+ _platform = "linux"
@classmethod
def _register_attributes(cls):
gateway = Attribute("gateway", "Hostname of the gateway machine",
flags = Flags.Design)
+ ip = Attribute("ip", "Linux host public IP address. "
+ "Must not be modified by the user unless hostname is 'localhost'",
+ flags = Flags.Design)
+
cls._register_attribute(hostname)
cls._register_attribute(username)
cls._register_attribute(port)
cls._register_attribute(tear_down)
cls._register_attribute(gateway_user)
cls._register_attribute(gateway)
+ cls._register_attribute(ip)
def __init__(self, ec, guid):
super(LinuxNode, self).__init__(ec, guid)
home = os.path.join(self._home_dir, home)
return home
+ @property
+ def nepi_home(self):
+ return os.path.join(self.home_dir, ".nepi")
+
@property
def usr_dir(self):
- return os.path.join(self.home_dir, "nepi-usr")
+ return os.path.join(self.nepi_home, "nepi-usr")
@property
def lib_dir(self):
@property
def exp_dir(self):
- return os.path.join(self.home_dir, "nepi-exp")
+ return os.path.join(self.nepi_home, "nepi-exp")
@property
def exp_home(self):
if self._os:
return self._os
- if self.get("hostname") not in ["localhost", "127.0.0.1"] and \
- not self.get("username"):
+ if not self.localhost and not self.get("username"):
msg = "Can't resolve OS, insufficient data "
self.error(msg)
raise RuntimeError, msg
@property
def localhost(self):
- return self.get("hostname") in ['localhost', '127.0.0.7', '::1']
+ return self.get("hostname") in ['localhost', '127.0.0.1', '::1']
def do_provision(self):
# check if host is alive
if self.get("cleanExperiment"):
self.clean_experiment()
- # Create shared directory structure
- self.mkdir(self.lib_dir)
- self.mkdir(self.bin_dir)
- self.mkdir(self.src_dir)
- self.mkdir(self.share_dir)
+ # Create shared directory structure and node home directory
+ paths = [self.lib_dir,
+ self.bin_dir,
+ self.src_dir,
+ self.share_dir,
+ self.node_home]
+
+ self.mkdir(paths)
+
+ # Get Public IP address if possible
+ if not self.get("ip"):
+ ip = None
+
+ if self.localhost:
+ ip = socket.gethostbyname(socket.gethostname())
+ else:
+ try:
+ ip = socket.gethostbyname(self.get("hostname"))
+ except:
+ msg = "DNS can not resolve hostname %s" % self.get("hostname")
+ self.debug(msg)
- # Create experiment node home directory
- self.mkdir(self.node_home)
+ self.set("ip", ip)
super(LinuxNode, self).do_provision()
ifaces = self.get_connected(LinuxInterface.get_rtype())
for iface in ifaces:
if iface.state < ResourceState.READY:
- self.ec.schedule(reschedule_delay, self.deploy)
+ self.ec.schedule(self.reschedule_delay, self.deploy)
return
super(LinuxNode, self).do_deploy()
# Node needs to wait until all associated RMs are released
# before it can be released
if rm.state != ResourceState.RELEASED:
- self.ec.schedule(reschedule_delay, self.release)
+ self.ec.schedule(self.reschedule_delay, self.release)
return
tear_down = self.get("tearDown")
def clean_processes(self):
self.info("Cleaning up processes")
-
- if self.get("hostname") in ["localhost", "127.0.0.2"]:
+
+ if self.localhost:
return
if self.get("username") != 'root':
cmd = ("sudo -S killall tcpdump || /bin/true ; " +
- "sudo -S kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; " +
"sudo -S killall -u %s || /bin/true ; " % self.get("username"))
else:
if self.state >= ResourceState.READY:
pids_temp = dict()
ps_aux = "ps aux |awk '{print $2,$11}'"
(out, err), proc = self.execute(ps_aux)
- for line in out.strip().split("\n"):
- parts = line.strip().split(" ")
- pids_temp[parts[0]] = parts[1]
- kill_pids = set(pids_temp.items()) - set(pids.items())
- kill_pids = ' '.join(dict(kill_pids).keys())
-
- cmd = ("killall tcpdump || /bin/true ; " +
- "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; " +
- "kill %s || /bin/true ; " % kill_pids)
+ if len(out) != 0:
+ for line in out.strip().split("\n"):
+ parts = line.strip().split(" ")
+ pids_temp[parts[0]] = parts[1]
+ kill_pids = set(pids_temp.items()) - set(pids.items())
+ kill_pids = ' '.join(dict(kill_pids).keys())
+
+ cmd = ("killall tcpdump || /bin/true ; " +
+ "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; " +
+ "kill %s || /bin/true ; " % kill_pids)
+ else:
+ cmd = ("killall tcpdump || /bin/true ; " +
+ "kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; ")
else:
cmd = ("killall tcpdump || /bin/true ; " +
"kill $(ps aux | grep '[n]epi' | awk '{print $2}') || /bin/true ; ")
"""
self.info("Cleaning up home")
- cmd = "cd %s ; find . -maxdepth 1 \( -name 'nepi-usr' -o -name 'nepi-exp' \) -execdir rm -rf {} + " % (
+ cmd = "cd %s ; find . -maxdepth 1 -name \.nepi -execdir rm -rf {} + " % (
self.home_dir )
return self.execute(cmd, with_lock = True)
stdout = 'stdout',
stderr = 'stderr',
sudo = False,
- tty = False):
+ tty = False,
+ strict_host_checking = False):
self.debug("Running command '%s'" % command)
agent = True,
identity = self.get("identity"),
server_key = self.get("serverKey"),
- tty = tty
+ tty = tty,
+ strict_host_checking = strict_host_checking
)
return (out, err), proc
gw = self.get("gateway"),
agent = True,
identity = self.get("identity"),
- server_key = self.get("serverKey")
+ server_key = self.get("serverKey"),
+ strict_host_checking = False
)
return pidtuple
gw = self.get("gateway"),
agent = True,
identity = self.get("identity"),
- server_key = self.get("serverKey")
+ server_key = self.get("serverKey"),
+ strict_host_checking = False
)
return status
agent = True,
sudo = sudo,
identity = self.get("identity"),
- server_key = self.get("serverKey")
+ server_key = self.get("serverKey"),
+ strict_host_checking = False
)
return (out, err), proc
if err:
msg = " Failed to upload files - src: %s dst: %s" % (";".join(src), dst)
self.error(msg, out, err)
-
+
+ msg = "%s out: %s err: %s" % (msg, out, err)
if raise_on_error:
raise RuntimeError, msg
return (out, err), proc
- def mkdir(self, path, clean = False):
+ def mkdir(self, paths, clean = False):
+ """ Paths is either a single remote directory path to create,
+ or a list of directories to create.
+ """
if clean:
- self.rmdir(path)
+ self.rmdir(paths)
+
+ if isinstance(paths, str):
+ paths = [paths]
- return self.execute("mkdir -p %s" % path, with_lock = True)
+ cmd = " ; ".join(map(lambda path: "mkdir -p %s" % path, paths))
- def rmdir(self, path):
- return self.execute("rm -rf %s" % path, with_lock = True)
+ return self.execute(cmd, with_lock = True)
+
+ def rmdir(self, paths):
+ """ Paths is either a single remote directory path to delete,
+ or a list of directories to delete.
+ """
+
+ if isinstance(paths, str):
+ paths = [paths]
+
+ cmd = " ; ".join(map(lambda path: "rm -rf %s" % path, paths))
+
+ return self.execute(cmd, with_lock = True)
def run_and_wait(self, command, home,
shfile = "cmd.sh",
""" Removes files that already exist in the Linux host from src list
"""
# construct a dictionary with { dst: src }
- dests = dict(map(
- lambda s: (os.path.join(dst, os.path.basename(s)), s ), s)) \
+ dests = dict(map(lambda s: (os.path.join(dst, os.path.basename(s)), s), src)) \
if len(src) > 1 else dict({dst: src[0]})
command = []