/[gli]/trunk/src/GLIArchitectureTemplate.py
Gentoo

Contents of /trunk/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 200 - (show annotations) (download) (as text)
Tue Jan 4 20:35:56 2005 UTC (13 years, 9 months ago) by codeman
File MIME type: text/x-python
File size: 38488 byte(s)
gettin back in my groove.  lots more fixes here.

1 """
2 Gentoo Linux Installer
3
4 $Id: GLIArchitectureTemplate.py,v 1.17 2005/01/04 20:35:56 codeman Exp $
5 Copyright 2004 Gentoo Technologies Inc.
6
7
8 The ArchitectureTemplate is largely meant to be an abstract class and an
9 interface (yes, it is both at the same time!). The purpose of this is to create
10 subclasses that populate all the methods with working methods for that architecture.
11 The only definitions that are filled in here are architecture independent.
12
13 """
14
15 import GLIUtility
16 from GLIException import *
17 # Until I switch my partition code to GLIUtility.spawn()
18 import commands
19
20 class ArchitectureTemplate:
21
22 def __init__(self,configuration=None, install_profile=None, client_controller=None):
23 self._client_configuration = configuration
24 self._install_profile = install_profile
25 self._cc = client_controller
26
27 # This will get used a lot, so it's probably
28 # better to store it in a variable than to call
29 # this method 100000 times.
30 self._chroot_dir = self._client_configuration.get_root_mount_point()
31
32 # These must be filled in by the subclass. _steps is a list of
33 # functions, that will carry out the installation. They must be
34 # in order.
35 #
36 # For example, self._steps might be: [preinstall, stage1, stage2, stage3, postinstall],
37 # where each entry is a function (with no arguments) that carries out the desired actions.
38 # Of course, steps will be different depending on the install_profile
39
40 self._architecture_name = "generic"
41 self._install_steps = [
42 (self.do_partitioning, "Partition"),
43 (self.mount_local_partitions, "Mount local partitions"),
44 (self.mount_network_shares, "Mount network (NFS) shares"),
45 (self.unpack_stage_tarball, "Unpack stage tarball"),
46 (self.configure_make_conf, "Configure /etc/make.conf"),
47 (self.install_portage_tree, "Portage tree voodoo"),
48 (self.prepare_chroot, "Preparing chroot"),
49 (self.stage1, "Performing bootstrap"),
50 (self.stage2, "Performing 'emerge system'"),
51 (self.set_timezone, "Setting timezone"),
52 (self.emerge_kernel_sources, "Emerge kernel sources"),
53 (self.build_kernel, "Building kernel"),
54 (self.install_logging_daemon, "Logger"),
55 (self.install_cron_daemon, "Cron daemon"),
56 (self.install_filesystem_tools, "Installing filesystem tools"),
57 (self.setup_network_post, "Configuring post-install networking"),
58 (self.install_bootloader, "Configuring and installing bootloader"),
59 (self.update_config_files, "Updating config files"),
60 (self.configure_rc_conf, "Updating /etc/rc.conf")
61 ]
62
63 def _depends(self, depends):
64 # Type checking
65 #if type(depends) not in [ list, str, tuple ]:
66 # raise "Dependencies must be a string or a list of strings"
67
68 # If it is a string, change it to a list for parsing
69 #if type(depends) == str:
70 # depends = [ depends ]
71
72 # Parse dependencies
73 #for dependency in depends:
74 # If the dependency has not been satisfied, check to see if 'ignore' has been turned on
75 # if not dependency in self._client_configuration.get_install_steps_completed():
76
77 #If ignore is on, just print a warning
78 # if self._install_profile.get_ignore_install_step_depends():
79 # print "Warning: You chose to ignore install step dependencies. The " + dependency + " was not met. Ignoring."
80 #If ignore is off, then raise exception
81 # else:
82 # raise GLIException("InstallTemplateError", 'warning', '_depends', "Install step dependency not met!")
83 pass
84 def get_install_steps(self):
85 return self._install_steps
86
87 # It is possible to override these methods in each Arch Template.
88 # It might be necessary to do so, if the arch needs something 'weird'.
89
90 def stage1(self):
91 "Stage 1 install -- bootstraping"
92 # Dependency checking
93 self._depends("preinstall")
94
95 # If we are doing a stage 1 install, then bootstrap
96 if self._install_profile.get_install_stage() == 1:
97 exitstatus = GLIUtility.spawn("/usr/portage/scripts/bootstrap.sh", True)
98 if not GLIUtility.exitsuccess(exitstatus):
99 raise GLIException("Stage1Error", 'fatal','stage1', "Bootstrapping failed!")
100
101 self._configuration.add_install_steps_completed("stage1")
102
103 def stage2(self):
104 # Dependency checking
105 self._depends("stage1")
106
107 # If we are doing a stage 1 or 2 install, then emerge system
108 if self._install_profile.get_install_stage() in [ 1, 2 ]:
109 exitstatus = GLIUtility.emerge("system")
110 if not GLIUtility.exitsuccess(exitstatus):
111 raise GLIException("Stage2Error", 'fatal','stage2', "Building the system failed!")
112
113 self._configuration.add_install_steps_completed("stage2")
114
115 def unpack_stage_tarball(self):
116 if not os.path.isdir(self._chroot_dir):
117 os.makedirs(self._chroot_dir)
118 GLIUtility.fetch_and_unpack_tarball(self._install_profile.get_stage_tarball_uri(), self._chroot_dir, keep_permissions=True)
119
120 def prepare_chroot(self):
121 ret = GLIUtility.spawn("cp -L /etc/resolv.conf /mnt/gentoo/etc/resolv.conf",True)
122 if not GLIUtility.exitsuccess(ret):
123 raise GLIException("CopyError", 'warning','preinstall','Could not copy resolv.conf!',True)
124
125 ret = GLIUtility.spawn("mount -t proc none /mnt/gentoo /proc")
126 if not GLIUtility.exitsuccess(ret):
127 raise GLIException("MountError", 'fatal','preinstall','Could not mount /proc')
128
129 # Set USE flags here
130 # might want to rewrite/use _edit_config from the GLIInstallTemplate
131 # Then you should be done... at least with the preinstall.
132
133 def notify_frontend(self, type, data):
134 self._cc.addNotification(type, data)
135
136 def install_packages(self):
137 "Will install any extra software!"
138 # Dependency checking
139 self._depends("emerge system")
140 installpackages = self._install_profile.get_install_packages()
141 for package in installpackages:
142 status = GLIUtility.emerge(package)
143 if not GLIUtility.exit_success(status):
144 raise GLIException("InstallPackagesError", 'warning', 'install_packages', "Could not emerge " + package + "!")
145
146 # This is part of the interface... subclasses MUST
147 # provide these methods filled in.
148 def stage3(self):
149 # This should probably start with building the kernel,
150 # that might be the only thing this actually needs
151 # to do.
152 pass
153
154 def postinstall(self):
155 pass
156
157 def partition(self):
158 pass
159
160 # **************************************************************************************
161
162 def _add_to_runlevel(self, script_name, runlevel="default"):
163 "Adds the script named 'script_name' to the runlevel 'runlevel' in the chroot environement"
164
165 # Do it
166 status = GLIUtility.spawn("rc-update add " + script_name + " " + runlevel, chroot=self._chroot_dir)
167 if not GLIUtility.exit_success(status):
168 raise GLIException("RunlevelAddError", 'warning', '_add_to_runlevel', "Failure adding " + script_name + " to runlevel " + runlevel + "!")
169
170 def mount_local_partitions(self):
171 "Mounts all partitions that are on the local machine"
172 # Dependency checking
173 self._depends("partition_local_drives")
174
175 def mount_network_shares(self):
176 "Mounts all network shares to the local machine"
177 # Dependency checking
178 self._depends([ "setup_network_pre", "mount_local_partitions" ])
179
180 def fetch_sources_from_cd(self):
181 "Gets sources from CD (required for non-network installation)"
182 # Dependency checking
183 self._depends("unpack_tarball")
184
185 def fetch_grp_from_cd(self):
186 "Gets grp binary packages from CD (required for non-network binary installation)"
187 # Dependency checking
188 self._depends("unpack_tarball")
189
190 def configure_make_conf(self):
191 "Configures make.conf"
192 # Dependency checking
193 self._depends("prepare_chroot")
194
195 # Get make.conf options
196 options = self._install_profile.get_make_conf()
197
198 # For each configuration option...
199 for key in options.keys():
200
201 # Add/Edit it into make.conf
202 GLIUtility.edit_config(self._chroot_dir + "/etc/make.conf", key, options[key])
203
204 def install_portage_tree(self):
205 "Get/update the portage tree"
206 # Dependency checking
207 self._depends("prepare_chroot")
208
209 # Check the type of portage tree fetching we'll do
210 # If it is custom, follow the path to the custom tarball and unpack it
211 if self._install_profile.get_portage_tree_sync_type() == "custom":
212
213 # Get portage tree info
214 portage_tree_snapshot_uri = self._install_profile.get_portage_tree_snapshot_uri()
215
216 # Fetch and unpack the tarball
217 self._fetch_and_unpack_tarball(portage_tree_snapshot_uri, self._client_configuration.get_root_mount_point() + "/usr/", self._client_configuration.get_root_mount_point() + "/")
218 if not GLIUtility.is_file(self._client_configuration.get_root_mount_point()+"/usr/portage/distfiles"):
219 exitstatus = GLIUtility.spawn("mkdir /usr/portage/distfiles",True)
220 if exitstatus != 0:
221 raise GLIException("MkdirError", 'fatal','install_portage_tree',"Making the distfiles directory failed.")
222 exitstatus = GLIUtility.spawn("cp /mnt/cdrom/distfiles/* "+self._client_configuration.get_root_mount_point()+"/usr/portage/distfiles/")
223 if exitstatus != 0:
224 raise GLIException("PortageError", 'fatal','install_portage_tree',"Failed to copy the distfiles to the new system")
225 # If the type is webrsync, then run emerge-webrsync
226 elif self._install_profile.get_portage_tree_sync_type() == "webrsync":
227 exitstatus = GLIUtility.spawn("emerge-webrsync", True)
228 if exitstatus != 0:
229 raise GLIException("EmergeWebRsyncError", 'fatal','install_portage_tre', "Failed to retrieve portage tree!")
230
231 # Otherwise, just run emerge sync
232 else:
233 exitstatus = self._emerge("sync")
234 if exitstatus != 0:
235 raise GLIException("EmergeSyncError", 'fatal','install_portage_tree', "Failed to retrieve portage tree!")
236
237 def set_timezone(self):
238 "Sets the timezone for the new environment"
239
240 # Dependency checking
241 self._depends("unpack_tarball")
242 #self._process_desc("Setting the timezone")
243
244 # Set symlink
245 if not os.access(self._client_configuration.get_root_mount_point() + "/etc/localtime", os.W_OK):
246 os.symlink(self._client_configuration.get_root_mount_point() + "/usr/share/zoneinfo/" + self._install_profile.get_time_zone(), self._client_configuration.get_root_mount_point() + "/etc/localtime")
247 if not (self._install_profile.get_time_zone() == "UTC"):
248 self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/rc.conf", "CLOCK", "local")
249
250 def configure_fstab(self):
251 "Configures fstab"
252 # Dependency checking
253 self._depends("unpack_tarball")
254 newfstab = ""
255 partitions = self._install_profile.get_fstab()
256 for partition in partitions:
257 if not GLIUtility.is_file(self._client_configuration.get_root_mount_point()+partition):
258 exitstatus = GLIUtility.spawn("mkdir " + partition, True)
259 if exitstatus != 0:
260 raise GLIException("MkdirError", 'fatal','configure_fstab', "Making the mount point failed!")
261 newfstab += partitions[partition][0] + "\t " + partition + "\t " + partitions[partition][1]
262 newfstab += "\t " + partitions[partition][2] + "\t "
263 if partition == "/boot":
264 newfstab += "1 2\n"
265 elif partition == "/":
266 newfstab += "0 1\n"
267 else:
268 newfstab += "0 0\n"
269 newfstab += "none /proc proc defaults 0 0\n"
270 newfstab += "none /dev/shm tmpfs defaults 0 0\n"
271 if GLIUtility.is_device("/dev/cdroms/cdrom0"):
272 newfstab += "/dev/cdroms/cdrom0 /mnt/cdrom auto noauto,user 0 0\n"
273
274 for netmount in self._install_profile.get_network_mounts():
275 if netmount['type'] == "nfs":
276 newfstab += netmount['host'] + ":" + netmount['export'] + "\t" + netmount['mountpoint'] + "\tnfs\t" + netmount['mountopts'] + "\t0 0\n"
277
278 file_name = self._client_configuration.get_root_mount_point() + "/etc/fstab"
279 try:
280 shutil.move(file_name, file_name + ".OLDdefault")
281 except:
282 pass
283 f = open(file_name, 'w')
284 f.writelines(newfstab)
285 f.close()
286
287
288 def emerge_kernel_sources(self):
289 "Fetches desired kernel sources"
290 # Dependency checking
291 self._depends("emerge_system")
292 exitstatus = self._emerge(self._install_profile.get_kernel_source_pkg())
293 if exitstatus != 0:
294 raise GLIException("EmergeKernelSourcesError", 'warning','emerge_kernel_sources',"Could not retrieve kernel sources!")
295 try:
296 os.stat(self._client_configuration.get_root_mount_point() + "/usr/src/linux")
297 except:
298 kernels = os.listdir(self._client_configuration.get_root_mount_point()+"/usr/src")
299 found_a_kernel = False
300 counter = 0
301 while not found_a_kernel:
302 if kernels[counter][0:6]=="linux-":
303 exitstatus = GLIUtility.spawn("ln -s /usr/src/"+kernels[counter]+ " /usr/src/linux",True)
304 found_a_kernel = True
305 else:
306 counter = counter + 1
307
308 def build_kernel(self):
309 "Builds kernel"
310 # Dependency checking
311 self._depends("emerge_kernel_sources")
312
313 exitstatus = self._emerge("genkernel")
314 if exitstatus != 0:
315 raise GLIException("EmergeGenKernelError", 'warning','build_kernel', "Could not emerge genkernel!")
316
317
318 # Null the genkernel_options
319 genkernel_options = ""
320
321 # Get the uri to the kernel config
322 kernel_config_uri = self._install_profile.get_kernel_config_uri()
323
324 # If the uri for the kernel config is not null, then
325 if kernel_config_uri != "":
326 self._get_uri(kernel_config_uri, self._client_configuration.get_root_mount_point() + "/root/kernel_config")
327 genkernel_options = genkernel_options + " --kernel-config=/root/kernel_config"
328
329 # Decide whether to use bootsplash or not
330 if self._install_profile.get_kernel_bootsplash():
331 genkernel_options = genkernel_options + " --bootsplash"
332 else:
333 genkernel_options = genkernel_options + " --no-bootsplash"
334
335 # This is code to choose whether or not genekernel will build an initrd or not
336 # Genkernel currently does not support this
337 #if self._install_profile.get_kernel_initrd():
338 # pass
339 #else:
340 # pass
341
342 # Run genkernel in chroot
343 print "genkernel all " + genkernel_options
344 exitstatus = GLIUtility.spawn("genkernel all " + genkernel_options, True)
345 if exitstatus != 0:
346 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build kernel!")
347
348 def install_logging_daemon(self):
349 "Installs and sets up logger"
350 # Dependency checking
351 self._depends("emerge_system")
352
353 # Get loggin daemon info
354 logging_daemon_pkg = self._install_profile.get_logging_daemon_pkg()
355 if logging_daemon_pkg:
356 # Emerge Logging Daemon
357 exitstatus = self._emerge(logging_daemon_pkg)
358 if exitstatus != 0:
359 raise GLIException("LoggingDaemonError", 'warning','install_logging_daemon', "Could not emerge " + logging_daemon_pkg + "!")
360
361 # Add Logging Daemon to default runlevel
362 self._add_to_runlevel(logging_daemon_pkg)
363
364 def install_cron_daemon(self):
365 "Installs and sets up cron"
366 # Dependency checking
367 self._depends("emerge_system")
368
369 # Get cron daemon info
370 cron_daemon_pkg = self._install_profile.get_cron_daemon_pkg()
371 if cron_daemon_pkg:
372 # Emerge Cron Daemon
373 exitstatus = self._emerge(cron_daemon_pkg)
374 if exitstatus != 0:
375 raise GLIException("CronDaemonError", 'warning', 'install_cron_daemon', "Could not emerge " + cron_daemon_pkg + "!")
376
377 # Add Cron Daemon to default runlevel
378 self._add_to_runlevel(cron_daemon_pkg)
379
380 # If the Cron Daemon is not vixie-cron, run crontab
381 if cron_daemon_pkg != "vixie-cron":
382 exitstatus = GLIUtility.spawn("crontab /etc/crontab", True)
383 if exitstatus != 0:
384 raise GLIException("CronDaemonError", 'warning', 'install_cron_daemon', "Failure making crontab!")
385
386 def install_filesystem_tools(self):
387 "Installs and sets up fstools"
388 # Dependency checking
389 self._depends("emerge_system")
390
391 # Get the list of file system tools to be installed
392 filesystem_tools = self._install_profile.get_filesystem_tools_pkgs()
393
394 # If the fstools var is a str, convert it to a list
395 if type(filesystem_tools) == str:
396 filesystem_tools = [ filesystem_tools ]
397
398 # For each fstool package in the list, install it
399 for package in filesystem_tools:
400 exitstatus = self._emerge(package)
401 if exitstatus != 0:
402 raise GLIException("FilesystemToolsError", 'warning', 'install_filesystem_tools', "Could not emerge " + package + "!")
403
404 def install_rp_pppoe(self):
405 "Installs rp-pppoe"
406 # Dependency checking
407 self._depends("emerge_system")
408
409 # If user wants us to install rp-pppoe, then do so
410 if self._install_profile.get_install_rp_pppoe():
411 exitstatus = self._emerge("rp-pppoe")
412 if exitstatus != 0:
413 raise GLIException("RP_PPPOEError", 'warning', 'install_rp_pppoe', "Could not emerge rp-pppoe!")
414
415 # Should we add a section here to automatically configure rp-pppoe?
416 # I think it should go into the setup_network_post section
417 # What do you guys think?
418
419 def install_pcmcia_cs(self):
420 "Installs and sets up pcmcia-cs"
421 # Dependency checking
422 self._depends("build_kernel")
423
424 # If user wants us to install pcmcia-cs, then do so
425 if self._install_profile.get_install_pcmcia_cs():
426 exitstatus = self._emerge("pcmcia-cs")
427 if exitstatus != 0:
428 raise GLIException("PCMCIA_CSError", 'warning', 'install_pcmcia_cs', "Could not emerge pcmcia-cs!")
429
430 # Add pcmcia-cs to the default runlevel
431 exitstatus = GLIUtility.spawn("rc-update add pcmcia default", True)
432 if exitstatus != 0:
433 raise GLIException("PCMCIA_CSError", 'warning', 'install_pcmcia_cs', "Could not add pcmcia-cs to the default runlevel!")
434
435 def install_bootloader(self):
436 "Installs and configures bootloader"
437 #
438 # THIS IS ARCHITECTURE DEPENDANT!!!
439 # This is the x86 way.. it uses grub
440 # Dependency checking
441 self._depends("build_kernel")
442
443 if self._install_profile.get_boot_loader_pkg():
444 exitstatus = self._emerge(self._install_profile.get_boot_loader_pkg())
445 if exitstatus != 0:
446 raise GLIException("BootLoaderEmergeError", 'fatal', 'install_bootloader', "Could not emerge bootloader!")
447 else:
448 pass
449
450 boot_device = ""
451 boot_minor = ""
452 root_device = ""
453 root_minor = ""
454 grub_root_minor = ""
455 grub_boot_minor = ""
456 grub_boot_drive = ""
457 grub_root_drive = ""
458 minornum = 0
459 #Assign root to the root mount point to make lines more readable
460 root = self._client_configuration.get_root_mount_point()
461 file_name = root + "/boot/grub/bootdevice"
462 file_name1 = root + "/boot/grub/rootdevice"
463 file_name2 = root + "/boot/grub/device.map"
464 file_name3 = root + "/boot/grub/kernel_name"
465 foundboot = False
466 partitions = self._install_profile.get_fstab()
467 for partition in partitions:
468 #if find a /boot then stop.. else we'll take a / and overwrite with a /boot if we find it too.
469 if (partition == "/boot"):
470 #try to get the drive LETTER from /dev/hdc1 8th character
471 boot_minor = partitions[partition][0][8]
472 grub_boot_minor = str(int(boot_minor) - 1)
473 boot_device = partitions[partition][0][0:8]
474 foundboot = True
475 if ( (partition == "/") and (not foundboot) ):
476 boot_minor = partitions[partition][0][8]
477 grub_boot_minor = str(int(boot_minor) - 1)
478 boot_device = partitions[partition][0][0:8]
479 #Foundboot IS STILL FALSE
480 if partition == "/":
481 root_minor = partitions[partition][0][8]
482 grub_root_minor = str(int(root_minor) - 1)
483 root_device = partitions[partition][0][0:8]
484
485 exitstatus0 = GLIUtility.spawn("ls -l " + boot_device + " > " + file_name)
486 exitstatus1 = GLIUtility.spawn("ls -l " + root_device + " > " + file_name1)
487 exitstatus2 = GLIUtility.spawn("echo quit | "+ root+"/sbin/grub --device-map="+file_name2)
488 exitstatus3 = GLIUtility.spawn("ls "+root+"/boot/kernel-* > "+file_name3)
489 exitstatus4 = GLIUtility.spawn("ls "+root+"/boot/initrd-* >> "+file_name3)
490 if (exitstatus0 != 0) or (exitstatus1 != 0) or (exitstatus2 != 0) or (exitstatus3 != 0) or (exitstatus4 != 0):
491 raise GLIException("BootloaderError", 'fatal', 'install_bootloader', "Error in one of THE FOUR run commands")
492
493 """
494 read the device map. sample looks like this:
495 (fd0) /dev/floppy/0
496 (hd0) /dev/ide/host2/bus0/target0/lun0/disc
497 (hd1) /dev/ide/host0/bus0/target0/lun0/disc
498 (hd2) /dev/ide/host0/bus0/target1/lun0/disc
499 """
500 e = open(file_name) #Looking for the boot device
501 ls_output = e.readlines()
502 e.close()
503 # looks like lr-xr-xr-x 1 root root 32 Oct 1 16:09 /dev/hda -> ide/host0/bus0/target0/lun0/disc
504 ls_output = ls_output[0].split(">")[-1]
505 ls_output = ls_output[1:]
506
507 eb = open(file_name1) #Looking for the root device
508 ls_outputb = eb.readlines()
509 eb.close()
510 ls_outputb = ls_outputb[0].split(">")[-1]
511 ls_outputb = ls_outputb[1:]
512
513 # Search for the key
514 f = open(file_name2)
515 file = f.readlines()
516 f.close()
517 for i in range(len(file)):
518 if file[i][11:] == ls_output:
519 #eurika we found the drivenum
520 grub_boot_drive = file[i][1:4]
521 if file[i][11:] == ls_outputb:
522 grub_root_drive = file[i][1:4]
523 if (not grub_root_drive) or (not grub_boot_drive):
524 raise GLIException("BootloaderError", 'fatal', 'install_bootloader',"Couldn't find the drive num in the list from the device.map")
525
526 g = open(file_name3)
527 kernel_name = g.readlines()
528 g.close()
529 if not kernel_name[0]:
530 raise GLIException("BootloaderError", 'fatal', 'install_bootloader',"Error: We have no kernel in /boot to put in the grub.conf file!")
531 kernel_name = map(string.strip, kernel_name)
532 kernel_name[0] = kernel_name[0].split(root)[1]
533 kernel_name[1] = kernel_name[1].split(root)[1]
534 #-------------------------------------------------------------
535 #OK, now that we have all the info, let's build that grub.conf
536 newgrubconf = ""
537 newgrubconf += "default 0\ntimeout 30\n"
538 if foundboot: #we have a /boot
539 newgrubconf += "splashimage=(" + grub_boot_drive + "," + grub_boot_minor + ")/grub/splash.xpm.gz\n"
540 else: #we have / and /boot needs to be included
541 newgrubconf += "splashimage=(" + grub_boot_drive + "," + grub_boot_minor + ")/boot/grub/splash.xpm.gz\n"
542
543 newgrubconf += "title=Gentoo Linux\n"
544 newgrubconf += "root (" + grub_boot_drive + "," + grub_boot_minor + ")\n"
545 if foundboot:
546 newgrubconf += "kernel " + kernel_name[0][5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
547 newgrubconf += root_device + root_minor + "\n"
548 newgrubconf += "initrd " + kernel_name[1][5:] + "\n"
549 else:
550 newgrubconf += "kernel /boot" + kernel_name[0][5:] + " root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root="
551 newgrubconf += root_device + root_minor + "\n"
552 newgrubconf += "initrd /boot" + kernel_name[1][5:] + "\n"
553
554 #-------------------------------------------------------------
555 #OK, now that the file is built. Install grub.
556 #cp /proc/mounts /etc/mtab
557 #grub-install --root-directory=/boot /dev/hda
558 #shutil.copy("/proc/mounts",root +"/etc/mtab")
559 grubinstallstring = "echo -en 'root ("+grub_boot_drive + "," + grub_boot_minor + ")\n"
560 if not self._install_profile.get_boot_loader_mbr():
561 grubinstallstring +="setup ("+grub_boot_drive + "," + grub_boot_minor + ")\n"
562 else:
563 grubinstallstring +="setup ("+grub_boot_drive+")\n"
564 grubinstallstring += "quit\n' | "+root+"/sbin/grub"
565 print grubinstallstring
566 exitstatus = GLIUtility.spawn(grubinstallstring,True)
567 if exitstatus != 0:
568 raise GLIException("GrubInstallError", 'fatal', 'install_bootloader', "Could not install grub!")
569
570 #now make the grub.conf file
571 file_name = root + "/boot/grub/grub.conf"
572 try:
573 shutil.move(file_name, file_name + ".OLDdefault")
574 except:
575 pass
576 f = open(file_name, 'w')
577 f.writelines(newgrubconf)
578 f.close()
579
580 def update_config_files(self):
581 "Runs etc-update (overwriting all config files), then re-configures the modified ones"
582 # Dependency checking
583 self._depends("emerge_system")
584
585 # Run etc-update overwriting all config files
586 status = GLIUtility.spawn('echo "-5" | etc-update', chroot=self._chroot_dir)
587 if not GLIUtility.exit_success(status):
588 raise GLIException("EtcUpdateError", 'warning', 'update_config_files', "Could not update config files!")
589
590 self.configure_make_conf()
591 self.configure_fstab()
592
593 def configure_rc_conf(self):
594 "Configures rc.conf"
595 # Dependency checking
596 self._depends("update_config_files")
597
598 # Get make.conf options
599 options = self._install_profile.get_rc_conf()
600
601 # For each configuration option...
602 for key in options.keys():
603
604 # Add/Edit it into rc.conf
605 self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/rc.conf", key, option[key])
606
607 def setup_network_post(self):
608 "Sets up the network for the first boot"
609 # Dependency checking
610 self._depends("unpack_tarball")
611
612 # Get hostname, domainname and nisdomainname
613 hostname = self._install_profile.get_hostname()
614 domainname = self._install_profile.get_domainname()
615 nisdomainname = self._install_profile.get_nisdomainname()
616
617 # Write the hostname to the hostname file
618 open(self._client_configuration.get_root_mount_point() + "/etc/hostname", "w").write(hostname + "\n")
619
620 # Write the domainname to the nisdomainname file
621 if domainname:
622 open(self._client_configuration.get_root_mount_point() + "/etc/dnsdomainname", "w").write(domainname + "\n")
623
624 # Write the nisdomainname to the nisdomainname file
625 if nisdomainname:
626 open(self._client_configuration.get_root_mount_point() + "/etc/nisdomainname", "w").write(nisdomainname + "\n")
627
628 #
629 # EDIT THE /ETC/HOSTS FILE
630 #
631
632 # The address we are editing is 127.0.0.1
633 hosts_ip = "127.0.0.1"
634
635 # If the hostname is localhost
636 if hostname == "localhost":
637 # If a domainname is set
638 if domainname:
639 hosts_line = hostname + "." + domainname + "\t" + hostname
640 else:
641 hosts_line = hostname
642 # If the hostname is not localhost
643 else:
644 # If a domainname is set
645 if domainname:
646 hosts_line = hostname + "." + domainname + "\t" + hostname + "\tlocalhost"
647 else:
648 hosts_line = "localhost\t" + hostname
649
650 # Write to file
651 self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/hosts", hosts_ip, hosts_line, True, '\t', False)
652
653 #
654 # SET DEFAULT GATEWAY
655 #
656
657 # Get default gateway
658 default_gateway = self._install_profile.get_default_gateway()
659
660 # If the default gateway exists, add it
661 if default_gateway:
662 self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/conf.d/net", "gateway", default_gateway)
663
664 #
665 # SET RESOLV INFO
666 #
667
668 # Get dns servers
669 dns_servers = self._install_profile.get_dns_servers()
670
671 # Clear the list
672 resolv_output = []
673
674 # If dns servers are set
675 if dns_servers:
676
677
678 # Parse each dns server
679 for dns_server in dns_servers:
680 # Add the server to the output
681 resolv_output.append("nameserver " + dns_server +"\n")
682
683 # If the domainname is set, then also output it
684 if domainname:
685 resolv_output.append("search " + domainname + "\n")
686
687 # Output to file
688 resolve_conf = open(self._client_configuration.get_root_mount_point() + "/etc/resolv.conf", "w")
689 resolve_conf.writelines(resolv_output)
690 resolve_conf.close()
691
692 #
693 # PARSE INTERFACES
694 #
695
696 # Fetch interfaces
697 interfaces = self._install_profile.get_network_interfaces()
698
699 # Parse each interface
700 for interface in interfaces.keys():
701
702 # If we are going to load the network at boot...
703 if interfaces[interface][2]:
704
705 # Add it to the default runlevel
706 exitstatus = GLIUtility.spawn("rc-update add net." + interface + " default", True)
707 if exitstatus != 0:
708 raise "NetStartupError", "Cannot add interface " + interface + " to the default runlevel!"
709
710 # Set what kind of interface it is
711 interface_type = interface[:3]
712
713 # Check to see if there is a startup script for this interface, if there isn't link to the proper script
714 try:
715 os.stat(self._client_configuration.get_root_mount_point() + "/etc/init.d/net." + interface)
716 except:
717 os.symlink(self._client_configuration.get_root_mount_point() + "/etc/init.d/net." + interface_type + "0", self._client_configuration.get_root_mount_point() + "/etc/init.d/net." + interface)
718
719 #
720 # ETHERNET
721 #
722 if interface_type == "eth":
723
724 #
725 # STATIC IP
726 #
727 # If the post-install device info is not None, then it is a static ip addy
728 if interfaces[interface][1]:
729 ip = interfaces[interface][0]
730 broadcast = interfaces[interface][1]
731 netmask = interfaces[interface][2]
732 # aliases = interfaces[interface][1][3]
733 # alias_ips = []
734 # alias_broadcasts = []
735 # alias_netmasks = []
736
737 # Write the static ip config to /etc/conf.d/net
738 self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/conf.d/net", "iface_" + interface, ip + " broadcast " + broadcast + " netmask " + netmask)
739
740 # If aliases are set
741 # if aliases:
742
743 # Parse aliases to format alias info
744 # for alias in aliases:
745 # alias_ips.append(alias[0])
746 # alias_broadcasts.append(alias[1])
747 # alias_netmasks.append(allias[2])
748
749 # Once the alias info has been gathered, then write it out
750 # Alias ips first
751 # self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/conf.d/net", "alias_" + interface, string.join(alias_ips))
752 # Alias broadcasts next
753 # self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/conf.d/net", "broadcast_" + interface, string.join(alias_broadcasts))
754 # Alias netmasks last
755 # self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/conf.d/net", "netmask_" + interface, string.join(alias_netmasks))
756
757 #
758 # DHCP IP
759 #
760 else:
761 self._edit_config(self._client_configuration.get_root_mount_point() + "/etc/conf.d/net", "iface_" + interface, "dhcp")
762
763 def set_root_password(self):
764 "Sets the root password"
765 # Dependency checking
766 self._depends("emerge_system")
767
768 status = GLIUtility.spawn('echo "root:' + self._install_profile.get_root_pass_hash() + '" | chpasswd -e', chroot=self._chroot_dir)
769 if not GLIUtility.exit_success(status):
770 raise GLIException("SetRootPasswordError", 'warning', 'set_root_password', "Failure to set root password!")
771
772 def set_users(self):
773 "Sets up the new users for the system"
774 # Dependency checking
775 self._depends("emerge_system")
776
777 # Loop for each user
778 for user in self._install_profile.get_users():
779
780 # Get values from the tuple
781 username = user[0]
782 password_hash = user[1]
783 groups = user[2]
784 shell = user[3]
785 home_dir = user[4]
786 uid = user[5]
787 comment = user[6]
788
789 options = [ "-m", "-p " + password_hash ]
790
791 # If the groups are specified
792 if groups:
793
794 # If just one group is listed as a string, make it a list
795 if groups == str:
796 groups = [ groups ]
797
798 # If only 1 group is listed
799 if len(groups) == 1:
800 options.append("-G " + groups[0])
801
802 # If there is more than one group
803 elif len(groups) > 1:
804 options.append('-G "' + string.join(groups, ",") + '"')
805
806 # If a shell is specified
807 if shell:
808 options.append("-s " + shell)
809
810 # If a home dir is specified
811 if home_dir:
812 options.append("-d " + home_dir)
813
814 # If a UID is specified
815 if uid:
816 options.append("-u " + str(uid))
817
818 # If a comment is specified
819 if comment:
820 options.append('-c "' + comment + '"')
821
822 # Add the user
823 exitstatus = GLIUtility.spawn('useradd ' + string.join(options) + ' ' + username, chroot=self._chroot_dir)
824 if not GLIUtility.exit_success(exitstatus):
825 raise GLIException("AddUserError", 'warning', 'set_users', "Failure to add user " + username)
826
827 def _cylinders_to_sectors(self, minor, start, end, sectors_in_cylinder):
828 cylinders = int(end) - int(start) + 1
829 total_sectors = cylinders * int(sectors_in_cylinder)
830 start_sector = int(start) * sectors_in_cylinder
831 end_sector = start_sector + total_sectors - 1
832 if int(minor) == 1 and start_sector == 0: start_sector = 63
833 return (start_sector, end_sector)
834
835 def _sectors_to_megabytes(self, sectors, sector_bytes=512):
836 return float((float(sectors) * sector_bytes)/ float(1024*1024))
837
838 def _sectors_to_bytes(self, sectors, sector_bytes=512):
839 return (int(sectors) * sector_bytes)
840
841 def _run_parted_command(self, device, cmd):
842 parted_output = commands.getoutput("parted -s " + device + " " + cmd)
843 print "parted -s " + device + " " + cmd
844
845 def _add_partition(self, device, start, end, type, fs):
846 start = self._sectors_to_megabytes(start)
847 end = self._sectors_to_megabytes(end)
848 self._run_parted_command(device, "mkpart " + type + " " + fs + " " + str(start) + " " + str(end))
849 if type == "ntfs":
850 pass
851 elif type == "ext2" or type == "ext3":
852 pass
853 else:
854 pass
855
856 def do_partitioning(self):
857 import GLIStorageDevice, parted, pprint
858
859 devices_old = {}
860 parts_old = {}
861 parts_new = self._install_profile.get_partition_tables()
862 drives = GLIStorageDevice.detect_devices()
863 drives.sort()
864 for drive in drives:
865 devices_old[drive] = GLIStorageDevice.Device(drive)
866 devices_old[drive].set_partitions_from_disk()
867 for part in devices_old.keys(): parts_old[part] = devices_old[part].get_install_profile_structure()
868
869 pp = pprint.PrettyPrinter(indent=4)
870 pp.pprint(parts_old)
871 pp.pprint(parts_new)
872
873 for dev in parts_old.keys():
874 parts_active = []
875 parts_lba = []
876 print "\nProcessing " + dev + "..."
877 parted_dev = parted.PedDevice.get(dev)
878 parted_disk = parted.PedDisk.new(parted_dev)
879 last_partition_touched = 0
880 sectors_in_cylinder = devices_old[dev]._sectors_in_cylinder
881 # First pass to delete old partitions that aren't resized
882 for part in parts_old[dev]:
883 oldpart = parts_old[dev][part]
884 old_start, old_end = self._cylinders_to_sectors(part, oldpart['start'], oldpart['end'], sectors_in_cylinder)
885 matchingminor = 0
886 for new_part in parts_new[dev]:
887 tmppart = parts_new[dev][new_part]
888 new_start, new_end = self._cylinders_to_sectors(new_part, tmppart['start'], tmppart['end'], sectors_in_cylinder)
889 if int(tmppart['start']) == int(oldpart['start']) and tmppart['format'] == False and tmppart['type'] == oldpart['type'] and int(tmppart['end']) == int(oldpart['end']):
890 matchingminor = new_part
891 print " Deleting old minor " + str(part) + " to be recreated later"
892 self._run_parted_command(dev, "rm " + str(part))
893 break
894 if int(tmppart['start']) == int(oldpart['start']) and tmppart['format'] == False and tmppart['type'] == oldpart['type'] and int(tmppart['end']) != int(oldpart['end']):
895 matchingminor = new_part
896 print " Ignoring old minor " + str(part) + " to resize later"
897 break
898 if not matchingminor:
899 print " No match found...deleting partition " + str(part)
900 self._run_parted_command(dev, "rm " + str(part))
901 else:
902 if parted_disk.get_partition(part).get_flag(1): # Active/boot
903 print " Partition " + str(part) + " was active...noted"
904 parts_active.append(int(matchingminor))
905 if parted_disk.get_partition(part).get_flag(7): # LBA
906 print " Partition " + str(part) + " was LBA...noted"
907 parts_lba.append(int(matchingminor))
908 # Second pass to resize old partitions that need to be resized
909 print " Second pass..."
910 for part in parts_old[dev]:
911 oldpart = parts_old[dev][part]
912 old_start, old_end = self._cylinders_to_sectors(part, oldpart['start'], oldpart['end'], sectors_in_cylinder)
913 for new_part in parts_new[dev]:
914 tmppart = parts_new[dev][new_part]
915 new_start, new_end = self._cylinders_to_sectors(new_part, tmppart['start'], tmppart['end'], sectors_in_cylinder)
916 if int(tmppart['start']) == int(oldpart['start']) and tmppart['format'] == False and tmppart['type'] == oldpart['type'] and int(tmppart['end']) != int(oldpart['end']):
917 print " Resizing old minor " + str(part) + " from " + str(oldpart['start']) + "-" + str(oldpart['end'])+ " to " + str(tmppart['start']) + "-" + str(tmppart['end'])
918 type = tmppart['type']
919 device = dev
920 minor = part
921 start = int(new_start)
922 end = int(new_end)
923 if type == "ext2" or type == "ext3":
924 total_sectors = end - start + 1
925 commands.getstatus("resize2fs " + device + str(minor) + " " + str(total_sectors) + "s")
926 print "resize2fs " + device + str(minor) + " " + str(total_sectors) + "s"
927 elif type == "ntfs":
928 total_sectors = end - start + 1
929 total_bytes = int(self._sectors_to_bytes(total_sectors))
930 commands.getstatus("ntfsresize --size " + str(total_bytes) + " " + device + str(minor))
931 print "ntfsresize --size " + str(total_bytes) + " " + device + str(minor)
932 else:
933 start = float(self._sectors_to_megabytes(start))
934 end = float(self._sectors_to_megabytes(end))
935 self._run_parted_command(device, "resize " + str(minor) + " " + str(start) + " " + str(end))
936 print " Deleting old minor " + str(part) + " to be recreated in 3rd pass"
937 self._run_parted_command(dev, "rm " + str(part))
938 break
939 # Third pass to create new partition table
940 print " Third pass..."
941 for part in parts_new[dev]:
942 newpart = parts_new[dev][part]
943 new_start, new_end = self._cylinders_to_sectors(part, newpart['start'], newpart['end'], sectors_in_cylinder)
944 if newpart['type'] == "extended":
945 print " Adding extended partition from " + str(newpart['start']) + " to " + str(newpart['end'])
946 self._add_partition(dev, new_start, new_end, "extended", "")
947 elif int(part) < 5:
948 print " Adding primary partition from " + str(newpart['start']) + " to " + str(newpart['end'])
949 self._add_partition(dev, new_start, new_end, "primary", newpart['type'])
950 elif int(part) > 4:
951 print " Adding logical partition from " + str(newpart['start']) + " to " + str(newpart['end'])
952 self._add_partition(dev, new_start, new_end, "logical", newpart['type'])
953 if int(part) in parts_active and not newpart['format']:
954 print " Partition was previously active...setting"
955 self._run_parted_command(dev, "set " + str(part) + " boot on")
956 if int(part) in parts_lba and not newpart['format']:
957 print " Partition was previously LBA...setting"
958 self._run_parted_command(dev, "set " + str(part) + " lba on")

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20