Run certain script before creation of tar.gz image.
[tools/mic.git] / mic / 3rdparty / pykickstart / sections.py
1 #
2 # sections.py:  Kickstart file sections.
3 #
4 # Chris Lumens <clumens@redhat.com>
5 #
6 # Copyright 2011 Red Hat, Inc.
7 #
8 # This copyrighted material is made available to anyone wishing to use, modify,
9 # copy, or redistribute it subject to the terms and conditions of the GNU
10 # General Public License v.2.  This program is distributed in the hope that it
11 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
12 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 # See the GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along with
16 # this program; if not, write to the Free Software Foundation, Inc., 51
17 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  Any Red Hat
18 # trademarks that are incorporated in the source code or documentation are not
19 # subject to the GNU General Public License and may only be used or replicated
20 # with the express permission of Red Hat, Inc. 
21 #
22 """
23 This module exports the classes that define a section of a kickstart file.  A
24 section is a chunk of the file starting with a %tag and ending with a %end.
25 Examples of sections include %packages, %pre, and %post.
26
27 You may use this module to define your own custom sections which will be
28 treated just the same as a predefined one by the kickstart parser.  All that
29 is necessary is to create a new subclass of Section and call
30 parser.registerSection with an instance of your new class.
31 """
32 from constants import *
33 from options import KSOptionParser
34 from version import *
35
36 class Section(object):
37     """The base class for defining kickstart sections.  You are free to
38        subclass this as appropriate.
39
40        Class attributes:
41
42        allLines    -- Does this section require the parser to call handleLine
43                       for every line in the section, even blanks and comments?
44        sectionOpen -- The string that denotes the start of this section.  You
45                       must start your tag with a percent sign.
46        timesSeen   -- This attribute is for informational purposes only.  It is
47                       incremented every time handleHeader is called to keep
48                       track of the number of times a section of this type is
49                       seen.
50     """
51     allLines = False
52     sectionOpen = ""
53     timesSeen = 0
54
55     def __init__(self, handler, **kwargs):
56         """Create a new Script instance.  At the least, you must pass in an
57            instance of a baseHandler subclass.
58
59            Valid kwargs:
60
61            dataObj --
62         """
63         self.handler = handler
64
65         self.version = self.handler.version
66
67         self.dataObj = kwargs.get("dataObj", None)
68
69     def finalize(self):
70         """This method is called when the %end tag for a section is seen.  It
71            is not required to be provided.
72         """
73         pass
74
75     def handleLine(self, line):
76         """This method is called for every line of a section.  Take whatever
77            action is appropriate.  While this method is not required to be
78            provided, not providing it does not make a whole lot of sense.
79
80            Arguments:
81
82            line -- The complete line, with any trailing newline.
83         """
84         pass
85
86     def handleHeader(self, lineno, args):
87         """This method is called when the opening tag for a section is seen.
88            Not all sections will need this method, though all provided with
89            kickstart include one.
90
91            Arguments:
92
93            args -- A list of all strings passed as arguments to the section
94                    opening tag.
95         """
96         self.timesSeen += 1
97
98 class NullSection(Section):
99     """This defines a section that pykickstart will recognize but do nothing
100        with.  If the parser runs across a %section that has no object registered,
101        it will raise an error.  Sometimes, you may want to simply ignore those
102        sections instead.  This class is useful for that purpose.
103     """
104     def __init__(self, *args, **kwargs):
105         """Create a new NullSection instance.  You must pass a sectionOpen
106            parameter (including a leading '%') for the section you wish to
107            ignore.
108         """
109         Section.__init__(self, *args, **kwargs)
110         self.sectionOpen = kwargs.get("sectionOpen")
111
112 class ScriptSection(Section):
113     allLines = True
114
115     def __init__(self, *args, **kwargs):
116         Section.__init__(self, *args, **kwargs)
117         self._script = {}
118         self._resetScript()
119
120     def _getParser(self):
121         op = KSOptionParser(self.version)
122         op.add_option("--erroronfail", dest="errorOnFail", action="store_true",
123                       default=False)
124         op.add_option("--interpreter", dest="interpreter", default="/bin/sh")
125         op.add_option("--log", "--logfile", dest="log")
126         return op
127
128     def _resetScript(self):
129         self._script = {"interp": "/bin/sh", "log": None, "errorOnFail": False,
130                         "lineno": None, "chroot": False, "body": []}
131
132     def handleLine(self, line):
133         self._script["body"].append(line)
134
135     def finalize(self):
136         if " ".join(self._script["body"]).strip() == "":
137             return
138
139         kwargs = {"interp": self._script["interp"],
140                   "inChroot": self._script["chroot"],
141                   "lineno": self._script["lineno"],
142                   "logfile": self._script["log"],
143                   "errorOnFail": self._script["errorOnFail"],
144                   "type": self._script["type"]}
145
146         s = self.dataObj (self._script["body"], **kwargs)
147         self._resetScript()
148
149         if self.handler:
150             self.handler.scripts.append(s)
151
152     def handleHeader(self, lineno, args):
153         """Process the arguments to a %pre/%post/%traceback header for later
154            setting on a Script instance once the end of the script is found.
155            This method may be overridden in a subclass if necessary.
156         """
157         Section.handleHeader(self, lineno, args)
158         op = self._getParser()
159
160         (opts, extra) = op.parse_args(args=args[1:], lineno=lineno)
161
162         self._script["interp"] = opts.interpreter
163         self._script["lineno"] = lineno
164         self._script["log"] = opts.log
165         self._script["errorOnFail"] = opts.errorOnFail
166         if hasattr(opts, "nochroot"):
167             self._script["chroot"] = not opts.nochroot
168
169 class PreScriptSection(ScriptSection):
170     sectionOpen = "%pre"
171
172     def _resetScript(self):
173         ScriptSection._resetScript(self)
174         self._script["type"] = KS_SCRIPT_PRE
175
176 class PostScriptSection(ScriptSection):
177     sectionOpen = "%post"
178
179     def _getParser(self):
180         op = ScriptSection._getParser(self)
181         op.add_option("--nochroot", dest="nochroot", action="store_true",
182                       default=False)
183         return op
184
185     def _resetScript(self):
186         ScriptSection._resetScript(self)
187         self._script["chroot"] = True
188         self._script["type"] = KS_SCRIPT_POST
189
190 class TracebackScriptSection(ScriptSection):
191     sectionOpen = "%traceback"
192
193     def _resetScript(self):
194         ScriptSection._resetScript(self)
195         self._script["type"] = KS_SCRIPT_TRACEBACK
196
197 class RunScriptSection(ScriptSection):
198     sectionOpen = "%runscript"
199     def _resetScript(self):
200         ScriptSection._resetScript(self)
201         self._script["type"] = KS_SCRIPT_RUN
202 class PackageSection(Section):
203     sectionOpen = "%packages"
204
205     def handleLine(self, line):
206         if not self.handler:
207             return
208
209         (h, s, t) = line.partition('#')
210         line = h.rstrip()
211
212         self.handler.packages.add([line])
213
214     def handleHeader(self, lineno, args):
215         """Process the arguments to the %packages header and set attributes
216            on the Version's Packages instance appropriate.  This method may be
217            overridden in a subclass if necessary.
218         """
219         Section.handleHeader(self, lineno, args)
220         op = KSOptionParser(version=self.version)
221         op.add_option("--excludedocs", dest="excludedocs", action="store_true",
222                       default=False)
223         op.add_option("--ignoremissing", dest="ignoremissing",
224                       action="store_true", default=False)
225         op.add_option("--nobase", dest="nobase", action="store_true",
226                       default=False)
227         op.add_option("--ignoredeps", dest="resolveDeps", action="store_false",
228                       deprecated=FC4, removed=F9)
229         op.add_option("--resolvedeps", dest="resolveDeps", action="store_true",
230                       deprecated=FC4, removed=F9)
231         op.add_option("--default", dest="defaultPackages", action="store_true",
232                       default=False, introduced=F7)
233         op.add_option("--instLangs", dest="instLangs", type="string",
234                       default="", introduced=F9)
235
236         (opts, extra) = op.parse_args(args=args[1:], lineno=lineno)
237
238         self.handler.packages.excludeDocs = opts.excludedocs
239         self.handler.packages.addBase = not opts.nobase
240         if opts.ignoremissing:
241             self.handler.packages.handleMissing = KS_MISSING_IGNORE
242         else:
243             self.handler.packages.handleMissing = KS_MISSING_PROMPT
244
245         if opts.defaultPackages:
246             self.handler.packages.default = True
247
248         if opts.instLangs:
249             self.handler.packages.instLangs = opts.instLangs