1 '''
2 Implements the base CFSNode class and a few inherited variants.
3
4 This file is part of RTSLib.
5 Copyright (c) 2011-2013 by Datera, Inc
6
7 Licensed under the Apache License, Version 2.0 (the "License"); you may
8 not use this file except in compliance with the License. You may obtain
9 a copy of the License at
10
11 http://www.apache.org/licenses/LICENSE-2.0
12
13 Unless required by applicable law or agreed to in writing, software
14 distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16 License for the specific language governing permissions and limitations
17 under the License.
18 '''
19
20 import os
21 import stat
22 from utils import fread, fwrite, RTSLibError, RTSLibNotInCFS
23
24
26
27
28 configfs_dir = '/sys/kernel/config/target'
29
30
31
34
37
39 '''
40 Creates the configFS node if it does not already exist, depending on
41 the mode.
42 any -> makes sure it exists, also works if the node already does exist
43 lookup -> make sure it does NOT exist
44 create -> create the node which must not exist beforehand
45 '''
46 if mode not in ['any', 'lookup', 'create']:
47 raise RTSLibError("Invalid mode: %s" % mode)
48 if self.exists and mode == 'create':
49 raise RTSLibError("This %s already exists in configFS."
50 % self.__class__.__name__)
51 elif not self.exists and mode == 'lookup':
52 raise RTSLibNotInCFS("No such %s in configfs: %s."
53 % (self.__class__.__name__, self.path))
54
55 if not self.exists:
56 try:
57 os.mkdir(self.path)
58 except:
59 raise RTSLibError("Could not create %s in configFS."
60 % self.__class__.__name__)
61
64
66 if not self.exists:
67 raise RTSLibNotInCFS("This %s does not exist in configFS."
68 % self.__class__.__name__)
69
71 '''
72 List files under a path depending on their owner's write permissions.
73 @param path: The path under which the files are expected to be. If the
74 path itself is not a directory, an empty list will be returned.
75 @type path: str
76 @param writable: If None (default), returns all parameters, if True,
77 returns read-write parameters, if False, returns just the read-only
78 parameters.
79 @type writable: bool or None
80 @return: List of file names filtered according to their write perms.
81 '''
82 if not os.path.isdir(path):
83 return []
84
85 if writable is None:
86 names = os.listdir(path)
87 elif writable:
88 names = [name for name in os.listdir(path)
89 if (os.stat("%s/%s" % (path, name))[stat.ST_MODE] \
90 & stat.S_IWUSR)]
91 else:
92 names = [os.path.basename(name) for name in os.listdir(path)
93 if not (os.stat("%s/%s" % (path, name))[stat.ST_MODE] \
94 & stat.S_IWUSR)]
95 names.sort()
96 return names
97
98
99
101 '''
102 @param writable: If None (default), returns all parameters, if True,
103 returns read-write parameters, if False, returns just the read-only
104 parameters.
105 @type writable: bool or None
106 @return: The list of existing RFC-3720 parameter names.
107 '''
108 self._check_self()
109 path = "%s/param" % self.path
110 return self._list_files(path, writable)
111
113 '''
114 @param writable: If None (default), returns all attributes, if True,
115 returns read-write attributes, if False, returns just the read-only
116 attributes.
117 @type writable: bool or None
118 @return: A list of existing attribute names as strings.
119 '''
120 self._check_self()
121 path = "%s/attrib" % self.path
122 return self._list_files(path, writable)
123
125 '''
126 Sets the value of a named attribute.
127 The attribute must exist in configFS.
128 @param attribute: The attribute's name. It is case-sensitive.
129 @type attribute: string
130 @param value: The attribute's value.
131 @type value: string
132 '''
133 self._check_self()
134 path = "%s/attrib/%s" % (self.path, str(attribute))
135 if not os.path.isfile(path):
136 raise RTSLibError("Cannot find attribute: %s."
137 % str(attribute))
138 else:
139 try:
140 fwrite(path, "%s" % str(value))
141 except Exception as e:
142 raise RTSLibError("Cannot set attribute %s: %s" % (attribute, e))
143
145 '''
146 @param attribute: The attribute's name. It is case-sensitive.
147 @return: The named attribute's value, as a string.
148 '''
149 self._check_self()
150 path = "%s/attrib/%s" % (self.path, str(attribute))
151 if not os.path.isfile(path):
152 raise RTSLibError("Cannot find attribute: %s."
153 % str(attribute))
154 else:
155 return fread(path)
156
158 '''
159 Sets the value of a named RFC-3720 parameter.
160 The parameter must exist in configFS.
161 @param parameter: The RFC-3720 parameter's name. It is case-sensitive.
162 @type parameter: string
163 @param value: The parameter's value.
164 @type value: string
165 '''
166 self._check_self()
167 path = "%s/param/%s" % (self.path, str(parameter))
168 if not os.path.isfile(path):
169 raise RTSLibError("Cannot find parameter: %s."
170 % str(parameter))
171 else:
172 try:
173 fwrite(path, "%s\n" % str(value))
174 except Exception as e:
175 raise RTSLibError("Cannot set attribute %s: %s" % (attribute, e))
176
178 '''
179 @param parameter: The RFC-3720 parameter's name. It is case-sensitive.
180 @type parameter: string
181 @return: The named parameter value as a string.
182 '''
183 self._check_self()
184 path = "%s/param/%s" % (self.path, str(parameter))
185 if not os.path.isfile(path):
186 raise RTSLibError("Cannot find RFC-3720 parameter: %s."
187 % str(parameter))
188 else:
189 return fread(path)
190
192 '''
193 If the underlying configFS object does not exist, this method does
194 nothing. If the underlying configFS object exists, this method attempts
195 to delete it.
196 '''
197 if self.exists:
198 os.rmdir(self.path)
199
200 path = property(_get_path,
201 doc="Get the configFS object path.")
202 exists = property(_exists,
203 doc="Is True as long as the underlying configFS object exists. " \
204 + "If the underlying configFS objects gets deleted " \
205 + "either by calling the delete() method, or by any " \
206 + "other means, it will be False.")
207
209 d = {}
210 attrs = {}
211 params = {}
212 for item in self.list_attributes(writable=True):
213 attrs[item] = int(self.get_attribute(item))
214 if attrs:
215 d['attributes'] = attrs
216 for item in self.list_parameters(writable=True):
217 params[item] = self.get_parameter(item)
218 if params:
219 d['parameters'] = params
220 return d
221
223 import doctest
224 doctest.testmod()
225
226 if __name__ == "__main__":
227 _test()
228