diff options
Diffstat (limited to 'scripts/lib/mic/3rdparty/pykickstart/base.py')
-rw-r--r-- | scripts/lib/mic/3rdparty/pykickstart/base.py | 466 |
1 files changed, 0 insertions, 466 deletions
diff --git a/scripts/lib/mic/3rdparty/pykickstart/base.py b/scripts/lib/mic/3rdparty/pykickstart/base.py deleted file mode 100644 index e6c8f56f9d..0000000000 --- a/scripts/lib/mic/3rdparty/pykickstart/base.py +++ /dev/null | |||
@@ -1,466 +0,0 @@ | |||
1 | # | ||
2 | # Chris Lumens <clumens@redhat.com> | ||
3 | # | ||
4 | # Copyright 2006, 2007, 2008 Red Hat, Inc. | ||
5 | # | ||
6 | # This copyrighted material is made available to anyone wishing to use, modify, | ||
7 | # copy, or redistribute it subject to the terms and conditions of the GNU | ||
8 | # General Public License v.2. This program is distributed in the hope that it | ||
9 | # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the | ||
10 | # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
11 | # See the GNU General Public License for more details. | ||
12 | # | ||
13 | # You should have received a copy of the GNU General Public License along with | ||
14 | # this program; if not, write to the Free Software Foundation, Inc., 51 | ||
15 | # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat | ||
16 | # trademarks that are incorporated in the source code or documentation are not | ||
17 | # subject to the GNU General Public License and may only be used or replicated | ||
18 | # with the express permission of Red Hat, Inc. | ||
19 | # | ||
20 | """ | ||
21 | Base classes for creating commands and syntax version object. | ||
22 | |||
23 | This module exports several important base classes: | ||
24 | |||
25 | BaseData - The base abstract class for all data objects. Data objects | ||
26 | are contained within a BaseHandler object. | ||
27 | |||
28 | BaseHandler - The base abstract class from which versioned kickstart | ||
29 | handler are derived. Subclasses of BaseHandler hold | ||
30 | BaseData and KickstartCommand objects. | ||
31 | |||
32 | DeprecatedCommand - An abstract subclass of KickstartCommand that should | ||
33 | be further subclassed by users of this module. When | ||
34 | a subclass is used, a warning message will be | ||
35 | printed. | ||
36 | |||
37 | KickstartCommand - The base abstract class for all kickstart commands. | ||
38 | Command objects are contained within a BaseHandler | ||
39 | object. | ||
40 | """ | ||
41 | import gettext | ||
42 | gettext.textdomain("pykickstart") | ||
43 | _ = lambda x: gettext.ldgettext("pykickstart", x) | ||
44 | |||
45 | import types | ||
46 | import warnings | ||
47 | from pykickstart.errors import * | ||
48 | from pykickstart.ko import * | ||
49 | from pykickstart.parser import Packages | ||
50 | from pykickstart.version import versionToString | ||
51 | |||
52 | ### | ||
53 | ### COMMANDS | ||
54 | ### | ||
55 | class KickstartCommand(KickstartObject): | ||
56 | """The base class for all kickstart commands. This is an abstract class.""" | ||
57 | removedKeywords = [] | ||
58 | removedAttrs = [] | ||
59 | |||
60 | def __init__(self, writePriority=0, *args, **kwargs): | ||
61 | """Create a new KickstartCommand instance. This method must be | ||
62 | provided by all subclasses, but subclasses must call | ||
63 | KickstartCommand.__init__ first. Instance attributes: | ||
64 | |||
65 | currentCmd -- The name of the command in the input file that | ||
66 | caused this handler to be run. | ||
67 | currentLine -- The current unprocessed line from the input file | ||
68 | that caused this handler to be run. | ||
69 | handler -- A reference to the BaseHandler subclass this | ||
70 | command is contained withing. This is needed to | ||
71 | allow referencing of Data objects. | ||
72 | lineno -- The current line number in the input file. | ||
73 | writePriority -- An integer specifying when this command should be | ||
74 | printed when iterating over all commands' __str__ | ||
75 | methods. The higher the number, the later this | ||
76 | command will be written. All commands with the | ||
77 | same priority will be written alphabetically. | ||
78 | """ | ||
79 | |||
80 | # We don't want people using this class by itself. | ||
81 | if self.__class__ is KickstartCommand: | ||
82 | raise TypeError, "KickstartCommand is an abstract class." | ||
83 | |||
84 | KickstartObject.__init__(self, *args, **kwargs) | ||
85 | |||
86 | self.writePriority = writePriority | ||
87 | |||
88 | # These will be set by the dispatcher. | ||
89 | self.currentCmd = "" | ||
90 | self.currentLine = "" | ||
91 | self.handler = None | ||
92 | self.lineno = 0 | ||
93 | |||
94 | # If a subclass provides a removedKeywords list, remove all the | ||
95 | # members from the kwargs list before we start processing it. This | ||
96 | # ensures that subclasses don't continue to recognize arguments that | ||
97 | # were removed. | ||
98 | for arg in filter(kwargs.has_key, self.removedKeywords): | ||
99 | kwargs.pop(arg) | ||
100 | |||
101 | def __call__(self, *args, **kwargs): | ||
102 | """Set multiple attributes on a subclass of KickstartCommand at once | ||
103 | via keyword arguments. Valid attributes are anything specified in | ||
104 | a subclass, but unknown attributes will be ignored. | ||
105 | """ | ||
106 | for (key, val) in kwargs.items(): | ||
107 | # Ignore setting attributes that were removed in a subclass, as | ||
108 | # if they were unknown attributes. | ||
109 | if key in self.removedAttrs: | ||
110 | continue | ||
111 | |||
112 | if hasattr(self, key): | ||
113 | setattr(self, key, val) | ||
114 | |||
115 | def __str__(self): | ||
116 | """Return a string formatted for output to a kickstart file. This | ||
117 | method must be provided by all subclasses. | ||
118 | """ | ||
119 | return KickstartObject.__str__(self) | ||
120 | |||
121 | def parse(self, args): | ||
122 | """Parse the list of args and set data on the KickstartCommand object. | ||
123 | This method must be provided by all subclasses. | ||
124 | """ | ||
125 | raise TypeError, "parse() not implemented for KickstartCommand" | ||
126 | |||
127 | def apply(self, instroot="/"): | ||
128 | """Write out the configuration related to the KickstartCommand object. | ||
129 | Subclasses which do not provide this method will not have their | ||
130 | configuration written out. | ||
131 | """ | ||
132 | return | ||
133 | |||
134 | def dataList(self): | ||
135 | """For commands that can occur multiple times in a single kickstart | ||
136 | file (like network, part, etc.), return the list that we should | ||
137 | append more data objects to. | ||
138 | """ | ||
139 | return None | ||
140 | |||
141 | def deleteRemovedAttrs(self): | ||
142 | """Remove all attributes from self that are given in the removedAttrs | ||
143 | list. This method should be called from __init__ in a subclass, | ||
144 | but only after the superclass's __init__ method has been called. | ||
145 | """ | ||
146 | for attr in filter(lambda k: hasattr(self, k), self.removedAttrs): | ||
147 | delattr(self, attr) | ||
148 | |||
149 | # Set the contents of the opts object (an instance of optparse.Values | ||
150 | # returned by parse_args) as attributes on the KickstartCommand object. | ||
151 | # It's useful to call this from KickstartCommand subclasses after parsing | ||
152 | # the arguments. | ||
153 | def _setToSelf(self, optParser, opts): | ||
154 | self._setToObj(optParser, opts, self) | ||
155 | |||
156 | # Sets the contents of the opts object (an instance of optparse.Values | ||
157 | # returned by parse_args) as attributes on the provided object obj. It's | ||
158 | # useful to call this from KickstartCommand subclasses that handle lists | ||
159 | # of objects (like partitions, network devices, etc.) and need to populate | ||
160 | # a Data object. | ||
161 | def _setToObj(self, optParser, opts, obj): | ||
162 | for key in filter (lambda k: getattr(opts, k) != None, optParser.keys()): | ||
163 | setattr(obj, key, getattr(opts, key)) | ||
164 | |||
165 | class DeprecatedCommand(KickstartCommand): | ||
166 | """Specify that a command is deprecated and no longer has any function. | ||
167 | Any command that is deprecated should be subclassed from this class, | ||
168 | only specifying an __init__ method that calls the superclass's __init__. | ||
169 | This is an abstract class. | ||
170 | """ | ||
171 | def __init__(self, writePriority=None, *args, **kwargs): | ||
172 | # We don't want people using this class by itself. | ||
173 | if self.__class__ is KickstartCommand: | ||
174 | raise TypeError, "DeprecatedCommand is an abstract class." | ||
175 | |||
176 | # Create a new DeprecatedCommand instance. | ||
177 | KickstartCommand.__init__(self, writePriority, *args, **kwargs) | ||
178 | |||
179 | def __str__(self): | ||
180 | """Placeholder since DeprecatedCommands don't work anymore.""" | ||
181 | return "" | ||
182 | |||
183 | def parse(self, args): | ||
184 | """Print a warning message if the command is seen in the input file.""" | ||
185 | mapping = {"lineno": self.lineno, "cmd": self.currentCmd} | ||
186 | warnings.warn(_("Ignoring deprecated command on line %(lineno)s: The %(cmd)s command has been deprecated and no longer has any effect. It may be removed from future releases, which will result in a fatal error from kickstart. Please modify your kickstart file to remove this command.") % mapping, DeprecationWarning) | ||
187 | |||
188 | |||
189 | ### | ||
190 | ### HANDLERS | ||
191 | ### | ||
192 | class BaseHandler(KickstartObject): | ||
193 | """Each version of kickstart syntax is provided by a subclass of this | ||
194 | class. These subclasses are what users will interact with for parsing, | ||
195 | extracting data, and writing out kickstart files. This is an abstract | ||
196 | class. | ||
197 | |||
198 | version -- The version this syntax handler supports. This is set by | ||
199 | a class attribute of a BaseHandler subclass and is used to | ||
200 | set up the command dict. It is for read-only use. | ||
201 | """ | ||
202 | version = None | ||
203 | |||
204 | def __init__(self, mapping=None, dataMapping=None, commandUpdates=None, | ||
205 | dataUpdates=None, *args, **kwargs): | ||
206 | """Create a new BaseHandler instance. This method must be provided by | ||
207 | all subclasses, but subclasses must call BaseHandler.__init__ first. | ||
208 | |||
209 | mapping -- A custom map from command strings to classes, | ||
210 | useful when creating your own handler with | ||
211 | special command objects. It is otherwise unused | ||
212 | and rarely needed. If you give this argument, | ||
213 | the mapping takes the place of the default one | ||
214 | and so must include all commands you want | ||
215 | recognized. | ||
216 | dataMapping -- This is the same as mapping, but for data | ||
217 | objects. All the same comments apply. | ||
218 | commandUpdates -- This is similar to mapping, but does not take | ||
219 | the place of the defaults entirely. Instead, | ||
220 | this mapping is applied after the defaults and | ||
221 | updates it with just the commands you want to | ||
222 | modify. | ||
223 | dataUpdates -- This is the same as commandUpdates, but for | ||
224 | data objects. | ||
225 | |||
226 | |||
227 | Instance attributes: | ||
228 | |||
229 | commands -- A mapping from a string command to a KickstartCommand | ||
230 | subclass object that handles it. Multiple strings can | ||
231 | map to the same object, but only one instance of the | ||
232 | command object should ever exist. Most users should | ||
233 | never have to deal with this directly, as it is | ||
234 | manipulated internally and called through dispatcher. | ||
235 | currentLine -- The current unprocessed line from the input file | ||
236 | that caused this handler to be run. | ||
237 | packages -- An instance of pykickstart.parser.Packages which | ||
238 | describes the packages section of the input file. | ||
239 | platform -- A string describing the hardware platform, which is | ||
240 | needed only by system-config-kickstart. | ||
241 | scripts -- A list of pykickstart.parser.Script instances, which is | ||
242 | populated by KickstartParser.addScript and describes the | ||
243 | %pre/%post/%traceback script section of the input file. | ||
244 | """ | ||
245 | |||
246 | # We don't want people using this class by itself. | ||
247 | if self.__class__ is BaseHandler: | ||
248 | raise TypeError, "BaseHandler is an abstract class." | ||
249 | |||
250 | KickstartObject.__init__(self, *args, **kwargs) | ||
251 | |||
252 | # This isn't really a good place for these, but it's better than | ||
253 | # everything else I can think of. | ||
254 | self.scripts = [] | ||
255 | self.packages = Packages() | ||
256 | self.platform = "" | ||
257 | |||
258 | # These will be set by the dispatcher. | ||
259 | self.commands = {} | ||
260 | self.currentLine = 0 | ||
261 | |||
262 | # A dict keyed by an integer priority number, with each value being a | ||
263 | # list of KickstartCommand subclasses. This dict is maintained by | ||
264 | # registerCommand and used in __str__. No one else should be touching | ||
265 | # it. | ||
266 | self._writeOrder = {} | ||
267 | |||
268 | self._registerCommands(mapping, dataMapping, commandUpdates, dataUpdates) | ||
269 | |||
270 | def __str__(self): | ||
271 | """Return a string formatted for output to a kickstart file.""" | ||
272 | retval = "" | ||
273 | |||
274 | if self.platform != "": | ||
275 | retval += "#platform=%s\n" % self.platform | ||
276 | |||
277 | retval += "#version=%s\n" % versionToString(self.version) | ||
278 | |||
279 | lst = self._writeOrder.keys() | ||
280 | lst.sort() | ||
281 | |||
282 | for prio in lst: | ||
283 | for obj in self._writeOrder[prio]: | ||
284 | retval += obj.__str__() | ||
285 | |||
286 | for script in self.scripts: | ||
287 | retval += script.__str__() | ||
288 | |||
289 | retval += self.packages.__str__() | ||
290 | |||
291 | return retval | ||
292 | |||
293 | def _insertSorted(self, lst, obj): | ||
294 | length = len(lst) | ||
295 | i = 0 | ||
296 | |||
297 | while i < length: | ||
298 | # If the two classes have the same name, it's because we are | ||
299 | # overriding an existing class with one from a later kickstart | ||
300 | # version, so remove the old one in favor of the new one. | ||
301 | if obj.__class__.__name__ > lst[i].__class__.__name__: | ||
302 | i += 1 | ||
303 | elif obj.__class__.__name__ == lst[i].__class__.__name__: | ||
304 | lst[i] = obj | ||
305 | return | ||
306 | elif obj.__class__.__name__ < lst[i].__class__.__name__: | ||
307 | break | ||
308 | |||
309 | if i >= length: | ||
310 | lst.append(obj) | ||
311 | else: | ||
312 | lst.insert(i, obj) | ||
313 | |||
314 | def _setCommand(self, cmdObj): | ||
315 | # Add an attribute on this version object. We need this to provide a | ||
316 | # way for clients to access the command objects. We also need to strip | ||
317 | # off the version part from the front of the name. | ||
318 | if cmdObj.__class__.__name__.find("_") != -1: | ||
319 | name = unicode(cmdObj.__class__.__name__.split("_", 1)[1]) | ||
320 | else: | ||
321 | name = unicode(cmdObj.__class__.__name__).lower() | ||
322 | |||
323 | setattr(self, name.lower(), cmdObj) | ||
324 | |||
325 | # Also, add the object into the _writeOrder dict in the right place. | ||
326 | if cmdObj.writePriority is not None: | ||
327 | if self._writeOrder.has_key(cmdObj.writePriority): | ||
328 | self._insertSorted(self._writeOrder[cmdObj.writePriority], cmdObj) | ||
329 | else: | ||
330 | self._writeOrder[cmdObj.writePriority] = [cmdObj] | ||
331 | |||
332 | def _registerCommands(self, mapping=None, dataMapping=None, commandUpdates=None, | ||
333 | dataUpdates=None): | ||
334 | if mapping == {} or mapping == None: | ||
335 | from pykickstart.handlers.control import commandMap | ||
336 | cMap = commandMap[self.version] | ||
337 | else: | ||
338 | cMap = mapping | ||
339 | |||
340 | if dataMapping == {} or dataMapping == None: | ||
341 | from pykickstart.handlers.control import dataMap | ||
342 | dMap = dataMap[self.version] | ||
343 | else: | ||
344 | dMap = dataMapping | ||
345 | |||
346 | if type(commandUpdates) == types.DictType: | ||
347 | cMap.update(commandUpdates) | ||
348 | |||
349 | if type(dataUpdates) == types.DictType: | ||
350 | dMap.update(dataUpdates) | ||
351 | |||
352 | for (cmdName, cmdClass) in cMap.iteritems(): | ||
353 | # First make sure we haven't instantiated this command handler | ||
354 | # already. If we have, we just need to make another mapping to | ||
355 | # it in self.commands. | ||
356 | cmdObj = None | ||
357 | |||
358 | for (key, val) in self.commands.iteritems(): | ||
359 | if val.__class__.__name__ == cmdClass.__name__: | ||
360 | cmdObj = val | ||
361 | break | ||
362 | |||
363 | # If we didn't find an instance in self.commands, create one now. | ||
364 | if cmdObj == None: | ||
365 | cmdObj = cmdClass() | ||
366 | self._setCommand(cmdObj) | ||
367 | |||
368 | # Finally, add the mapping to the commands dict. | ||
369 | self.commands[cmdName] = cmdObj | ||
370 | self.commands[cmdName].handler = self | ||
371 | |||
372 | # We also need to create attributes for the various data objects. | ||
373 | # No checks here because dMap is a bijection. At least, that's what | ||
374 | # the comment says. Hope no one screws that up. | ||
375 | for (dataName, dataClass) in dMap.iteritems(): | ||
376 | setattr(self, dataName, dataClass) | ||
377 | |||
378 | def dispatcher(self, args, lineno): | ||
379 | """Call the appropriate KickstartCommand handler for the current line | ||
380 | in the kickstart file. A handler for the current command should | ||
381 | be registered, though a handler of None is not an error. Returns | ||
382 | the data object returned by KickstartCommand.parse. | ||
383 | |||
384 | args -- A list of arguments to the current command | ||
385 | lineno -- The line number in the file, for error reporting | ||
386 | """ | ||
387 | cmd = args[0] | ||
388 | |||
389 | if not self.commands.has_key(cmd): | ||
390 | raise KickstartParseError, formatErrorMsg(lineno, msg=_("Unknown command: %s" % cmd)) | ||
391 | elif self.commands[cmd] != None: | ||
392 | self.commands[cmd].currentCmd = cmd | ||
393 | self.commands[cmd].currentLine = self.currentLine | ||
394 | self.commands[cmd].lineno = lineno | ||
395 | |||
396 | # The parser returns the data object that was modified. This could | ||
397 | # be a BaseData subclass that should be put into a list, or it | ||
398 | # could be the command handler object itself. | ||
399 | obj = self.commands[cmd].parse(args[1:]) | ||
400 | lst = self.commands[cmd].dataList() | ||
401 | if lst is not None: | ||
402 | lst.append(obj) | ||
403 | |||
404 | return obj | ||
405 | |||
406 | def maskAllExcept(self, lst): | ||
407 | """Set all entries in the commands dict to None, except the ones in | ||
408 | the lst. All other commands will not be processed. | ||
409 | """ | ||
410 | self._writeOrder = {} | ||
411 | |||
412 | for (key, val) in self.commands.iteritems(): | ||
413 | if not key in lst: | ||
414 | self.commands[key] = None | ||
415 | |||
416 | def hasCommand(self, cmd): | ||
417 | """Return true if there is a handler for the string cmd.""" | ||
418 | return hasattr(self, cmd) | ||
419 | |||
420 | |||
421 | ### | ||
422 | ### DATA | ||
423 | ### | ||
424 | class BaseData(KickstartObject): | ||
425 | """The base class for all data objects. This is an abstract class.""" | ||
426 | removedKeywords = [] | ||
427 | removedAttrs = [] | ||
428 | |||
429 | def __init__(self, *args, **kwargs): | ||
430 | """Create a new BaseData instance. | ||
431 | |||
432 | lineno -- Line number in the ks-file where this object was defined | ||
433 | """ | ||
434 | |||
435 | # We don't want people using this class by itself. | ||
436 | if self.__class__ is BaseData: | ||
437 | raise TypeError, "BaseData is an abstract class." | ||
438 | |||
439 | KickstartObject.__init__(self, *args, **kwargs) | ||
440 | self.lineno = 0 | ||
441 | |||
442 | def __str__(self): | ||
443 | """Return a string formatted for output to a kickstart file.""" | ||
444 | return "" | ||
445 | |||
446 | def __call__(self, *args, **kwargs): | ||
447 | """Set multiple attributes on a subclass of BaseData at once via | ||
448 | keyword arguments. Valid attributes are anything specified in a | ||
449 | subclass, but unknown attributes will be ignored. | ||
450 | """ | ||
451 | for (key, val) in kwargs.items(): | ||
452 | # Ignore setting attributes that were removed in a subclass, as | ||
453 | # if they were unknown attributes. | ||
454 | if key in self.removedAttrs: | ||
455 | continue | ||
456 | |||
457 | if hasattr(self, key): | ||
458 | setattr(self, key, val) | ||
459 | |||
460 | def deleteRemovedAttrs(self): | ||
461 | """Remove all attributes from self that are given in the removedAttrs | ||
462 | list. This method should be called from __init__ in a subclass, | ||
463 | but only after the superclass's __init__ method has been called. | ||
464 | """ | ||
465 | for attr in filter(lambda k: hasattr(self, k), self.removedAttrs): | ||
466 | delattr(self, attr) | ||