from nepi.execution.attribute import Attribute, Flags, Types
from nepi.execution.trace import Trace, TraceAttr
-from nepi.execution.resource import ResourceManager, clsinit_copy, ResourceState
+from nepi.execution.resource import ResourceManager, clsinit_copy, \
+ ResourceState, reschedule_delay
from nepi.resources.linux.application import LinuxApplication
from nepi.resources.linux.node import OSType
+from nepi.util.timefuncs import tnow, tdiffsec
-from nepi.util.sshfuncs import ProcStatus
-from nepi.util.timefuncs import strfnow, strfdiff
import os
+# TODO: use ccndlogging to dynamically change the logging level
+
+
@clsinit_copy
class LinuxCCND(LinuxApplication):
_rtype = "LinuxCCND"
" 128 - face registration debugging \n"
" -1 - max logging \n"
" Or apply bitwise OR to these values to get combinations of them",
- flags = Flags.ExecReadOnly)
+ type = Types.Integer,
+ flags = Flags.Design)
port = Attribute("port", "Sets the CCN_LOCAL_PORT environmental variable. "
"Defaults to 9695 ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
sockname = Attribute("sockname",
"Sets the CCN_LOCAL_SCOKNAME environmental variable. "
"Defaults to /tmp/.ccnd.sock",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
capacity = Attribute("capacity",
"Sets the CCND_CAP environmental variable. "
"Capacity limit in terms of ContentObjects",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
mtu = Attribute("mtu", "Sets the CCND_MTU environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
data_pause = Attribute("dataPauseMicrosec",
"Sets the CCND_DATA_PAUSE_MICROSEC environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
default_stale = Attribute("defaultTimeToStale",
"Sets the CCND_DEFAULT_TIME_TO_STALE environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
max_stale = Attribute("maxTimeToStale",
"Sets the CCND_MAX_TIME_TO_STALE environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
max_rte = Attribute("maxRteMicrosec",
"Sets the CCND_MAX_RTE_MICROSEC environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
keystore = Attribute("keyStoreDirectory",
"Sets the CCND_KEYSTORE_DIRECTORY environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
listen_on = Attribute("listenOn",
"Sets the CCND_LISTEN_ON environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
autoreg = Attribute("autoreg",
"Sets the CCND_AUTOREG environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
prefix = Attribute("prefix",
"Sets the CCND_PREFIX environmental variable. ",
- flags = Flags.ExecReadOnly)
+ flags = Flags.Design)
cls._register_attribute(debug)
cls._register_attribute(port)
def __init__(self, ec, guid):
super(LinuxCCND, self).__init__(ec, guid)
- # Marks whether daemon is running
- self._running = False
+ self._home = "ccnd-%s" % self.guid
+ self._version = "ccnx"
- def deploy(self):
- if not self.get("command"):
- self.set("command", self._default_command)
-
- if not self.get("depends"):
- self.set("depends", self._default_dependencies)
+ @property
+ def version(self):
+ return self._version
+
+ @property
+ def path(self):
+ return "PATH=$PATH:${BIN}/%s/" % self.version
+
+ def do_deploy(self):
+ if not self.node or self.node.state < ResourceState.READY:
+ self.debug("---- RESCHEDULING DEPLOY ---- node state %s " % self.node.state )
+
+ # ccnd needs to wait until node is deployed and running
+ self.ec.schedule(reschedule_delay, self.deploy)
+ else:
+ if not self.get("command"):
+ self.set("command", self._start_command)
+
+ if not self.get("depends"):
+ self.set("depends", self._dependencies)
+
+ if not self.get("sources"):
+ self.set("sources", self._sources)
+
+ sources = self.get("sources")
+ source = sources.split(" ")[0]
+ basename = os.path.basename(source)
+ self._version = ( basename.strip().replace(".tar.gz", "")
+ .replace(".tar","")
+ .replace(".gz","")
+ .replace(".zip","") )
+
+ if not self.get("build"):
+ self.set("build", self._build)
+
+ if not self.get("install"):
+ self.set("install", self._install)
- if not self.get("sources"):
- self.set("sources", self._default_sources)
+ if not self.get("env"):
+ self.set("env", self._environment)
- if not self.get("build"):
- self.set("build", self._default_build)
+ command = self.get("command")
- if not self.get("install"):
- self.set("install", self._default_install)
+ self.info("Deploying command '%s' " % command)
- if not self.get("env"):
- self.set("env", self._default_environment)
+ self.do_discover()
+ self.do_provision()
- super(LinuxCCND, self).deploy()
+ self.set_ready()
- # As soon as the ccnd sources are deployed, we launch the
- # daemon ( we don't want to lose time launching the ccn
- # daemon later on )
- if self._state == ResourceState.READY:
- self._start_in_background()
- self._running = True
+ def upload_start_command(self):
+ command = self.get("command")
+ env = self.get("env")
- def start(self):
- # CCND should already be started by now.
- # Nothing to do but to set the state to STARTED
- if self._running:
- self._start_time = strfnow()
- self._state = ResourceState.STARTED
+ # We want to make sure the ccnd is running
+ # before the experiment starts.
+ # Run the command as a bash script in background,
+ # in the host ( but wait until the command has
+ # finished to continue )
+ env = self.replace_paths(env)
+ command = self.replace_paths(command)
+
+ shfile = os.path.join(self.app_home, "start.sh")
+ self.node.run_and_wait(command, self.run_home,
+ shfile = shfile,
+ overwrite = False,
+ env = env)
+
+ def do_start(self):
+ if self.state == ResourceState.READY:
+ command = self.get("command")
+ self.info("Starting command '%s'" % command)
+
+ self.set_started()
else:
msg = " Failed to execute command '%s'" % command
self.error(msg, out, err)
- self._state = ResourceState.FAILED
raise RuntimeError, msg
- def stop(self):
+ def do_stop(self):
command = self.get('command') or ''
- state = self.state
- if state == ResourceState.STARTED:
+ if self.state == ResourceState.STARTED:
self.info("Stopping command '%s'" % command)
command = "ccndstop"
env = env and self.replace_paths(env)
# Upload the command to a file, and execute asynchronously
- self.node.run_and_wait(command, self.app_home,
- shfile = "ccndstop.sh",
+ shfile = os.path.join(self.app_home, "stop.sh")
+ self.node.run_and_wait(command, self.run_home,
+ shfile = shfile,
+ overwrite = False,
env = env,
pidfile = "ccndstop_pidfile",
ecodefile = "ccndstop_exitcode",
stdout = "ccndstop_stdout",
stderr = "ccndstop_stderr")
-
- super(LinuxCCND, self).stop()
-
+ self.set_stopped()
+
@property
def state(self):
# First check if the ccnd has failed
- if self._running and strfdiff(strfnow(), self._last_state_check) > state_check_delay:
- state_check_delay = 0.5
- (out, err), proc = self._cndstatus()
+ state_check_delay = 0.5
+ if self._state == ResourceState.STARTED and \
+ tdiffsec(tnow(), self._last_state_check) > state_check_delay:
+ (out, err), proc = self._ccndstatus()
retcode = proc.poll()
if retcode == 1 and err.find("No such file or directory") > -1:
# ccnd is not running (socket not found)
- self._running = False
- self._state = ResourceState.FINISHED
+ self.set_stopped()
elif retcode:
# other errors ...
- self._running = False
- msg = " Failed to execute command '%s'" % command
+ msg = " Failed to execute command '%s'" % self.get("command")
self.error(msg, out, err)
- self._state = ResourceState.FAILED
-
- self._last_state_check = strfnow()
+ self.fail()
- if self._state == ResourceState.READY:
- # CCND is really deployed only when ccn daemon is running
- if not self._running:
- return ResourceState.PROVISIONED
+ self._last_state_check = tnow()
return self._state
- @property
def _ccndstatus(self):
env = self.get('env') or ""
environ = self.node.format_environment(env, inline = True)
- command = environ + "; ccndstatus"
+ command = environ + " ccndstatus"
command = self.replace_paths(command)
return self.node.execute(command)
@property
- def _default_command(self):
+ def _start_command(self):
return "ccndstart"
@property
- def _default_dependencies(self):
- if self.node.os in [ OSType.FEDORA_12 , OSType.FEDORA_14 ]:
+ def _dependencies(self):
+ if self.node.use_rpm:
return ( " autoconf openssl-devel expat-devel libpcap-devel "
" ecryptfs-utils-devel libxml2-devel automake gawk "
" gcc gcc-c++ git pcre-devel make ")
- elif self.node.os in [ OSType.UBUNTU , OSType.DEBIAN]:
+ elif self.node.use_deb:
return ( " autoconf libssl-dev libexpat-dev libpcap-dev "
" libecryptfs0 libxml2-utils automake gawk gcc g++ "
" git-core pkg-config libpcre3-dev make ")
return ""
@property
- def _default_sources(self):
- return "http://www.ccnx.org/releases/ccnx-0.7.1.tar.gz"
+ def _sources(self):
+ return "http://www.ccnx.org/releases/ccnx-0.8.1.tar.gz"
@property
- def _default_build(self):
+ def _build(self):
sources = self.get("sources").split(" ")[0]
sources = os.path.basename(sources)
return (
# Evaluate if ccnx binaries are already installed
" ( "
- " test -f ${EXP_HOME}/ccnx/bin/ccnd && "
- " echo 'sources found, nothing to do' "
+ " test -f ${BIN}/%(version)s/ccnd && "
+ " echo 'binaries found, nothing to do' "
" ) || ( "
# If not, untar and build
" ( "
- " mkdir -p ${SOURCES}/ccnx && "
- " tar xf ${SOURCES}/%(sources)s --strip-components=1 -C ${SOURCES}/ccnx "
+ " mkdir -p ${SRC}/%(version)s && "
+ " tar xf ${SRC}/%(sources)s --strip-components=1 -C ${SRC}/%(version)s "
" ) && "
- "cd ${SOURCES}/ccnx && "
+ "cd ${SRC}/%(version)s && "
# Just execute and silence warnings...
" ( ./configure && make ) "
- " )") % ({ 'sources': sources })
+ " )") % ({ 'sources': sources,
+ 'version': self.version
+ })
@property
- def _default_install(self):
+ def _install(self):
return (
# Evaluate if ccnx binaries are already installed
" ( "
- " test -f ${EXP_HOME}/ccnx/bin/ccnd && "
- " echo 'sources found, nothing to do' "
+ " test -f ${BIN}/%(version)s/ccnd && "
+ " echo 'binaries found, nothing to do' "
" ) || ( "
# If not, install
- " mkdir -p ${EXP_HOME}/ccnx/bin && "
- " cp -r ${SOURCES}/ccnx ${EXP_HOME}"
+ " mkdir -p ${BIN}/%(version)s && "
+ " mv ${SRC}/%(version)s/bin/* ${BIN}/%(version)s/ "
" )"
- )
+ ) % ({ 'version': self.version
+ })
@property
- def _default_environment(self):
+ def _environment(self):
envs = dict({
"debug": "CCND_DEBUG",
"port": "CCN_LOCAL_PORT",
"prefix" : "CCND_PREFIX",
})
- env = "PATH=$PATH:${EXP_HOME}/ccnx/bin "
- env += " ".join(map(lambda k: "%s=%s" % (envs.get(k), self.get(k)) \
+ env = self.path
+ env += " ".join(map(lambda k: "%s=%s" % (envs.get(k), str(self.get(k))) \
if self.get(k) else "", envs.keys()))
return env
-
+
def valid_connection(self, guid):
# TODO: Validate!
return True