source: trunk/packages/xen-3.1/xen-3.1/tools/pygrub/src/GrubConf.py @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 7.6 KB
Line 
1#
2# GrubConf.py - Simple grub.conf parsing
3#
4# Copyright 2005-2006 Red Hat, Inc.
5# Jeremy Katz <katzj@redhat.com>
6#
7# This software may be freely redistributed under the terms of the GNU
8# general public license.
9#
10# You should have received a copy of the GNU General Public License
11# along with this program; if not, write to the Free Software
12# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
13#
14
15import os, sys
16import logging
17
18def grub_split(s, maxsplit = -1):
19    eq = s.find('=')
20    if eq == -1:
21        return s.split(None, maxsplit)
22
23    # see which of a space or tab is first
24    sp = s.find(' ')
25    tab = s.find('\t')
26    if (tab != -1 and tab < sp) or (tab != -1 and sp == -1):
27        sp = tab
28
29    if eq != -1 and eq < sp or (eq != -1 and sp == -1):
30        return s.split('=', maxsplit)
31    else:
32        return s.split(None, maxsplit)
33
34def grub_exact_split(s, num):
35    ret = grub_split(s, num - 1)
36    if len(ret) < num:
37        return ret + [""] * (num - len(ret))
38    return ret
39
40def get_path(s):
41    """Returns a tuple of (GrubDiskPart, path) corresponding to string."""
42    if not s.startswith('('):
43        return (None, s)
44    idx = s.find(')')
45    if idx == -1:
46        raise ValueError, "Unable to find matching ')'"
47    d = s[:idx]
48    return (GrubDiskPart(d), s[idx + 1:])
49
50class GrubDiskPart(object):
51    def __init__(self, str):
52        if str.find(',') != -1:
53            (self.disk, self.part) = str.split(",", 2)
54        else:
55            self.disk = str
56            self.part = None
57
58    def __repr__(self):
59        if self.part is not None:
60            return "d%dp%d" %(self.disk, self.part)
61        else:
62            return "d%d" %(self,disk,)
63
64    def get_disk(self):
65        return self._disk
66    def set_disk(self, val):
67        val = val.replace("(", "").replace(")", "")
68        self._disk = int(val[2:])
69    disk = property(get_disk, set_disk)
70
71    def get_part(self):
72        return self._part
73    def set_part(self, val):
74        if val is None:
75            self._part = val
76            return
77        val = val.replace("(", "").replace(")", "")
78        self._part = int(val)
79    part = property(get_part, set_part)
80
81class GrubImage(object):
82    def __init__(self, lines):
83        self.reset(lines)
84
85    def __repr__(self):
86        return ("title: %s\n" 
87                "  root: %s\n"
88                "  kernel: %s\n"
89                "  args: %s\n"
90                "  initrd: %s\n" %(self.title, self.root, self.kernel,
91                                   self.args, self.initrd))
92
93    def reset(self, lines):
94        self._root = self._initrd = self._kernel = self._args = None
95        self.title = ""
96        self.lines = []
97        map(self.set_from_line, lines)
98
99    def set_from_line(self, line, replace = None):
100        (com, arg) = grub_exact_split(line, 2)
101
102        if self.commands.has_key(com):
103            if self.commands[com] is not None:
104                exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
105            else:
106                logging.info("Ignored image directive %s" %(com,))
107        else:
108            logging.warning("Unknown image directive %s" %(com,))
109
110        # now put the line in the list of lines
111        if replace is None:
112            self.lines.append(line)
113        else:
114            self.lines.pop(replace)
115            self.lines.insert(replace, line)
116
117    def set_root(self, val):
118        self._root = GrubDiskPart(val)
119    def get_root(self):
120        return self._root
121    root = property(get_root, set_root)
122
123    def set_kernel(self, val):
124        if val.find(" ") == -1:
125            self._kernel = get_path(val)
126            self._args = None
127            return
128        (kernel, args) = val.split(None, 1)
129        self._kernel = get_path(kernel)
130        self._args = args
131    def get_kernel(self):
132        return self._kernel
133    def get_args(self):
134        return self._args
135    kernel = property(get_kernel, set_kernel)
136    args = property(get_args)
137
138    def set_initrd(self, val):
139        self._initrd = get_path(val)
140    def get_initrd(self):
141        return self._initrd
142    initrd = property(get_initrd, set_initrd)
143
144    # set up command handlers
145    commands = { "title": "self.title",
146                 "root": "self.root",
147                 "rootnoverify": "self.root",
148                 "kernel": "self.kernel",
149                 "initrd": "self.initrd",
150                 "chainloader": None,
151                 "module": None}
152       
153
154class GrubConfigFile(object):
155    def __init__(self, fn = None):
156        self.filename = fn
157        self.images = []
158        self.timeout = -1
159        self._default = 0
160
161        if fn is not None:
162            self.parse()
163
164    def parse(self, buf = None):
165        if buf is None:
166            if self.filename is None:
167                raise ValueError, "No config file defined to parse!"
168
169            f = open(self.filename, 'r')
170            lines = f.readlines()
171            f.close()
172        else:
173            lines = buf.split("\n")
174
175        img = []
176        for l in lines:
177            l = l.strip()
178            # skip blank lines
179            if len(l) == 0:
180                continue
181            # skip comments
182            if l.startswith('#'):
183                continue
184            # new image
185            if l.startswith("title"):
186                if len(img) > 0:
187                    self.add_image(GrubImage(img))
188                img = [l]
189                continue
190               
191            if len(img) > 0:
192                img.append(l)
193                continue
194
195            (com, arg) = grub_exact_split(l, 2)
196            if self.commands.has_key(com):
197                if self.commands[com] is not None:
198                    exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
199                else:
200                    logging.info("Ignored directive %s" %(com,))
201            else:
202                logging.warning("Unknown directive %s" %(com,))
203               
204        if len(img) > 0:
205            self.add_image(GrubImage(img))
206
207    def set(self, line):
208        (com, arg) = grub_exact_split(line, 2)
209        if self.commands.has_key(com):
210            if self.commands[com] is not None:
211                exec("%s = r\"%s\"" %(self.commands[com], arg.strip()))
212            else:
213                logging.info("Ignored directive %s" %(com,))
214        else:
215            logging.warning("Unknown directive %s" %(com,))
216
217    def add_image(self, image):
218        self.images.append(image)
219
220    def _get_default(self):
221        return self._default
222    def _set_default(self, val):
223        if val == "saved":
224            self._default = -1
225        else:
226            self._default = int(val)
227
228        if self._default < 0:
229            raise ValueError, "default must be positive number"
230    default = property(_get_default, _set_default)
231
232    def set_splash(self, val):
233        self._splash = get_path(val)
234    def get_splash(self):
235        return self._splash
236    splash = property(get_splash, set_splash)
237
238    # set up command handlers
239    commands = { "default": "self.default",
240                 "timeout": "self.timeout",
241                 "fallback": "self.fallback",
242                 "hiddenmenu": "self.hiddenmenu",
243                 "splashimage": "self.splash",
244                 "password": "self.password" }
245    for c in ("bootp", "color", "device", "dhcp", "hide", "ifconfig",
246              "pager", "partnew", "parttype", "rarp", "serial",
247              "setkey", "terminal", "terminfo", "tftpserver", "unhide"):
248        commands[c] = None
249    del c
250
251
252if __name__ == "__main__":
253    if sys.argv < 2:
254        raise RuntimeError, "Need a grub.conf to read"
255    g = GrubConfigFile(sys.argv[1])
256    for i in g.images:
257        print i #, i.title, i.root, i.kernel, i.args, i.initrd
Note: See TracBrowser for help on using the repository browser.