Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 239 lines (183 sloc) 6.472 kb
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
1 #!/usr/bin/python
9a7b83b @alonswartz turnkeylinux.com -> turnkeylinux.org
alonswartz authored
2 # Copyright (c) 2008 Alon Swartz <alon@turnkeylinux.org> - all rights reserved
e1adde0 @alonswartz added copyright notices
alonswartz authored
3
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
4 """
5 Debian Installer Live
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
6
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
7 Drives the installation, executing components according to alpha-numeric
8 ordering, and responsible for dynamically assembling the menu and executing
9 components when they are selected.
10
11 Similar to d-i's main-menu, di-live's menu will only be visible when debconf
12 priority is low or medium. Priority is reduced when a component fails,
13 and returns to original level when next component completes successfully.
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
14
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
15 Options:
16 -d --debug Set DEBCONF_DEBUG=developer DEBIAN_FRONTEND=readline
17
18 """
ba9b00f @alonswartz removed component.title
alonswartz authored
19
20 import re
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
21 import os
22 import sys
23 import getopt
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
24 import debconf
25
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
26 from os.path import *
27
957f39f @alonswartz added helper log method for debugging
alonswartz authored
28 LOGFILE = '/var/log/di-live.log'
29 def log(s):
30 file(LOGFILE, 'a').write(s + "\n")
31
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
32 class Error(Exception):
33 pass
34
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
35 class Debian_Priority:
36 """class for controlling DEBIAN_PRIORITY"""
37
38 def __init__(self):
39 self.original = os.environ.get('DEBIAN_PRIORITY')
40 self.current = self.original
41
42 def __del__(self):
43 self.revert()
44
45 def get(self):
46 return self.current
47
48 def set(self, priority):
49 if priority in (None, self.current):
50 return
51
52 priorities = ('low', 'medium', 'high', 'critical')
53 if priority not in priorities:
54 raise Error('illegal debian priority', priority)
55
56 os.environ['DEBIAN_PRIORITY'] = priority
57 self.current = priority
58
59 def revert(self):
60 """revert priority back to original priority"""
61 self.set(self.original)
62
63 def decrease(self):
64 """decrease priority to medium (or low if original was low)"""
65 if self.original == 'low':
66 self.set('low')
67 else:
68 self.set('medium')
69
70 class Menu:
71 """class for controlling a debconf menu with choices"""
72
73 def __init__(self, template, title=None, priority='high', subst='CHOICES'):
74 debconf.runFrontEnd()
75 self.template = template
76 self.db = debconf.Debconf(title)
c43a156 @alonswartz component titles is menu set by querying debconf (i18n support)
alonswartz authored
77
4e81eef @alonswartz set menu with 'backup' capability (cancel installation)
alonswartz authored
78 self.db.capb('backup')
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
79 self.priority = priority
80 self.subst = subst
81
82 def __del__(self):
83 self.db.stop()
84
c43a156 @alonswartz component titles is menu set by querying debconf (i18n support)
alonswartz authored
85 def display(self, names):
86 titles = []
87 self.choices = {}
88 for name in names:
4bba156 @alonswartz capitalize default component title
alonswartz authored
89 title = name.capitalize()
c43a156 @alonswartz component titles is menu set by querying debconf (i18n support)
alonswartz authored
90 try:
91 template = 'debian-installer/%s/title' % name
92 title = self.db.metaget(template, 'description')
93 except debconf.DebconfError, e:
94 if not e[0] == 10:
95 raise Error('DebconfError', e)
96
97 titles.append(title)
98 self.choices[title] = name
99
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
100 self.db.reset(self.template)
c43a156 @alonswartz component titles is menu set by querying debconf (i18n support)
alonswartz authored
101 self.db.subst(self.template, self.subst, ", ".join(titles))
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
102 self.db.input(self.priority, self.template)
103 try:
104 self.db.go()
105 except debconf.DebconfError, e:
106 if not e[0] == 30 and not e[1] == "backup":
107 raise Error('debconf error', e)
108
109 def get_choice(self):
c43a156 @alonswartz component titles is menu set by querying debconf (i18n support)
alonswartz authored
110 ret = self.db.get(self.template)
111 if self.choices.has_key(ret):
112 return self.choices[ret]
113 return ret
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
114
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
115 class Component:
116 """class for managing a component"""
117
118 def __init__(self, path):
119 self.path = path
ba9b00f @alonswartz removed component.title
alonswartz authored
120 self.name = re.sub('^[\d]*', '', basename(path))
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
121 self.exitcode = None
122
123 def execute(self):
124 error = os.system(self.path)
125 if error:
126 self.exitcode = os.WEXITSTATUS(error)
127 return False
128
129 self.exitcode = 0
130 return True
131
132 class Components(dict):
133 """class for holding components"""
134
135 def __init__(self, dirpath):
136 if not exists(dirpath):
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
137 raise Error('non existent components path', dirpath)
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
138
139 for file in os.listdir(dirpath):
c5424e8 @alonswartz explicitly check if component is executable
alonswartz authored
140 path = join(dirpath, file)
141 if self._is_executable(path):
142 self.add(path)
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
143
144 def __iter__(self):
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
145 """return component in alpha-numeric ordering according to name"""
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
146 keys = self.keys()
147 keys.sort()
148 for key in keys:
149 yield self[key]
150
151 @staticmethod
152 def _is_executable(path):
153 if os.stat(path).st_mode & 0111 == 0:
154 return False
155 return True
156
157 def add(self, path):
158 if not self._is_executable(path):
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
159 raise Error('component not executable', path)
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
160
161 name = basename(path)
162 self[name] = Component(path)
163
164 def remove(self, name):
165 del self[name]
166
167 class Components_Menu:
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
168 """class to mimic d-i main-menu"""
169
c5424e8 @alonswartz explicitly check if component is executable
alonswartz authored
170 def __init__(self, components_dir, menu_template, menu_title=None):
171 self.components = Components(components_dir)
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
172 self.menu = Menu(menu_template, menu_title)
173
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
174 self.priority = Debian_Priority()
175
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
176 def _get_next_component(self):
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
177 if self.priority.get() in ('low', 'medium'):
c43a156 @alonswartz component titles is menu set by querying debconf (i18n support)
alonswartz authored
178 self.menu.display([ c.name for c in self.components ])
ba9b00f @alonswartz removed component.title
alonswartz authored
179 choice = self.menu.get_choice()
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
180
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
181 for c in self.components:
ba9b00f @alonswartz removed component.title
alonswartz authored
182 if c.name == choice:
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
183 return c
184 else:
185 for c in self.components:
cddde56 @alonswartz bugfix: determine ordering explicitly by basename(component.path)
alonswartz authored
186 if basename(c.path) > self.last:
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
187 return c
188
189 return None
190
191 def run(self):
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
192 self.last = ''
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
193 while 1:
194 component = self._get_next_component()
195 if component is None:
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
196 break
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
197
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
198 component.execute()
199 if component.exitcode == 0:
cddde56 @alonswartz bugfix: determine ordering explicitly by basename(component.path)
alonswartz authored
200 self.last = basename(component.path)
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
201 self.priority.revert()
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
202 else:
510d4ed @alonswartz cleaned up di-live (main-menu)
alonswartz authored
203 self.priority.decrease()
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
204
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
205 def usage(s=None):
206 if s:
207 print >> sys.stderr, "Error:", s
208 print >> sys.stderr, "Syntax: %s [options]" % sys.argv[0]
209 print >> sys.stderr, __doc__
210 sys.exit(1)
211
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
212 def main():
e1d8d63 @alonswartz added --debug, --help options, and docstring
alonswartz authored
213 try:
214 opts, args = getopt.gnu_getopt(sys.argv[1:], "hd", ['help', 'debug'])
215 except getopt.GetoptError, e:
216 usage(e)
217
218 debug = False
219 for opt, val in opts:
220 if opt in ('-h', '--help'):
221 usage()
222 elif opt in ('-d', '--debug'):
223 debug = True
224
225 if debug:
226 os.environ['DEBCONF_DEVELOPER'] = 'developer'
227 os.environ['DEBIAN_FRONTEND'] = 'readline'
228
4dd00e3 @alonswartz re-wrote di-live (main-menu) in python
alonswartz authored
229 components_dir = '/usr/lib/di-live.d'
230 menu_template = 'di-live/main_menu'
231 menu_title = 'Debian Installer Live'
232
233 Components_Menu(components_dir, menu_template, menu_title).run()
234
235
236 if __name__ == "__main__":
237 main()
901cac4 @alonswartz added grub-installer component script and packaging
alonswartz authored
238
Something went wrong with that request. Please try again.