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