miscell cleanup and prettyfication in collector and application
[nepi.git] / nepi / resources / all / collector.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 version 2 as
7 #    published by the Free Software Foundation;
8 #
9 #    This program is distributed in the hope that it will be useful,
10 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #    GNU General Public License for more details.
13 #
14 #    You should have received a copy of the GNU General Public License
15 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 #
17 # Author: Alina Quereilhac <alina.quereilhac@inria.fr>
18
19 from nepi.execution.attribute import Attribute, Flags, Types
20 from nepi.execution.trace import Trace, TraceAttr
21 from nepi.execution.resource import ResourceManager, clsinit_copy, \
22         ResourceState, ResourceAction
23
24 import os
25 import tempfile
26
27 @clsinit_copy
28 class Collector(ResourceManager):
29     """ The collector entity is reponsible of collecting traces
30     of a same type associated to RMs into a local directory.
31
32     .. class:: Class Args :
33
34         :param ec: The Experiment controller
35         :type ec: ExperimentController
36         :param guid: guid of the RM
37         :type guid: int
38
39     """
40     _rtype = "Collector"
41     _help = "A Collector can be attached to a trace name on another " \
42         "ResourceManager and will retrieve and store the trace content " \
43         "in a local file at the end of the experiment"
44     _platform = "all"
45
46     @classmethod
47     def _register_attributes(cls):
48         cls._register_attribute(
49             Attribute("traceName", 
50                       "Name of the trace to be collected", 
51                       flags = Flags.Design))
52         cls._register_attribute(
53             Attribute("subDir", 
54                       "Sub directory to collect traces into", 
55                       flags = Flags.Design))
56         cls._register_attribute(
57             Attribute("rename", 
58                       "Name to give to the collected trace file", 
59                       flags = Flags.Design))
60
61     def __init__(self, ec, guid):
62         super(Collector, self).__init__(ec, guid)
63         self._store_path =  None
64
65     @property
66     def store_path(self):
67         return self._store_path
68    
69     def do_provision(self):
70         trace_name = self.get("traceName")
71         if not trace_name:
72             self.fail()
73             
74             msg = "No traceName was specified"
75             self.error(msg)
76             raise RuntimeError(msg)
77
78         self._store_path = self.ec.run_dir
79
80         subdir = self.get("subDir")
81         if subdir:
82             self._store_path = os.path.join(self.store_path, subdir)
83         
84         msg = "Creating local directory at {} to store {} traces "\
85               .format(self.store_path, trace_name)
86         self.info(msg)
87
88         try:
89             os.makedirs(self.store_path)
90         except OSError:
91             pass
92
93         super(Collector, self).do_provision()
94
95     def do_deploy(self):
96         self.do_discover()
97         self.do_provision()
98
99         super(Collector, self).do_deploy()
100
101     def do_release(self):
102         trace_name = self.get("traceName")
103         rename = self.get("rename") or trace_name
104
105         msg = "Collecting '{}' traces to local directory {}"\
106               .format(trace_name, self.store_path)
107         self.info(msg)
108
109         rms = self.get_connected()
110         for rm in rms:
111             fpath = os.path.join(self.store_path, "{}.{}"\
112                                  .format(rm.guid, rename))
113
114             try:
115                 result = self.ec.trace(rm.guid, trace_name)
116                 print("collector.do_release ..")
117                 with open(fpath, "w") as f:
118                     f.write(result)
119             except:
120                 import traceback
121                 err = traceback.format_exc()
122                 msg = "Couldn't retrieve trace {} for {} at {} "\
123                     .format(trace_name, rm.guid, fpath)
124                 self.error(msg, out = "", err = err)
125                 continue
126
127         super(Collector, self).do_release()
128
129     def valid_connection(self, guid):
130         # TODO: Validate!
131         return True
132