Adding NS3 FDNetDevice RM
[nepi.git] / src / nepi / execution / attribute.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 ### Attribute Types
21 class Types:
22     """ Allowed types for the Attribute value
23     """
24     String  = "STRING"
25     Bool    = "BOOL"
26     Enumerate    = "ENUM"
27     Double  = "DOUBLE"
28     Integer = "INTEGER"
29
30 ### Attribute Flags
31 class Flags:
32     """ Flags to characterize the scope of an Attribute
33     """
34     # Attribute value can not be read (it is hidden to the user) 
35     NoRead    = 1 # 1
36     
37     # Attribute value can not be modified (it is not editable by the user)
38     NoWrite   = 1 << 1 # 2
39     
40     # Attribute value can be modified only before deployment
41     Design  = 1 << 2 # 4
42
43     # Attribute value will be used at deployment time for initial configuration
44     Construct    = 1 << 3 #  8
45
46     # Attribute provides credentials to access resources
47     Credential  = 1 << 4  | Design # 16 + 4
48
49     # Attribute is a filter used to discover resources
50     Filter  = 1 << 5 | Design # 32 + 4
51
52     # Attribute Flag is reserved for internal RM usage (i.e. should be 
53     # transparent to the user)
54     Reserved  = 1 << 6 # 64
55
56     # Attribute global is set to all resources of rtype
57     Global  = 1 << 7 # 128
58
59
60 class Attribute(object):
61     """ An Attribute exposes a configuration parameter of a resource
62     """
63
64     def __init__(self, name, help, type = Types.String,
65             flags = None, default = None, allowed = None,
66             range = None, set_hook = None):
67         """
68         :param name: Name of the Attribute
69         :type name: str
70
71         :param help: Description of the Attribute
72         :type help: str
73         
74         :param type: The type expected for the Attribute value.
75                      Should be one of Attribute.Types
76         :type type: str
77
78         :param flags: Defines Attribute behavior (i.e. whether it is read-only,
79                 read and write, etc). This parameter must take its values from
80                 Attribute.Flags. Flags values can be bitwised
81         :type flags: hex
82
83         :param default: Default value for the Attribute
84         :type default: Depends on the type of Attribute
85         
86         :param allowed: List of values that the Attribute can take. 
87                 This parameter is only meaningful for Enumerate type Attributes
88         :type allowed: list
89         
90         :param range: (max, min) tuple with range of possible values for
91                 Attributes.
92                 This parameter is only meaningful for Integer or Double type
93                 Attributes
94         :type range: (int, int) or (float, float)
95         
96         :param set_hook: Function that will be executed whenever a new 
97                 value is set for the Attribute.
98         :type set_hook: function
99
100     """
101         self._name = name
102         self._help = help
103         self._type = type
104         self._flags = flags or 0
105         self._allowed = allowed
106         self._range = range
107         self._default = self._value = default
108         # callback to be invoked upon changing the 
109         # attribute value
110         self.set_hook = set_hook
111
112     @property
113     def name(self):
114         """ Returns the name of the Attribute """
115         return self._name
116
117     @property
118     def default(self):
119         """ Returns the default value of the Attribute """
120         return self._default
121
122     @property
123     def type(self):
124         """ Returns the type of the Attribute """
125         return self._type
126
127     @property
128     def help(self):
129         """ Returns the description of the Attribute """
130         return self._help
131
132     @property
133     def flags(self):
134         """ Returns the flags of the Attribute """
135         return self._flags
136
137     @property
138     def allowed(self):
139         """ Returns the set of allowed values for the Attribute """
140         return self._allowed
141
142     @property
143     def range(self):
144         """ Returns the range of allowed numerical values for the Attribute """
145         return self._range
146
147     def has_flag(self, flag):
148         """ Returns True if the Attribute has the flag 'flag'
149
150         :param flag: Flag to be checked
151         :type flag: Flags
152         """
153         return (self._flags & flag) == flag
154
155     def get_value(self):
156         """ Returns the value of the Attribute """
157         return self._value
158
159     def set_value(self, value):
160         """ Configure a new value for the Attribute """
161         valid = True
162
163         if self.type == Types.Enumerate:
164             valid = value in self._allowed
165
166         if self.type in [Types.Double, Types.Integer] and self.range:
167             (min, max) = self.range
168
169             value = float(value)
170
171             valid = (value >= min and value <= max) 
172         
173         valid = valid and self.is_valid_value(value)
174
175         if valid: 
176             if self.set_hook:
177                 # Hook receives old value, new value
178                 value = self.set_hook(self._value, value)
179
180             self._value = value
181         else:
182             raise ValueError("Invalid value %s for attribute %s" %
183                     (str(value), self.name))
184
185     value = property(get_value, set_value)
186
187     def is_valid_value(self, value):
188         """ Attribute subclasses will override this method to add 
189         adequate validation"""
190         return True
191
192     @property
193     def has_changed(self):
194         """ Returns True if the value has changed from the default """
195         return self.value != self.default
196