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

Contents of /trunk/src/GLIArchitectureTemplate.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 204 - (show annotations) (download) (as text)
Tue Jan 4 22:42:32 2005 UTC (13 years, 5 months ago) by codeman
File MIME type: text/x-python
File size: 29826 byte(s)
you like the fixes?  ok i'll keep em coming.

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