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

Contents of /trunk/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 136 - (hide annotations) (download) (as text)
Sun Nov 21 06:42:32 2004 UTC (13 years, 7 months ago) by agaffney
File MIME type: text/x-python
File size: 36917 byte(s)
add get_install_steps() to ArchTemplate

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