First CCN RMs working example for Linux
[nepi.git] / src / nepi / resources / linux / ccn / ccncontent.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.trace import Trace, TraceAttr
22 from nepi.execution.resource import ResourceManager, clsinit_copy, ResourceState, \
23     ResourceAction
24 from nepi.resources.linux.application import LinuxApplication
25 from nepi.resources.linux.ccn.ccnr import LinuxCCNR
26 from nepi.util.timefuncs import strfnow, strfdiff
27
28 import os
29
30 reschedule_delay = "0.5s"
31
32 @clsinit_copy
33 class LinuxCCNContent(LinuxApplication):
34     _rtype = "LinuxCCNContent"
35
36     @classmethod
37     def _register_attributes(cls):
38         content_name = Attribute("contentName",
39                 "The name of the content to publish (e.g. ccn:/VIDEO) ",
40                 flags = Flags.ExecReadOnly)
41
42         content = Attribute("content",
43                 "The content to publish. It can be a path to a file or plain text ",
44                 flags = Flags.ExecReadOnly)
45
46         cls._register_attribute(content_name)
47         cls._register_attribute(content)
48
49     def __init__(self, ec, guid):
50         super(LinuxCCNContent, self).__init__(ec, guid)
51         self._home = "content-%s" % self.guid
52         self._published = False
53         
54     @property
55     def ccnr(self):
56         ccnr = self.get_connected(LinuxCCNR.rtype())
57         if ccnr: return ccnr[0]
58         return None
59
60     @property
61     def node(self):
62         if self.ccnr: return self.ccnr.node
63         return None
64
65     def deploy(self):
66         if not self.get("command"):
67             self.set("command", self._default_command)
68         
69         if not self.get("env"):
70             self.set("env", self._default_environment)
71
72         if not self.get("stdin"):
73             # set content to stdin, so the content will be
74             # uploaded during provision
75             self.set("stdin", self.get("content"))
76
77         # Wait until associated ccnd is provisioned
78         ccnr = self.ccnr
79
80         if not ccnr or ccnr.state < ResourceState.READY:
81             # ccnr needs to wait until ccnd is deployed and running
82             self.ec.schedule(reschedule_delay, self.deploy)
83         else:
84             # Invoke the actual deployment
85             super(LinuxCCNContent, self).deploy()
86
87             # As soon as the ccnr is running we can push the content
88             # to the repository ( we don't want to lose time launching 
89             # writting the content to the repository later on )
90             if self._state == ResourceState.READY:
91                 self._start_in_background()
92                 self._published = True
93
94     def start(self):
95         # CCNR should already be started by now.
96         # Nothing to do but to set the state to STARTED
97         if self._published:
98             self._start_time = strfnow()
99             self._state = ResourceState.STARTED
100         else:
101             msg = "Failed to execute command '%s'" % command
102             self.error(msg, out, err)
103             self._state = ResourceState.FAILED
104             raise RuntimeError, msg
105
106     @property
107     def state(self):
108         state = super(LinuxCCNContent, self).state
109         if self._state in [ResourceState.FINISHED, ResourceState.FAILED]:
110             self._published = False
111
112         if self._state == ResourceState.READY:
113             # CCND is really deployed only when ccn daemon is running 
114             if not self._published:
115                 return ResourceState.PROVISIONED
116  
117         return self._state
118
119     @property
120     def _default_command(self):
121         return "ccnseqwriter -r %s " % self.get("contentName")
122
123     @property
124     def _default_environment(self):
125         env = "PATH=$PATH:${EXP_HOME}/ccnx/bin "
126         return env            
127         
128     def valid_connection(self, guid):
129         # TODO: Validate!
130         return True
131