1 |
slords |
1.1 |
# |
2 |
|
|
# kickstart.py: kickstart install support |
3 |
|
|
# |
4 |
|
|
# Copyright 1999-2004 Red Hat, Inc. |
5 |
|
|
# |
6 |
|
|
# This software may be freely redistributed under the terms of the GNU |
7 |
|
|
# library public license. |
8 |
|
|
# |
9 |
|
|
# You should have received a copy of the GNU Library Public License |
10 |
|
|
# along with this program; if not, write to the Free Software |
11 |
|
|
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
12 |
|
|
# |
13 |
|
|
|
14 |
|
|
import iutil |
15 |
|
|
import isys |
16 |
|
|
import os |
17 |
|
|
from installclass import BaseInstallClass |
18 |
|
|
from partitioning import * |
19 |
|
|
from autopart import * |
20 |
|
|
from fsset import * |
21 |
|
|
from flags import flags |
22 |
|
|
from constants import * |
23 |
|
|
import sys |
24 |
|
|
import raid |
25 |
|
|
import string |
26 |
|
|
import partRequests |
27 |
|
|
import urllib2 |
28 |
|
|
import lvm |
29 |
|
|
|
30 |
|
|
from rhpl.translate import _ |
31 |
|
|
from rhpl.log import log |
32 |
|
|
|
33 |
|
|
KS_MISSING_PROMPT = 0 |
34 |
|
|
KS_MISSING_IGNORE = 1 |
35 |
|
|
|
36 |
|
|
class KickstartError(Exception): |
37 |
|
|
def __init__(self, val = ""): |
38 |
|
|
self.value = val |
39 |
|
|
|
40 |
|
|
def __str__ (self): |
41 |
|
|
return self.value |
42 |
|
|
|
43 |
|
|
class KickstartValueError(KickstartError): |
44 |
|
|
def __init__(self, val = ""): |
45 |
|
|
self.value = val |
46 |
|
|
|
47 |
|
|
def __str__ (self): |
48 |
|
|
return self.value |
49 |
|
|
|
50 |
|
|
class KSAppendException(KickstartError): |
51 |
|
|
def __init__(self, s=""): |
52 |
|
|
self.str = s |
53 |
|
|
|
54 |
|
|
def __str__(self): |
55 |
|
|
return self.str |
56 |
|
|
|
57 |
|
|
class Script: |
58 |
|
|
def __repr__(self): |
59 |
|
|
str = ("(s: '%s' i: %s c: %d)") % \ |
60 |
|
|
(self.script, self.interp, self.inChroot) |
61 |
|
|
return string.replace(str, "\n", "|") |
62 |
|
|
|
63 |
|
|
def __init__(self, script, interp, inChroot, logfile = None): |
64 |
|
|
self.script = script |
65 |
|
|
self.interp = interp |
66 |
|
|
self.inChroot = inChroot |
67 |
|
|
self.logfile = logfile |
68 |
|
|
|
69 |
|
|
def run(self, chroot, serial): |
70 |
|
|
scriptRoot = "/" |
71 |
|
|
if self.inChroot: |
72 |
|
|
scriptRoot = chroot |
73 |
|
|
|
74 |
|
|
path = scriptRoot + "/tmp/ks-script" |
75 |
|
|
|
76 |
|
|
f = open(path, "w") |
77 |
|
|
f.write(self.script) |
78 |
|
|
f.close() |
79 |
|
|
os.chmod(path, 0700) |
80 |
|
|
|
81 |
|
|
if self.logfile is not None: |
82 |
|
|
messages = self.logfile |
83 |
|
|
elif serial: |
84 |
|
|
messages = "/tmp/ks-script.log" |
85 |
|
|
else: |
86 |
|
|
messages = "/dev/tty3" |
87 |
|
|
|
88 |
|
|
rc = iutil.execWithRedirect(self.interp, |
89 |
|
|
[self.interp,"/tmp/ks-script"], |
90 |
|
|
stdout = messages, stderr = messages, |
91 |
|
|
root = scriptRoot) |
92 |
|
|
|
93 |
|
|
if rc != 0: |
94 |
|
|
log("WARNING - Error code %s encountered running a kickstart %%pre/%%post script", rc) |
95 |
|
|
|
96 |
|
|
os.unlink(path) |
97 |
|
|
|
98 |
|
|
class KickstartBase(BaseInstallClass): |
99 |
|
|
name = "kickstart" |
100 |
slords |
1.4 |
|
101 |
slords |
1.3 |
def postAction(self, rootPath, serial, intf): |
102 |
|
|
win = intf.waitWindow(_("Post Install Script"), |
103 |
|
|
_("The post installation script is running...")) |
104 |
|
|
|
105 |
|
|
script = ( "/sbin/syslogd &\n" |
106 |
|
|
"sleep 2\n" |
107 |
|
|
"/sbin/e-smith/signal-event post-install\n" ) |
108 |
|
|
s = Script(script, interp="/bin/sh", inChroot=1) |
109 |
|
|
log("%s", s) |
110 |
|
|
s.run(rootPath, serial) |
111 |
|
|
win.pop() |
112 |
slords |
1.4 |
|
113 |
slords |
1.1 |
log("Running kickstart %%post script(s)") |
114 |
|
|
for script in self.postScripts: |
115 |
|
|
script.run(rootPath, serial) |
116 |
|
|
log("All kickstart %%post script(s) have been run") |
117 |
|
|
|
118 |
|
|
def doRootPw(self, id, args): |
119 |
|
|
(args, extra) = isys.getopt(args, '', [ 'iscrypted' ]) |
120 |
|
|
|
121 |
|
|
isCrypted = 0 |
122 |
|
|
for n in args: |
123 |
|
|
(str, arg) = n |
124 |
|
|
if (str == '--iscrypted'): |
125 |
|
|
isCrypted = 1 |
126 |
|
|
|
127 |
|
|
if len(extra) != 1: |
128 |
|
|
raise KickstartValueError, "a single argument is expected to rootPw" |
129 |
|
|
|
130 |
|
|
self.setRootPassword(id, extra[0], isCrypted = isCrypted) |
131 |
|
|
self.skipSteps.append("accounts") |
132 |
|
|
|
133 |
|
|
def doFirewall(self, id, args): |
134 |
|
|
(args, extra) = isys.getopt(args, '', |
135 |
|
|
[ 'dhcp', 'ssh', 'telnet', 'smtp', 'http', 'ftp', 'enabled', |
136 |
|
|
'enable', 'port=', 'high', 'medium', 'disabled', 'disable', |
137 |
|
|
'trust=' ]) |
138 |
|
|
|
139 |
|
|
enable = -1 |
140 |
|
|
trusts = [] |
141 |
|
|
ports = [] |
142 |
|
|
|
143 |
|
|
for n in args: |
144 |
|
|
(str, arg) = n |
145 |
|
|
if str == '--ssh': |
146 |
|
|
ports.append("22:tcp") |
147 |
|
|
elif str == '--telnet': |
148 |
|
|
ports.append("23:tcp") |
149 |
|
|
elif str == '--smtp': |
150 |
|
|
ports.append("25:tcp") |
151 |
|
|
elif str == '--http': |
152 |
|
|
ports.extend(["80:tcp", "443:tcp"]) |
153 |
|
|
elif str == '--ftp': |
154 |
|
|
ports.append("21:tcp") |
155 |
|
|
elif str == '--high' or str == '--medium': |
156 |
|
|
log("used deprecated firewall option: %s" %(str[2:],)) |
157 |
|
|
enable = 1 |
158 |
|
|
elif str == '--enabled' or str == "--enable": |
159 |
|
|
enable = 1 |
160 |
|
|
elif str == '--disabled' or str == "--disable": |
161 |
|
|
enable = 0 |
162 |
|
|
elif str == '--trust': |
163 |
|
|
trusts.append(arg) |
164 |
|
|
elif str == '--port': |
165 |
|
|
theports = arg.split(",") |
166 |
|
|
for p in theports: |
167 |
|
|
p = p.strip() |
168 |
|
|
if p.find(":") == -1: |
169 |
|
|
p = "%s:tcp" %(p,) |
170 |
|
|
ports.append(p) |
171 |
|
|
|
172 |
|
|
self.setFirewall(id, enable, trusts, ports) |
173 |
|
|
|
174 |
|
|
def doSELinux(self, id, args): |
175 |
|
|
(args, extra) = isys.getopt(args, '', |
176 |
|
|
[ 'disabled', 'enforcing', |
177 |
|
|
'permissive' ] ) |
178 |
|
|
|
179 |
|
|
sel = 2 |
180 |
|
|
|
181 |
|
|
for n in args: |
182 |
|
|
(str, arg) = n |
183 |
|
|
if str == "--disabled": |
184 |
|
|
sel = 0 |
185 |
|
|
elif str == "--permissive": |
186 |
|
|
sel = 1 |
187 |
|
|
elif str == "--enforcing": |
188 |
|
|
sel = 2 |
189 |
|
|
|
190 |
|
|
self.setSELinux(id, sel) |
191 |
|
|
|
192 |
|
|
def doZFCP(self, id, args): |
193 |
|
|
(args, extra) = isys.getopt(args, '', |
194 |
|
|
["devnum", "scsiid", "wwpn", "scsilun", |
195 |
|
|
"fcplun"]) |
196 |
|
|
|
197 |
|
|
devnum = None |
198 |
|
|
scsiid = None |
199 |
|
|
wwpn = None |
200 |
|
|
scsilun = None |
201 |
|
|
fcplun = None |
202 |
|
|
|
203 |
|
|
for n in args: |
204 |
|
|
(str, arg) = n |
205 |
|
|
if str == "--devnum": |
206 |
|
|
devnum = id.zfcp.sanitizeDeviceInput(arg) |
207 |
|
|
elif str == "--scsid": |
208 |
|
|
scsiid = id.zfcp.sanitizeHexInput(arg) |
209 |
|
|
elif str == "--wwpn": |
210 |
|
|
wwpn = id.zfcp.sanitizeHexInput(arg) |
211 |
|
|
elif str == "--scsilun": |
212 |
|
|
scsilun = id.zfcp.sanitizeHexInput(arg) |
213 |
|
|
elif str == "--fcplun": |
214 |
|
|
fcplun = id.zfcp.sanitizeFCPLInput(arg) |
215 |
|
|
|
216 |
|
|
if id.zfcp.checkValidDevice(devnum) == -1: |
217 |
|
|
raise KickstartValueError, "Invalid devnum specified" |
218 |
|
|
if id.zfcp.checkValidID(scsiid) == -1: |
219 |
|
|
raise KickstartValueError, "Invalid scsiid specified" |
220 |
|
|
if id.zfcp.checkValid64BitHex(wwpn) == -1: |
221 |
|
|
raise KickstartValueError, "Invalid wwpn specified" |
222 |
|
|
if id.zfcp.checkValidID(scsilun) == -1: |
223 |
|
|
raise KickstartValueError, "Invalid scsilun specified" |
224 |
|
|
if id.zfcp.checkValid64BitHex(fcplun) == -1: |
225 |
|
|
raise KickstartValueError, "Invalid fcplun specified" |
226 |
|
|
|
227 |
|
|
if ((devnum is None) or (scsiid is None) or (wwpn is None) |
228 |
|
|
or (scsilun is None) or (fcplun is None)): |
229 |
|
|
raise KickstartError, "ZFCP config must specify all of devnum, scsiid, wwpn, scsilun, and fcplun" |
230 |
|
|
|
231 |
|
|
self.setZFCP(id, devnum, scsiid, wwpn, scsilun, fcplun) |
232 |
|
|
self.skipSteps.append("zfcpconfig") |
233 |
|
|
|
234 |
|
|
def doAuthconfig(self, id, args): |
235 |
|
|
(args, extra) = isys.getopt(args, '', |
236 |
|
|
[ 'useshadow', 'enableshadow', |
237 |
|
|
'enablemd5', |
238 |
|
|
'enablenis', 'nisdomain=', 'nisserver=', |
239 |
|
|
'enableldap', 'enableldapauth', 'ldapserver=', 'ldapbasedn=', |
240 |
|
|
'enableldaptls', |
241 |
|
|
'enablekrb5', 'krb5realm=', 'krb5kdc=', 'krb5adminserver=', |
242 |
|
|
'enablehesiod', 'hesiodlhs=', 'hesiodrhs=', |
243 |
|
|
'enablesmbauth', 'smbservers=', 'smbworkgroup=', |
244 |
|
|
'enablecache']) |
245 |
|
|
|
246 |
|
|
useShadow = 0 |
247 |
|
|
|
248 |
|
|
useMd5 = 0 |
249 |
|
|
|
250 |
|
|
useNis = 0 |
251 |
|
|
nisServer = "" |
252 |
|
|
nisDomain = "" |
253 |
|
|
nisBroadcast = 0 |
254 |
|
|
|
255 |
|
|
useLdap = 0 |
256 |
|
|
useLdapauth = 0 |
257 |
|
|
useLdaptls = 0 |
258 |
|
|
ldapServer = "" |
259 |
|
|
ldapBasedn = "" |
260 |
|
|
|
261 |
|
|
useKrb5 = 0 |
262 |
|
|
krb5Realm = "" |
263 |
|
|
krb5Kdc = "" |
264 |
|
|
krb5Admin = "" |
265 |
|
|
|
266 |
|
|
useHesiod = 0 |
267 |
|
|
hesiodLhs = "" |
268 |
|
|
hesiodRhs = "" |
269 |
|
|
|
270 |
|
|
useSamba = 0 |
271 |
|
|
smbServers = "" |
272 |
|
|
smbWorkgroup = "" |
273 |
|
|
|
274 |
|
|
enableCache = 0 |
275 |
|
|
|
276 |
|
|
for n in args: |
277 |
|
|
(str, arg) = n |
278 |
|
|
if (str == '--enablenis'): |
279 |
|
|
useNis = 1 |
280 |
|
|
elif (str == '--useshadow') or (str == '--enableshadow'): |
281 |
|
|
useShadow = 1 |
282 |
|
|
elif (str == '--enablemd5'): |
283 |
|
|
useMd5 = 1 |
284 |
|
|
elif (str == '--nisserver'): |
285 |
|
|
nisServer = arg |
286 |
|
|
elif (str == '--nisdomain'): |
287 |
|
|
nisDomain = arg |
288 |
|
|
elif (str == '--enableldap'): |
289 |
|
|
useLdap = 1 |
290 |
|
|
elif (str == '--enableldapauth'): |
291 |
|
|
useLdapauth = 1 |
292 |
|
|
elif (str == '--ldapserver'): |
293 |
|
|
ldapServer = arg |
294 |
|
|
elif (str == '--ldapbasedn'): |
295 |
|
|
ldapBasedn = arg |
296 |
|
|
elif (str == '--enableldaptls'): |
297 |
|
|
useLdaptls = 1 |
298 |
|
|
elif (str == '--enablekrb5'): |
299 |
|
|
useKrb5 = 1 |
300 |
|
|
elif (str == '--krb5realm'): |
301 |
|
|
krb5Realm = arg |
302 |
|
|
elif (str == '--krb5kdc'): |
303 |
|
|
krb5Kdc = arg |
304 |
|
|
elif (str == '--krb5adminserver'): |
305 |
|
|
krb5Admin = arg |
306 |
|
|
elif (str == '--enablehesiod'): |
307 |
|
|
useHesiod = 1 |
308 |
|
|
elif (str == '--hesiodlhs'): |
309 |
|
|
hesiodLhs = arg |
310 |
|
|
elif (str == '--hesiodrhs'): |
311 |
|
|
hesiodRhs = arg |
312 |
|
|
elif (str == '--enablesmbauth'): |
313 |
|
|
useSamba = 1 |
314 |
|
|
elif (str == '--smbservers'): |
315 |
|
|
smbServers = arg |
316 |
|
|
elif (str == '--smbworkgroup'): |
317 |
|
|
smbWorkgroup = arg |
318 |
|
|
elif (str == '--enablecache'): |
319 |
|
|
enableCache = 1 |
320 |
|
|
|
321 |
|
|
|
322 |
|
|
if useNis and not nisServer: nisBroadcast = 1 |
323 |
|
|
|
324 |
|
|
self.setAuthentication(id, useShadow, useMd5, |
325 |
|
|
useNis, nisDomain, nisBroadcast, nisServer, |
326 |
|
|
useLdap, useLdapauth, ldapServer, |
327 |
|
|
ldapBasedn, useLdaptls, |
328 |
|
|
useKrb5, krb5Realm, krb5Kdc, krb5Admin, |
329 |
|
|
useHesiod, hesiodLhs, hesiodRhs, |
330 |
|
|
useSamba, smbServers, smbWorkgroup, |
331 |
|
|
enableCache) |
332 |
|
|
|
333 |
|
|
self.skipSteps.append("authentication") |
334 |
|
|
|
335 |
|
|
def doBootloader (self, id, args, useLilo = 0): |
336 |
|
|
(args, extra) = isys.getopt(args, '', |
337 |
|
|
[ 'append=', 'location=', 'useLilo', 'lba32', |
338 |
|
|
'password=', 'md5pass=', 'linear', 'nolinear', |
339 |
|
|
'upgrade', 'driveorder=']) |
340 |
|
|
|
341 |
|
|
validLocations = [ "mbr", "partition", "none", "boot" ] |
342 |
|
|
appendLine = "" |
343 |
|
|
location = "mbr" |
344 |
|
|
password = None |
345 |
|
|
md5pass = None |
346 |
|
|
forceLBA = 0 |
347 |
|
|
linear = 1 |
348 |
|
|
upgrade = 0 |
349 |
|
|
driveorder = [] |
350 |
|
|
|
351 |
|
|
for n in args: |
352 |
|
|
(str, arg) = n |
353 |
|
|
if str == '--append': |
354 |
|
|
appendLine = arg |
355 |
|
|
elif str == '--location': |
356 |
|
|
location = arg |
357 |
|
|
elif str == '--useLilo': |
358 |
|
|
# log("used deprecated option --useLilo, ignoring") |
359 |
|
|
useLilo = 1 |
360 |
|
|
elif str == '--linear': |
361 |
|
|
linear = 1 |
362 |
|
|
elif str == '--nolinear': |
363 |
|
|
linear = 0 |
364 |
|
|
elif str == '--lba32': |
365 |
|
|
forceLBA = 1 |
366 |
|
|
elif str == '--password': |
367 |
|
|
password = arg |
368 |
|
|
elif str == '--md5pass': |
369 |
|
|
md5pass = arg |
370 |
|
|
elif str == '--upgrade': |
371 |
|
|
upgrade = 1 |
372 |
|
|
elif str == '--driveorder': |
373 |
|
|
driveorder = string.split(arg, ',') |
374 |
|
|
|
375 |
|
|
if location not in validLocations: |
376 |
|
|
raise KickstartValueError, "mbr, partition, or none expected for bootloader command" |
377 |
|
|
if location == "none": |
378 |
|
|
location = None |
379 |
|
|
elif location == "partition": |
380 |
|
|
location = "boot" |
381 |
|
|
|
382 |
|
|
if upgrade and not id.upgrade.get(): |
383 |
|
|
raise KickstartError, "Selected upgrade mode for bootloader but not doing an upgrade" |
384 |
|
|
|
385 |
|
|
if upgrade: |
386 |
|
|
id.bootloader.kickstart = 1 |
387 |
|
|
id.bootloader.doUpgradeOnly = 1 |
388 |
|
|
|
389 |
|
|
if location is None: |
390 |
|
|
self.skipSteps.append("bootloadersetup") |
391 |
|
|
self.skipSteps.append("instbootloader") |
392 |
|
|
else: |
393 |
|
|
self.showSteps.append("bootloadersetup") |
394 |
|
|
self.setBootloader(id, useLilo, location, linear, forceLBA, |
395 |
|
|
password, md5pass, appendLine, driveorder) |
396 |
|
|
|
397 |
|
|
self.skipSteps.append("upgbootloader") |
398 |
|
|
self.skipSteps.append("bootloader") |
399 |
|
|
self.skipSteps.append("bootloaderadvanced") |
400 |
|
|
|
401 |
|
|
def doLilo (self, id, args): |
402 |
|
|
self.doBootloader(id, args, useLilo = 1) |
403 |
|
|
|
404 |
|
|
def doFirstboot(self, id, args): |
405 |
|
|
(args, extra) = isys.getopt(args, '', |
406 |
|
|
['reconfig', 'enable', 'enabled', |
407 |
|
|
'disable', 'disabled']) |
408 |
|
|
|
409 |
|
|
fb = FIRSTBOOT_SKIP |
410 |
|
|
|
411 |
|
|
for n in args: |
412 |
|
|
(str, arg) = n |
413 |
|
|
if str == '--reconfig': |
414 |
|
|
fb = FIRSTBOOT_RECONFIG |
415 |
|
|
elif str == '--enable' or str == "--enabled": |
416 |
|
|
fb = FIRSTBOOT_DEFAULT |
417 |
|
|
elif str == '--disable' or str == "--disabled": |
418 |
|
|
fb = FIRSTBOOT_SKIP |
419 |
|
|
|
420 |
|
|
id.firstboot = fb |
421 |
|
|
|
422 |
|
|
|
423 |
|
|
def doLiloCheck (self, id, args): |
424 |
|
|
drives = isys.hardDriveDict ().keys() |
425 |
|
|
drives.sort(isys.compareDrives) |
426 |
|
|
device = drives[0] |
427 |
|
|
isys.makeDevInode(device, '/tmp/' + device) |
428 |
|
|
fd = os.open('/tmp/' + device, os.O_RDONLY) |
429 |
|
|
os.unlink('/tmp/' + device) |
430 |
|
|
block = os.read(fd, 512) |
431 |
|
|
os.close(fd) |
432 |
|
|
if block[6:10] == "LILO": |
433 |
|
|
sys.exit(0) |
434 |
|
|
|
435 |
|
|
def doTimezone(self, id, args): |
436 |
|
|
(args, extra) = isys.getopt(args, '', |
437 |
|
|
[ 'utc' ]) |
438 |
|
|
|
439 |
|
|
isUtc = 0 |
440 |
|
|
|
441 |
|
|
for n in args: |
442 |
|
|
(str, arg) = n |
443 |
|
|
if str == '--utc': |
444 |
|
|
isUtc = 1 |
445 |
|
|
|
446 |
|
|
self.setTimezoneInfo(id, extra[0], asUtc = isUtc) |
447 |
|
|
|
448 |
|
|
self.skipSteps.append("timezone") |
449 |
|
|
|
450 |
|
|
|
451 |
|
|
def doXconfig(self, id, args): |
452 |
|
|
(args, extra) = isys.getopt(args, '', |
453 |
|
|
[ 'server=', 'card=', 'videoram=', |
454 |
|
|
'monitor=', 'hsync=', 'vsync=', |
455 |
|
|
'resolution=', 'depth=', |
456 |
|
|
'startxonboot', 'noprobe', 'defaultdesktop=' ]) |
457 |
|
|
|
458 |
|
|
if extra: |
459 |
|
|
raise KickstartValueError, "unexpected arguments to xconfig command" |
460 |
|
|
|
461 |
|
|
server = None |
462 |
|
|
card = None |
463 |
|
|
videoRam = None |
464 |
|
|
monitor = None |
465 |
|
|
hsync = None |
466 |
|
|
vsync = None |
467 |
|
|
resolution = None |
468 |
|
|
depth = None |
469 |
|
|
noProbe = 0 |
470 |
|
|
startX = 0 |
471 |
|
|
defaultdesktop = "" |
472 |
|
|
|
473 |
|
|
for n in args: |
474 |
|
|
(str, arg) = n |
475 |
|
|
if (str == "--noprobe"): |
476 |
|
|
noProbe = 1 |
477 |
|
|
elif (str == "--server"): |
478 |
|
|
server = arg |
479 |
|
|
elif (str == "--card"): |
480 |
|
|
card = arg |
481 |
|
|
elif (str == "--videoram"): |
482 |
|
|
videoRam = arg |
483 |
|
|
elif (str == "--monitor"): |
484 |
|
|
monitor = arg |
485 |
|
|
elif (str == "--hsync"): |
486 |
|
|
hsync = arg |
487 |
|
|
elif (str == "--vsync"): |
488 |
|
|
vsync = arg |
489 |
|
|
elif (str == "--resolution"): |
490 |
|
|
resolution = arg |
491 |
|
|
elif (str == "--depth"): |
492 |
|
|
depth = string.atoi(arg) |
493 |
|
|
elif (str == "--startxonboot"): |
494 |
|
|
startX = 1 |
495 |
|
|
elif (str == "--defaultdesktop"): |
496 |
|
|
defaultdesktop = arg |
497 |
|
|
|
498 |
|
|
self.configureX(id, server, card, videoRam, monitor, hsync, vsync, |
499 |
|
|
resolution, depth, noProbe, startX) |
500 |
|
|
self.setDesktop(id, defaultdesktop) |
501 |
|
|
|
502 |
|
|
self.skipSteps.append("videocard") |
503 |
|
|
self.skipSteps.append("monitor") |
504 |
|
|
self.skipSteps.append("xcustom") |
505 |
|
|
self.skipSteps.append("handleX11pkgs") |
506 |
|
|
self.skipSteps.append("checkmonitorok") |
507 |
|
|
self.skipSteps.append("setsanex") |
508 |
|
|
|
509 |
|
|
def doMonitor(self, id, args): |
510 |
|
|
(args, extra) = isys.getopt(args, '', |
511 |
|
|
[ 'monitor=', 'hsync=', 'vsync=' ]) |
512 |
|
|
|
513 |
|
|
if extra: |
514 |
|
|
raise KickstartValueError, "unexpected arguments to monitor command" |
515 |
|
|
|
516 |
|
|
monitor = None |
517 |
|
|
hsync = None |
518 |
|
|
vsync = None |
519 |
|
|
|
520 |
|
|
for n in args: |
521 |
|
|
(str, arg) = n |
522 |
|
|
if (str == "--monitor"): |
523 |
|
|
monitor = arg |
524 |
|
|
elif (str == "--hsync"): |
525 |
|
|
hsync = arg |
526 |
|
|
elif (str == "--vsync"): |
527 |
|
|
vsync = arg |
528 |
|
|
|
529 |
|
|
self.skipSteps.append("monitor") |
530 |
|
|
self.skipSteps.append("checkmonitorok") |
531 |
|
|
|
532 |
|
|
self.setMonitor(id, hsync = hsync, vsync = vsync, |
533 |
|
|
monitorName = monitor) |
534 |
|
|
|
535 |
|
|
def doUpgrade(self, id, args): |
536 |
|
|
self.installType = "upgrade" |
537 |
|
|
id.upgrade.set(1) |
538 |
|
|
|
539 |
|
|
def doNetwork(self, id, args): |
540 |
|
|
# nodns is only used by the loader |
541 |
|
|
(args, extra) = isys.getopt(args, '', |
542 |
|
|
[ 'bootproto=', 'ip=', 'netmask=', 'gateway=', 'nameserver=', |
543 |
|
|
'nodns', 'device=', 'hostname=', 'ethtool=', 'onboot=', |
544 |
|
|
'dhcpclass=', 'essid=', 'wepkey=', 'notksdevice']) |
545 |
|
|
bootProto = "dhcp" |
546 |
|
|
ip = None |
547 |
|
|
netmask = "" |
548 |
|
|
gateway = "" |
549 |
|
|
nameserver = "" |
550 |
|
|
hostname = "" |
551 |
|
|
ethtool = "" |
552 |
|
|
essid = "" |
553 |
|
|
wepkey = "" |
554 |
|
|
onboot = 1 |
555 |
|
|
device = None |
556 |
|
|
dhcpclass = None |
557 |
|
|
for n in args: |
558 |
|
|
(str, arg) = n |
559 |
|
|
if str == "--bootproto": |
560 |
|
|
bootProto = arg |
561 |
|
|
elif str == "--ip": |
562 |
|
|
ip = arg |
563 |
|
|
elif str == "--netmask": |
564 |
|
|
netmask = arg |
565 |
|
|
elif str == "--gateway": |
566 |
|
|
gateway = arg |
567 |
|
|
elif str == "--nameserver": |
568 |
|
|
nameserver = arg |
569 |
|
|
elif str == "--device": |
570 |
|
|
device = arg |
571 |
|
|
elif str == "--hostname": |
572 |
|
|
hostname = arg |
573 |
|
|
elif str== "--ethtool": |
574 |
|
|
ethtool = arg |
575 |
|
|
elif str == "--essid": |
576 |
|
|
essid = arg |
577 |
|
|
elif str == "--wepkey": |
578 |
|
|
wepkey = arg |
579 |
|
|
elif str== "--onboot": |
580 |
|
|
if arg == 'no': |
581 |
|
|
onboot = 0 |
582 |
|
|
else: |
583 |
|
|
onboot = 1 |
584 |
|
|
elif str == "--class": |
585 |
|
|
dhcpclass = arg |
586 |
|
|
|
587 |
|
|
self.setNetwork(id, bootProto, ip, netmask, ethtool, device=device, onboot=onboot, dhcpclass=dhcpclass, essid=essid, wepkey=wepkey) |
588 |
|
|
if hostname != "": |
589 |
|
|
self.setHostname(id, hostname, override = 1) |
590 |
|
|
if nameserver != "": |
591 |
|
|
self.setNameserver(id, nameserver) |
592 |
|
|
if gateway != "": |
593 |
|
|
self.setGateway(id, gateway) |
594 |
|
|
|
595 |
|
|
def doLang(self, id, args): |
596 |
|
|
self.setLanguage(id, args[0]) |
597 |
|
|
self.skipSteps.append("language") |
598 |
|
|
|
599 |
|
|
def doLangSupport (self, id, args): |
600 |
|
|
(args, extra) = isys.getopt(args, '', [ 'default=' ]) |
601 |
|
|
deflang = "en_US.UTF-8" |
602 |
|
|
if args: |
603 |
|
|
deflang = args[0][1] |
604 |
|
|
else: |
605 |
|
|
# if they specified no default we default to en_US if |
606 |
|
|
# they installed support for more than one lang, otherwise |
607 |
|
|
# we default to the one language they specified support for |
608 |
|
|
if extra is None: |
609 |
|
|
deflang = "en_US.UTF-8" |
610 |
|
|
elif len(extra) >= 1: |
611 |
|
|
deflang = extra[0] |
612 |
|
|
else: |
613 |
|
|
deflang = "en_US.UTF-8" |
614 |
|
|
|
615 |
|
|
self.setLanguageDefault (id, deflang) |
616 |
|
|
self.setLanguageSupport(id, extra) |
617 |
|
|
|
618 |
|
|
self.skipSteps.append("languagesupport") |
619 |
|
|
|
620 |
|
|
def doKeyboard(self, id, args): |
621 |
|
|
self.setKeyboard(id, args[0]) |
622 |
|
|
id.keyboard.beenset = 1 |
623 |
|
|
self.skipSteps.append("keyboard") |
624 |
|
|
|
625 |
|
|
def doZeroMbr(self, id, args): |
626 |
|
|
self.setZeroMbr(id, 1) |
627 |
|
|
|
628 |
|
|
def doMouse(self, id, args): |
629 |
|
|
#Don't do anything with mice anymore |
630 |
|
|
return |
631 |
|
|
|
632 |
|
|
## (args, extra) = isys.getopt(args, '', [ 'device=', 'emulthree' ]) |
633 |
|
|
## mouseType = "none" |
634 |
|
|
## device = None |
635 |
|
|
## emulThree = 0 |
636 |
|
|
|
637 |
|
|
## for n in args: |
638 |
|
|
## (str, arg) = n |
639 |
|
|
## if str == "--device": |
640 |
|
|
## device = arg |
641 |
|
|
## elif str == "--emulthree": |
642 |
|
|
## emulThree = 1 |
643 |
|
|
|
644 |
|
|
## if extra: |
645 |
|
|
## mouseType = extra[0] |
646 |
|
|
|
647 |
|
|
## if mouseType != "none": |
648 |
|
|
## self.setMouse(id, mouseType, device, emulThree) |
649 |
|
|
|
650 |
|
|
## self.skipSteps.append("mouse") |
651 |
|
|
|
652 |
|
|
def doReboot(self, id, args): |
653 |
|
|
self.skipSteps.append("complete") |
654 |
|
|
|
655 |
|
|
def doSkipX(self, id, args): |
656 |
|
|
self.skipSteps.append("checkmonitorok") |
657 |
|
|
self.skipSteps.append("setsanex") |
658 |
|
|
self.skipSteps.append("videocard") |
659 |
|
|
self.skipSteps.append("monitor") |
660 |
|
|
self.skipSteps.append("xcustom") |
661 |
|
|
self.skipSteps.append("handleX11pkgs") |
662 |
|
|
self.skipSteps.append("writexconfig") |
663 |
|
|
if id.xsetup is not None: |
664 |
|
|
id.xsetup.skipx = 1 |
665 |
|
|
|
666 |
|
|
def doInteractive(self, id, args): |
667 |
|
|
self.interactive = 1 |
668 |
|
|
|
669 |
|
|
def doAutoStep(self, id, args): |
670 |
|
|
flags.autostep = 1 |
671 |
|
|
flags.autoscreenshot = 0 |
672 |
|
|
|
673 |
|
|
(xargs, xtra) = isys.getopt(args, '', ['autoscreenshot']) |
674 |
|
|
for n in xargs: |
675 |
|
|
(str, arg) = n |
676 |
|
|
if str == "--autoscreenshot": |
677 |
|
|
flags.autoscreenshot = 1 |
678 |
|
|
|
679 |
|
|
|
680 |
|
|
# read the kickstart config... if parsePre is set, only parse |
681 |
|
|
# the %pre, otherwise ignore the %pre. assume we're starting in where |
682 |
|
|
def readKickstart(self, id, file, parsePre = 0, where = "commands"): |
683 |
|
|
handlers = { |
684 |
|
|
"auth" : self.doAuthconfig , |
685 |
|
|
"authconfig" : self.doAuthconfig , |
686 |
|
|
"autopart" : self.doAutoPart , |
687 |
|
|
"cdrom" : None , |
688 |
|
|
"clearpart" : self.doClearPart , |
689 |
|
|
"ignoredisk" : self.doIgnoreDisk , |
690 |
|
|
"device" : None , |
691 |
|
|
"deviceprobe" : None , |
692 |
|
|
"driverdisk" : None , |
693 |
|
|
"firewall" : self.doFirewall , |
694 |
|
|
"selinux" : self.doSELinux , |
695 |
|
|
"harddrive" : None , |
696 |
|
|
"install" : None , |
697 |
|
|
"keyboard" : self.doKeyboard , |
698 |
|
|
"lang" : self.doLang , |
699 |
|
|
"langsupport" : self.doLangSupport , |
700 |
|
|
"lilo" : self.doLilo , |
701 |
|
|
"bootloader" : self.doBootloader , |
702 |
|
|
"lilocheck" : self.doLiloCheck , |
703 |
|
|
"mouse" : self.doMouse , |
704 |
|
|
"network" : self.doNetwork , |
705 |
|
|
"nfs" : None , |
706 |
|
|
"part" : self.definePartition , |
707 |
|
|
"partition" : self.definePartition , |
708 |
|
|
"raid" : self.defineRaid , |
709 |
|
|
"volgroup" : self.defineVolumeGroup, |
710 |
|
|
"logvol" : self.defineLogicalVolume, |
711 |
|
|
"reboot" : self.doReboot , |
712 |
|
|
"poweroff" : self.doReboot , |
713 |
|
|
"halt" : self.doReboot , |
714 |
|
|
"shutdown" : self.doReboot , |
715 |
|
|
"rootpw" : self.doRootPw , |
716 |
|
|
"skipx" : self.doSkipX , |
717 |
|
|
"text" : None , |
718 |
|
|
"graphical" : None , |
719 |
|
|
"cmdline" : None , |
720 |
|
|
"timezone" : self.doTimezone , |
721 |
|
|
"url" : None , |
722 |
|
|
"upgrade" : self.doUpgrade , |
723 |
|
|
"xconfig" : self.doXconfig , |
724 |
|
|
"monitor" : self.doMonitor , |
725 |
|
|
"xdisplay" : None , |
726 |
|
|
"zerombr" : self.doZeroMbr , |
727 |
|
|
"interactive" : self.doInteractive , |
728 |
|
|
"autostep" : self.doAutoStep , |
729 |
|
|
"firstboot" : self.doFirstboot , |
730 |
|
|
"vnc" : None , |
731 |
|
|
} |
732 |
|
|
|
733 |
|
|
packages = [] |
734 |
|
|
groups = [] |
735 |
|
|
excludedPackages = [] |
736 |
|
|
|
737 |
|
|
script = "" |
738 |
|
|
scriptInterp = "/bin/sh" |
739 |
|
|
scriptLog = None |
740 |
|
|
if where == "pre" or where == "traceback": |
741 |
|
|
scriptChroot = 0 |
742 |
|
|
else: |
743 |
|
|
scriptChroot = 1 |
744 |
|
|
|
745 |
|
|
for n in open(file).readlines(): |
746 |
|
|
args = isys.parseArgv(n) |
747 |
|
|
|
748 |
|
|
# don't eliminate white space or comments from scripts |
749 |
|
|
if where not in ["pre", "post", "traceback"]: |
750 |
|
|
if not args or args[0][0] == '#': continue |
751 |
|
|
|
752 |
|
|
if args and (args[0] in ["%pre", "%post", "%traceback"]): |
753 |
|
|
if ((where =="pre" and parsePre) or |
754 |
|
|
(where in ["post", "traceback"] and not parsePre)): |
755 |
|
|
s = Script(script, scriptInterp, scriptChroot, scriptLog) |
756 |
|
|
if where == "pre": |
757 |
|
|
self.preScripts.append(s) |
758 |
|
|
elif where == "post": |
759 |
|
|
self.postScripts.append(s) |
760 |
|
|
else: |
761 |
|
|
self.tracebackScripts.append(s) |
762 |
|
|
|
763 |
|
|
where = args[0][1:] |
764 |
|
|
args = isys.parseArgv(n) |
765 |
|
|
|
766 |
|
|
script = "" |
767 |
|
|
scriptInterp = "/bin/sh" |
768 |
|
|
scriptLog = None |
769 |
|
|
if where == "pre" or where == "traceback": |
770 |
|
|
scriptChroot = 0 |
771 |
|
|
else: |
772 |
|
|
scriptChroot = 1 |
773 |
|
|
|
774 |
|
|
argList = [ 'interpreter=', "log=", "logfile=" ] |
775 |
|
|
if where == "post": |
776 |
|
|
argList.append('nochroot') |
777 |
|
|
|
778 |
|
|
(args, extra) = isys.getopt(args, '', argList) |
779 |
|
|
for n in args: |
780 |
|
|
(str, arg) = n |
781 |
|
|
|
782 |
|
|
if str == "--nochroot": |
783 |
|
|
scriptChroot = 0 |
784 |
|
|
elif str == "--interpreter": |
785 |
|
|
scriptInterp = arg |
786 |
|
|
elif str == "--log" or str == "--logfile": |
787 |
|
|
scriptLog = arg |
788 |
|
|
|
789 |
|
|
elif args and args[0] == "%include" and not parsePre: |
790 |
|
|
if len(args) < 2: |
791 |
|
|
raise KickstartError, "Invalid %include line" |
792 |
|
|
else: |
793 |
|
|
# read in the included file and set our where appropriately |
794 |
|
|
where = self.readKickstart(id, args[1], where = where) |
795 |
|
|
elif args and args[0] == "%packages": |
796 |
|
|
if ((where =="pre" and parsePre) or |
797 |
|
|
(where in ["post", "traceback"] and not parsePre)): |
798 |
|
|
s = Script(script, scriptInterp, scriptChroot, scriptLog) |
799 |
|
|
if where == "pre": |
800 |
|
|
self.preScripts.append(s) |
801 |
|
|
elif where == "post": |
802 |
|
|
self.postScripts.append(s) |
803 |
|
|
else: |
804 |
|
|
self.tracebackScripts.append(s) |
805 |
|
|
|
806 |
|
|
# if we're parsing the %pre, we don't need to continue |
807 |
|
|
if parsePre: |
808 |
|
|
continue |
809 |
|
|
|
810 |
|
|
if len(args) > 1: |
811 |
|
|
for arg in args[1:]: |
812 |
|
|
if arg == "--resolvedeps": |
813 |
|
|
id.handleDeps = RESOLVE_DEPS |
814 |
|
|
elif arg == "--ignoredeps": |
815 |
|
|
id.handleDeps = IGNORE_DEPS |
816 |
|
|
elif arg == "--excludedocs": |
817 |
|
|
id.excludeDocs = 1 |
818 |
|
|
elif arg == "--ignoremissing": |
819 |
|
|
self.handleMissing = KS_MISSING_IGNORE |
820 |
|
|
elif arg == "--nobase": |
821 |
|
|
self.addBase = 0 |
822 |
|
|
|
823 |
|
|
where = "packages" |
824 |
|
|
self.skipSteps.append("package-selection") |
825 |
|
|
else: |
826 |
|
|
# if we're parsing the %pre and not in the pre, continue |
827 |
|
|
if parsePre and where != "pre": |
828 |
|
|
continue |
829 |
|
|
elif where == "packages": |
830 |
|
|
#Scan for comments in package list...drop off |
831 |
|
|
#everything after "#" mark |
832 |
|
|
try: |
833 |
|
|
ind = string.index(n, "#") |
834 |
|
|
n = n[:ind] |
835 |
|
|
except: |
836 |
|
|
#No "#" found in line |
837 |
|
|
pass |
838 |
|
|
|
839 |
|
|
if n[0] == '@': |
840 |
|
|
n = n[1:] |
841 |
|
|
n = string.strip (n) |
842 |
|
|
groups.append(n) |
843 |
|
|
elif n[0] == '-': |
844 |
|
|
n = n[1:] |
845 |
|
|
n = string.strip(n) |
846 |
|
|
excludedPackages.append(n) |
847 |
|
|
else: |
848 |
|
|
n = string.strip (n) |
849 |
|
|
packages.append(n) |
850 |
|
|
elif where == "commands": |
851 |
|
|
if handlers.has_key(args[0]): |
852 |
|
|
if handlers[args[0]] is not None: |
853 |
|
|
handlers[args[0]](id, args[1:]) |
854 |
|
|
else: |
855 |
|
|
# unrecognized command |
856 |
|
|
raise KickstartError, "Unrecognized ks command: %s\nOn the line: %s" % (args[0], n) |
857 |
|
|
elif where in ["pre", "post", "traceback"]: |
858 |
|
|
script = script + n |
859 |
|
|
else: |
860 |
|
|
raise KickstartError, "I'm lost in kickstart" |
861 |
|
|
|
862 |
|
|
self.groupList.extend(groups) |
863 |
|
|
self.packageList.extend(packages) |
864 |
|
|
self.excludedList.extend(excludedPackages) |
865 |
|
|
|
866 |
|
|
# test to see if they specified to clear partitions and also |
867 |
|
|
# tried to --onpart on a logical partition |
868 |
|
|
# |
869 |
|
|
# XXX |
870 |
|
|
# |
871 |
|
|
#if iutil.getArch() == 'i386' and self.fstab: |
872 |
|
|
#clear = self.getClearParts() |
873 |
|
|
#if clear == FSEDIT_CLEAR_LINUX or clear == FSEDIT_CLEAR_ALL: |
874 |
|
|
#for (mntpoint, (dev, fstype, reformat)) in self.fstab: |
875 |
|
|
#if int(dev[-1:]) > 4: |
876 |
|
|
#raise RuntimeError, "Clearpart and --onpart on non-primary partition %s not allowed" % dev |
877 |
|
|
|
878 |
|
|
if ((where =="pre" and parsePre) or |
879 |
|
|
(where in ["post", "traceback"] and not parsePre)): |
880 |
|
|
s = Script(script, scriptInterp, scriptChroot, scriptLog) |
881 |
|
|
if where == "pre": |
882 |
|
|
self.preScripts.append(s) |
883 |
|
|
elif where == "post": |
884 |
|
|
self.postScripts.append(s) |
885 |
|
|
else: |
886 |
|
|
self.tracebackScripts.append(s) |
887 |
|
|
|
888 |
|
|
return where |
889 |
|
|
|
890 |
|
|
def doClearPart(self, id, args): |
891 |
|
|
type = CLEARPART_TYPE_NONE |
892 |
|
|
drives = None |
893 |
|
|
initAll = 0 |
894 |
|
|
|
895 |
|
|
(args, extra) = isys.getopt(args, '', [ 'linux', 'all', 'drives=', |
896 |
|
|
'initlabel', 'none']) |
897 |
|
|
|
898 |
|
|
for n in args: |
899 |
|
|
(str, arg) = n |
900 |
|
|
if str == '--linux': |
901 |
|
|
type = CLEARPART_TYPE_LINUX |
902 |
|
|
elif str == '--all': |
903 |
|
|
type = CLEARPART_TYPE_ALL |
904 |
|
|
elif str == '--drives': |
905 |
|
|
drives = string.split(arg, ',') |
906 |
|
|
elif str == '--initlabel': |
907 |
|
|
initAll = 1 |
908 |
|
|
elif str == '--none': |
909 |
|
|
type = CLEARPART_TYPE_NONE |
910 |
|
|
|
911 |
|
|
self.setClearParts(id, type, drives, initAll = initAll) |
912 |
|
|
|
913 |
|
|
# this adds a partition to the autopartition list replacing anything |
914 |
|
|
# else with this mountpoint so that you can use autopart and override / |
915 |
|
|
def addPartRequest(self, partitions, request): |
916 |
|
|
if not request.mountpoint: |
917 |
|
|
partitions.autoPartitionRequests.append(request) |
918 |
|
|
return |
919 |
|
|
|
920 |
|
|
for req in partitions.autoPartitionRequests: |
921 |
|
|
if req.mountpoint and req.mountpoint == request.mountpoint: |
922 |
|
|
partitions.autoPartitionRequests.remove(req) |
923 |
|
|
break |
924 |
|
|
partitions.autoPartitionRequests.append(request) |
925 |
|
|
|
926 |
|
|
def doAutoPart(self, id, args): |
927 |
|
|
# sets up default autopartitioning. use clearpart separately |
928 |
|
|
# if you want it |
929 |
|
|
self.setDefaultPartitioning(id, doClear = 0) |
930 |
|
|
|
931 |
|
|
id.partitions.isKickstart = 1 |
932 |
|
|
|
933 |
|
|
self.skipSteps.append("partition") |
934 |
|
|
self.skipSteps.append("partitionmethod") |
935 |
|
|
self.skipSteps.append("partitionmethodsetup") |
936 |
|
|
self.skipSteps.append("fdisk") |
937 |
|
|
self.skipSteps.append("autopartition") |
938 |
|
|
self.skipSteps.append("zfcpconfig") |
939 |
|
|
|
940 |
|
|
def defineLogicalVolume(self, id, args): |
941 |
|
|
(args, extra) = isys.getopt(args, '', [ 'vgname=', |
942 |
|
|
'size=', |
943 |
|
|
'name=', |
944 |
|
|
'fstype=', |
945 |
|
|
'percent=', |
946 |
|
|
'maxsize=', |
947 |
|
|
'grow', |
948 |
|
|
'recommended', |
949 |
|
|
'noformat', |
950 |
|
|
'useexisting']) |
951 |
|
|
|
952 |
|
|
mountpoint = None |
953 |
|
|
vgname = None |
954 |
|
|
size = None |
955 |
|
|
name = None |
956 |
|
|
fstype = None |
957 |
|
|
percent = None |
958 |
|
|
grow = 0 |
959 |
|
|
maxSizeMB = 0 |
960 |
|
|
format = 1 |
961 |
|
|
recommended = None |
962 |
|
|
preexist = 0 |
963 |
|
|
|
964 |
|
|
for n in args: |
965 |
|
|
(str, arg) = n |
966 |
|
|
if str == '--vgname': |
967 |
|
|
vgname = arg |
968 |
|
|
elif str == '--size': |
969 |
|
|
size = int(arg) |
970 |
|
|
elif str == '--name': |
971 |
|
|
name = arg |
972 |
|
|
elif str == '--fstype': |
973 |
|
|
fstype = arg |
974 |
|
|
elif str == '--percent': |
975 |
|
|
percent = int(arg) |
976 |
|
|
elif str == '--maxsize': |
977 |
|
|
maxSizeMB = int(arg) |
978 |
|
|
elif str == '--grow': |
979 |
|
|
grow = 1 |
980 |
|
|
elif str == '--recommended': |
981 |
|
|
recommended = 1 |
982 |
|
|
elif str == "--noformat": |
983 |
|
|
format = 0 |
984 |
|
|
preexist = 1 |
985 |
|
|
elif str == "--useexisting": |
986 |
|
|
preexist = 1 |
987 |
|
|
|
988 |
|
|
if extra[0] == 'swap': |
989 |
|
|
filesystem = fileSystemTypeGet('swap') |
990 |
|
|
mountpoint = None |
991 |
|
|
if recommended: |
992 |
|
|
(size, maxSizeMB) = iutil.swapSuggestion() |
993 |
|
|
grow = 1 |
994 |
|
|
else: |
995 |
|
|
if fstype: |
996 |
|
|
filesystem = fileSystemTypeGet(fstype) |
997 |
|
|
else: |
998 |
|
|
filesystem = fileSystemTypeGetDefault() |
999 |
|
|
|
1000 |
|
|
mountpoint = extra[0] |
1001 |
|
|
|
1002 |
|
|
# sanity check mountpoint |
1003 |
|
|
if mountpoint is not None and mountpoint[0] != '/': |
1004 |
|
|
raise KickstartError, "The mount point \"%s\" is not valid." % (mountpoint,) |
1005 |
|
|
|
1006 |
|
|
if not vgname: |
1007 |
|
|
raise KickstartError, "Must specify the volume group for the logical volume to be in" |
1008 |
|
|
if not size and not percent and not preexist: |
1009 |
|
|
raise KickstartError, "Must specify the size of a logical volume" |
1010 |
|
|
if percent and percent <= 0 or percent > 100: |
1011 |
|
|
raise KickstartValueError, "Logical Volume percentage must be between 0 and 100 percent" |
1012 |
|
|
|
1013 |
|
|
if not name: |
1014 |
|
|
raise KickstartError, "Must specify a logical volume name" |
1015 |
|
|
|
1016 |
|
|
vgid = self.ksVGMapping[vgname] |
1017 |
|
|
for areq in id.partitions.autoPartitionRequests: |
1018 |
|
|
if areq.type == REQUEST_LV: |
1019 |
|
|
if areq.volumeGroup == vgid and areq.logicalVolumeName == name: |
1020 |
|
|
raise KickstartValueError, "Logical volume name %s already used in volume group %s" % (name,vgname) |
1021 |
|
|
|
1022 |
|
|
if not self.ksVGMapping.has_key(vgname): |
1023 |
|
|
raise KickstartValueError, "Logical volume specifies a non-existent volume group" |
1024 |
|
|
|
1025 |
|
|
request = partRequests.LogicalVolumeRequestSpec(filesystem, |
1026 |
|
|
format = format, |
1027 |
|
|
mountpoint = mountpoint, |
1028 |
|
|
size = size, |
1029 |
|
|
percent = percent, |
1030 |
|
|
volgroup = vgid, |
1031 |
|
|
lvname = name, |
1032 |
|
|
grow = grow, |
1033 |
|
|
maxSizeMB=maxSizeMB, |
1034 |
|
|
preexist = preexist) |
1035 |
|
|
self.addPartRequest(id.partitions, request) |
1036 |
|
|
|
1037 |
|
|
|
1038 |
|
|
def defineVolumeGroup(self, id, args): |
1039 |
|
|
(args, extra) = isys.getopt(args, '', ['noformat','useexisting', |
1040 |
|
|
'pesize=']) |
1041 |
|
|
|
1042 |
|
|
preexist = 0 |
1043 |
|
|
format = 1 |
1044 |
|
|
pesize = 32768 |
1045 |
|
|
|
1046 |
|
|
vgname = extra[0] |
1047 |
|
|
|
1048 |
|
|
for n in args: |
1049 |
|
|
(str, arg) = n |
1050 |
|
|
if str == '--noformat' or str == '--useexisting': |
1051 |
|
|
preexist = 1 |
1052 |
|
|
format = 0 |
1053 |
|
|
elif str == "--pesize": |
1054 |
|
|
pesize = int(arg) |
1055 |
|
|
|
1056 |
|
|
pvs = [] |
1057 |
|
|
# get the unique ids of each of the physical volumes |
1058 |
|
|
for pv in extra[1:]: |
1059 |
|
|
if pv not in self.ksPVMapping.keys(): |
1060 |
|
|
raise KickstartError, "Tried to use an undefined partition in Volume Group specification" |
1061 |
|
|
pvs.append(self.ksPVMapping[pv]) |
1062 |
|
|
|
1063 |
|
|
if len(pvs) == 0 and not preexist: |
1064 |
|
|
raise KickstartError, "Volume group defined without any physical volumes" |
1065 |
|
|
|
1066 |
|
|
if pesize not in lvm.getPossiblePhysicalExtents(floor=1024): |
1067 |
|
|
raise KickstartError, "Volume group specified invalid pesize: %d" %(pesize,) |
1068 |
|
|
|
1069 |
|
|
# get a sort of hackish id |
1070 |
|
|
uniqueID = self.ksID |
1071 |
|
|
self.ksVGMapping[extra[0]] = uniqueID |
1072 |
|
|
self.ksID = self.ksID + 1 |
1073 |
|
|
|
1074 |
|
|
request = partRequests.VolumeGroupRequestSpec(vgname = vgname, |
1075 |
|
|
physvols = pvs, |
1076 |
|
|
preexist = preexist, |
1077 |
|
|
format = format, |
1078 |
|
|
pesize = pesize) |
1079 |
|
|
request.uniqueID = uniqueID |
1080 |
|
|
self.addPartRequest(id.partitions, request) |
1081 |
|
|
|
1082 |
|
|
def defineRaid(self, id, args): |
1083 |
|
|
(args, extra) = isys.getopt(args, '', [ 'level=', 'device=', |
1084 |
|
|
'spares=', 'fstype=', |
1085 |
|
|
'noformat', 'useexisting'] ) |
1086 |
|
|
|
1087 |
|
|
level = None |
1088 |
|
|
raidDev = None |
1089 |
|
|
spares = 0 |
1090 |
|
|
fstype = None |
1091 |
|
|
format = 1 |
1092 |
|
|
uniqueID = None |
1093 |
|
|
preexist = 0 |
1094 |
|
|
|
1095 |
|
|
for n in args: |
1096 |
|
|
(str, arg) = n |
1097 |
|
|
if str == '--level': |
1098 |
|
|
level = arg |
1099 |
|
|
elif str == "--device": |
1100 |
|
|
raidDev = arg |
1101 |
|
|
if raidDev[0:2] == "md": |
1102 |
|
|
raidDev = raidDev[2:] |
1103 |
|
|
raidDev = int(raidDev) |
1104 |
|
|
elif str == "--spares": |
1105 |
|
|
spares = int(arg) |
1106 |
|
|
elif str == "--noformat": |
1107 |
|
|
format = 0 |
1108 |
|
|
preexist = 1 |
1109 |
|
|
elif str == "--useexisting": |
1110 |
|
|
preexist = 1 |
1111 |
|
|
elif str == "--fstype": |
1112 |
|
|
fstype = arg |
1113 |
|
|
|
1114 |
|
|
if extra[0] == 'swap': |
1115 |
|
|
filesystem = fileSystemTypeGet('swap') |
1116 |
|
|
mountpoint = None |
1117 |
|
|
elif extra[0].startswith("pv."): |
1118 |
|
|
filesystem = fileSystemTypeGet("physical volume (LVM)") |
1119 |
|
|
mountpoint = None |
1120 |
|
|
|
1121 |
|
|
if self.ksPVMapping.has_key(extra[0]): |
1122 |
|
|
raise KickstartError, "Defined PV partition %s multiple times" % (extra[0],) |
1123 |
|
|
|
1124 |
|
|
# get a sort of hackish id |
1125 |
|
|
uniqueID = self.ksID |
1126 |
|
|
self.ksPVMapping[extra[0]] = uniqueID |
1127 |
|
|
self.ksID = self.ksID + 1 |
1128 |
|
|
else: |
1129 |
|
|
if fstype: |
1130 |
|
|
filesystem = fileSystemTypeGet(fstype) |
1131 |
|
|
else: |
1132 |
|
|
filesystem = fileSystemTypeGetDefault() |
1133 |
|
|
|
1134 |
|
|
mountpoint = extra[0] |
1135 |
|
|
|
1136 |
|
|
# sanity check mountpoint |
1137 |
|
|
if mountpoint is not None and mountpoint[0] != '/': |
1138 |
|
|
raise KickstartError, "The mount point \"%s\" is not valid." % (mountpoint,) |
1139 |
|
|
|
1140 |
|
|
raidmems = [] |
1141 |
|
|
# get the unique ids of each of the raid members |
1142 |
|
|
for member in extra[1:]: |
1143 |
|
|
if member not in self.ksRaidMapping.keys(): |
1144 |
|
|
raise KickstartError, "Tried to use an undefined partition in RAID specification" |
1145 |
|
|
if member in self.ksUsedMembers: |
1146 |
|
|
raise KickstartError, "Tried to use the RAID member %s in two or more RAID specifications" % (member,) |
1147 |
|
|
|
1148 |
|
|
raidmems.append(self.ksRaidMapping[member]) |
1149 |
|
|
self.ksUsedMembers.append(member) |
1150 |
|
|
|
1151 |
|
|
# XXX this shouldn't have to happen =\ |
1152 |
|
|
if raid.isRaid0(level): |
1153 |
|
|
level = "RAID0" |
1154 |
|
|
elif raid.isRaid1(level): |
1155 |
|
|
level = "RAID1" |
1156 |
|
|
elif raid.isRaid5(level): |
1157 |
|
|
level = "RAID5" |
1158 |
|
|
elif raid.isRaid6(level): |
1159 |
|
|
level = "RAID6" |
1160 |
|
|
|
1161 |
|
|
if not level and preexist == 0: |
1162 |
|
|
raise KickstartValueError, "RAID Partition defined without RAID level" |
1163 |
|
|
if len(raidmems) == 0 and preexist == 0: |
1164 |
|
|
raise KickstartValueError, "RAID Partition defined without any RAID members" |
1165 |
|
|
|
1166 |
|
|
request = partRequests.RaidRequestSpec(filesystem, |
1167 |
|
|
mountpoint = mountpoint, |
1168 |
|
|
raidmembers = raidmems, |
1169 |
|
|
raidlevel = level, |
1170 |
|
|
raidspares = spares, |
1171 |
|
|
format = format, |
1172 |
|
|
raidminor = raidDev, |
1173 |
|
|
preexist = preexist) |
1174 |
|
|
|
1175 |
|
|
if uniqueID: |
1176 |
|
|
request.uniqueID = uniqueID |
1177 |
|
|
if preexist and raidDev is not None: |
1178 |
|
|
request.device = "md%s" %(raidDev,) |
1179 |
|
|
|
1180 |
|
|
self.addPartRequest(id.partitions, request) |
1181 |
|
|
|
1182 |
|
|
|
1183 |
|
|
def definePartition(self, id, args): |
1184 |
|
|
# we set up partition requests (whee!) |
1185 |
|
|
size = None |
1186 |
|
|
grow = None |
1187 |
|
|
maxSize = None |
1188 |
|
|
disk = None |
1189 |
|
|
onPart = None |
1190 |
|
|
fsopts = None |
1191 |
|
|
type = None |
1192 |
|
|
primOnly = None |
1193 |
|
|
format = 1 |
1194 |
|
|
fstype = None |
1195 |
|
|
mountpoint = None |
1196 |
|
|
uniqueID = None |
1197 |
|
|
start = None |
1198 |
|
|
end = None |
1199 |
|
|
badblocks = None |
1200 |
|
|
recommended = None |
1201 |
|
|
|
1202 |
|
|
(args, extra) = isys.getopt(args, '', [ 'size=', 'maxsize=', |
1203 |
|
|
'grow', 'onpart=', 'ondisk=', |
1204 |
|
|
'bytes-per-inode=', 'usepart=', |
1205 |
|
|
'type=', 'fstype=', 'asprimary', |
1206 |
|
|
'noformat', 'start=', 'end=', |
1207 |
|
|
'badblocks', 'recommended', |
1208 |
|
|
'ondrive=', 'onbiosdisk=' ]) |
1209 |
|
|
|
1210 |
|
|
for n in args: |
1211 |
|
|
(str, arg) = n |
1212 |
|
|
if str == '--size': |
1213 |
|
|
size = int(arg) |
1214 |
|
|
elif str == '--maxsize': |
1215 |
|
|
maxSize = int(arg) |
1216 |
|
|
elif str == '--grow': |
1217 |
|
|
grow = 1 |
1218 |
|
|
elif str == '--onpart' or str == '--usepart': |
1219 |
|
|
onPart = arg |
1220 |
|
|
elif str == '--ondisk' or str == '--ondrive': |
1221 |
|
|
disk = arg |
1222 |
|
|
elif str == '--onbiosdisk': |
1223 |
|
|
disk = isys.doGetBiosDisk(arg) |
1224 |
|
|
if disk is None: |
1225 |
|
|
raise KickstartValueError, "Specified BIOS disk %s cannot be determined" %(arg,) |
1226 |
|
|
elif str == '--bytes-per-inode': |
1227 |
|
|
fsopts = ['-i', arg] |
1228 |
|
|
# XXX this doesn't do anything right now |
1229 |
|
|
elif str == '--type': |
1230 |
|
|
type = int(arg) |
1231 |
|
|
elif str == "--active": |
1232 |
|
|
active = 1 |
1233 |
|
|
elif str == "--asprimary": |
1234 |
|
|
primOnly = 1 |
1235 |
|
|
elif str == "--noformat": |
1236 |
|
|
format = 0 |
1237 |
|
|
elif str == "--fstype": |
1238 |
|
|
fstype = arg |
1239 |
|
|
elif str == "--start": |
1240 |
|
|
start = int(arg) |
1241 |
|
|
elif str == "--end": |
1242 |
|
|
end = int(arg) |
1243 |
|
|
elif str == "--badblocks": |
1244 |
|
|
# no longer support badblocks checking |
1245 |
|
|
log("WARNING: --badblocks specified but is no longer supported") |
1246 |
|
|
elif str == "--recommended": |
1247 |
|
|
recommended = 1 |
1248 |
|
|
|
1249 |
|
|
if len(extra) != 1: |
1250 |
|
|
raise KickstartValueError, "partition command requires one anonymous argument" |
1251 |
|
|
|
1252 |
|
|
if extra[0] == 'swap': |
1253 |
|
|
filesystem = fileSystemTypeGet('swap') |
1254 |
|
|
mountpoint = None |
1255 |
|
|
if recommended: |
1256 |
|
|
(size, maxSize) = iutil.swapSuggestion() |
1257 |
|
|
grow = 1 |
1258 |
|
|
# if people want to specify no mountpoint for some reason, let them |
1259 |
|
|
# this is really needed for pSeries boot partitions :( |
1260 |
|
|
elif extra[0] == 'None': |
1261 |
|
|
mountpoint = None |
1262 |
|
|
if fstype: |
1263 |
|
|
filesystem = fileSystemTypeGet(fstype) |
1264 |
|
|
else: |
1265 |
|
|
filesystem = fileSystemTypeGetDefault() |
1266 |
|
|
elif extra[0] == 'prepboot': |
1267 |
|
|
filesystem = fileSystemTypeGet("PPC PReP Boot") |
1268 |
|
|
mountpoint = None |
1269 |
|
|
elif extra[0].startswith("raid."): |
1270 |
|
|
filesystem = fileSystemTypeGet("software RAID") |
1271 |
|
|
|
1272 |
|
|
if self.ksRaidMapping.has_key(extra[0]): |
1273 |
|
|
raise KickstartError, "Defined RAID partition %s multiple times" % (extra[0],) |
1274 |
|
|
|
1275 |
|
|
# get a sort of hackish id |
1276 |
|
|
uniqueID = self.ksID |
1277 |
|
|
self.ksRaidMapping[extra[0]] = uniqueID |
1278 |
|
|
self.ksID = self.ksID + 1 |
1279 |
|
|
elif extra[0].startswith("pv."): |
1280 |
|
|
filesystem = fileSystemTypeGet("physical volume (LVM)") |
1281 |
|
|
|
1282 |
|
|
if self.ksPVMapping.has_key(extra[0]): |
1283 |
|
|
raise KickstartError, "Defined PV partition %s multiple times" % (extra[0],) |
1284 |
|
|
|
1285 |
|
|
# get a sort of hackish id |
1286 |
|
|
uniqueID = self.ksID |
1287 |
|
|
self.ksPVMapping[extra[0]] = uniqueID |
1288 |
|
|
self.ksID = self.ksID + 1 |
1289 |
|
|
# XXX should we let people not do this for some reason? |
1290 |
|
|
elif extra[0] == "/boot/efi": |
1291 |
|
|
filesystem = fileSystemTypeGet("vfat") |
1292 |
|
|
mountpoint = extra[0] |
1293 |
|
|
else: |
1294 |
|
|
if fstype: |
1295 |
|
|
filesystem = fileSystemTypeGet(fstype) |
1296 |
|
|
mountpoint = extra[0] |
1297 |
|
|
else: |
1298 |
|
|
filesystem = fileSystemTypeGetDefault() |
1299 |
|
|
mountpoint = extra[0] |
1300 |
|
|
|
1301 |
|
|
if (size is None) and (not start and not end) and (not onPart): |
1302 |
|
|
raise KickstartValueError, "partition command requires a size specification" |
1303 |
|
|
if start and not disk: |
1304 |
|
|
raise KickstartValueError, "partition command with start cylinder requires a drive specification" |
1305 |
|
|
if disk and disk not in isys.hardDriveDict().keys(): |
1306 |
|
|
raise KickstartValueError, "specified disk %s in partition command which does not exist" %(disk,) |
1307 |
|
|
|
1308 |
|
|
# XXX bytes per inode is the only per fs option at the moment |
1309 |
|
|
# and we can assume that it works like this since it only works |
1310 |
|
|
# with ext[23] |
1311 |
|
|
if fsopts: |
1312 |
|
|
filesystem.extraFormatArgs.extend(fsopts) |
1313 |
|
|
|
1314 |
|
|
request = partRequests.PartitionSpec(filesystem, |
1315 |
|
|
mountpoint = mountpoint, |
1316 |
|
|
format = 1) |
1317 |
|
|
|
1318 |
|
|
if size is not None: |
1319 |
|
|
request.size = size |
1320 |
|
|
if start: |
1321 |
|
|
request.start = start |
1322 |
|
|
if end: |
1323 |
|
|
request.end = end |
1324 |
|
|
if grow: |
1325 |
|
|
request.grow = 1 |
1326 |
|
|
if maxSize: |
1327 |
|
|
request.maxSizeMB = maxSize |
1328 |
|
|
if disk: |
1329 |
|
|
request.drive = [ disk ] |
1330 |
|
|
if primOnly: |
1331 |
|
|
request.primary = 1 |
1332 |
|
|
if not format: |
1333 |
|
|
request.format = 0 |
1334 |
|
|
if uniqueID: |
1335 |
|
|
request.uniqueID = uniqueID |
1336 |
|
|
if badblocks: |
1337 |
|
|
request.badblocks = badblocks |
1338 |
|
|
if onPart: |
1339 |
|
|
# strip spurious /dev |
1340 |
|
|
if onPart.startswith("/dev/"): |
1341 |
|
|
onPart = onPart[5:] |
1342 |
|
|
request.device = onPart |
1343 |
|
|
for areq in id.partitions.autoPartitionRequests: |
1344 |
|
|
if areq.device is not None and areq.device == onPart: |
1345 |
|
|
raise KickstartValueError, "Partition %s already used" %(onPart,) |
1346 |
|
|
|
1347 |
|
|
self.addPartRequest(id.partitions, request) |
1348 |
|
|
id.partitions.isKickstart = 1 |
1349 |
|
|
|
1350 |
|
|
self.skipSteps.append("partition") |
1351 |
|
|
self.skipSteps.append("partitionmethod") |
1352 |
|
|
self.skipSteps.append("partitionmethodsetup") |
1353 |
|
|
self.skipSteps.append("fdisk") |
1354 |
|
|
self.skipSteps.append("autopartition") |
1355 |
|
|
self.skipSteps.append("zfcpconfig") |
1356 |
|
|
|
1357 |
|
|
def doIgnoreDisk(self, id, args): |
1358 |
|
|
# add disks to ignore list |
1359 |
|
|
drives = [] |
1360 |
|
|
(args, extra) = isys.getopt(args, '', [ 'drives=' ]) |
1361 |
|
|
|
1362 |
|
|
for n in args: |
1363 |
|
|
(str, arg) = n |
1364 |
|
|
if str == '--drives': |
1365 |
|
|
drives = string.split(arg, ',') |
1366 |
|
|
|
1367 |
|
|
self.setIgnoredDisks(id, drives) |
1368 |
|
|
|
1369 |
|
|
def setSteps(self, dispatch): |
1370 |
|
|
if self.installType == "upgrade": |
1371 |
slords |
1.3 |
from upgradeclass import InstallClass |
1372 |
slords |
1.1 |
theUpgradeclass = InstallClass(0) |
1373 |
|
|
theUpgradeclass.setSteps(dispatch) |
1374 |
|
|
|
1375 |
|
|
# we have no way to specify migrating yet |
1376 |
|
|
dispatch.skipStep("upgrademigfind") |
1377 |
|
|
dispatch.skipStep("upgrademigratefs") |
1378 |
|
|
dispatch.skipStep("upgradecontinue") |
1379 |
|
|
dispatch.skipStep("findinstall", permanent = 1) |
1380 |
|
|
dispatch.skipStep("language") |
1381 |
|
|
dispatch.skipStep("keyboard") |
1382 |
|
|
# dispatch.skipStep("mouse") |
1383 |
|
|
dispatch.skipStep("welcome") |
1384 |
|
|
dispatch.skipStep("betanag") |
1385 |
|
|
dispatch.skipStep("installtype") |
1386 |
|
|
else: |
1387 |
|
|
BaseInstallClass.setSteps(self, dispatch) |
1388 |
|
|
dispatch.skipStep("findrootparts") |
1389 |
|
|
|
1390 |
|
|
if self.interactive or flags.autostep: |
1391 |
|
|
dispatch.skipStep("installtype") |
1392 |
|
|
dispatch.skipStep("partitionmethod") |
1393 |
|
|
dispatch.skipStep("partitionmethodsetup") |
1394 |
|
|
dispatch.skipStep("fdisk") |
1395 |
|
|
dispatch.skipStep("autopartition") |
1396 |
|
|
dispatch.skipStep("bootdisk") |
1397 |
|
|
|
1398 |
|
|
# because these steps depend on the monitor being probed |
1399 |
|
|
# properly, and will stop you if you have an unprobed monitor, |
1400 |
|
|
# we should skip them for autostep |
1401 |
|
|
if flags.autostep: |
1402 |
|
|
dispatch.skipStep("checkmonitorok") |
1403 |
|
|
dispatch.skipStep("monitor") |
1404 |
|
|
return |
1405 |
|
|
|
1406 |
|
|
dispatch.skipStep("bootdisk") |
1407 |
|
|
dispatch.skipStep("welcome") |
1408 |
|
|
dispatch.skipStep("betanag") |
1409 |
|
|
dispatch.skipStep("confirminstall") |
1410 |
|
|
dispatch.skipStep("confirmupgrade") |
1411 |
|
|
dispatch.skipStep("network") |
1412 |
|
|
dispatch.skipStep("installtype") |
1413 |
|
|
|
1414 |
|
|
# skipping firewall by default, disabled by default |
1415 |
|
|
dispatch.skipStep("firewall") |
1416 |
|
|
|
1417 |
|
|
for n in self.skipSteps: |
1418 |
|
|
dispatch.skipStep(n) |
1419 |
|
|
for n in self.showSteps: |
1420 |
|
|
dispatch.skipStep(n, skip = 0) |
1421 |
|
|
|
1422 |
|
|
def setInstallData(self, id, intf = None): |
1423 |
|
|
BaseInstallClass.setInstallData(self, id) |
1424 |
|
|
|
1425 |
|
|
self.setEarlySwapOn(1) |
1426 |
|
|
self.postScripts = [] |
1427 |
|
|
self.preScripts = [] |
1428 |
|
|
self.tracebackScripts = [] |
1429 |
|
|
|
1430 |
|
|
self.installType = "install" |
1431 |
|
|
self.id = id |
1432 |
|
|
self.id.firstboot = FIRSTBOOT_SKIP |
1433 |
|
|
|
1434 |
|
|
# parse the %pre |
1435 |
|
|
try: |
1436 |
|
|
self.readKickstart(id, self.file, parsePre = 1) |
1437 |
|
|
except KickstartError, e: |
1438 |
|
|
raise KickstartError, e |
1439 |
|
|
|
1440 |
|
|
log("Running kickstart %%pre script(s)") |
1441 |
|
|
for script in self.preScripts: |
1442 |
|
|
script.run("/", self.serial) |
1443 |
|
|
log("All kickstart %%pre script(s) have been run") |
1444 |
|
|
|
1445 |
|
|
# now read the kickstart file for real |
1446 |
|
|
try: |
1447 |
|
|
self.readKickstart(id, self.file) |
1448 |
|
|
except KickstartError, e: |
1449 |
|
|
log("Exception parsing ks.cfg: %s" %(e,)) |
1450 |
|
|
if intf is None: |
1451 |
|
|
raise KickstartError, e |
1452 |
|
|
else: |
1453 |
|
|
intf.kickstartErrorWindow(e.__str__()) |
1454 |
|
|
|
1455 |
|
|
def runTracebackScripts(self): |
1456 |
|
|
log("Running kickstart %%traceback script(s)") |
1457 |
|
|
for script in self.tracebackScripts: |
1458 |
|
|
script.run("/", self.serial) |
1459 |
|
|
|
1460 |
|
|
# Note that this assumes setGroupSelection() is called before |
1461 |
|
|
# setPackageSelection() |
1462 |
|
|
def setPackageSelection(self, hdlist, intf): |
1463 |
|
|
for n in self.packageList: |
1464 |
|
|
|
1465 |
|
|
# allow arch:name syntax |
1466 |
slords |
1.3 |
if n.find(".") != -1: |
1467 |
slords |
1.1 |
fields = n.split(".") |
1468 |
|
|
name = string.join(fields[:-1], ".") |
1469 |
|
|
arch = fields[-1] |
1470 |
|
|
found = 0 |
1471 |
|
|
if hdlist.pkgnames.has_key(name): |
1472 |
|
|
pkgs = hdlist.pkgnames[name] |
1473 |
|
|
for (nevra, parch) in pkgs: |
1474 |
|
|
if parch == arch: |
1475 |
|
|
hdlist.pkgs[nevra].select() |
1476 |
|
|
found = 1 |
1477 |
|
|
continue |
1478 |
|
|
if found: |
1479 |
|
|
continue |
1480 |
|
|
|
1481 |
|
|
if hdlist.has_key(n): |
1482 |
|
|
hdlist[n].select() |
1483 |
|
|
continue |
1484 |
|
|
|
1485 |
|
|
if self.handleMissing == KS_MISSING_IGNORE: |
1486 |
|
|
log("package %s doesn't exist, ignoring" %(n,)) |
1487 |
|
|
continue |
1488 |
|
|
|
1489 |
|
|
|
1490 |
|
|
rc = intf.messageWindow(_("Missing Package"), |
1491 |
|
|
_("You have specified that the " |
1492 |
|
|
"package '%s' should be installed. " |
1493 |
|
|
"This package does not exist. " |
1494 |
|
|
"Would you like to continue or " |
1495 |
|
|
"abort your installation?") %(n,), |
1496 |
|
|
type="custom", |
1497 |
|
|
custom_buttons=[_("_Abort"), |
1498 |
|
|
_("_Continue")]) |
1499 |
|
|
if rc == 0: |
1500 |
|
|
sys.exit(1) |
1501 |
|
|
else: |
1502 |
|
|
pass |
1503 |
|
|
|
1504 |
|
|
|
1505 |
|
|
def setGroupSelection(self, grpset, intf): |
1506 |
|
|
grpset.unselectAll() |
1507 |
|
|
|
1508 |
|
|
if self.addBase: |
1509 |
|
|
grpset.selectGroup("base") |
1510 |
|
|
for n in self.groupList: |
1511 |
|
|
try: |
1512 |
|
|
grpset.selectGroup(n) |
1513 |
|
|
except KeyError: |
1514 |
|
|
if self.handleMissing == KS_MISSING_IGNORE: |
1515 |
|
|
log("group %s doesn't exist, ignoring" %(n,)) |
1516 |
|
|
else: |
1517 |
|
|
rc = intf.messageWindow(_("Missing Group"), |
1518 |
|
|
_("You have specified that the " |
1519 |
|
|
"group '%s' should be installed. " |
1520 |
|
|
"This group does not exist. " |
1521 |
|
|
"Would you like to continue or " |
1522 |
|
|
"abort your installation?") |
1523 |
|
|
%(n,), |
1524 |
|
|
type="custom", |
1525 |
|
|
custom_buttons=[_("_Abort"), |
1526 |
|
|
_("_Continue")]) |
1527 |
|
|
if rc == 0: |
1528 |
|
|
sys.exit(1) |
1529 |
|
|
else: |
1530 |
|
|
pass |
1531 |
|
|
|
1532 |
|
|
for n in self.excludedList: |
1533 |
|
|
# allow arch:name syntax |
1534 |
slords |
1.3 |
if n.find(".") != -1: |
1535 |
slords |
1.1 |
fields = n.split(".") |
1536 |
|
|
name = string.join(fields[:-1], ".") |
1537 |
|
|
arch = fields[-1] |
1538 |
|
|
if grpset.hdrlist.pkgnames.has_key(name): |
1539 |
|
|
pkgs = grpset.hdrlist.pkgnames[name] |
1540 |
|
|
for (nevra, parch) in pkgs: |
1541 |
|
|
if parch == arch: |
1542 |
|
|
grpset.hdrlist.pkgs[nevra].unselect(isManual = 1) |
1543 |
|
|
continue |
1544 |
|
|
|
1545 |
|
|
if grpset.hdrlist.has_key(n): |
1546 |
|
|
grpset.hdrlist[n].unselect(isManual = 1) |
1547 |
|
|
else: |
1548 |
|
|
log("%s does not exist, can't exclude" %(n,)) |
1549 |
|
|
|
1550 |
|
|
|
1551 |
|
|
def __init__(self, file, serial): |
1552 |
|
|
self.serial = serial |
1553 |
|
|
self.file = file |
1554 |
|
|
self.skipSteps = [] |
1555 |
|
|
self.showSteps = [] |
1556 |
|
|
self.interactive = 0 |
1557 |
|
|
self.addBase = 1 |
1558 |
|
|
self.packageList = [] |
1559 |
|
|
self.groupList = [] |
1560 |
|
|
self.excludedList = [] |
1561 |
|
|
self.ksRaidMapping = {} |
1562 |
|
|
self.ksUsedMembers = [] |
1563 |
|
|
self.ksPVMapping = {} |
1564 |
|
|
self.ksVGMapping = {} |
1565 |
|
|
# XXX hack to give us a starting point for RAID, LVM, etc unique IDs. |
1566 |
|
|
self.ksID = 100000 |
1567 |
|
|
|
1568 |
|
|
# how to handle missing packages |
1569 |
|
|
self.handleMissing = KS_MISSING_PROMPT |
1570 |
|
|
|
1571 |
|
|
BaseInstallClass.__init__(self, 0) |
1572 |
|
|
|
1573 |
|
|
def Kickstart(file, serial): |
1574 |
|
|
|
1575 |
|
|
f = open(file, "r") |
1576 |
|
|
lines = f.readlines() |
1577 |
|
|
f.close() |
1578 |
|
|
|
1579 |
|
|
passedLines = [] |
1580 |
|
|
while lines: |
1581 |
|
|
l = lines[0] |
1582 |
|
|
lines = lines[1:] |
1583 |
|
|
if l == "%installclass\n": |
1584 |
|
|
break |
1585 |
|
|
passedLines.append(l) |
1586 |
|
|
|
1587 |
|
|
if lines: |
1588 |
|
|
newKsFile = file + ".new" |
1589 |
|
|
f = open(newKsFile, "w") |
1590 |
|
|
f.writelines(passedLines) |
1591 |
|
|
f.close() |
1592 |
|
|
|
1593 |
|
|
f = open('/tmp/ksclass.py', "w") |
1594 |
|
|
f.writelines(lines) |
1595 |
|
|
f.close() |
1596 |
|
|
|
1597 |
|
|
oldPath = sys.path |
1598 |
|
|
sys.path.append('/tmp') |
1599 |
|
|
|
1600 |
|
|
from ksclass import CustomKickstart |
1601 |
|
|
os.unlink("/tmp/ksclass.py") |
1602 |
|
|
|
1603 |
|
|
ksClass = CustomKickstart(newKsFile, serial) |
1604 |
|
|
os.unlink(newKsFile) |
1605 |
|
|
else: |
1606 |
|
|
ksClass = KickstartBase(file, serial) |
1607 |
|
|
|
1608 |
|
|
return ksClass |
1609 |
|
|
|
1610 |
|
|
|
1611 |
|
|
# see if any vnc parameters are specified in the kickstart file |
1612 |
|
|
def parseKickstartVNC(ksfile): |
1613 |
|
|
try: |
1614 |
|
|
f = open(ksfile, "r") |
1615 |
|
|
except: |
1616 |
|
|
raise KSAppendException("Unable to open ks file %s" % (ksfile,)) |
1617 |
|
|
|
1618 |
|
|
lines = f.readlines() |
1619 |
|
|
f.close() |
1620 |
|
|
|
1621 |
|
|
usevnc = 0 |
1622 |
|
|
vnchost = None |
1623 |
|
|
vncport = None |
1624 |
|
|
vncpasswd = None |
1625 |
|
|
for l in lines: |
1626 |
|
|
args = isys.parseArgv(l) |
1627 |
|
|
|
1628 |
|
|
if args: |
1629 |
|
|
if args[0] in ("%pre", "%post", "%traceback", "%packages"): |
1630 |
|
|
break |
1631 |
|
|
|
1632 |
|
|
if args[0] != 'vnc': |
1633 |
|
|
continue |
1634 |
|
|
else: |
1635 |
|
|
continue |
1636 |
|
|
|
1637 |
|
|
idx = 1 |
1638 |
|
|
while idx < len(args): |
1639 |
|
|
if args[idx] == "--password": |
1640 |
|
|
try: |
1641 |
|
|
vncpasswd = args[idx+1] |
1642 |
|
|
except: |
1643 |
|
|
raise KickstartError, "Missing argument to vnc --password option" |
1644 |
|
|
idx += 2 |
1645 |
|
|
elif args[idx] == "--connect": |
1646 |
|
|
try: |
1647 |
|
|
connectspec = args[idx+1] |
1648 |
|
|
except: |
1649 |
|
|
raise KickstartError, "Missing argument to vnc --connect option" |
1650 |
|
|
cargs = string.split(connectspec, ":") |
1651 |
|
|
vnchost = cargs[0] |
1652 |
|
|
if len(cargs) > 1: |
1653 |
|
|
if len(cargs[1]) > 0: |
1654 |
|
|
vncport = cargs[1] |
1655 |
|
|
|
1656 |
|
|
idx += 2 |
1657 |
|
|
else: |
1658 |
|
|
raise KickstartError, "Unknown vnc option %s" % (args[idx],) |
1659 |
|
|
|
1660 |
|
|
usevnc = 1 |
1661 |
|
|
break |
1662 |
|
|
|
1663 |
|
|
return (usevnc, vncpasswd, vnchost, vncport) |
1664 |
|
|
|
1665 |
|
|
# |
1666 |
|
|
# look through ksfile and if it contains a line: |
1667 |
|
|
# |
1668 |
|
|
# %ksappend <url> |
1669 |
|
|
# |
1670 |
|
|
# pull <url> down and append to /tmp/ks.cfg. This is run before we actually |
1671 |
|
|
# parse the complete kickstart file. |
1672 |
|
|
# |
1673 |
|
|
# Main use is to have the ks.cfg you send to the loader by minimal, and then |
1674 |
|
|
# use %ksappend to pull via https anything private (like passwords, etc) in |
1675 |
|
|
# the second stage. |
1676 |
|
|
# |
1677 |
|
|
def pullRemainingKickstartConfig(ksfile): |
1678 |
|
|
try: |
1679 |
|
|
f = open(ksfile, "r") |
1680 |
|
|
except: |
1681 |
|
|
raise KSAppendException("Unable to open ks file %s" % (ksfile,)) |
1682 |
|
|
|
1683 |
|
|
lines = f.readlines() |
1684 |
|
|
f.close() |
1685 |
|
|
|
1686 |
|
|
url = None |
1687 |
|
|
for l in lines: |
1688 |
|
|
ll = l.strip() |
1689 |
|
|
if string.find(ll, "%ksappend") == -1: |
1690 |
|
|
continue |
1691 |
|
|
|
1692 |
|
|
try: |
1693 |
|
|
(xxx, ksurl) = string.split(ll, ' ') |
1694 |
|
|
except: |
1695 |
|
|
raise KSAppendException("Illegal url for %%ksappend - %s" % (ll,)) |
1696 |
|
|
|
1697 |
|
|
log("Attempting to pull second part of ks.cfg from url %s" % (ksurl,)) |
1698 |
|
|
|
1699 |
|
|
try: |
1700 |
|
|
url = urllib2.urlopen(ksurl) |
1701 |
|
|
except urllib2.HTTPError, e: |
1702 |
|
|
raise KSAppendException("IOError: %s:%s" % (e.code, e.msg)) |
1703 |
|
|
except urllib2.URLError, e: |
1704 |
|
|
raise KSAppendException("IOError: -1:%s" % (e.reason,)) |
1705 |
|
|
else: |
1706 |
|
|
# sanity check result - sometimes FTP doesnt |
1707 |
|
|
# catch a file is missing |
1708 |
|
|
try: |
1709 |
|
|
clen = url.info()['content-length'] |
1710 |
|
|
except Exception, e: |
1711 |
|
|
clen = 0 |
1712 |
|
|
|
1713 |
|
|
if clen < 1: |
1714 |
|
|
raise KSAppendException("IOError: -1:File not found") |
1715 |
|
|
|
1716 |
|
|
break |
1717 |
|
|
|
1718 |
|
|
# if we got something then rewrite /tmp/ks.cfg with new information |
1719 |
|
|
if url is not None: |
1720 |
|
|
os.rename("/tmp/ks.cfg", "/tmp/ks.cfg-part1") |
1721 |
|
|
|
1722 |
|
|
# insert contents of original /tmp/ks.cfg w/o %ksappend line |
1723 |
|
|
f = open("/tmp/ks.cfg", 'w+') |
1724 |
|
|
for l in lines: |
1725 |
|
|
ll = l.strip() |
1726 |
|
|
if string.find(ll, "%ksappend") != -1: |
1727 |
|
|
continue |
1728 |
|
|
f.write(l) |
1729 |
|
|
|
1730 |
|
|
# now write part we just grabbed |
1731 |
|
|
f.write(url.read()) |
1732 |
|
|
f.close() |
1733 |
|
|
|
1734 |
|
|
# close up url and we're done |
1735 |
|
|
url.close() |
1736 |
|
|
|
1737 |
|
|
return None |
1738 |
|
|
|