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

Contents of /trunk/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 215 - (hide annotations) (download) (as text)
Wed Jan 5 22:50:07 2005 UTC (13 years, 4 months ago) by codeman
File MIME type: text/x-python
File size: 32429 byte(s)
my midday update on GLI

1 samyron 79 """
2     Gentoo Linux Installer
3    
4 codeman 215 $Id: GLIArchitectureTemplate.py,v 1.24 2005/01/05 22:50:07 codeman 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 codeman 209 import GLIUtility, os, string, sys, shutil
16 agaffney 126 from GLIException import *
17 agaffney 127 # Until I switch my partition code to GLIUtility.spawn()
18     import commands
19 samyron 79
20     class ArchitectureTemplate:
21 agaffney 108 def __init__(self,configuration=None, install_profile=None, client_controller=None):
22 codeman 200 self._client_configuration = configuration
23 samyron 79 self._install_profile = install_profile
24 agaffney 108 self._cc = client_controller
25 samyron 79
26 samyron 102 # This will get used a lot, so it's probably
27     # better to store it in a variable than to call
28     # this method 100000 times.
29 codeman 200 self._chroot_dir = self._client_configuration.get_root_mount_point()
30 samyron 102
31 samyron 79 # These must be filled in by the subclass. _steps is a list of
32     # functions, that will carry out the installation. They must be
33     # in order.
34     #
35     # For example, self._steps might be: [preinstall, stage1, stage2, stage3, postinstall],
36     # where each entry is a function (with no arguments) that carries out the desired actions.
37     # Of course, steps will be different depending on the install_profile
38    
39     self._architecture_name = "generic"
40 codeman 215 #self._install_steps = [ (self.do_partitioning, "Partition"), TEMPORARY thing only.
41 agaffney 136 self._install_steps = [
42     (self.mount_local_partitions, "Mount local partitions"),
43     (self.mount_network_shares, "Mount network (NFS) shares"),
44     (self.unpack_stage_tarball, "Unpack stage tarball"),
45     (self.configure_make_conf, "Configure /etc/make.conf"),
46     (self.install_portage_tree, "Portage tree voodoo"),
47     (self.prepare_chroot, "Preparing chroot"),
48     (self.stage1, "Performing bootstrap"),
49     (self.stage2, "Performing 'emerge system'"),
50     (self.set_timezone, "Setting timezone"),
51     (self.emerge_kernel_sources, "Emerge kernel sources"),
52     (self.build_kernel, "Building kernel"),
53     (self.install_logging_daemon, "Logger"),
54     (self.install_cron_daemon, "Cron daemon"),
55     (self.install_filesystem_tools, "Installing filesystem tools"),
56     (self.setup_network_post, "Configuring post-install networking"),
57     (self.install_bootloader, "Configuring and installing bootloader"),
58     (self.update_config_files, "Updating config files"),
59     (self.configure_rc_conf, "Updating /etc/rc.conf")
60     ]
61 codeman 200
62 samyron 79
63 agaffney 136 def get_install_steps(self):
64     return self._install_steps
65    
66 codeman 201 def notify_frontend(self, type, data):
67     self._cc.addNotification(type, data)
68    
69 samyron 79 # It is possible to override these methods in each Arch Template.
70     # It might be necessary to do so, if the arch needs something 'weird'.
71    
72 codeman 201 def _add_to_runlevel(self, script_name, runlevel="default"):
73     "Adds the script named 'script_name' to the runlevel 'runlevel' in the chroot environement"
74    
75     # Do it
76     status = GLIUtility.spawn("rc-update add " + script_name + " " + runlevel, chroot=self._chroot_dir)
77     if not GLIUtility.exit_success(status):
78     raise GLIException("RunlevelAddError", 'warning', '_add_to_runlevel', "Failure adding " + script_name + " to runlevel " + runlevel + "!")
79    
80 codeman 209 def _emerge(self, package, binary=False, binary_only=False):
81 codeman 201 if binary_only:
82     return GLIUtility.spawn("emerge -K " + package, display_on_tty8=True, chroot=self._chroot_dir)
83     elif binary:
84     return GLIUtility.spawn("emerge -k " + package, display_on_tty8=True, chroot=self._chroot_dir)
85     else:
86     return GLIUtility.spawn("emerge " + package, display_on_tty8=True, chroot=self._chroot_dir)
87    
88 codeman 209 def _edit_config(self, filename, newvalues, delimeter='=', quotes_around_value=True):
89 codeman 201 """
90     filename = file to be editted
91     newvlaues = a dictionary of VARIABLE:VALUE pairs
92     """
93 codeman 209 if not GLIUtility.is_file(filename):
94     raise GLIException("NoSuchFileError", 'notice','_edit_config',filename + ' does not exist!')
95 codeman 201
96     f = open(filename)
97     file = f.readlines()
98     f.close()
99    
100     for key in newvalues.keys():
101     regexpr = '^\s*#?\s*' + key + '\s*' + delimeter + '.*$'
102     regexpr = re.compile(regexpr)
103    
104     for i in range(0, len(file)):
105     if regexpr.match(file[i]):
106     if not file[i][0] == '#':
107     file[i] = '#' + file[i]
108    
109     file.append('\n# Added by GLI\n')
110     if quotes_around_value:
111     file.append(key + delimeter + '"' + newvalues[key] + '"\n')
112     else:
113     file.append(key + delimeter + newvalues[key]+'\n')
114    
115     f = open(filename,'w')
116     f.writelines(file)
117     f.flush()
118     f.close()
119    
120    
121 samyron 79 def stage1(self):
122     "Stage 1 install -- bootstraping"
123    
124     # If we are doing a stage 1 install, then bootstrap
125     if self._install_profile.get_install_stage() == 1:
126 codeman 201 exitstatus = GLIUtility.spawn("/usr/portage/scripts/bootstrap.sh", chroot=self._chroot_dir)
127 samyron 79 if not GLIUtility.exitsuccess(exitstatus):
128 samyron 186 raise GLIException("Stage1Error", 'fatal','stage1', "Bootstrapping failed!")
129 codeman 201
130 samyron 79 def stage2(self):
131     # If we are doing a stage 1 or 2 install, then emerge system
132     if self._install_profile.get_install_stage() in [ 1, 2 ]:
133 codeman 201 exitstatus = self._emerge("system")
134 samyron 79 if not GLIUtility.exitsuccess(exitstatus):
135 samyron 186 raise GLIException("Stage2Error", 'fatal','stage2', "Building the system failed!")
136 samyron 79
137 agaffney 133 def unpack_stage_tarball(self):
138     if not os.path.isdir(self._chroot_dir):
139     os.makedirs(self._chroot_dir)
140 codeman 215 GLIUtility.fetch_and_unpack_tarball(self._install_profile.get_stage_tarball_uri(), self._chroot_dir, temp_directory=self._chroot_dir, keep_permissions=True)
141 samyron 79
142 agaffney 133 def prepare_chroot(self):
143 codeman 215 # Copy resolv.conf to new env
144     try:
145     shutil.copy("/etc/resolv.conf", self._chroot_dir + "/etc/resolv.conf")
146     except:
147     pass
148     ret = GLIUtility.spawn("mount -t proc none "+self._chroot_dir+"/proc")
149 samyron 79 if not GLIUtility.exitsuccess(ret):
150 codeman 215 raise GLIException("MountError", 'fatal','prepare_chroot','Could not mount /proc')
151 samyron 79
152     # Set USE flags here
153     # might want to rewrite/use _edit_config from the GLIInstallTemplate
154     # Then you should be done... at least with the preinstall.
155    
156 samyron 102 def install_packages(self):
157     "Will install any extra software!"
158 codeman 201
159 samyron 102 installpackages = self._install_profile.get_install_packages()
160     for package in installpackages:
161 codeman 201 status = self._emerge(package)
162     if not GLIUtility.exitsuccess(status):
163 samyron 186 raise GLIException("InstallPackagesError", 'warning', 'install_packages', "Could not emerge " + package + "!")
164 samyron 102
165     # **************************************************************************************
166    
167    
168     def mount_local_partitions(self):
169     "Mounts all partitions that are on the local machine"
170 codeman 213 #{ 1: { 'end': 1999871, 'format': False, 'mb': 0,
171     #'mountopts': '', 'mountpoint': '', 'start': 63, 'type': 'linux-swap'},
172     #2: { 'end': 240121727, 'format': False, 'mb': 0, 'mountopts': '',
173     #'mountpoint': '', 'start': 1999872, 'type': 'ext3'}}
174     #{'/dev/hdz': {1: {'end': 4, 'mb': 0, 'format': False, 'start': 0, 'mountopts': '', 'mountpoint': '', 'type': 'ext2', 'minor': 1}, 2: {'end': 129, 'mb': 0, 'format': False, 'start': 5, 'mountopts': '', 'mountpoint': '', 'type': 'linux-swap', 'minor': 2}, 3: {'end': 12579, 'mb': 0, 'format': False, 'start': 130, 'mountopts': '', 'mountpoint': '', 'type': 'reiserfs', 'minor': 3}, 4: {'end': 24320, 'mb': 0, 'format': False, 'start': 12580, 'mountopts': '', 'mountpoint': '', 'type': 'reiserfs', 'minor': 4}}}
175    
176     parts = self._install_profile.get_partition_tables()
177 codeman 215 parts_to_mount = {}
178 codeman 213 for device in parts:
179     #in parts['/dev/hda']
180     for partition in parts[device]:
181 codeman 214 #print parts[device][partition]
182 codeman 213 mountpoint = parts[device][partition]['mountpoint']
183     mountopts = parts[device][partition]['mountopts']
184     minor = str(parts[device][partition]['minor'])
185     partition_type = parts[device][partition]['type']
186     if mountpoint:
187     if mountopts:
188     mountopts = "-o "+mountopts+" "
189     if partition_type:
190     partition_type = "-t "+partition_type+" "
191 codeman 215 parts_to_mount[mountpoint]= {0: mountopts, 1: partition_type, 2: minor}
192    
193    
194 codeman 213 if partition_type == "linux-swap":
195     ret = GLIUtility.spawn("swapon "+device+minor)
196     if not GLIUtility.exitsuccess(ret):
197     raise GLIException("MountError", 'warning','mount_local_partitions','Could not activate swap')
198 codeman 215 sorted_list = []
199     for key in parts_to_mount.keys(): sorted_list.append(key)
200     sorted_list.sort()
201    
202     for mountpoint in sorted_list:
203     mountopts = parts_to_mount[mountpoint][0]
204     partition_type = parts_to_mount[mountpoint][1]
205     minor = parts_to_mount[mountpoint][2]
206     if not GLIUtility.is_file(self._chroot_dir+mountpoint):
207     exitstatus = GLIUtility.spawn("mkdir -p " + self._chroot_dir + mountpoint)
208     if exitstatus != 0:
209     raise GLIException("MkdirError", 'fatal','mount_local_partitions', "Making the mount point failed!")
210     ret = GLIUtility.spawn("mount "+partition_type+mountopts+device+minor+" "+self._chroot_dir+mountpoint)
211     if not GLIUtility.exitsuccess(ret):
212     raise GLIException("MountError", 'warning','mount_local_partitions','Could not mount a partition')
213    
214 samyron 102 def mount_network_shares(self):
215     "Mounts all network shares to the local machine"
216 codeman 204 pass
217 codeman 201
218 samyron 102 def fetch_sources_from_cd(self):
219     "Gets sources from CD (required for non-network installation)"
220 codeman 204 pass
221 samyron 102
222     def fetch_grp_from_cd(self):
223     "Gets grp binary packages from CD (required for non-network binary installation)"
224 codeman 204 pass
225 codeman 201
226 samyron 102 def configure_make_conf(self):
227     "Configures make.conf"
228 codeman 201
229 samyron 102 # Get make.conf options
230     options = self._install_profile.get_make_conf()
231    
232     # For each configuration option...
233     for key in options.keys():
234    
235     # Add/Edit it into make.conf
236 codeman 201 self._edit_config(self._chroot_dir + "/etc/make.conf", key, options[key])
237 samyron 102
238     def install_portage_tree(self):
239     "Get/update the portage tree"
240    
241     # Check the type of portage tree fetching we'll do
242     # If it is custom, follow the path to the custom tarball and unpack it
243     if self._install_profile.get_portage_tree_sync_type() == "custom":
244    
245     # Get portage tree info
246     portage_tree_snapshot_uri = self._install_profile.get_portage_tree_snapshot_uri()
247    
248     # Fetch and unpack the tarball
249 codeman 201 GLIUtility.fetch_and_unpack_tarball(portage_tree_snapshot_uri, self._chroot_dir + "/usr/", self._chroot_dir + "/")
250     if not GLIUtility.is_file(self._chroot_dir+"/usr/portage/distfiles"):
251     exitstatus = GLIUtility.spawn("mkdir /usr/portage/distfiles",chroot=self._chroot_dir)
252 samyron 102 if exitstatus != 0:
253 samyron 186 raise GLIException("MkdirError", 'fatal','install_portage_tree',"Making the distfiles directory failed.")
254 codeman 201 #!!!!!!!!!!FIXME THIS SHOULD NOT BE HERE
255     exitstatus = GLIUtility.spawn("cp /mnt/cdrom/distfiles/* "+self._chroot_dir+"/usr/portage/distfiles/")
256 samyron 102 if exitstatus != 0:
257 samyron 186 raise GLIException("PortageError", 'fatal','install_portage_tree',"Failed to copy the distfiles to the new system")
258 samyron 102 # If the type is webrsync, then run emerge-webrsync
259     elif self._install_profile.get_portage_tree_sync_type() == "webrsync":
260 codeman 201 exitstatus = GLIUtility.spawn("emerge-webrsync", chroot=self._chroot_dir)
261 samyron 102 if exitstatus != 0:
262 samyron 186 raise GLIException("EmergeWebRsyncError", 'fatal','install_portage_tre', "Failed to retrieve portage tree!")
263 samyron 102
264     # Otherwise, just run emerge sync
265     else:
266     exitstatus = self._emerge("sync")
267     if exitstatus != 0:
268 samyron 186 raise GLIException("EmergeSyncError", 'fatal','install_portage_tree', "Failed to retrieve portage tree!")
269 samyron 102
270     def set_timezone(self):
271     "Sets the timezone for the new environment"
272     # Set symlink
273 codeman 201 if not os.access(self._chroot_dir + "/etc/localtime", os.W_OK):
274     os.symlink(self._chroot_dir + "/usr/share/zoneinfo/" + self._install_profile.get_time_zone(), self._chroot_dir + "/etc/localtime")
275 samyron 102 if not (self._install_profile.get_time_zone() == "UTC"):
276 codeman 201 self._edit_config(self._chroot_dir + "/etc/rc.conf", "CLOCK", "local")
277 samyron 102
278     def configure_fstab(self):
279     "Configures fstab"
280     newfstab = ""
281     partitions = self._install_profile.get_fstab()
282     for partition in partitions:
283 codeman 201 if not GLIUtility.is_file(self._chroot_dir+partition):
284 codeman 214 exitstatus = GLIUtility.spawn("mkdir " + self._chroot_dir + partition)
285 samyron 102 if exitstatus != 0:
286 samyron 186 raise GLIException("MkdirError", 'fatal','configure_fstab', "Making the mount point failed!")
287 samyron 102 newfstab += partitions[partition][0] + "\t " + partition + "\t " + partitions[partition][1]
288     newfstab += "\t " + partitions[partition][2] + "\t "
289     if partition == "/boot":
290     newfstab += "1 2\n"
291     elif partition == "/":
292     newfstab += "0 1\n"
293     else:
294     newfstab += "0 0\n"
295     newfstab += "none /proc proc defaults 0 0\n"
296     newfstab += "none /dev/shm tmpfs defaults 0 0\n"
297     if GLIUtility.is_device("/dev/cdroms/cdrom0"):
298     newfstab += "/dev/cdroms/cdrom0 /mnt/cdrom auto noauto,user 0 0\n"
299 agaffney 161
300     for netmount in self._install_profile.get_network_mounts():
301     if netmount['type'] == "nfs":
302     newfstab += netmount['host'] + ":" + netmount['export'] + "\t" + netmount['mountpoint'] + "\tnfs\t" + netmount['mountopts'] + "\t0 0\n"
303 samyron 102
304 codeman 201 file_name = self._chroot_dir + "/etc/fstab"
305 samyron 102 try:
306     shutil.move(file_name, file_name + ".OLDdefault")
307     except:
308     pass
309     f = open(file_name, 'w')
310     f.writelines(newfstab)
311     f.close()
312    
313    
314     def emerge_kernel_sources(self):
315     "Fetches desired kernel sources"
316     exitstatus = self._emerge(self._install_profile.get_kernel_source_pkg())
317     if exitstatus != 0:
318 samyron 186 raise GLIException("EmergeKernelSourcesError", 'warning','emerge_kernel_sources',"Could not retrieve kernel sources!")
319 samyron 102 try:
320 codeman 201 os.stat(self._chroot_dir + "/usr/src/linux")
321 samyron 102 except:
322 codeman 201 kernels = os.listdir(self._chroot_dir+"/usr/src")
323 samyron 102 found_a_kernel = False
324     counter = 0
325     while not found_a_kernel:
326     if kernels[counter][0:6]=="linux-":
327 codeman 201 exitstatus = GLIUtility.spawn("ln -s /usr/src/"+kernels[counter]+ " /usr/src/linux",chroot=self._chroot_dir)
328 samyron 102 found_a_kernel = True
329     else:
330     counter = counter + 1
331    
332     def build_kernel(self):
333     "Builds kernel"
334     exitstatus = self._emerge("genkernel")
335     if exitstatus != 0:
336 samyron 186 raise GLIException("EmergeGenKernelError", 'warning','build_kernel', "Could not emerge genkernel!")
337 samyron 102
338     # Null the genkernel_options
339     genkernel_options = ""
340    
341     # Get the uri to the kernel config
342     kernel_config_uri = self._install_profile.get_kernel_config_uri()
343    
344     # If the uri for the kernel config is not null, then
345     if kernel_config_uri != "":
346 codeman 201 GLIUtility.get_uri(kernel_config_uri, self._chroot_dir + "/root/kernel_config")
347 samyron 102 genkernel_options = genkernel_options + " --kernel-config=/root/kernel_config"
348    
349     # Decide whether to use bootsplash or not
350     if self._install_profile.get_kernel_bootsplash():
351     genkernel_options = genkernel_options + " --bootsplash"
352     else:
353     genkernel_options = genkernel_options + " --no-bootsplash"
354    
355     # This is code to choose whether or not genekernel will build an initrd or not
356     # Genkernel currently does not support this
357     #if self._install_profile.get_kernel_initrd():
358     # pass
359     #else:
360     # pass
361    
362     # Run genkernel in chroot
363     print "genkernel all " + genkernel_options
364 codeman 201 exitstatus = GLIUtility.spawn("genkernel all " + genkernel_options, chroot=self._chroot_dir)
365 samyron 102 if exitstatus != 0:
366 samyron 186 raise GLIException("KernelBuildError", 'fatal', 'build_kernel', "Could not build kernel!")
367 samyron 102
368     def install_logging_daemon(self):
369     "Installs and sets up logger"
370     # Get loggin daemon info
371     logging_daemon_pkg = self._install_profile.get_logging_daemon_pkg()
372     if logging_daemon_pkg:
373     # Emerge Logging Daemon
374     exitstatus = self._emerge(logging_daemon_pkg)
375     if exitstatus != 0:
376 samyron 186 raise GLIException("LoggingDaemonError", 'warning','install_logging_daemon', "Could not emerge " + logging_daemon_pkg + "!")
377 samyron 102
378     # Add Logging Daemon to default runlevel
379     self._add_to_runlevel(logging_daemon_pkg)
380    
381     def install_cron_daemon(self):
382     "Installs and sets up cron"
383     # Get cron daemon info
384     cron_daemon_pkg = self._install_profile.get_cron_daemon_pkg()
385     if cron_daemon_pkg:
386     # Emerge Cron Daemon
387     exitstatus = self._emerge(cron_daemon_pkg)
388     if exitstatus != 0:
389 samyron 186 raise GLIException("CronDaemonError", 'warning', 'install_cron_daemon', "Could not emerge " + cron_daemon_pkg + "!")
390 samyron 102
391     # Add Cron Daemon to default runlevel
392     self._add_to_runlevel(cron_daemon_pkg)
393    
394     # If the Cron Daemon is not vixie-cron, run crontab
395     if cron_daemon_pkg != "vixie-cron":
396 codeman 201 exitstatus = GLIUtility.spawn("crontab /etc/crontab", chroot=self._chroot_dir)
397 samyron 102 if exitstatus != 0:
398 samyron 186 raise GLIException("CronDaemonError", 'warning', 'install_cron_daemon', "Failure making crontab!")
399 samyron 102
400     def install_filesystem_tools(self):
401     "Installs and sets up fstools"
402     # Get the list of file system tools to be installed
403     filesystem_tools = self._install_profile.get_filesystem_tools_pkgs()
404    
405     # If the fstools var is a str, convert it to a list
406     if type(filesystem_tools) == str:
407     filesystem_tools = [ filesystem_tools ]
408    
409     # For each fstool package in the list, install it
410     for package in filesystem_tools:
411     exitstatus = self._emerge(package)
412     if exitstatus != 0:
413 samyron 186 raise GLIException("FilesystemToolsError", 'warning', 'install_filesystem_tools', "Could not emerge " + package + "!")
414 samyron 102
415     def install_rp_pppoe(self):
416     "Installs rp-pppoe"
417     # If user wants us to install rp-pppoe, then do so
418     if self._install_profile.get_install_rp_pppoe():
419     exitstatus = self._emerge("rp-pppoe")
420     if exitstatus != 0:
421 samyron 186 raise GLIException("RP_PPPOEError", 'warning', 'install_rp_pppoe', "Could not emerge rp-pppoe!")
422 samyron 102
423     # Should we add a section here to automatically configure rp-pppoe?
424     # I think it should go into the setup_network_post section
425     # What do you guys think?
426    
427     def install_pcmcia_cs(self):
428     "Installs and sets up pcmcia-cs"
429     # If user wants us to install pcmcia-cs, then do so
430     if self._install_profile.get_install_pcmcia_cs():
431     exitstatus = self._emerge("pcmcia-cs")
432     if exitstatus != 0:
433 samyron 186 raise GLIException("PCMCIA_CSError", 'warning', 'install_pcmcia_cs', "Could not emerge pcmcia-cs!")
434 samyron 102
435     # Add pcmcia-cs to the default runlevel
436 codeman 201 self._add_to_runlevel(pcmcia)
437 samyron 102
438     def update_config_files(self):
439     "Runs etc-update (overwriting all config files), then re-configures the modified ones"
440     # Run etc-update overwriting all config files
441     status = GLIUtility.spawn('echo "-5" | etc-update', chroot=self._chroot_dir)
442     if not GLIUtility.exit_success(status):
443 samyron 186 raise GLIException("EtcUpdateError", 'warning', 'update_config_files', "Could not update config files!")
444 samyron 102
445     self.configure_make_conf()
446     self.configure_fstab()
447    
448     def configure_rc_conf(self):
449     "Configures rc.conf"
450     # Get make.conf options
451     options = self._install_profile.get_rc_conf()
452    
453     # For each configuration option...
454     for key in options.keys():
455    
456     # Add/Edit it into rc.conf
457 codeman 209 self._edit_config(self._chroot_dir + "/etc/rc.conf", key, options[key])
458 samyron 102
459     def setup_network_post(self):
460     "Sets up the network for the first boot"
461     # Get hostname, domainname and nisdomainname
462     hostname = self._install_profile.get_hostname()
463     domainname = self._install_profile.get_domainname()
464     nisdomainname = self._install_profile.get_nisdomainname()
465    
466     # Write the hostname to the hostname file
467 codeman 201 open(self._chroot_dir + "/etc/hostname", "w").write(hostname + "\n")
468 samyron 102
469     # Write the domainname to the nisdomainname file
470     if domainname:
471 codeman 201 open(self._chroot_dir + "/etc/dnsdomainname", "w").write(domainname + "\n")
472 samyron 102
473     # Write the nisdomainname to the nisdomainname file
474     if nisdomainname:
475 codeman 201 open(self._chroot_dir + "/etc/nisdomainname", "w").write(nisdomainname + "\n")
476 samyron 102
477     #
478     # EDIT THE /ETC/HOSTS FILE
479     #
480    
481     # The address we are editing is 127.0.0.1
482     hosts_ip = "127.0.0.1"
483    
484     # If the hostname is localhost
485     if hostname == "localhost":
486     # If a domainname is set
487     if domainname:
488     hosts_line = hostname + "." + domainname + "\t" + hostname
489     else:
490     hosts_line = hostname
491     # If the hostname is not localhost
492     else:
493     # If a domainname is set
494     if domainname:
495     hosts_line = hostname + "." + domainname + "\t" + hostname + "\tlocalhost"
496     else:
497     hosts_line = "localhost\t" + hostname
498    
499     # Write to file
500 codeman 201 self._edit_config(self._chroot_dir + "/etc/hosts", hosts_ip, hosts_line, True, '\t', False)
501 samyron 102
502     #
503     # SET DEFAULT GATEWAY
504     #
505    
506     # Get default gateway
507     default_gateway = self._install_profile.get_default_gateway()
508    
509     # If the default gateway exists, add it
510     if default_gateway:
511 codeman 201 self._edit_config(self._chroot_dir + "/etc/conf.d/net", "gateway", default_gateway)
512 samyron 102
513     #
514     # SET RESOLV INFO
515     #
516    
517     # Get dns servers
518     dns_servers = self._install_profile.get_dns_servers()
519    
520     # Clear the list
521     resolv_output = []
522    
523     # If dns servers are set
524     if dns_servers:
525    
526    
527     # Parse each dns server
528     for dns_server in dns_servers:
529     # Add the server to the output
530     resolv_output.append("nameserver " + dns_server +"\n")
531    
532     # If the domainname is set, then also output it
533     if domainname:
534     resolv_output.append("search " + domainname + "\n")
535    
536     # Output to file
537 codeman 201 resolve_conf = open(self._chroot_dir + "/etc/resolv.conf", "w")
538 samyron 102 resolve_conf.writelines(resolv_output)
539     resolve_conf.close()
540    
541     #
542     # PARSE INTERFACES
543     #
544    
545     # Fetch interfaces
546     interfaces = self._install_profile.get_network_interfaces()
547    
548     # Parse each interface
549     for interface in interfaces.keys():
550    
551     # If we are going to load the network at boot...
552     if interfaces[interface][2]:
553    
554     # Add it to the default runlevel
555 codeman 202 self._add_to_runlevel("net."+interface)
556 samyron 102
557     # Set what kind of interface it is
558     interface_type = interface[:3]
559    
560     # Check to see if there is a startup script for this interface, if there isn't link to the proper script
561     try:
562 codeman 201 os.stat(self._chroot_dir + "/etc/init.d/net." + interface)
563 samyron 102 except:
564 codeman 201 os.symlink(self._chroot_dir + "/etc/init.d/net." + interface_type + "0", self._chroot_dir + "/etc/init.d/net." + interface)
565 samyron 102
566     #
567     # ETHERNET
568     #
569     if interface_type == "eth":
570    
571     #
572     # STATIC IP
573     #
574     # If the post-install device info is not None, then it is a static ip addy
575     if interfaces[interface][1]:
576     ip = interfaces[interface][0]
577     broadcast = interfaces[interface][1]
578     netmask = interfaces[interface][2]
579     # aliases = interfaces[interface][1][3]
580     # alias_ips = []
581     # alias_broadcasts = []
582     # alias_netmasks = []
583    
584     # Write the static ip config to /etc/conf.d/net
585 codeman 201 self._edit_config(self._chroot_dir + "/etc/conf.d/net", "iface_" + interface, ip + " broadcast " + broadcast + " netmask " + netmask)
586 samyron 102
587     # If aliases are set
588     # if aliases:
589    
590     # Parse aliases to format alias info
591     # for alias in aliases:
592     # alias_ips.append(alias[0])
593     # alias_broadcasts.append(alias[1])
594     # alias_netmasks.append(allias[2])
595    
596     # Once the alias info has been gathered, then write it out
597     # Alias ips first
598 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "alias_" + interface, string.join(alias_ips))
599 samyron 102 # Alias broadcasts next
600 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "broadcast_" + interface, string.join(alias_broadcasts))
601 samyron 102 # Alias netmasks last
602 codeman 201 # self._edit_config(self._chroot_dir + "/etc/conf.d/net", "netmask_" + interface, string.join(alias_netmasks))
603 samyron 102
604     #
605     # DHCP IP
606     #
607     else:
608 codeman 201 self._edit_config(self._chroot_dir + "/etc/conf.d/net", "iface_" + interface, "dhcp")
609 samyron 102
610     def set_root_password(self):
611     "Sets the root password"
612     status = GLIUtility.spawn('echo "root:' + self._install_profile.get_root_pass_hash() + '" | chpasswd -e', chroot=self._chroot_dir)
613     if not GLIUtility.exit_success(status):
614 samyron 186 raise GLIException("SetRootPasswordError", 'warning', 'set_root_password', "Failure to set root password!")
615 samyron 102
616     def set_users(self):
617     "Sets up the new users for the system"
618     # Loop for each user
619     for user in self._install_profile.get_users():
620    
621     # Get values from the tuple
622     username = user[0]
623     password_hash = user[1]
624     groups = user[2]
625     shell = user[3]
626     home_dir = user[4]
627     uid = user[5]
628     comment = user[6]
629    
630     options = [ "-m", "-p " + password_hash ]
631    
632     # If the groups are specified
633     if groups:
634    
635     # If just one group is listed as a string, make it a list
636     if groups == str:
637     groups = [ groups ]
638    
639     # If only 1 group is listed
640     if len(groups) == 1:
641     options.append("-G " + groups[0])
642    
643     # If there is more than one group
644     elif len(groups) > 1:
645     options.append('-G "' + string.join(groups, ",") + '"')
646    
647     # If a shell is specified
648     if shell:
649     options.append("-s " + shell)
650    
651     # If a home dir is specified
652     if home_dir:
653     options.append("-d " + home_dir)
654    
655     # If a UID is specified
656     if uid:
657     options.append("-u " + str(uid))
658    
659     # If a comment is specified
660     if comment:
661     options.append('-c "' + comment + '"')
662    
663     # Add the user
664     exitstatus = GLIUtility.spawn('useradd ' + string.join(options) + ' ' + username, chroot=self._chroot_dir)
665     if not GLIUtility.exit_success(exitstatus):
666 samyron 186 raise GLIException("AddUserError", 'warning', 'set_users', "Failure to add user " + username)
667 agaffney 111
668 codeman 213 def install_bootloader(self):
669     "THIS FUNCTION MUST BE DONE BY THE INDIVIDUAL ARCH"
670     pass
671    
672 agaffney 126 def _cylinders_to_sectors(self, minor, start, end, sectors_in_cylinder):
673 agaffney 127 cylinders = int(end) - int(start) + 1
674     total_sectors = cylinders * int(sectors_in_cylinder)
675     start_sector = int(start) * sectors_in_cylinder
676 agaffney 111 end_sector = start_sector + total_sectors - 1
677 agaffney 127 if int(minor) == 1 and start_sector == 0: start_sector = 63
678 agaffney 111 return (start_sector, end_sector)
679    
680 agaffney 126 def _sectors_to_megabytes(self, sectors, sector_bytes=512):
681 agaffney 111 return float((float(sectors) * sector_bytes)/ float(1024*1024))
682    
683 agaffney 131 def _sectors_to_bytes(self, sectors, sector_bytes=512):
684     return (int(sectors) * sector_bytes)
685 agaffney 111
686 agaffney 126 def _run_parted_command(self, device, cmd):
687 agaffney 127 parted_output = commands.getoutput("parted -s " + device + " " + cmd)
688 agaffney 111 print "parted -s " + device + " " + cmd
689    
690 agaffney 126 def _add_partition(self, device, start, end, type, fs):
691 agaffney 118 start = self._sectors_to_megabytes(start)
692     end = self._sectors_to_megabytes(end)
693 agaffney 127 self._run_parted_command(device, "mkpart " + type + " " + fs + " " + str(start) + " " + str(end))
694 agaffney 117 if type == "ntfs":
695     pass
696     elif type == "ext2" or type == "ext3":
697     pass
698     else:
699     pass
700 agaffney 111
701     def do_partitioning(self):
702 agaffney 127 import GLIStorageDevice, parted, pprint
703 agaffney 111
704     devices_old = {}
705     parts_old = {}
706     parts_new = self._install_profile.get_partition_tables()
707     drives = GLIStorageDevice.detect_devices()
708     drives.sort()
709     for drive in drives:
710     devices_old[drive] = GLIStorageDevice.Device(drive)
711     devices_old[drive].set_partitions_from_disk()
712     for part in devices_old.keys(): parts_old[part] = devices_old[part].get_install_profile_structure()
713    
714 agaffney 127 pp = pprint.PrettyPrinter(indent=4)
715     pp.pprint(parts_old)
716     pp.pprint(parts_new)
717    
718 agaffney 111 for dev in parts_old.keys():
719     parts_active = []
720 agaffney 123 parts_lba = []
721 agaffney 111 print "\nProcessing " + dev + "..."
722     parted_dev = parted.PedDevice.get(dev)
723     parted_disk = parted.PedDisk.new(parted_dev)
724     last_partition_touched = 0
725     sectors_in_cylinder = devices_old[dev]._sectors_in_cylinder
726     # First pass to delete old partitions that aren't resized
727     for part in parts_old[dev]:
728     oldpart = parts_old[dev][part]
729 agaffney 118 old_start, old_end = self._cylinders_to_sectors(part, oldpart['start'], oldpart['end'], sectors_in_cylinder)
730 agaffney 111 matchingminor = 0
731     for new_part in parts_new[dev]:
732     tmppart = parts_new[dev][new_part]
733 agaffney 118 new_start, new_end = self._cylinders_to_sectors(new_part, tmppart['start'], tmppart['end'], sectors_in_cylinder)
734 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']):
735 agaffney 111 matchingminor = new_part
736     print " Deleting old minor " + str(part) + " to be recreated later"
737 agaffney 118 self._run_parted_command(dev, "rm " + str(part))
738 agaffney 111 break
739 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']):
740 agaffney 111 matchingminor = new_part
741     print " Ignoring old minor " + str(part) + " to resize later"
742     break
743     if not matchingminor:
744     print " No match found...deleting partition " + str(part)
745 agaffney 118 self._run_parted_command(dev, "rm " + str(part))
746 agaffney 111 else:
747 agaffney 123 if parted_disk.get_partition(part).get_flag(1): # Active/boot
748 agaffney 111 print " Partition " + str(part) + " was active...noted"
749 agaffney 127 parts_active.append(int(matchingminor))
750 agaffney 123 if parted_disk.get_partition(part).get_flag(7): # LBA
751     print " Partition " + str(part) + " was LBA...noted"
752 agaffney 127 parts_lba.append(int(matchingminor))
753 agaffney 111 # Second pass to resize old partitions that need to be resized
754     print " Second pass..."
755     for part in parts_old[dev]:
756     oldpart = parts_old[dev][part]
757 agaffney 118 old_start, old_end = self._cylinders_to_sectors(part, oldpart['start'], oldpart['end'], sectors_in_cylinder)
758 agaffney 111 for new_part in parts_new[dev]:
759     tmppart = parts_new[dev][new_part]
760 agaffney 118 new_start, new_end = self._cylinders_to_sectors(new_part, tmppart['start'], tmppart['end'], sectors_in_cylinder)
761 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']):
762 agaffney 111 print " Resizing old minor " + str(part) + " from " + str(oldpart['start']) + "-" + str(oldpart['end'])+ " to " + str(tmppart['start']) + "-" + str(tmppart['end'])
763 agaffney 118 type = tmppart['type']
764     device = dev
765     minor = part
766 agaffney 127 start = int(new_start)
767     end = int(new_end)
768 agaffney 118 if type == "ext2" or type == "ext3":
769     total_sectors = end - start + 1
770     commands.getstatus("resize2fs " + device + str(minor) + " " + str(total_sectors) + "s")
771     print "resize2fs " + device + str(minor) + " " + str(total_sectors) + "s"
772     elif type == "ntfs":
773     total_sectors = end - start + 1
774 agaffney 131 total_bytes = int(self._sectors_to_bytes(total_sectors))
775     commands.getstatus("ntfsresize --size " + str(total_bytes) + " " + device + str(minor))
776     print "ntfsresize --size " + str(total_bytes) + " " + device + str(minor)
777 agaffney 118 else:
778     start = float(self._sectors_to_megabytes(start))
779     end = float(self._sectors_to_megabytes(end))
780     self._run_parted_command(device, "resize " + str(minor) + " " + str(start) + " " + str(end))
781 agaffney 111 print " Deleting old minor " + str(part) + " to be recreated in 3rd pass"
782 agaffney 118 self._run_parted_command(dev, "rm " + str(part))
783 agaffney 111 break
784     # Third pass to create new partition table
785     print " Third pass..."
786     for part in parts_new[dev]:
787     newpart = parts_new[dev][part]
788 agaffney 118 new_start, new_end = self._cylinders_to_sectors(part, newpart['start'], newpart['end'], sectors_in_cylinder)
789 agaffney 111 if newpart['type'] == "extended":
790     print " Adding extended partition from " + str(newpart['start']) + " to " + str(newpart['end'])
791 agaffney 127 self._add_partition(dev, new_start, new_end, "extended", "")
792     elif int(part) < 5:
793 agaffney 111 print " Adding primary partition from " + str(newpart['start']) + " to " + str(newpart['end'])
794 agaffney 127 self._add_partition(dev, new_start, new_end, "primary", newpart['type'])
795     elif int(part) > 4:
796 agaffney 111 print " Adding logical partition from " + str(newpart['start']) + " to " + str(newpart['end'])
797 agaffney 127 self._add_partition(dev, new_start, new_end, "logical", newpart['type'])
798     if int(part) in parts_active and not newpart['format']:
799 agaffney 111 print " Partition was previously active...setting"
800 agaffney 118 self._run_parted_command(dev, "set " + str(part) + " boot on")
801 agaffney 127 if int(part) in parts_lba and not newpart['format']:
802 agaffney 123 print " Partition was previously LBA...setting"
803     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