X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fnepi%2Fresources%2Flinux%2Fccn%2Ffibentry.py;h=8712708145bc1e7fef45a330748d712a7c6908db;hb=6285ca51026efb69642eea9dfc7c480e722d84a9;hp=c6698586815690fb033e387571d3096b533bdd21;hpb=92372be9a67510ff8796cb063b9a14e5b8c9d828;p=nepi.git diff --git a/src/nepi/resources/linux/ccn/fibentry.py b/src/nepi/resources/linux/ccn/fibentry.py index c6698586..87127081 100644 --- a/src/nepi/resources/linux/ccn/fibentry.py +++ b/src/nepi/resources/linux/ccn/fibentry.py @@ -3,9 +3,8 @@ # 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 @@ -21,26 +20,28 @@ from nepi.execution.attribute import Attribute, Flags, Types from nepi.execution.trace import Trace, TraceAttr from nepi.execution.resource import clsinit_copy, ResourceState, \ ResourceAction -from nepi.resources.linux.ccn.ccnapplication import LinuxCCNApplication +from nepi.resources.linux.application import LinuxApplication +from nepi.resources.linux.ccn.ccnd import LinuxCCND from nepi.util.timefuncs import tnow import os +import socket +import time -reschedule_delay = "0.5s" # TODO: Add rest of options for ccndc!!! # Implement ENTRY DELETE!! @clsinit_copy -class LinuxFIBEntry(LinuxCCNApplication): - _rtype = "LinuxFIBEntry" +class LinuxFIBEntry(LinuxApplication): + _rtype = "linux::FIBEntry" @classmethod def _register_attributes(cls): uri = Attribute("uri", "URI prefix to match and route for this FIB entry", default = "ccnx:/", - flags = Flags.ExecReadOnly) + flags = Flags.Design) protocol = Attribute("protocol", "Transport protocol used in network connection to peer " @@ -48,61 +49,176 @@ class LinuxFIBEntry(LinuxCCNApplication): type = Types.Enumerate, default = "udp", allowed = ["udp", "tcp"], - flags = Flags.ExecReadOnly) + flags = Flags.Design) host = Attribute("host", - "Peer host used in network connection for this FIB entry. ", - flags = Flags.ExecReadOnly) + "Peer hostname used in network connection for this FIB entry. ", + flags = Flags.Design) port = Attribute("port", "Peer port address used in network connection to peer " "for this FIB entry.", - flags = Flags.ExecReadOnly) + flags = Flags.Design) + + ip = Attribute("ip", + "Peer host public IP used in network connection for this FIB entry. ", + flags = Flags.Design) cls._register_attribute(uri) cls._register_attribute(protocol) cls._register_attribute(host) cls._register_attribute(port) + cls._register_attribute(ip) + + @classmethod + def _register_traces(cls): + ping = Trace("ping", "Ping to the peer end") + mtr = Trace("mtr", "Mtr to the peer end") + traceroute = Trace("traceroute", "Tracerout to the peer end") + + cls._register_trace(ping) + cls._register_trace(mtr) + cls._register_trace(traceroute) def __init__(self, ec, guid): super(LinuxFIBEntry, self).__init__(ec, guid) self._home = "fib-%s" % self.guid + self._ping = None + self._traceroute = None + self._ccnd = None + + @property + def ccnd(self): + if not self._ccnd: + ccnd = self.get_connected(LinuxCCND.get_rtype()) + if ccnd: + self._ccnd = ccnd[0] + + return self._ccnd + + @property + def ping(self): + if not self._ping: + from nepi.resources.linux.ping import LinuxPing + ping = self.get_connected(LinuxPing.get_rtype()) + if ping: + self._ping = ping[0] + + return self._ping + + @property + def traceroute(self): + if not self._traceroute: + from nepi.resources.linux.traceroute import LinuxTraceroute + traceroute = self.get_connected(LinuxTraceroute.get_rtype()) + if traceroute: + self._traceroute = traceroute[0] + + return self._traceroute + + @property + def node(self): + if self.ccnd: return self.ccnd.node + return None + + def trace(self, name, attr = TraceAttr.ALL, block = 512, offset = 0): + if name == "ping": + if not self.ping: + return None + return self.ec.trace(self.ping.guid, "stdout", attr, block, offset) - def deploy(self): + if name == "traceroute": + if not self.traceroute: + return None + return self.ec.trace(self.traceroute.guid, "stdout", attr, block, offset) + + return super(LinuxFIBEntry, self).trace(name, attr, block, offset) + + def do_deploy(self): # Wait until associated ccnd is provisioned if not self.ccnd or self.ccnd.state < ResourceState.READY: # ccnr needs to wait until ccnd is deployed and running - self.ec.schedule(reschedule_delay, self.deploy) + self.ec.schedule(self.reschedule_delay, self.deploy) else: - command = self._start_command - env = self._environment + if not self.get("ip"): + host = self.get("host") + ip = socket.gethostbyname(host) + self.set("ip", ip) + + if not self.get("command"): + self.set("command", self._start_command) - self.set("command", command) - self.set("env", env) + if not self.get("env"): + self.set("env", self._environment) + + command = self.get("command") self.info("Deploying command '%s' " % command) - self.node.mkdir(self.app_home) - self.execute_command(command, env) + self.do_discover() + self.do_provision() + self.configure() + + self.set_ready() + + def upload_start_command(self): + command = self.get("command") + env = self.get("env") + + # We want to make sure the FIB entries are created + # before the experiment starts. + # Run the command as a bash script in the background, + # in the host ( but wait until the command has + # finished to continue ) + env = env and self.replace_paths(env) + command = self.replace_paths(command) - self.debug("----- READY ---- ") - self._ready_time = tnow() - self._state = ResourceState.READY + # ccndc seems to return exitcode OK even if a (dns) error + # occurred, so we need to account for this case here. + (out, err), proc = self.execute_command(command, + env, blocking = True) - def start(self): - if self._state in [ResourceState.READY, ResourceState.STARTED]: + if proc.poll(): + msg = "Failed to execute command" + self.error(msg, out, err) + raise RuntimeError(msg) + + def configure(self): + if self.trace_enabled("ping") and not self.ping: + self.info("Configuring PING trace") + ping = self.ec.register_resource("linux::Ping") + self.ec.set(ping, "printTimestamp", True) + self.ec.set(ping, "target", self.get("host")) + self.ec.set(ping, "earlyStart", True) + self.ec.register_connection(ping, self.node.guid) + self.ec.register_connection(ping, self.guid) + # schedule ping deploy + self.ec.deploy(guids=[ping], group = self.deployment_group) + + if self.trace_enabled("traceroute") and not self.traceroute: + self.info("Configuring TRACEROUTE trace") + traceroute = self.ec.register_resource("linux::Traceroute") + self.ec.set(traceroute, "printTimestamp", True) + self.ec.set(traceroute, "continuous", True) + self.ec.set(traceroute, "target", self.get("host")) + self.ec.set(traceroute, "earlyStart", True) + self.ec.register_connection(traceroute, self.node.guid) + self.ec.register_connection(traceroute, self.guid) + # schedule mtr deploy + self.ec.deploy(guids=[traceroute], group = self.deployment_group) + + def do_start(self): + if self.state == ResourceState.READY: command = self.get("command") self.info("Starting command '%s'" % command) - self._start_time = tnow() - self._state = ResourceState.STARTED + self.set_started() else: msg = " Failed to execute command '%s'" % command self.error(msg, out, err) - self._state = ResourceState.FAILED - raise RuntimeError, msg + raise RuntimeError(msg) - def stop(self): + def do_stop(self): command = self.get('command') env = self.get('env') @@ -110,27 +226,28 @@ class LinuxFIBEntry(LinuxCCNApplication): self.info("Stopping command '%s'" % command) command = self._stop_command - self.execute_command(command, env) + (out, err), proc = self.execute_command(command, env, + blocking = True) - self._stop_time = tnow() - self._state = ResourceState.STOPPED + self.set_stopped() - @property - def state(self): - return self._state + if err: + msg = " Failed to execute command '%s'" % command + self.error(msg, out, err) + raise RuntimeError(msg) @property def _start_command(self): uri = self.get("uri") or "" protocol = self.get("protocol") or "" - host = self.get("host") or "" + ip = self.get("ip") or "" port = self.get("port") or "" # add ccnx:/example.com/ udp 224.0.0.204 52428 return "ccndc add %(uri)s %(protocol)s %(host)s %(port)s" % ({ "uri" : uri, "protocol": protocol, - "host": host, + "host": ip, "port": port }) @@ -138,17 +255,21 @@ class LinuxFIBEntry(LinuxCCNApplication): def _stop_command(self): uri = self.get("uri") or "" protocol = self.get("protocol") or "" - host = self.get("host") or "" + ip = self.get("ip") or "" port = self.get("port") or "" # add ccnx:/example.com/ udp 224.0.0.204 52428 return "ccndc del %(uri)s %(protocol)s %(host)s %(port)s" % ({ "uri" : uri, "protocol": protocol, - "host": host, + "host": ip, "port": port }) + @property + def _environment(self): + return self.ccnd.path + def valid_connection(self, guid): # TODO: Validate! return True