/[gli]/branches/qs/src/GLIQSProfile.py
Gentoo

Contents of /branches/qs/src/GLIQSProfile.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1911 - (show annotations) (download) (as text)
Mon Jul 21 00:39:32 2008 UTC (5 years, 11 months ago) by codeman
File MIME type: text/x-python
File size: 36868 byte(s)
adding a new module to create/parse quickstart profiles
it's about halfway done.

1 """
2 # Copyright 1999-2008 Gentoo Foundation
3 # This source code is distributed under the terms of version 2 of the GNU
4 # General Public License as published by the Free Software Foundation, a copy
5 # of which can be found in the main directory of this project.
6 Gentoo Linux Installer
7
8 $Id $
9
10 The QSProfile contains all information related to the new system to be
11 installed.
12 It is maintained in the class and writeable/loadable at any time in any state.
13 """
14
15 import string
16 import os
17 import GLIUtility
18 from GLIException import *
19 import gettext
20 try:
21 gettext.install('GLIQSProfile', './languages')
22 translator = gettext.translation('GLIQSProfile', './languages')
23 _ = translator.gettext
24 except:
25 _ = gettext.gettext
26
27 ##
28 # This class contains all the settings used during the install
29 class QSProfile:
30 """
31 An object representation of a profile.
32 QSProfile is an object representation of a parsed quickstart installation
33 config file.
34 """
35
36 ##
37 # Initializes all variables to default values and adds handlers.
38 def __init__(self):
39
40 # Configuration information - profile data
41 # All variables must be declared here with a default value to ensure
42 # the XML will correctly serialize.
43
44 self._boot_device = ""
45 self._boot_loader_mbr = True
46 self._boot_loader_pkg = "grub"
47 self._bootloader_kernel_args = ""
48 self._cron_daemon_pkg = "vixie-cron"
49 self._kernel_source_pkg = "livecd-kernel"
50 self._logging_daemon_pkg = "syslog-ng"
51 self._users = []
52 self._root_pass_hash = ""
53 self._time_zone = "UTC"
54 self._portage_tree = GLIUtility.get_cd_snapshot_uri()
55 self._domainname = "localdomain"
56 self._hostname = "localhost"
57 self._mounts = []
58 self._network_mounts = []
59 self._network_interfaces = {}
60 self._make_conf = {}
61 self._dns_servers = ()
62 self._default_gateway = ()
63 self._install_packages = ()
64 self._services = ()
65 self._etc_files = {}
66 self._temp_etc_file = {}
67 self._verbose = True
68
69 # This is the root mount point
70 self._root_mount_point = "/mnt/gentoo"
71
72 ##
73 # Parses the given filename populating the profile configuration
74 # @param filename Parameter description
75 def load_profile(self, filename):
76 fh = open(filename)
77 while (line = fh.readline()):
78 type = line.split(' ')[0]
79 rest = line.split(' ')[1:]
80 if (type == "###STOP"):
81 break
82 if (type == "bootloader_install_device"): self.set_boot_device(rest) #includes mbr setting?
83 if (type == "bootloader"): self.set_boot_loader_pkg(rest)
84 if (type == "bootloader_kernel_args"): self.set_bootloader_kernel_args(rest)
85 if (type == "chroot_dir"): self.set_root_mount_point(rest)
86 if (type == "cron"): self.set_cron_daemon_pkg(rest)
87 if (type == "domainname"): self.set_domainname(rest)
88 if (type == "extra_packages"): self.set_install_packages(rest)
89 if (type == "hostname"): self.set_hostname(rest)
90 #if (type == "distcc"
91 if (type == "logger"): self.set_logging_daemon_pkg(rest)
92 if (type == "mountfs"): self.add_mount(rest)
93 if (type == "net"): self.add_network_interface(rest)
94 if (type == "netmount"): self.add_netmount(rest)
95 if (type == "nisdomainname"): self.set_nisdomainname(rest)
96 if (type == "rcadd"): self.add_service(rest)
97 if (type == "rootpw_crypt"): self.set_root_pass_hash(rest)
98 if (type == "timezone"): self.set_time_zone(rest)
99 if (type == "tree_type"): self.set_portage_tree(rest)
100 #if (type == "users"
101 if (type == "verbose"): self.set_verbose(rest)
102 if (type == "###Make.conf###"):
103 pass
104 if (type == "###etc/portage###"):
105 pass
106 fh.close()
107
108 ##
109 # This method writes out the profile of the configuration data.
110 def write_profile(self):
111 output = ""
112 if self.get_boot_device(): output += "bootloader_install_device\t" + self.get_boot_device() + "\n"
113 if self.get_bootloader(): output += "bootloader\t" + self.get_boot_loader_pkg() + "\n"
114 if self.get_bootloader_kernel_args(): output += "bootloader_kernel_args\t" + self.get_bootloader_kernel_args() + "\n"
115 if self.get_root_mount_point(): output += "chroot_dir\t" + self.get_root_mount_point() + "\n"
116 if self.get_cron_daemon_pkg(): output += "cron\t" + self.get_cron_daemon_pkg() + "\n"
117 if self.get_domainname(): output += "domainname\t" + self.get_domainname() + "\n"
118 if self.get_install_packages(): output += "extra_packages\t" + self.get_install_packages() + "\n"
119 if self.get_hostname(): output += "hostname\t" + self.get_hostname() + "\n"
120 if self.get_logging_daemon_pkg(): output += "logger\t" + self.get_logging_daemon_pkg() + "\n"
121 if self.get_mounts():
122 for mount in self.get_mounts():
123 output += "mountfs\t" + mount + "\n"
124
125 if self.get_network_interfaces():
126 for net_iface in self.get_network_interfaces():
127 output += "net\t" + net_iface + "\n"
128 if self.get_network_mounts():
129 for mount in self.get_network_mounts():
130 output += "netmount\t" + mount + "\n"
131
132 if self.get_nisdomainname(): output += "nisdomainname\t" + self.get_nisdomainname() + "\n"
133 if self.get_services():
134 for service in self.get_services():
135 output += "rcadd\t" + service
136
137 if self.get_root_pass_hash(): output += "rootpw_crypt\t" + self.get_root_pass_hash() + "\n"
138 if self.get_time_zone(): output += "timezone\t" + self.get_time_zone() + "\n"
139 if self.get_portage_tree(): output += "tree_type\t" + self.get_portage_tree() + "\n"
140 if self.get_verbose(): output += "verbose\t" + self.get_verbose() + "\n"
141
142
143
144
145
146 return output
147 ############################################################################
148 ############################################################################
149 #### Boot Device Selection
150
151 ##
152 # boot_device is a string to decide which device to install the bootloader to
153 # @param boot_loader_pkg boot device with full /dev
154 def set_boot_device(self, boot_device):
155 #check data type
156 if type(boot_device) != str:
157 raise GLIException("BootDevice", 'fatal', 'set_boot_device', "Input must be type 'string'!")
158 self._boot_device = boot_device
159
160 ##
161 # returns boot_device
162 def get_boot_device(self):
163 return self._boot_device
164
165 ############################################################################
166 #### Bootloader Package Selection
167
168 ##
169 # boot_loader_pkg is a string to decide which boot loader to install. (ie. 'grub')
170 # @param boot_loader_pkg bootloader package name (like grub or lilo)
171 def set_boot_loader_pkg(self, boot_loader_pkg):
172 # Check data type
173 if type(boot_loader_pkg) != str:
174 raise GLIException("BootLoaderPKG", 'fatal', 'set_boot_loader_pkg', "Input must be type 'string'!")
175 self._boot_loader_pkg = boot_loader_pkg
176
177 ##
178 # returns boot_loader_pkg
179 def get_boot_loader_pkg(self):
180 return self._boot_loader_pkg
181
182 ############################################################################
183 #### Bootloader Kernel Arguments
184
185 ##
186 # FIXME: agaffney, what error checking needs to be done here?
187 # kernel_args are the arguments to pass the kernel at boot from the bootloader.
188 # @param bootloader_kernel_args FIXME no idea.
189 def set_bootloader_kernel_args(self, bootloader_kernel_args):
190 self._bootloader_kernel_args = bootloader_kernel_args
191
192 ##
193 # Returns kernel arguments
194 def get_bootloader_kernel_args(self):
195 return self._bootloader_kernel_args
196
197 ############################################################################
198 #### Cron Daemon Package
199
200 ##
201 # cron_daemon_pkg is a string to determine which cron daemon to install and configure (ie. 'vixie-cron')
202 # @param cron_daemon_pkg package name
203 def set_cron_daemon_pkg(self, cron_daemon_pkg):
204 # Check data type
205 if type(cron_daemon_pkg) != str:
206 raise GLIException("CronDaemonPKGError", 'fatal', 'set_cron_daemon_pkg', "Input must be type 'string'!")
207 self._cron_daemon_pkg = cron_daemon_pkg
208
209 ##
210 # Returns the cron daemon pkg name
211 def get_cron_daemon_pkg(self):
212 return self._cron_daemon_pkg
213
214
215 ############################################################################
216 #### Network Gateway
217
218 ##
219 # Set the default gateway for the post-installed system.
220 # The format of the input is: <default-gateway interface="interface name">ip of gateway</default-gateway>
221 # It saves this information in the following format: (<interface>, <ip of gateway>)
222 # @param gateway gateway ip address
223 def set_default_gateway(self, gateway):
224 if not GLIUtility.is_realstring(gateway):
225 raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', "The gateway must be a non-empty string!")
226
227 if not GLIUtility.is_eth_device(interface):
228 raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', "Invalid device!")
229 if not GLIUtility.is_ip(gateway):
230 raise GLIException("DefaultGateway", 'fatal', 'set_default_gateway', "The IP Provided is not valid!")
231 self._default_gateway = (interface, gateway)
232
233 ##
234 # Returns the default gateway
235 def get_default_gateway(self):
236 return self._default_gateway
237
238 ############################################################################
239 #### DNS Servers
240
241 ##
242 # Set the DNS servers for the post-installed system.
243 # @param dns_servers a tuple or space-separated list of dns servers
244 def set_dns_servers(self, dns_servers):
245 if type(dns_servers) == tuple:
246 dns_servers = dns_servers[0:3]
247 elif type(dns_servers) == str:
248 dns_servers = string.split(dns_servers)
249 else:
250 raise GLIException("DnsServersError", 'fatal', 'set_dns_servers', "Invalid input!")
251
252 for server in dns_servers:
253 if not GLIUtility.is_ip(server):
254 raise GLIException("DnsServersError", 'fatal', 'set_dns_servers', server + " must be a valid IP address!")
255
256 self._dns_servers = dns_servers
257
258 ##
259 # This returns a tuple of the form: (<nameserver 1>, <nameserver 2>, <nameserver 3>)
260 def get_dns_servers(self):
261 return self._dns_servers
262
263 ############################################################################
264 #### Domainname
265
266 ##
267 # domainname is a string containing the domainname for the new system. (ie. 'mydomain.com'; NOT FQDN)
268 # @param domainname string of the domain name
269 def set_domainname(self, domainname):
270 # Check type
271 if type(domainname) != str:
272 raise GLIException("DomainnameError", 'fatal', 'set_domainname', "Must be a string!")
273 self._domainname = domainname
274
275 ##
276 # Returns domainname
277 def get_domainname(self):
278 return self._domainname
279
280 ##
281 # Used internally for XML parsing...adds an entry to a file
282 # @param xml_path Used internally by the XML parser. Should be None when calling directly
283 # @param value uhh...the value
284 # @param attr used for XML parsing
285 def add_etc_files_file_entry(self, xml_path, value, attr):
286 if 'name' in attr.getNames():
287 if not self._temp_etc_file:
288 self._temp_etc_file = {}
289 self._temp_etc_file[attr['name']] = value
290 else:
291 if not self._temp_etc_file:
292 self._temp_etc_file = []
293 self._temp_etc_file.append(value)
294
295 ##
296 # Used internally for XML parsing...adds a file
297 # @param xml_path Used internally by the XML parser. Should be None when calling directly
298 # @param unused this should be obvious
299 # @param attr used for XML parsing
300 def add_etc_files_file(self, xml_path, unused, attr):
301 self._etc_files[attr['name']] = self._temp_etc_file
302 self._temp_etc_file = None
303
304 ##
305 # Returns etc_files structure
306 def get_etc_files(self):
307 return self._etc_files
308
309 ##
310 # Replaces etc_files structure with one passed in
311 # @param etc_files new etc_files structure
312 def set_etc_files(self, etc_files):
313 self._etc_files = etc_files
314
315 ##
316 # Serializes the etc_files structure
317 def serialize_etc_files(self):
318 self.xmldoc += "<etc-files>"
319 for etc_file in self._etc_files:
320 self.xmldoc += "<file name=\"%s\">" % etc_file
321 for entry in self._etc_files[etc_file]:
322 self.xmldoc += "<entry"
323 if isinstance(self._etc_files[etc_file], dict):
324 self.xmldoc += " name=\"%s\">%s" % (entry, self._etc_files[etc_file][entry])
325 else:
326 self.xmldoc += ">%s" % entry
327 self.xmldoc += "</entry>"
328 self.xmldoc += "</file>"
329 self.xmldoc += "</etc-files>"
330
331
332
333 ############################################################################
334 #### Hostname
335
336 ##
337 # Hostname is a string containing the hostname for the new system. (ie. 'myhost'; NOT 'myhost.mydomain.com')
338 # @param hostname string of hostname
339 def set_hostname(self, hostname):
340 # Check type
341 if type(hostname) != str:
342 raise GLIException("HostnameError", 'fatal', 'set_hostname', "Must be a string!")
343 self._hostname = hostname
344
345 ##
346 # Returns hostname
347 def get_hostname(self):
348 return self._hostname
349
350
351 ############################################################################
352 #### Install Distcc
353
354 ##
355 # This tells the installer whether or not to install the distcc package
356 # @param install_distcc boolean
357 def set_install_distcc(self, install_distcc):
358 if type(install_distcc) != bool:
359 if type(install_distcc) == str:
360 install_distcc = GLIUtility.strtobool(install_distcc)
361 else:
362 raise GLIException("InstallDistcc", 'fatal', 'set_install_distcc', "Input must be type 'bool' or equiv string!")
363
364 self._install_distcc = install_distcc
365
366 ##
367 # Returns the boolean _install_distcc
368 def get_install_distcc(self):
369 return self._install_distcc
370
371 ############################################################################
372 #### Install Package List
373 ##
374 # Returns the list of packages to include in the Extra Packages screens.
375 def get_install_package_list(self):
376 install_package_list = {
377 'Desktop': (_(u"Popular Desktop Applications"),
378 {"media-sound/audacious": _(u"GTK+ music player"),
379 "media-sound/alsa-utils": _(u"Utilities for ALSA, useful for enabling sound"),
380 "media-sound/easytag": _(u"A GTK+ tagging program for MP3, OGG, FLAC, and more"),
381 "mail-client/evolution": _(u"A GNOME groupware application, a Microsoft Outlook workalike"),
382 "net-im/gaim": _(u"GTK+ Instant Messenger client"),
383 "net-ftp/gftp": _(u"GTK+ FTP Client"),
384 "media-gfx/gimp": _(u"GNU Image Manipulation Program"),
385 "app-cdr/gnomebaker": _(u"GNOME CD Writing Software"),
386 "media-gfx/gtkam": _(u"GTK+ application for transferring pictures from a digital camera"),
387 "media-gfx/inkscape": _(u"A SVG based generic vector-drawing program"),
388 "app-cdr/k3b": _(u"KDE CD Writing Software"),
389 "app-office/koffice": _(u"An integrated office suite for KDE, the K Desktop Environment"),
390 "www-client/mozilla-firefox": _(u"The Mozilla Firefox Web Browser"),
391 "mail-client/mozilla-thunderbird": _(u"Thunderbird Mail Client"),
392 "media-video/mplayer": _(u"Media Player for Linux"),
393 "app-office/openoffice": _(u"OpenOffice.org, a full office productivity suite."),
394 "app-office/openoffice-bin": _(u"Same as OpenOffice but a binary package (no compiling!)"),
395 "net-nntp/pan": _(u"GTK news reader"),
396 "media-sound/rhythmbox": _(u"Music management and playback software for GNOME"),
397 "www-client/seamonkey": _(u"Open replacement for the Mozilla Suite"),
398 "mail-client/sylpheed": _(u"A light weight email client and news reader"),
399 "mail-client/sylpheed-claws": _(u"A light weight email client and news reader"),
400 "media-video/vlc": _(u"VLC media player - Video player and streamer"),
401 "net-irc/xchat": _(u"GTK+ Graphical IRC Client"),
402 "media-video/xine-ui": _(u"Xine movie player") }),
403 'Servers': (_(u"Applications often found on servers."),
404 {"net-www/apache": _(u"Apache Web Server"),
405 "net-print/cups": _(u"The Common Unix Printing System"),
406 "mail-mta/exim": _(u"A highly configurable, drop-in replacement for sendmail"),
407 "net-firewall/iptables": _(u"Linux kernel (2.4+) firewall, NAT and packet mangling tools"),
408 "dev-db/mysql": _(u"A fast, multi-threaded, multi-user SQL database server"),
409 "dev-lang/php": _(u"The PHP scripting language"),
410 "mail-mta/postfix": _(u"A fast and secure drop-in replacement for sendmail"),
411 "dev-db/postgresql": _(u"sophisticated Object-Relational DBMS"),
412 "net-ftp/proftpd": _(u"ProFTP Server"),
413 "net-fs/samba": _(u"SAMBA client/server programs for UNIX"),
414 "mail-mta/sendmail": _(u"Widely-used Mail Transport Agent (MTA)"), }),
415 'X11': (_(u"Window managers and X selection."),
416 {"x11-themes/gentoo-artwork-livecd": _(u"Desktop background used on this disk"),
417 "gnome-base/gnome": _(u"The Gnome Desktop Environment"),
418 "kde-base/kde-meta": _(u"The K Desktop Environment"),
419 "x11-wm/blackbox": _(u"A small, fast, full-featured window manager for X"),
420 "x11-wm/enlightenment": _(u"Enlightenment Window Manager"),
421 "x11-wm/fluxbox": _(u"Fluxbox is an X11 window manager featuring tabs and an iconbar"),
422 "x11-wm/icewm": _(u"IceWM is designed for speed, size, and simplicity"),
423 "x11-wm/windowmaker": _(u"Windowmaker is a window manager featuring the look and feel of NEXTSTEP"),
424 "xfce-base/xfce4": _(u"XFCE Desktop Environment"),
425 "x11-apps/xdm": _(u"X Display Manager"),
426 "gnome-base/gdm": _(u"GNOME Display Manager"),
427 "kde-base/kdm": _(u"KDE Display Manager"),
428 "x11-base/xorg-x11": _(u"An X11 implementation maintained by the X.Org Foundation") }),
429 'Misc': (_(u"Miscellaneous Applications you may want."),
430 {"net-p2p/bittorrent": _(u"tool for distributing files via a distributed network of nodes"),
431 "app-editors/bluefish": _(u"GTK+ Web IDE"),
432 "app-editors/emacs": _(u"An incredibly powerful, extensible text editor"),
433 "app-admin/gkrellm": _(u"Single process stack of various system monitors"),
434 "app-editors/gvim": _(u"GUI version of the Vim text editor"),
435 "net-misc/keychain": _(u"ssh-agent manager"),
436 "app-admin/logrotate": _(u"Rotates, compresses, and mails system logs"),
437 "net-misc/ntp": _(u"Network Time Protocol suite/programs"),
438 "net-misc/rdesktop": _(u"A Remote Desktop Protocol Client"),
439 "sys-apps/slocate": _(u"Secure way to index and quickly search for files on your system"),
440 "net-analyzer/traceroute": _(u"Utility to trace the route of IP packets"),
441 "app-portage/ufed": _(u"Gentoo Linux USE flags editor"),
442 "app-editors/vim": _(u"Vim, an improved vi-style text editor"),
443 "net-analyzer/wireshark": _(u"A commercial-quality network protocol analyzer") }),
444 'Recommended': (_(u"Applications recommended by the GLI Team."),
445 {"dev-util/anjuta": _(u"A versatile IDE for GNOME"),
446 "app-forensics/chkrootkit": _(u"a tool to locally check for signs of a rootkit"),
447 "games-arcade/crack-attack": _(u"Addictive OpenGL-based block game"),
448 "app-crypt/gnupg": _(u"The GNU Privacy Guard, a GPL PGP replacement"),
449 "net-analyzer/net-snmp": _(u"Software for generating and retrieving SNMP data"),
450 "net-analyzer/netcat": _(u"the network swiss army knife"),
451 "net-analyzer/nmap": _(u"A utility for network exploration or security auditing"),
452 "app-misc/screen": _(u"full-screen window manager that multiplexes between several processes"),
453 "app-text/xpdf": _(u"An X Viewer for PDF Files") })
454 }
455 return install_package_list
456
457 ############################################################################
458 #### Install Packages
459
460 ##
461 # Sets up the list of packages to be installed for the new system.
462 # @param install_packages The space-separated list of packages to install.
463 def set_install_packages(self, install_packages):
464 if type(install_packages) == str:
465 install_packages = string.split(install_packages)
466 else:
467 raise GLIException("InstallPackagesError", 'fatal', 'set_install_packages', "Invalid input!")
468
469 for install_package in install_packages:
470 if not GLIUtility.is_realstring(install_package):
471 raise GLIException("InstallPackagesError", 'fatal', 'set_install_packages', install_package + " must be a valid string!")
472 self._install_packages = install_packages
473
474 ##
475 # This returns a list of the packages
476 def get_install_packages(self):
477 return self._install_packages
478
479
480 ############################################################################
481 #### Logging Daemon Package
482
483 ##
484 # logging_daemon_pkg is a string to determine which logging daemon to install and configure (ie. 'sysklogd')
485 # @param logging_daemon_pkg package name of logging daemon to be emerged
486 def set_logging_daemon_pkg(self, logging_daemon_pkg):
487 # Check data type
488 if type(logging_daemon_pkg) != str:
489 raise GLIException("LoggingDaemonPKGError", 'fatal', 'set_logging_daemon_pkg', "Input must be type 'string'!")
490 self._logging_daemon_pkg = logging_daemon_pkg
491
492 ##
493 # Returns logging daemon pkg name
494 def get_logging_daemon_pkg(self):
495 return self._logging_daemon_pkg
496
497 ############################################################################
498 #### /etc/make.conf Configuration
499
500 ##
501 # Adds a variable to the new system make.conf
502 # @param xml_path Used internally by the XML parser. Should be None when calling directly
503 # @param data a string that is the value of the variable name.
504 # @param attr an xml attribute that contains the name of the variable
505 # OR attr is a variable name, like 'USE'. This makes it easier for front-end designers.
506 def make_conf_add_var(self, xml_path, data, attr):
507 if 'name' not in attr.keys():
508 raise GLIException("MakeConfError", 'fatal', 'make_conf_add_var', "Every value needs to have a variable name!")
509
510 varName = attr['name']
511 if not "make.conf" in self._etc_files:
512 self._etc_files['make.conf'] = {}
513 self._make_conf[str(varName)] = str(data)
514
515 ##
516 # make_conf is a dictionary that will be set to _make_conf
517 # There is no checking that needs to be done, so please sure sure that the make_conf dictionary
518 # that is passed in is valid.
519 # @param make_conf a dictionary that will be set to _make_conf
520 def set_make_conf(self, make_conf):
521 self._etc_files['make.conf'] = make_conf
522
523 ##
524 # Return a dictionary of the make.conf
525 def get_make_conf(self):
526 if "make.conf" in self._etc_files:
527 return self._etc_files['make.conf']
528 else:
529 return {}
530
531 ##
532 # Serializes make.conf (no longer used)
533 def serialize_make_conf(self):
534 if self.get_make_conf() != {}:
535 self.xmldoc += "<make-conf>"
536
537 # keys should always be in the same order!
538 make_conf = self.get_make_conf()
539 make_conf_keys = make_conf.keys()
540 make_conf_keys.sort()
541
542 for var in make_conf_keys:
543 self.xmldoc += "<variable name=\"%s\">%s</variable>" % (var, make_conf[var])
544
545 self.xmldoc += "</make-conf>"
546
547
548
549 ############################################################################
550 #### Mounts
551
552 ##
553 # Mounts used during the installation and for fstab and bootloader config.
554 # @param mount_entry the entry info, in a tuple, i guess.
555 def add_mount(self, mount_entry):
556 #mount_entry = {'devnode': '', 'mountopts': '', 'mountpoint': '', 'type': ''}
557 if type(attr) == tuple:
558 mount_entry['devnode'] = attr[0]
559 mount_entry['mountopts'] = attr[1]
560 mount_entry['mountpoint'] = attr[2]
561 mount_entry['type'] = attr[3]
562 self._mounts.append(mount_entry)
563
564 ##
565 # Sets Mounts given a mounts found probably in the config file. Not sure if used.
566 # @param netmounts Parameter description
567 def set_mounts(self, mounts):
568 self._mounts = mounts
569
570 ##
571 # Returns the mounts.
572 def get_mounts(self):
573 return self._mounts
574
575 ############################################################################
576 #### MTA Selection
577
578 ##
579 # Sets the intended MTA package
580 # @param mta package name of mta
581 def set_mta_pkg(self, mta_pkg):
582 if type(mta_pkg) != str:
583 raise GLIException("MTAError", 'fatal', 'set_mta_pkg', "The MTA must be a string!")
584 self._mta_pkg = mta_pkg
585
586 ##
587 # returns the MTA
588 def get_mta_pkg(self):
589 return self._mta_pkg
590
591 ############################################################################
592 #### Network Interface Selection
593
594 ##
595 # This adds an ethernet device to the _network_interfaces dictionary.
596 # The format of this dictionary is:
597 # { <eth_device> : (options tuple), ... }
598 #
599 # eth_device can be a valid ethernet device eth0, eth1, wlan*... OR
600 # it can be a valid MAC address.
601 #
602 # The format of the options tuple is for a static IP:
603 # ( <ip address>, <broadcast>, <netmask> )
604 #
605 # For DHCP, the format of the options tuple is:
606 # ( 'dhcp', <dhcp options>, None )
607 #
608 # We keep the None as a placeholder, to not break anything that uses this
609 # in other parts of the installer.
610 #
611 # Aliases are no longer needed in the tuple because they can be treated like
612 # an individual interface. GLIUtility.is_eth_device will recognize
613 # @param xml_path Used internally by the XML parser. Should be None when calling directly
614 # @param device the type and name of the device
615 # @param attr should be dhcp or a tuple of the ip addresses.
616 def add_network_interface(self, xml_path, device, attr):
617 options = None
618 ip = broadcast = netmask = dhcp_options = None
619 dhcp = True
620
621 if type(device) != str:
622 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "Invalid or unimplimented device type (" + device + ")!")
623
624 if not GLIUtility.is_eth_device(device):
625 device = GLIUtility.format_mac(device)
626 if not GLIUtility.is_mac(device):
627 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "Invalid or unimplimented device type (" + device + ")!")
628
629 if type(attr) == tuple:
630 ip = attr[0]
631 dhcp_options = broadcast = attr[1]
632 netmask = attr[2]
633 if ip != 'dhcp':
634 dhcp = False
635 else:
636 for attrName in attr.keys():
637 if attrName == 'ip':
638 ip = str(attr[attrName])
639 elif attrName == 'broadcast':
640 broadcast = str(attr[attrName])
641 elif attrName == 'netmask':
642 netmask = str(attr[attrName])
643 elif attrName == 'options':
644 dhcp_options = str(attr[attrName])
645
646 if ip != 'dhcp' and ip != None:
647 dhcp = False
648
649 if not dhcp:
650 if not GLIUtility.is_ip(ip):
651 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The ip address you specified for " + device + " is not valid!")
652 if not GLIUtility.is_ip(broadcast):
653 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The broadcast address you specified for " + device + " is not valid!")
654 if not GLIUtility.is_ip(netmask):
655 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The netmask address you specified for " + device + " is not valid!")
656 options = (ip, broadcast, netmask)
657 else:
658 options = ('dhcp', dhcp_options, None)
659
660 self._network_interfaces[device] = options
661
662 ##
663 # This method sets the network interfaces diction to network_interfaces.
664 # This method uses the function add_network_interfaces to do all of the real work.
665 # @param network_interfaces a dict with all the networking info. see add_ for specification.
666 def set_network_interfaces(self, network_interfaces):
667 # Check type
668 if type(network_interfaces) != dict:
669 raise GLIException("NetworkInterfacesError", 'fatal', 'set_network_interfaces', "Must be a dictionary!")
670
671 self._network_interfaces = {}
672 for device in network_interfaces:
673 self.add_network_interface(None, device, network_interfaces[device])
674
675 ##
676 # Returns network_interfaces
677 def get_network_interfaces(self):
678 return self._network_interfaces
679
680 ##
681 # Serialize Network Interfaces
682 def serialize_network_interfaces(self):
683 if self.get_network_interfaces() != {}:
684 self.xmldoc += "<network-interfaces>"
685 interfaces = self.get_network_interfaces()
686 for iface in interfaces:
687 if interfaces[iface][0] == 'dhcp':
688 attrs = "ip=\"dhcp\""
689 if interfaces[iface][1] != None:
690 dhcp_options = "options=\"%s\"" % interfaces[iface][1]
691 attrs = attrs + " " + dhcp_options
692 self.xmldoc += "<device %s>%s</device>" % (attrs, iface)
693 else:
694 self.xmldoc += "<device ip=\"%s\" broadcast=\"%s\" netmask=\"%s\">%s</device>" % (interfaces[iface][0], interfaces[iface][1], interfaces[iface][2], iface)
695 self.xmldoc += "</network-interfaces>"
696
697 ############################################################################
698 #### Network Mounts
699
700 ##
701 # FIXME: agaffney: Brief description of function
702 # @param netmount_entry the entry info, in a tuple, i guess
703 def add_netmount(self, netmount_entry):
704 #netmount_entry = {'export': '', 'host': '', 'mountopts': '', 'mountpoint': '', 'type': ''}
705 if type(attr) == tuple:
706 netmount_entry['export'] = attr[0]
707 netmount_entry['host'] = attr[1]
708 netmount_entry['mountopts'] = attr[2]
709 netmount_entry['mountpoint'] = attr[3]
710 netmount_entry['type'] = attr[4]
711 else:
712 if "export" in attr.getNames():
713 for attrName in attr.getNames():
714 netmount_entry[attrName] = str(attr.getValue(attrName))
715 self._network_mounts.append(netmount_entry)
716
717 ##
718 # Sets Network Mounts given a netmounts found probably in the config file. Not sure if used.
719 # @param netmounts Parameter description
720 def set_network_mounts(self, netmounts):
721 self._network_mounts = netmounts
722
723 ##
724 # Returns the network mounts.
725 def get_network_mounts(self):
726 return self._network_mounts
727
728 ############################################################################
729 #### NIS Domain Name
730
731 ##
732 # nisdomainname is a string containing the NIS domainname for the new system.
733 # @param nisdomainname the name. is a string.
734 def set_nisdomainname(self, nisdomainname):
735 # Check type
736 if type(nisdomainname) != str:
737 raise GLIException("NISDomainnameError", 'fatal', 'set_nisdomainname', "Must be a string!")
738
739 self._nisdomainname = nisdomainname
740
741 ##
742 # Returns nisdomainname
743 def get_nisdomainname(self):
744 return self._nisdomainname
745
746
747
748 ############################################################################
749 #### Portage Snapshot URI
750
751 ##
752 # portage_tree_snapshot_uri is a string defining the path to a portage tree
753 # snapshot. (ie. 'file:///mnt/cdrom/snapshots/portage-*.tar.bz2')
754 # @param portage_tree_snapshot_uri URI of the portage tree shapshot location
755 def set_portage_tree_snapshot_uri(self, portage_tree_snapshot_uri):
756 # Check type
757 if type(portage_tree_snapshot_uri) != str:
758 raise GLIException("PortageTreeSnapshotURIError", 'fatal', 'set_portage_tree_snapshot_uri', "Must be a string!")
759
760 self._portage_tree_snapshot_uri = portage_tree_snapshot_uri
761
762 ##
763 # Returns portage_tree_snapshot_uri
764 def get_portage_tree_snapshot_uri(self):
765 return self._portage_tree_snapshot_uri
766
767
768 ############################################################################
769 #### Root Mount Point For New System
770
771 ##
772 # Sets the root_mount_point for the new system to be installed to
773 # @param root_mount_point new location for the root mount point
774 def set_root_mount_point(self, root_mount_point):
775 self._root_mount_point = root_mount_point
776
777 ##
778 # Returns the root_mount_point
779 def get_root_mount_point(self):
780 return self._root_mount_point
781
782 ############################################################################
783 #### Root Password Hash
784
785 ##
786 # root_pass_hash is a string containing an md5 password hash to be assinged as the password for the root user.
787 # @param root_pass_hash Parameter description
788 def set_root_pass_hash(self, root_pass_hash):
789 # Check type
790 if type(root_pass_hash) != str:
791 raise GLIException("RootPassHashError", 'fatal', 'set_root_pass_hash', "Must be a string!")
792 self._root_pass_hash = root_pass_hash
793
794 ##
795 # Returns root_pass_hash
796 def get_root_pass_hash(self):
797 return self._root_pass_hash
798
799 ############################################################################
800 #### Services
801
802 ##
803 # Set the services to be started on bootup. Services should be
804 # seperated by ','. WARNING: This used to be ' ' instead!
805 # @param services comma-separated list of services
806 def set_services(self, services):
807 if type(services) == str:
808 services = services.split(',')
809 else:
810 raise GLIException("ServicesError", 'fatal', 'set_services', "Invalid input!")
811
812 for service in services:
813 if not GLIUtility.is_realstring(service):
814 raise GLIException("ServicesError", 'fatal', 'set_services', service + " must be a valid string!")
815 self._services = services
816
817 ##
818 # This returns a list of the packages:
819 def get_services(self):
820 return self._services
821
822 ############################################################################
823 #### Timezone
824
825 ##
826 # time_zone is a string defining the time zone to use.
827 # Time zones are found in /usr/share/zoneinfo/. Syntax is 'UTC' or 'US/Eastern'.
828 # @param time_zone string of the intended timezone
829 def set_time_zone(self, time_zone):
830 # Check type
831 if type(time_zone) != str:
832 raise GLIException("TimeZoneError", 'fatal', 'set_time_zone', "Must be a string!")
833 self._time_zone = time_zone
834
835 ##
836 # Returns time_zone
837 def get_time_zone(self):
838 return self._time_zone
839
840 ############################################################################
841 #### Users
842
843 ##
844 # Adds a user to the list of users
845 # @param username name of user to be added
846 # @param attr=None parameters for the user.
847 def add_user(self, username, attr=None):
848 """
849 This will take a username (that is a string) and a set of attributes and it will verify everything is valid
850 and convert it into a 7-tuple set. Then it adds this tuple into the users list.
851 username and hash are manditory. All other attributes are optional. Or this method will
852 take a 7-tuple set, verify it's correctness and then append it to the _users list.
853 All items are strings except <uid>, which is an integer, and groups, which is a tuple.
854
855 The finished tuples look like this:
856 ( <user name>, <password hash>, (<tuple of groups>), <shell>, <home directory>, <user id>, <user comment> )
857
858 """
859 hash = ''
860 shell = None
861 groups = None
862 shell = None
863 homedir = None
864 uid = None
865 comment = None
866
867 if type(username) == tuple:
868 if len(username) != 7:
869 raise GLIException("UserError", 'fatal', 'add_user', "Wrong format for user tuple!")
870
871 username_tmp = username[0]
872 hash = username[1]
873 groups = username[2]
874 shell = username[3]
875 homedir = username[4]
876 uid = username[5]
877 comment = username[6]
878 username = username_tmp
879
880 if type(groups) != tuple:
881 if groups != None:
882 groups = tuple(groups.split(','))
883 else:
884 for attrName in attr.keys():
885 if attrName == 'groups':
886 groups = tuple(str(attr[attrName]).split(','))
887 elif attrName == 'shell':
888 shell = str(attr[attrName])
889 elif attrName == 'hash':
890 hash = str(attr[attrName])
891 elif attrName == 'homedir':
892 homedir = str(attr[attrName])
893 elif attrName == 'uid':
894 if attr[attrName]:
895 uid = int(attr[attrName])
896 elif attrName == 'comment':
897 comment = str(attr[attrName])
898
899 allowable_nonalphnum_characters = '_-'
900
901 if not GLIUtility.is_realstring(username):
902 raise GLIException("UserError", 'fatal', 'add_user', "username must be a non-empty string")
903
904 if username[0] not in (string.lowercase + string.uppercase):
905 raise GLIException("UsersError", 'fatal', 'add_user', "A username must start with a letter!")
906
907 for x in username:
908 if x not in (string.lowercase + string.uppercase + string.digits + allowable_nonalphnum_characters):
909 raise GLIException("UsersError", 'fatal', 'add_user', "A username must contain only letters, numbers, or these symbols: " + allowable_nonalphnum_characters)
910
911 for user in self._users:
912 if username == user[0]:
913 raise GLIException("UserError", 'fatal', 'add_user', "This username already exists!")
914
915 if (hash == None) or (hash == ''):
916 raise GLIException("UserError", 'fatal', 'add_user', "A password hash must be given for every user!")
917
918 self._users.append((username,hash,groups,shell,homedir,uid,comment))
919
920 ##
921 # Remove "username" from the _users list.
922 # @param username name of user to be removed
923 def remove_user(self, username):
924 for user in self._users:
925 if username == user[0]:
926 self._users.remove(user)
927 break
928
929 ##
930 # users is a tuple(user) of tuple's. This sets _users to this set of tuples.
931 # @param users a tuple(user) of tuple's.
932 def set_users(self, users):
933 self._users = []
934 if users != None:
935 for user in users:
936 self._users.append(user)
937
938 ##
939 # Returns users
940 def get_users(self):
941 return self._users
942
943 ##
944 # Serializes users
945 def serialize_users(self):
946 if self.get_users() != []:
947 self.xmldoc += "<users>"
948 users = self.get_users()
949 for user in users:
950 attrstr = ""
951 username = user[0]
952
953 if user[1] != None:
954 attrstr += "hash=\"%s\" " % user[1]
955 if user[2] != None:
956 attrstr += "groups=\"%s\" " % string.join(user[2],',')
957 if user[3] != None:
958 attrstr += "shell=\"%s\" " % user[3]
959 if user[4] != None:
960 attrstr += "homedir=\"%s\" " % user[4]
961 if user[5] != None:
962 attrstr += "uid=\"%s\" " % user[5]
963 if user[6] != None:
964 attrstr += "comment=\"%s\" " % user[6]
965
966 self.xmldoc += "<user %s>%s</user>" % (string.strip(attrstr), username)
967 self.xmldoc += "</users>"
968
969 ##
970 # Sets the Verbose mode (DEBUG mode)
971 # @param verbose flag. boolean.
972 def set_verbose(self, verbose):
973 if type(verbose) == str:
974 verbose = GLIUtility.strtobool(verbose)
975 self._verbose = verbose
976
977 ##
978 # Returns the verbose (DEBUG) flag
979 def get_verbose(self):
980 return self._verbose

  ViewVC Help
Powered by ViewVC 1.1.20