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

Contents of /trunk/src/GLIInstallProfile.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1291 - (show annotations) (download) (as text)
Fri Feb 10 02:01:58 2006 UTC (14 years, 7 months ago) by agaffney
File MIME type: text/x-python
File size: 67197 byte(s)
  src/GLIPortage.py:
  use tar to transfer files from image dir to /mnt/gentoo instead of 'cp -a'
  src/GLIStorageDevice.py,src/GLIInstallProfile.py,src/templates/x86AT.py:
  'resized' flag

1 """
2 # Copyright 1999-2005 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: GLIInstallProfile.py,v 1.84 2006/02/10 02:01:58 agaffney Exp $
9
10 The GLI module contains all classes used in the Gentoo Linux Installer (or GLI).
11 The InstallProfile contains all information related to the new system to be
12 installed.
13
14 PROCEDURE TO ADD NEW VARIABLES:
15 1. Add a handler to the list. If the variable has children make sure you do it right.
16 Look at the existing structure to get an idea.
17 2. Create a section for the two or three functions.
18 3. Create the get_variable_name and set_variable_name functions.
19 Ensure the set function has correct error checking.
20 4. If a simple value, add to the list in the general serialize() function.
21 If more complex add a serialize_variable_name to the list of special cases.
22 Then add the serialize_variable_name function to the section for the variable.
23 """
24
25 import string
26 import xml.sax
27 import os
28 import GLIUtility
29 import SimpleXMLParser
30 import xml.dom.minidom
31 import GLIStorageDevice
32 from GLIException import *
33
34 ##
35 # This class contains all the settings used during the install
36 class InstallProfile:
37 """
38 An object representation of a profile.
39 InstallProfile is an object representation of a parsed installation
40 profile file.
41 """
42
43 ##
44 # Initializes all variables to default values and adds handlers.
45 def __init__(self):
46
47 # Configuration information - profile data
48 # All variables must be declared here with a default value to ensure
49 # the XML will correctly serialize.
50 self._cron_daemon_pkg = "vixie-cron"
51 self._logging_daemon_pkg = "syslog-ng"
52 self._boot_device = ""
53 self._boot_loader_mbr = True
54 self._boot_loader_pkg = ""
55 self._kernel_modules = []
56 self._kernel_config_uri = ""
57 self._kernel_build_method = "genkernel"
58 self._bootloader_kernel_args = ""
59 self._kernel_initrd = True
60 self._kernel_bootsplash = False
61 self._kernel_source_pkg = "livecd-kernel"
62 self._users = []
63 self._root_pass_hash = ""
64 self._time_zone = "UTC"
65 self._stage_tarball_uri = ""
66 self._install_stage = 3
67 self._portage_tree_sync_type = "sync"
68 self._portage_tree_snapshot_uri = ""
69 self._domainname = "localdomain"
70 self._hostname = "localhost"
71 self._http_proxy = ""
72 self._ftp_proxy = ""
73 self._rsync_proxy = ""
74 self._nisdomainname = ""
75 self._partition_tables = {}
76 self._network_mounts = []
77 self._temp_partition_table = {} # temp
78 self._network_interfaces = {}
79 self._make_conf = {}
80 # self._rc_conf = {}
81 self._install_rp_pppoe = False
82 self._filesystem_tools = ()
83 self._install_pcmcia_cs = False
84 self._dns_servers = ()
85 self._default_gateway = ()
86 self._install_packages = ()
87 self._services = ()
88 self._mta_pkg = ""
89 self._grp_install = False
90 self._post_install_script_uri = ""
91 self._etc_files = {}
92 self._temp_etc_file = {}
93 self._dynamic_stage3 = False
94 self._install_distcc = False
95 self.xmldoc = ""
96
97 # Parser handler calls. For each XML attribute and children of that attribute, a handler is needed.
98 self._parser = SimpleXMLParser.SimpleXMLParser()
99 self._parser.addHandler('gli-profile/bootloader', self.set_boot_loader_pkg)
100 self._parser.addHandler('gli-profile/boot-device', self.set_boot_device)
101 self._parser.addHandler('gli-profile/bootloader-kernel-args', self.set_bootloader_kernel_args)
102 self._parser.addHandler('gli-profile/bootloader-mbr', self.set_boot_loader_mbr)
103 self._parser.addHandler('gli-profile/cron-daemon', self.set_cron_daemon_pkg)
104 self._parser.addHandler('gli-profile/default-gateway', self.set_default_gateway)
105 self._parser.addHandler('gli-profile/dns-servers', self.set_dns_servers)
106 self._parser.addHandler('gli-profile/domainname', self.set_domainname)
107 self._parser.addHandler('gli-profile/dynamic-stage3', self.set_dynamic_stage3)
108 self._parser.addHandler('gli-profile/etc-files/file', self.add_etc_files_file, call_on_null=True)
109 self._parser.addHandler('gli-profile/etc-files/file/entry', self.add_etc_files_file_entry, call_on_null=True)
110 self._parser.addHandler('gli-profile/ftp-proxy', self.set_ftp_proxy)
111 self._parser.addHandler('gli-profile/grp-install', self.set_grp_install)
112 self._parser.addHandler('gli-profile/hostname', self.set_hostname)
113 self._parser.addHandler('gli-profile/http-proxy', self.set_http_proxy)
114 self._parser.addHandler('gli-profile/install-distcc', self.set_install_distcc)
115 self._parser.addHandler('gli-profile/install-packages', self.set_install_packages)
116 self._parser.addHandler('gli-profile/install-pcmcia-cs', self.set_install_pcmcia_cs)
117 self._parser.addHandler('gli-profile/install-rp-pppoe', self.set_install_rp_pppoe)
118 self._parser.addHandler('gli-profile/install-stage', self.set_install_stage)
119 self._parser.addHandler('gli-profile/kernel-bootsplash', self.set_kernel_bootsplash)
120 self._parser.addHandler('gli-profile/kernel-build-method', self.set_kernel_build_method)
121 self._parser.addHandler('gli-profile/kernel-config', self.set_kernel_config_uri)
122 self._parser.addHandler('gli-profile/kernel-initrd', self.set_kernel_initrd)
123 self._parser.addHandler('gli-profile/kernel-modules/module', self.add_kernel_module)
124 self._parser.addHandler('gli-profile/kernel-source', self.set_kernel_source_pkg)
125 self._parser.addHandler('gli-profile/logging-daemon', self.set_logging_daemon_pkg)
126 # self._parser.addHandler('gli-profile/make-conf/variable', self.make_conf_add_var)
127 self._parser.addHandler('gli-profile/mta', self.set_mta_pkg)
128 self._parser.addHandler('gli-profile/network-interfaces/device', self.add_network_interface)
129 self._parser.addHandler('gli-profile/network-mounts/netmount', self.add_netmount, call_on_null=True)
130 self._parser.addHandler('gli-profile/nisdomainname', self.set_nisdomainname)
131 self._parser.addHandler('gli-profile/partitions/device', self.add_partitions_device, call_on_null=True)
132 self._parser.addHandler('gli-profile/partitions/device/partition', self.add_partitions_device_partition, call_on_null=True)
133 self._parser.addHandler('gli-profile/portage-snapshot', self.set_portage_tree_snapshot_uri)
134 self._parser.addHandler('gli-profile/portage-tree-sync', self.set_portage_tree_sync_type)
135 self._parser.addHandler('gli-profile/post-install-script-uri', self.set_post_install_script_uri)
136 # self._parser.addHandler('gli-profile/rc-conf/variable', self.rc_conf_add_var)
137 self._parser.addHandler('gli-profile/root-pass-hash', self.set_root_pass_hash)
138 self._parser.addHandler('gli-profile/rsync-proxy', self.set_rsync_proxy)
139 self._parser.addHandler('gli-profile/services', self.set_services)
140 self._parser.addHandler('gli-profile/stage-tarball', self.set_stage_tarball_uri)
141 self._parser.addHandler('gli-profile/time-zone', self.set_time_zone)
142 self._parser.addHandler('gli-profile/users/user', self.add_user)
143
144 ##
145 # Parses the given filename populating the client_configuration.
146 # @param filename Parameter description
147 def parse(self, filename):
148 self._parser.parse(filename)
149
150 ##
151 # This method serializes the configuration data and output a nice XML document.
152 # NOTE: this method currently does not serialize: _partition_tables or _kernel_modules
153 def serialize(self):
154 xmltab = { 'boot-device': self.get_boot_device,
155 'bootloader': self.get_boot_loader_pkg,
156 'bootloader-mbr': self.get_boot_loader_mbr,
157 'bootloader-kernel-args': self.get_bootloader_kernel_args,
158 'cron-daemon': self.get_cron_daemon_pkg,
159 'domainname': self.get_domainname,
160 'dynamic-stage3': self.get_dynamic_stage3,
161 'ftp-proxy': self.get_ftp_proxy,
162 'grp-install': self.get_grp_install,
163 'hostname': self.get_hostname,
164 'http-proxy': self.get_http_proxy,
165 'install-distcc': self.get_install_distcc,
166 'install-pcmcia-cs': self.get_install_pcmcia_cs,
167 'install-rp-pppoe': self.get_install_rp_pppoe,
168 'install-stage': self.get_install_stage,
169 'kernel-bootsplash': self.get_kernel_bootsplash,
170 'kernel-build-method': self.get_kernel_build_method,
171 'kernel-config': self.get_kernel_config_uri,
172 'kernel-initrd': self.get_kernel_initrd,
173 'kernel-source': self.get_kernel_source_pkg,
174 'logging-daemon': self.get_logging_daemon_pkg,
175 'mta': self.get_mta_pkg,
176 'nisdomainname': self.get_nisdomainname,
177 'portage-snapshot': self.get_portage_tree_snapshot_uri,
178 'portage-tree-sync': self.get_portage_tree_sync_type,
179 'post-install-script-uri': self.get_post_install_script_uri,
180 'root-pass-hash': self.get_root_pass_hash,
181 'rsync-proxy': self.get_rsync_proxy,
182 'stage-tarball': self.get_stage_tarball_uri,
183 'time-zone': self.get_time_zone,
184 }
185 self.xmldoc = "<?xml version=\"1.0\"?>"
186 self.xmldoc += "<gli-profile>"
187
188 # Normal cases
189 for key in xmltab.keys():
190 self.xmldoc += "<%s>%s</%s>" % (key, xmltab[key](), key)
191
192 # Special cases
193 self.serialize_default_gateway()
194 self.serialize_dns_servers()
195 self.serialize_install_packages()
196 self.serialize_kernel_modules()
197 # self.serialize_make_conf()
198 self.serialize_network_interfaces()
199 self.serialize_network_mounts()
200 self.serialize_partition_tables()
201 # self.serialize_rc_conf()
202 self.serialize_services()
203 self.serialize_users()
204 self.serialize_etc_files()
205
206 self.xmldoc += "</gli-profile>"
207
208 dom = xml.dom.minidom.parseString(self.xmldoc)
209 return dom.toprettyxml()
210
211 ############################################################################
212 ############################################################################
213 #### Boot Device Selection
214
215 ##
216 # boot_device is a string to decide which device to install the bootloader to
217 # @param xml_path Used internally by the XML parser. Should be None when calling directly
218 # @param boot_loader_pkg boot device with full /dev
219 # @param xml_attr not used here
220
221 def set_boot_device(self, xml_path, boot_device, xml_attr):
222 #check data type
223 if type(boot_device) != str:
224 raise GLIException("BootDevice", 'fatal', 'set_boot_device', "Input must be type 'string'!")
225 self._boot_device = boot_device
226
227 ##
228 # returns boot_device
229 def get_boot_device(self):
230 return self._boot_device
231
232 ############################################################################
233 #### Bootloader Package Selection
234
235 ##
236 # boot_loader_pkg is a string to decide which boot loader to install. (ie. 'grub')
237 # @param xml_path Used internally by the XML parser. Should be None when calling directly
238 # @param boot_loader_pkg bootloader package name (like grub or lilo)
239 # @param xml_attr not used here
240 def set_boot_loader_pkg(self, xml_path, boot_loader_pkg, xml_attr):
241 # Check data type
242 if type(boot_loader_pkg) != str:
243 raise GLIException("BootLoaderPKG", 'fatal', 'set_boot_loader_pkg', "Input must be type 'string'!")
244 self._boot_loader_pkg = boot_loader_pkg
245
246 ##
247 # returns boot_loader_pkg
248 def get_boot_loader_pkg(self):
249 return self._boot_loader_pkg
250
251 ############################################################################
252 #### Bootloader Kernel Arguments
253
254 ##
255 # FIXME: agaffney, what error checking needs to be done here?
256 # kernel_args are the arguments to pass the kernel at boot from the bootloader.
257 # @param xml_path Used internally by the XML parser. Should be None when calling directly
258 # @param bootloader_kernel_args FIXME no idea.
259 # @param xml_attr not used here.
260 def set_bootloader_kernel_args(self, xml_path, bootloader_kernel_args, xml_attr):
261 self._bootloader_kernel_args = bootloader_kernel_args
262
263 ##
264 # Returns kernel arguments
265 def get_bootloader_kernel_args(self):
266 return self._bootloader_kernel_args
267
268 ############################################################################
269 #### Bootloader Installation to MBR
270
271 ##
272 # boot_loader_mbr is a bool. True installs boot loader to MBR.
273 # False installs boot loader to the boot or root partition.
274 # @param xml_path Used internally by the XML parser. Should be None when calling directly
275 # @param boot_loader_mbr
276 # @param xml_attr Parameter description
277 def set_boot_loader_mbr(self, xml_path, boot_loader_mbr, xml_attr):
278 # Check data type
279 if type(boot_loader_mbr) != bool:
280 if type(boot_loader_mbr) == str:
281 boot_loader_mbr = GLIUtility.strtobool(boot_loader_mbr)
282 else:
283 raise GLIException("BootLoaderMBRError", 'fatal', 'set_boot_loader_mbr', "Input must be type 'bool'!")
284 self._boot_loader_mbr = boot_loader_mbr
285
286 ##
287 # returns boot_loader_mbr
288 def get_boot_loader_mbr(self):
289 return self._boot_loader_mbr
290
291 ############################################################################
292 #### Cron Daemon Package
293
294 ##
295 # cron_daemon_pkg is a string to determine which cron daemon to install and configure (ie. 'vixie-cron')
296 # @param xml_path Used internally by the XML parser. Should be None when calling directly
297 # @param cron_daemon_pkg package name
298 # @param xml_attr Not used here.
299 def set_cron_daemon_pkg(self, xml_path, cron_daemon_pkg, xml_attr):
300 # Check data type
301 if type(cron_daemon_pkg) != str:
302 raise GLIException("CronDaemonPKGError", 'fatal', 'set_cron_daemon_pkg', "Input must be type 'string'!")
303 self._cron_daemon_pkg = cron_daemon_pkg
304
305 ##
306 # Returns the cron daemon pkg name
307 def get_cron_daemon_pkg(self):
308 return self._cron_daemon_pkg
309
310 ############################################################################
311 #### Network Gateway
312
313 ##
314 # Set the default gateway for the post-installed system.
315 # The format of the input is: <default-gateway interface="interface name">ip of gateway</default-gateway>
316 # It saves this information in the following format: (<interface>, <ip of gateway>)
317 # @param xml_path Used internally by the XML parser. Should be None when calling directly
318 # @param gateway gateway ip address
319 # @param xml_attr Parameter description
320 def set_default_gateway(self, xml_path, gateway, xml_attr):
321 if not GLIUtility.is_realstring(gateway):
322 raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', "The gateway must be a non-empty string!")
323 if not 'interface' in xml_attr.keys():
324 raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', 'No interface information specified!')
325
326 interface = str(xml_attr['interface'])
327
328 if not GLIUtility.is_eth_device(interface):
329 raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', "Invalid device!")
330 if not GLIUtility.is_ip(gateway):
331 raise GLIException("DefaultGateway", 'fatal', 'set_default_gateway', "The IP Provided is not valid!")
332 self._default_gateway = (interface, gateway)
333
334 ##
335 # Returns the default gateway
336 def get_default_gateway(self):
337 return self._default_gateway
338
339 ##
340 # Serializes default_gateway
341 def serialize_default_gateway(self):
342 if self.get_default_gateway() != ():
343 gw = self.get_default_gateway()
344 self.xmldoc += "<default-gateway interface=\"%s\">%s</default-gateway>" % (gw[0], gw[1])
345
346
347 ############################################################################
348 #### DNS Servers
349
350 ##
351 # Set the DNS servers for the post-installed system.
352 # @param xml_path Used internally by the XML parser. Should be None when calling directly
353 # @param dns_servers a tuple or space-separated list of dns servers
354 # @param xml_attr Parameter description
355 def set_dns_servers(self, xml_path, dns_servers, xml_attr):
356 if type(dns_servers) == tuple:
357 dns_servers = dns_servers[0:3]
358 elif type(dns_servers) == str:
359 dns_servers = string.split(dns_servers)
360 else:
361 raise GLIException("DnsServersError", 'fatal', 'set_dns_servers', "Invalid input!")
362
363 for server in dns_servers:
364 if not GLIUtility.is_ip(server):
365 raise GLIException("DnsServersError", 'fatal', 'set_dns_servers', server + " must be a valid IP address!")
366
367 self._dns_servers = dns_servers
368
369 ##
370 # This returns a tuple of the form: (<nameserver 1>, <nameserver 2>, <nameserver 3>)
371 def get_dns_servers(self):
372 return self._dns_servers
373
374 ##
375 # Serializes DNS Servers
376 def serialize_dns_servers(self):
377 if self.get_dns_servers() != ():
378 self.xmldoc += "<dns-servers>"
379 self.xmldoc += string.join(self.get_dns_servers(), ' ')
380 self.xmldoc += "</dns-servers>"
381
382 ############################################################################
383 #### Domainname
384
385 ##
386 # domainname is a string containing the domainname for the new system. (ie. 'mydomain.com'; NOT FQDN)
387 # @param xml_path Used internally by the XML parser. Should be None when calling directly
388 # @param domainname string of the domain name
389 # @param xml_attr not used here
390 def set_domainname(self, xml_path, domainname, xml_attr):
391 # Check type
392 if type(domainname) != str:
393 raise GLIException("DomainnameError", 'fatal', 'set_domainname', "Must be a string!")
394 self._domainname = domainname
395
396 ##
397 # Returns domainname
398 def get_domainname(self):
399 return self._domainname
400
401 ###################################################################
402 ##
403 # Set whether or not to build the stage3 from the LiveCD
404 # @param xml_path Used internally by the XML parser. Should be None when calling directly
405 # @param dynamic_stage3 True/False
406 # @param xml_attr not used here
407 def set_dynamic_stage3(self, xml_path, dynamic_stage3, xml_attr):
408 if type(dynamic_stage3) != bool:
409 if type(dynamic_stage3) == str:
410 self._dynamic_stage3 = GLIUtility.strtobool(dynamic_stage3)
411 else:
412 raise GLIException("DynamicStage3", 'fatal', 'set_dynamic_stage3', "Input must be type 'bool'!")
413 else:
414 self._dynamic_stage3 = dynamic_stage3
415
416 ##
417 # Returns whether or not to build the stage3 from the LiveCD
418 def get_dynamic_stage3(self):
419 return self._dynamic_stage3
420
421 ##
422 # Used internally for XML parsing...adds an entry to a file
423 # @param xml_path Used internally by the XML parser. Should be None when calling directly
424 # @param value uhh...the value
425 # @param attr used for XML parsing
426 def add_etc_files_file_entry(self, xml_path, value, attr):
427 if 'name' in attr.getNames():
428 if not self._temp_etc_file:
429 self._temp_etc_file = {}
430 self._temp_etc_file[attr['name']] = value
431 else:
432 if not self._temp_etc_file:
433 self._temp_etc_file = []
434 self._temp_etc_file.append(value)
435
436 ##
437 # Used internally for XML parsing...adds a file
438 # @param xml_path Used internally by the XML parser. Should be None when calling directly
439 # @param unused this should be obvious
440 # @param attr used for XML parsing
441 def add_etc_files_file(self, xml_path, unused, attr):
442 self._etc_files[attr['name']] = self._temp_etc_file
443 self._temp_etc_file = None
444
445 ##
446 # Returns etc_files structure
447 def get_etc_files(self):
448 return self._etc_files
449
450 ##
451 # Replaces etc_files structure with one passed in
452 # @param etc_files new etc_files structure
453 def set_etc_files(self, etc_files):
454 self._etc_files = etc_files
455
456 ##
457 # Serializes the etc_files structure
458 def serialize_etc_files(self):
459 self.xmldoc += "<etc-files>"
460 for etc_file in self._etc_files:
461 self.xmldoc += "<file name=\"%s\">" % etc_file
462 for entry in self._etc_files[etc_file]:
463 self.xmldoc += "<entry"
464 if isinstance(self._etc_files[etc_file], dict):
465 self.xmldoc += " name=\"%s\">%s" % (entry, self._etc_files[etc_file][entry])
466 else:
467 self.xmldoc += ">%s" % entry
468 self.xmldoc += "</entry>"
469 self.xmldoc += "</file>"
470 self.xmldoc += "</etc-files>"
471
472
473 ############################################################################
474 #### FTP Proxy
475
476 ##
477 # FTP proxy is a uri containing a proxy if needed for ftp traffic. (ie. 'ftp://myhost.mydomain:myport')
478 # @param xml_path Used internally by the XML parser. Should be None when calling directly
479 # @param ftp_proxy ftp proxy address
480 # @param xml_attr not used here
481 def set_ftp_proxy(self, xml_path, ftp_proxy, xml_attr):
482 # Check type
483 if ftp_proxy and not GLIUtility.is_uri(ftp_proxy):
484 raise GLIException("FTPProxyError", 'fatal', 'set_ftp_proxy', "Must be a uri!")
485 self._ftp_proxy = ftp_proxy
486
487 ##
488 # Returns FTP proxy
489 def get_ftp_proxy(self):
490 return self._ftp_proxy
491
492 ############################################################################
493 #### GRP Install
494
495 ##
496 # grp_install is a bool. True installs GRP. False doesn't.
497 # @param xml_path Used internally by the XML parser. Should be None when calling directly
498 # @param grp_install boolean
499 # @param xml_attr Parameter description
500 def set_grp_install(self, xml_path, grp_install, xml_attr):
501 # Check data type
502 if type(grp_install) != bool:
503 if type(grp_install) == str:
504 grp_install = GLIUtility.strtobool(grp_install)
505 else:
506 raise GLIException("GRPInstall", 'fatal', 'set_grp_install', "Input must be type 'bool'!")
507 self._grp_install = grp_install
508
509 ##
510 # returns grp_install
511 def get_grp_install(self):
512 return self._grp_install
513
514 ############################################################################
515 #### Hostname
516
517 ##
518 # Hostname is a string containing the hostname for the new system. (ie. 'myhost'; NOT 'myhost.mydomain.com')
519 # @param xml_path Used internally by the XML parser. Should be None when calling directly
520 # @param hostname string of hostname
521 # @param xml_attr not used here.
522 def set_hostname(self, xml_path, hostname, xml_attr):
523 # Check type
524 if type(hostname) != str:
525 raise GLIException("HostnameError", 'fatal', 'set_hostname', "Must be a string!")
526 self._hostname = hostname
527
528 ##
529 # Returns hostname
530 def get_hostname(self):
531 return self._hostname
532
533 ############################################################################
534 #### HTTP Proxy
535
536 ##
537 # HTTP proxy is a URI containing a proxy if needed for http traffic. (ie. 'http://myhost.mydomain:myport')
538 # @param xml_path Used internally by the XML parser. Should be None when calling directly
539 # @param http_proxy http proxy address
540 # @param xml_attr not used here
541 def set_http_proxy(self, xml_path, http_proxy, xml_attr):
542 # Check type
543 if http_proxy and not GLIUtility.is_uri(http_proxy):
544 raise GLIException("HTTPProxyError", 'fatal', 'set_http_proxy', "Must be a uri!")
545 self._http_proxy = http_proxy
546
547 ##
548 # Returns HTTP proxy
549 def get_http_proxy(self):
550 return self._http_proxy
551
552 ############################################################################
553 #### Install Distcc
554
555 ##
556 # This tells the installer whether or not to install the distcc package
557 # @param xml_path Used internally by the XML parser. Should be None when calling directly
558 # @param install_distcc boolean
559 # @param xml_attr Parameter description
560 def set_install_distcc(self, xml_path, install_distcc, xml_attr):
561 if type(install_distcc) != bool:
562 if type(install_distcc) == str:
563 install_distcc = GLIUtility.strtobool(install_distcc)
564 else:
565 raise GLIException("InstallDistcc", 'fatal', 'set_install_distcc', "Input must be type 'bool'!")
566
567 self._install_distcc = install_distcc
568
569 ##
570 # Returns the boolean _install_distcc
571 def get_install_distcc(self):
572 return self._install_distcc
573
574 ############################################################################
575 #### Install Package List
576 ##
577 # Returns the list of packages to include in the Extra Packages screens.
578 def get_install_package_list(self):
579 install_package_list = {
580 'Desktop': ("Popular Desktop Applications",
581 {"bittorrent": "tool for distributing files via a distributed network of nodes",
582 "evolution": "A GNOME groupware application, a Microsoft Outlook workalike",
583 "gaim": "GTK Instant Messenger client",
584 "gftp": "Gnome based FTP Client",
585 "gimp": "GNU Image Manipulation Program",
586 "inkscape": "A SVG based generic vector-drawing program",
587 "koffice": "An integrated office suite for KDE, the K Desktop Environment",
588 "mozilla": "The Mozilla Web Browser",
589 "mozilla-firefox": "The Mozilla Firefox Web Browser",
590 "mozilla-thunderbird": "Thunderbird Mail Client",
591 "mplayer": "Media Player for Linux",
592 "openoffice": "OpenOffice.org, a full office productivity suite.",
593 "openoffice-bin": "Same as OpenOffice but a binary package (no compiling!)",
594 "realplayer": "Real Media Player",
595 "rhythmbox": "Music management and playback software for GNOME",
596 "vlc": "VLC media player - Video player and streamer",
597 "xchat": "Graphical IRC Client",
598 "xine-ui": "Xine movie player",
599 "xmms": "X MultiMedia System" }),
600 'Servers': ("Applications often found on servers.",
601 {"apache": "Apache Web Server",
602 "cups": "The Common Unix Printing System",
603 "exim": "A highly configurable, drop-in replacement for sendmail",
604 "iptables": "Linux kernel (2.4+) firewall, NAT and packet mangling tools",
605 "mod_php": "Apache module for PHP",
606 "mysql": "A fast, multi-threaded, multi-user SQL database server",
607 "postfix": "A fast and secure drop-in replacement for sendmail",
608 "postgresql": "sophisticated Object-Relational DBMS",
609 "proftpd": "ProFTP Server",
610 "samba": "SAMBA client/server programs for UNIX",
611 "sendmail": "Widely-used Mail Transport Agent (MTA)",
612 "traceroute": "Utility to trace the route of IP packets" }),
613 'X11': ("Window managers and X selection.",
614 {"xorg-x11": "An X11 implementation maintained by the X.Org Foundation",
615 "gnome": "The Gnome Desktop Environment",
616 "kde": "The K Desktop Environment",
617 "blackbox": "A small, fast, full-featured window manager for X",
618 "enlightenment": "Enlightenment Window Manager",
619 "fluxbox": "Fluxbox is an X11 window manager featuring tabs and an iconbar",
620 "xfce4": "XFCE Desktop Environment" }),
621 'Misc': ("Miscellaneous Applications you may want.",
622 {"emacs": "An incredibly powerful, extensible text editor",
623 "ethereal": "A commercial-quality network protocol analyzer",
624 "gkrellm": "Single process stack of various system monitors",
625 "gvim": "GUI version of the Vim text editor",
626 "keychain": "ssh-agent manager",
627 "logrotate": "Rotates, compresses, and mails system logs",
628 "ntp": "Network Time Protocol suite/programs",
629 "rdesktop": "A Remote Desktop Protocol Client",
630 "slocate": "Secure way to index and quickly search for files on your system",
631 "ufed": "Gentoo Linux USE flags editor",
632 "vim": "Vim, an improved vi-style text editor" }),
633 'Recommended': ("Applications recommended by the GLI Team.",
634 {"anjuta": "A versatile IDE for GNOME",
635 "chkrootkit": "a tool to locally check for signs of a rootkit",
636 "crack-attack": "Addictive OpenGL-based block game",
637 "gnupg": "The GNU Privacy Guard, a GPL pgp replacement",
638 "net-snmp": "Software for generating and retrieving SNMP data",
639 "netcat": "the network swiss army knife",
640 "nmap": "A utility for network exploration or security auditing",
641 "screen": "full-screen window manager that multiplexes between several processes",
642 "xpdf": "An X Viewer for PDF Files" })
643 }
644 return install_package_list
645
646 ############################################################################
647 #### Install Packages
648
649 ##
650 # Sets up the list of packages to be installed for the new system.
651 # @param xml_path Used internally by the XML parser. Should be None when calling directly
652 # @param install_packages The space-separated list of packages to install.
653 # @param xml_attr Parameter description
654 def set_install_packages(self, xml_path, install_packages, xml_attr):
655 if type(install_packages) == str:
656 install_packages = string.split(install_packages)
657 else:
658 raise GLIException("InstallPackagesError", 'fatal', 'set_install_packages', "Invalid input!")
659
660 for install_package in install_packages:
661 if not GLIUtility.is_realstring(install_package):
662 raise GLIException("InstallPackagesError", 'fatal', 'set_install_packages', install_package + " must be a valid string!")
663 self._install_packages = install_packages
664
665 ##
666 # This returns a list of the packages
667 def get_install_packages(self):
668 return self._install_packages
669
670 ##
671 # Serializes install_packages
672 def serialize_install_packages(self):
673 if self.get_install_packages() != ():
674 self.xmldoc += "<install-packages>"
675 self.xmldoc += string.join(self.get_install_packages(), ' ')
676 self.xmldoc += "</install-packages>"
677
678 ############################################################################
679 #### PCMCIA-CS
680
681 ##
682 # This tells the installer whether or not to install the pcmcia_cs package
683 # @param xml_path Used internally by the XML parser. Should be None when calling directly
684 # @param install_pcmcia boolean
685 # @param xml_attr Parameter description
686 def set_install_pcmcia_cs(self, xml_path, install_pcmcia, xml_attr):
687 if type(install_pcmcia) != bool:
688 if type(install_pcmcia) == str:
689 install_pcmcia = GLIUtility.strtobool(install_pcmcia)
690 else:
691 raise GLIException("InstallPcmciaCS", 'fatal', 'set_install_pcmcia_cs', "Input must be type 'bool'!")
692
693 self._install_pcmcia_cs = install_pcmcia
694
695 ##
696 # Returns the boolean _install_pcmcia_cs
697 def get_install_pcmcia_cs(self):
698 return self._install_pcmcia_cs
699
700 ############################################################################
701 #### RP-PPPoE Installation
702
703 ##
704 # Tell the installer whether or not to install the rp-pppoe package
705 # @param xml_path Used internally by the XML parser. Should be None when calling directly
706 # @param install_rp_pppoe boolean
707 # @param xml_attr Parameter description
708 def set_install_rp_pppoe(self, xml_path, install_rp_pppoe, xml_attr):
709 if type(install_rp_pppoe) != bool:
710 if type(install_rp_pppoe) == str:
711 install_rp_pppoe = GLIUtility.strtobool(install_rp_pppoe)
712 else:
713 raise GLIException("InstallRP_PPPOE", 'fatal', 'set_install_rp_pppoe', "Invalid input!")
714
715 self._install_rp_pppoe = install_rp_pppoe
716
717 ##
718 # Return the boolean value of _install_rp_pppoe
719 def get_install_rp_pppoe(self):
720 return self._install_rp_pppoe
721
722 ############################################################################
723 #### Install Stage
724
725 ##
726 # install_stage is a integer to define which stage install to use. Appropriate stages are 1-3.
727 # @param xml_path Used internally by the XML parser. Should be None when calling directly
728 # @param install_stage install stage number
729 # @param xml_attr not used here.
730 def set_install_stage(self, xml_path, install_stage, xml_attr):
731 # Check type
732 if type(install_stage) != int:
733 if type(install_stage) == str:
734 install_stage = int(install_stage)
735 else:
736 raise GLIException("InstallStageError", 'fatal', 'set_install_stage', "Must be an integer!")
737
738 # Check for stage bounds
739 if 0 < install_stage < 4:
740 self._install_stage = install_stage
741 else:
742 raise GLIException("InstallStageError", 'fatal', 'set_install_stage', "install_stage must be 1-3!")
743
744 ##
745 # Returns install_stage
746 def get_install_stage(self):
747 return self._install_stage
748
749 ############################################################################
750 #### Kernel Bootsplash Option
751
752 ##
753 # kernel_bootsplash is a bool to determine whether or not to install bootsplash into the kernel.
754 # True builds in bootsplash support to the initrd.
755 # WARNING: kernel_source_pkg must contain a kernel with bootsplash support or the bootsplash will not appear.
756 # If you set this to true, it will build an initrd kernel even if you chose false for kernel_initrd!
757 # @param xml_path Used internally by the XML parser. Should be None when calling directly
758 # @param kernel_bootsplash boolean
759 # @param xml_attr not used here.
760 def set_kernel_bootsplash(self, xml_path, kernel_bootsplash, xml_attr):
761 # Check type
762 if type(kernel_bootsplash) != bool:
763 if type(kernel_bootsplash) == str:
764 kernel_bootsplash = GLIUtility.strtobool(kernel_bootsplash)
765 else:
766 raise GLIException("KernelBootsplashError", 'fatal', 'set_kernel_bootsplash', "Must be a bool!")
767
768 self._kernel_bootsplash = kernel_bootsplash
769
770 ##
771 # Returns kernel_bootsplash
772 def get_kernel_bootsplash(self):
773 return self._kernel_bootsplash
774
775 ############################################################################
776 #### Kernel Build Method
777
778 ##
779 # kernel_build_method is a string specifying what build method you wish to use for the kernel.
780 # Can also be a http:// or ftp:// path.
781 # @param xml_path Used internally by the XML parser. Should be None when calling directly
782 # @param kernel_build_method URI of kernel .config file
783 # @param xml_attr not used here.
784 def set_kernel_build_method(self, xml_path, kernel_build_method, xml_attr):
785 # Check type
786 if type(kernel_build_method) != str:
787 raise GLIException("KernelBuildMethodError", 'fatal', 'set_kernel_build_method', "Must be a string!")
788
789 self._kernel_build_method = kernel_build_method
790
791 ##
792 # Returns kernel_build_method
793 def get_kernel_build_method(self):
794 return self._kernel_build_method
795
796 ############################################################################
797 #### Kernel Configuration URI
798
799 ##
800 # kernel_config_uri is a string that is the path to the kernel config file you wish to use.
801 # Can also be a http:// or ftp:// path.
802 # @param xml_path Used internally by the XML parser. Should be None when calling directly
803 # @param kernel_config_uri URI of kernel .config file
804 # @param xml_attr not used here.
805 def set_kernel_config_uri(self, xml_path, kernel_config_uri, xml_attr):
806 # Check type
807 if type(kernel_config_uri) != str:
808 raise GLIException("KernelConfigURIError", 'fatal', 'set_kernel_config_uri', "Must be a string!")
809
810 # Check validity (now done in the FE)
811 #if not (kernel_config_uri):
812 # raise GLIException("KernelConfigURIError", 'fatal', 'set_kernel_config_uri', "Empty Kernel URI!")
813
814 self._kernel_config_uri = kernel_config_uri
815
816 ##
817 # Returns kernel_config_uri
818 def get_kernel_config_uri(self):
819 return self._kernel_config_uri
820
821 ############################################################################
822 #### Kernel Initrd Option
823
824 ##
825 # kernel_initrd is a bool to determine whether or not to build an initrd kernel. False builds a non-initrd kernel.
826 # (overwritten by kernel_bootsplash; needs genkernel non-initrd support not yet present)
827 # @param xml_path Used internally by the XML parser. Should be None when calling directly
828 # @param kernel_initrd boolean
829 # @param xml_attr not used here
830 def set_kernel_initrd(self, xml_path, kernel_initrd, xml_attr):
831 # Check type
832 if type(kernel_initrd) != bool:
833 if type(kernel_initrd) == str:
834 kernel_initrd = GLIUtility.strtobool(kernel_initrd)
835 else:
836 raise GLIException("KernelInitRDError", 'fatal', 'set_kernel_initrd', "Must be a bool!")
837
838 self._kernel_initrd = kernel_initrd
839
840 ##
841 # Returns kernel_initrd
842 def get_kernel_initrd(self):
843 return self._kernel_initrd
844
845 ############################################################################
846 #### Kernel Modules
847
848 ##
849 # Add a kernel module to the list of kernel modules
850 # @param xml_path Used internally by the XML parser. Should be None when calling directly
851 # @param kernel_module string of a module name
852 # @param xml_attr not used here
853 def add_kernel_module(self, xml_path, kernel_module, xml_attr):
854 if type(kernel_module) != str:
855 raise GLIException("KernelModuleError", 'fatal', 'add_kernel_module', "The kernel module must be a string!")
856 self._kernel_modules.append(kernel_module)
857
858 ##
859 # "kernel_modules is a tuple of strings containing names of modules to automatically load at boot time. (ie. '( 'ide-scsi', )')"
860 # @param kernel_modules Parameter description
861 def set_kernel_modules(self, kernel_modules):
862 # Check type
863 if type(kernel_modules) != tuple:
864 raise GLIException("KernelModulesError", 'fatal', 'set_kernel_modules', "Must be a tuple!")
865
866 self._kernel_modules = []
867
868 # Check tuple data type
869 for module in kernel_modules:
870 self._kernel_modules.append(module)
871
872 ##
873 # Returns kernel_modules
874 def get_kernel_modules(self):
875 return self._kernel_modules
876
877 ##
878 # Serializes kernel modules
879 def serialize_kernel_modules(self):
880 if self.get_kernel_modules() != []:
881 kernel_modules = self.get_kernel_modules()
882 self.xmldoc += "<kernel-modules>";
883 for module in kernel_modules:
884 self.xmldoc += "<module>%s</module>" % module
885 self.xmldoc += "</kernel-modules>";
886
887 ############################################################################
888 #### Kernel Sources
889
890 ##
891 # kernel_source_pkg is a string to define which kernel source to use. (ie. 'gentoo-sources')
892 # @param xml_path Used internally by the XML parser. Should be None when calling directly
893 # @param kernel_source_pkg package name of the kernel sources to be emerged
894 # @param xml_attr not used here.
895 def set_kernel_source_pkg(self, xml_path, kernel_source_pkg, xml_attr):
896 # Check type
897 if type(kernel_source_pkg) != str:
898 raise GLIException("KernelSourcePKGError", 'fatal', 'set_kernel_source_pkg', "Must be a string!")
899 self._kernel_source_pkg = kernel_source_pkg
900
901 ##
902 # Returns kernel_source_pkg
903 def get_kernel_source_pkg(self):
904 return self._kernel_source_pkg
905
906 ############################################################################
907 #### Logging Daemon Package
908
909 ##
910 # logging_daemon_pkg is a string to determine which logging daemon to install and configure (ie. 'sysklogd')
911 # @param xml_path Used internally by the XML parser. Should be None when calling directly
912 # @param logging_daemon_pkg package name of logging daemon to be emerged
913 # @param xml_attr Parameter description
914 def set_logging_daemon_pkg(self, xml_path, logging_daemon_pkg, xml_attr):
915 # Check data type
916 if type(logging_daemon_pkg) != str:
917 raise GLIException("LoggingDaemonPKGError", 'fatal', 'set_logging_daemon_pkg', "Input must be type 'string'!")
918 self._logging_daemon_pkg = logging_daemon_pkg
919
920 ##
921 # Returns logging daemon pkg name
922 def get_logging_daemon_pkg(self):
923 return self._logging_daemon_pkg
924
925 ############################################################################
926 #### /etc/make.conf Configuration
927
928 ##
929 # Adds a variable to the new system make.conf
930 # @param xml_path Used internally by the XML parser. Should be None when calling directly
931 # @param data a string that is the value of the variable name.
932 # @param attr an xml attribute that contains the name of the variable
933 # OR attr is a variable name, like 'USE'. This makes it easier for front-end designers.
934 def make_conf_add_var(self, xml_path, data, attr):
935 if 'name' not in attr.keys():
936 raise GLIException("MakeConfError", 'fatal', 'make_conf_add_var', "Every value needs to have a variable name!")
937
938 varName = attr['name']
939 if not "make.conf" in self._etc_files:
940 self._etc_files['make.conf'] = {}
941 self._make_conf[str(varName)] = str(data)
942
943 ##
944 # make_conf is a dictionary that will be set to _make_conf
945 # There is no checking that needs to be done, so please sure sure that the make_conf dictionary
946 # that is passed in is valid.
947 # @param make_conf a dictionary that will be set to _make_conf
948 def set_make_conf(self, make_conf):
949 self._etc_files['make.conf'] = make_conf
950
951 ##
952 # Return a dictionary of the make.conf
953 def get_make_conf(self):
954 if "make.conf" in self._etc_files:
955 return self._etc_files['make.conf']
956 else:
957 return {}
958
959 ##
960 # Serializes make.conf (no longer used)
961 def serialize_make_conf(self):
962 if self.get_make_conf() != {}:
963 self.xmldoc += "<make-conf>"
964
965 # keys should always be in the same order!
966 make_conf = self.get_make_conf()
967 make_conf_keys = make_conf.keys()
968 make_conf_keys.sort()
969
970 for var in make_conf_keys:
971 self.xmldoc += "<variable name=\"%s\">%s</variable>" % (var, make_conf[var])
972
973 self.xmldoc += "</make-conf>"
974
975 ############################################################################
976 #### MTA Selection
977
978 ##
979 # Sets the intended MTA package
980 # @param xml_path Used internally by the XML parser. Should be None when calling directly
981 # @param mta package name of mta
982 # @param xml_attr Parameter description
983 def set_mta_pkg(self, xml_path, mta_pkg, xml_attr):
984 if type(mta_pkg) != str:
985 raise GLIException("MTAError", 'fatal', 'set_mta_pkg', "The MTA must be a string!")
986 self._mta_pkg = mta_pkg
987
988 ##
989 # returns the MTA
990 def get_mta_pkg(self):
991 return self._mta_pkg
992
993 ############################################################################
994 #### Network Interface Selection
995
996 ##
997 # This adds an ethernet device to the _network_interfaces dictionary.
998 # The format of this dictionary is:
999 # { <eth_device> : (options tuple), ... }
1000 #
1001 # eth_device can be a valid ethernet device eth0, eth1, wlan*... OR
1002 # it can be a valid MAC address.
1003 #
1004 # The format of the options tuple is for a static IP:
1005 # ( <ip address>, <broadcast>, <netmask> )
1006 #
1007 # For DHCP, the format of the options tuple is:
1008 # ( 'dhcp', <dhcp options>, None )
1009 #
1010 # We keep the None as a placeholder, to not break anything that uses this
1011 # in other parts of the installer.
1012 #
1013 # Aliases are no longer needed in the tuple because they can be treated like
1014 # an individual interface. GLIUtility.is_eth_device will recognize
1015 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1016 # @param device the type and name of the device
1017 # @param attr should be dhcp or a tuple of the ip addresses.
1018 def add_network_interface(self, xml_path, device, attr):
1019 options = None
1020 ip = broadcast = netmask = dhcp_options = None
1021 dhcp = True
1022
1023 if type(device) != str:
1024 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "Invalid or unimplimented device type (" + device + ")!")
1025
1026 if not GLIUtility.is_eth_device(device):
1027 device = GLIUtility.format_mac(device)
1028 if not GLIUtility.is_mac(device):
1029 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "Invalid or unimplimented device type (" + device + ")!")
1030
1031 if type(attr) == tuple:
1032 ip = attr[0]
1033 dhcp_options = broadcast = attr[1]
1034 netmask = attr[2]
1035 if ip != 'dhcp':
1036 dhcp = False
1037 else:
1038 for attrName in attr.keys():
1039 if attrName == 'ip':
1040 ip = str(attr[attrName])
1041 elif attrName == 'broadcast':
1042 broadcast = str(attr[attrName])
1043 elif attrName == 'netmask':
1044 netmask = str(attr[attrName])
1045 elif attrName == 'options':
1046 dhcp_options = str(attr[attrName])
1047
1048 if ip != 'dhcp' and ip != None:
1049 dhcp = False
1050
1051 if not dhcp:
1052 if not GLIUtility.is_ip(ip):
1053 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The ip address you specified for " + device + " is not valid!")
1054 if not GLIUtility.is_ip(broadcast):
1055 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The broadcast address you specified for " + device + " is not valid!")
1056 if not GLIUtility.is_ip(netmask):
1057 raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The netmask address you specified for " + device + " is not valid!")
1058 options = (ip, broadcast, netmask)
1059 else:
1060 options = ('dhcp', dhcp_options, None)
1061
1062 self._network_interfaces[device] = options
1063
1064 ##
1065 # This method sets the network interfaces diction to network_interfaces.
1066 # This method uses the function add_network_interfaces to do all of the real work.
1067 # @param network_interfaces a dict with all the networking info. see add_ for specification.
1068 def set_network_interfaces(self, network_interfaces):
1069 # Check type
1070 if type(network_interfaces) != dict:
1071 raise GLIException("NetworkInterfacesError", 'fatal', 'set_network_interfaces', "Must be a dictionary!")
1072
1073 self._network_interfaces = {}
1074 for device in network_interfaces:
1075 self.add_network_interface(None, device, network_interfaces[device])
1076
1077 ##
1078 # Returns network_interfaces
1079 def get_network_interfaces(self):
1080 return self._network_interfaces
1081
1082 ##
1083 # Serialize Network Interfaces
1084 def serialize_network_interfaces(self):
1085 if self.get_network_interfaces() != {}:
1086 self.xmldoc += "<network-interfaces>"
1087 interfaces = self.get_network_interfaces()
1088 for iface in interfaces:
1089 if interfaces[iface][0] == 'dhcp':
1090 attrs = "ip=\"dhcp\""
1091 if interfaces[iface][1] != None:
1092 dhcp_options = "options=\"%s\"" % interfaces[iface][1]
1093 attrs = attrs + " " + dhcp_options
1094 self.xmldoc += "<device %s>%s</device>" % (attrs, iface)
1095 else:
1096 self.xmldoc += "<device ip=\"%s\" broadcast=\"%s\" netmask=\"%s\">%s</device>" % (interfaces[iface][0], interfaces[iface][1], interfaces[iface][2], iface)
1097 self.xmldoc += "</network-interfaces>"
1098
1099 ############################################################################
1100 #### Network Mounts
1101
1102 ##
1103 # FIXME: agaffney: Brief description of function
1104 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1105 # @param unused Parameter description
1106 # @param attr Parameter description
1107 def add_netmount(self, xml_path, unused, attr):
1108 netmount_entry = {'export': '', 'host': '', 'mountopts': '', 'mountpoint': '', 'type': ''}
1109 if type(attr) == tuple:
1110 netmount_entry['export'] = attr[0]
1111 netmount_entry['host'] = attr[1]
1112 netmount_entry['mountopts'] = attr[2]
1113 netmount_entry['mountpoint'] = attr[3]
1114 netmount_entry['type'] = attr[4]
1115 else:
1116 if "export" in attr.getNames():
1117 for attrName in attr.getNames():
1118 netmount_entry[attrName] = str(attr.getValue(attrName))
1119 self._network_mounts.append(netmount_entry)
1120
1121 ##
1122 # Sets Network Mounts given a netmounts found probably in the config file. Not sure if used.
1123 # @param netmounts Parameter description
1124 def set_network_mounts(self, netmounts):
1125 self._network_mounts = netmounts
1126
1127 ##
1128 # Returns the network mounts.
1129 def get_network_mounts(self):
1130 return self._network_mounts
1131
1132 ##
1133 # Serializes network mounts
1134 def serialize_network_mounts(self):
1135 if self.get_network_mounts() != {}:
1136 netmounts = self.get_network_mounts()
1137 self.xmldoc += "<network-mounts>"
1138 for mount in netmounts:
1139 self.xmldoc += "<netmount host=\"%s\" export=\"%s\" type=\"%s\" mountpoint=\"%s\" mountopts=\"%s\" />" % (mount['host'], mount['export'], mount['type'], mount['mountpoint'], mount['mountopts'])
1140 self.xmldoc += "</network-mounts>"
1141
1142 ############################################################################
1143 #### NIS Domain Name
1144
1145 ##
1146 # nisdomainname is a string containing the NIS domainname for the new system.
1147 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1148 # @param nisdomainname the name. is a string.
1149 # @param xml_attr not used here
1150 def set_nisdomainname(self, xml_path, nisdomainname, xml_attr):
1151 # Check type
1152 if type(nisdomainname) != str:
1153 raise GLIException("NISDomainnameError", 'fatal', 'set_nisdomainname', "Must be a string!")
1154
1155 self._nisdomainname = nisdomainname
1156
1157 ##
1158 # Returns nisdomainname
1159 def get_nisdomainname(self):
1160 return self._nisdomainname
1161
1162 ############################################################################
1163 #### Partitioning
1164
1165 ##
1166 # FIXME: agaffney
1167 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1168 # @param unused Parameter description
1169 # @param attr Parameter description
1170 def add_partitions_device(self, xml_path, unused, attr):
1171 devnode = None
1172 if type(attr) == tuple:
1173 devnode = attr[0]
1174 disklabel = attr[1]
1175 else:
1176 if "devnode" in attr.getNames():
1177 devnode = str(attr.getValue("devnode"))
1178 if "disklabel" in attr.getNames():
1179 disklabel = str(attr.getValue("disklabel"))
1180 else:
1181 disklabel = ""
1182 self._partition_current_device = devnode
1183 self._partition_tables[devnode] = GLIStorageDevice.Device(devnode)
1184 self._partition_tables[devnode].set_disklabel(disklabel)
1185 # Add code to import self._temp_partition_table into the Device object
1186 self._partition_tables[devnode].set_partitions_from_install_profile_structure(self._temp_partition_table)
1187 self._temp_partition_table = {}
1188
1189
1190 ##
1191 # FIXME: agaffney
1192 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1193 # @param unused Parameter description
1194 # @param attr Parameter description
1195 def add_partitions_device_partition(self, xml_path, unused, attr):
1196 part_entry = {'end': 0, 'format': None, 'mb': 0, 'minor': 0, 'mountopts': '', 'mountpoint': '', 'origminor': '', 'start': 0, 'type': ''}
1197 # if type(attr) == tuple:
1198 # part_entry['end'] = attr[0]
1199 # part_entry['format'] = attr[1]
1200 # part_entry['mb'] = attr[2]
1201 # part_entry['minor'] = attr[3]
1202 # part_entry['mountopts'] = attr[4]
1203 # part_entry['mountpoint'] = attr[5]
1204 # part_entry['origminor'] = attr[6]
1205 # part_entry['start'] = attr[7]
1206 # part_entry['type'] = attr[8]
1207 # else:
1208 if "minor" in attr.getNames():
1209 for attrName in attr.getNames():
1210 part_entry[attrName] = str(attr.getValue(attrName))
1211 if type(part_entry['format']) == str: part_entry['format'] = GLIUtility.strtobool(part_entry['format'])
1212 if type(part_entry['resized']) == str: part_entry['resized'] = GLIUtility.strtobool(part_entry['resized'])
1213 # if GLIUtility.is_numeric(part_entry['end']): part_entry['end'] = long(part_entry['end'])
1214 # if GLIUtility.is_numeric(part_entry['start']): part_entry['start'] = long(part_entry['start'])
1215 if GLIUtility.is_numeric(part_entry['mb']): part_entry['mb'] = long(part_entry['mb'])
1216 if GLIUtility.is_numeric(part_entry['minor']):
1217 if part_entry['type'] == "free":
1218 part_entry['minor'] = float(part_entry['minor'])
1219 else:
1220 part_entry['minor'] = int(part_entry['minor'])
1221 if GLIUtility.is_numeric(part_entry['origminor']): part_entry['origminor'] = int(part_entry['origminor'])
1222 self._temp_partition_table[part_entry['minor']] = part_entry
1223
1224 ############################################################################
1225 #### Partition Tables
1226
1227 ##
1228 # Sets the partition Tables
1229 # @param partition_tables multilevel dictionary described below.
1230 def set_partition_tables(self, partition_tables):
1231 """
1232 Sets the partition tables. A partition is a multi level dictionary in the following format:
1233 { <device (local)>: <partition table>, <device (nfs)>: <mount point> }
1234
1235 <device (local)> is a string containing the path to the local file. (ie. '/dev/hda')
1236 <device (nfs)> is a string containing the ip address of the nfs mount. (ie. '192.168.1.2')
1237
1238 <partition table> is a dictionary in the following format:
1239 { <minor>: { 'mb': <size in mb>, 'type': <type>, 'mountpoint': <mount point>, 'start': <start cylinder>,
1240 'end': <end cylinder>, 'mountopts': <mount options>, 'format': <format> } }
1241
1242 ie. partition_tables['/dev/hda'][1] would return { 'mb': 0, 'type': 'ext3', 'mountpoint': '/boot', 'start': 12345,
1243 'end': 34567, 'mountopts': 'auto', format: 'False' }
1244
1245 Types are as follows:
1246 string: <device>, <mount point>, <mount options>, <type>
1247 integer: <minor>, <size in mb>, <start cylinder>, <end cylinder>
1248 boolean: <format>
1249
1250 Current <type> options include:
1251 ext2, ext3, reiserfs, xfs, jfs, linux-swap, extended, others?
1252
1253 There will be a method in the partitioning code to make sure that the current parition_tables can actually be implemented.
1254 Should we call that function to test the culpability of our potential partitioning scheme?
1255 Should we create a method in the Controller to take raw variables and put them in the proper structure?
1256 Are all filesystems supported by all arches?
1257 """
1258
1259 # All the sanity checks are being commented out until I can fix them for the GLIStorageDevice stuff
1260 """
1261 if type(partition_tables) != dict:
1262 raise GLIException("PartitionTableError", 'fatal', 'set_partition_tables', "Invalid data type! partition_tables is a dict...")
1263
1264 for device in partition_tables:
1265
1266 # If the device is a valid local device...
1267 if GLIUtility.is_device(device):
1268
1269 # We should check to make sure device is in /proc/partitions
1270 # If it is in /proc/partitions, it is a partitionable device
1271
1272 # ... then loop through each minor to check data
1273 for minor in partition_tables[device]:
1274
1275 # Make sure that the <minor> is an integer or can be converted to one
1276 try:
1277 int(minor)
1278 except:
1279 raise GLIException("ParitionTableError", 'fatal', 'set_partition_tables', "The minor you specified (" + minor + ") is not an integer!")
1280
1281 # Make sure that a minor number is valid
1282 if minor < 1:
1283 raise GLIException("ParitionTableError", 'fatal', 'set_partition_tables', "The minor you specified (" + minor + ") is not a valid minor!")
1284
1285 # Make sure that <size>, <type> and <mount point> are all set
1286 #if len(partition_tables[device][minor]) != 3:
1287 # raise GLIException("ParitionTableError", 'fatal', 'set_partition_tables', "The number of attributes for minor " + minor + " is incorrect!")
1288 #
1289 # Make sure that the <size> is an integer or can be converted to one
1290 #try:
1291 # int(partition_tables[device][minor][0])
1292 #except:
1293 # raise GLIException("ParitionTableError", 'fatal', 'set_partition_tables', "The size you specified (" + partition_tables[device][minor][0] + ") is not an integer!")
1294
1295 # Else, if the device is a valid remote device (hostname or ip)
1296 elif GLIUtility.is_ip(device) or GLIUtility.is_hostname(device):
1297
1298 pass
1299 # Make sure that only the mount point is set
1300 # if type(partition_tables[device]) != str:
1301 # raise GLIException("ParitionTableError", 'fatal', 'set_partition_tables', "Invalid mount point for nfs mount (device: " + device + ")!")
1302
1303 # If the device is not a local or remote device, then it is invalid
1304 else:
1305 raise GLIException("PartitionTableError", 'fatal', 'set_partition_tables', "The device you specified (" + device + ") is not valid!")
1306 """
1307
1308 # If all the tests clear, then set the variable
1309 self._partition_tables = partition_tables
1310
1311 ##
1312 # Returns partition_tables
1313 def get_partition_tables(self):
1314 return self._partition_tables
1315
1316 ##
1317 # Serializes partition tables
1318 def serialize_partition_tables(self):
1319 if self.get_partition_tables() != {}:
1320 partitions = self.get_partition_tables()
1321 self.xmldoc += "<partitions>";
1322 for device in partitions.keys():
1323 self.xmldoc += "<device devnode=\"%s\" disklabel=\"%s\">" % (device, partitions[device].get_disklabel())
1324 ips = partitions[device].get_install_profile_structure()
1325 for minor in ips:
1326 part = ips[minor]
1327 self.xmldoc += "<partition minor=\"%s\" origminor=\"%s\" mb=\"%s\" type=\"%s\" mountpoint=\"%s\" mountopts=\"%s\" format=\"%s\" mkfsopts=\"%s\" resized=\"%s\" />" % (str(minor), str(part['origminor']), str(part['mb']), str(part['type']), str(part['mountpoint']), str(part['mountopts']), str(part['format']), str(part['mkfsopts']), str(part['resized']))
1328 self.xmldoc += "</device>"
1329 self.xmldoc += "</partitions>"
1330
1331 ############################################################################
1332 #### Portage Snapshot URI
1333
1334 ##
1335 # portage_tree_snapshot_uri is a string defining the path to a portage tree
1336 # snapshot. (ie. 'file:///mnt/cdrom/snapshots/portage-*.tar.bz2')
1337 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1338 # @param portage_tree_snapshot_uri URI of the portage tree shapshot location
1339 # @param xml_attr not used here
1340 def set_portage_tree_snapshot_uri(self, xml_path, portage_tree_snapshot_uri, xml_attr):
1341 # Check type
1342 if type(portage_tree_snapshot_uri) != str:
1343 raise GLIException("PortageTreeSnapshotURIError", 'fatal', 'set_portage_tree_snapshot_uri', "Must be a string!")
1344
1345 self._portage_tree_snapshot_uri = portage_tree_snapshot_uri
1346
1347 ##
1348 # Returns portage_tree_snapshot_uri
1349 def get_portage_tree_snapshot_uri(self):
1350 return self._portage_tree_snapshot_uri
1351
1352 ############################################################################
1353 #### Portage Tree Sync Type
1354
1355 ##
1356 # Sets the sync type to be used by portage
1357 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1358 # @param portage_tree_sync string with sync type
1359 # @param xml_attr not used here
1360 def set_portage_tree_sync_type(self, xml_path, portage_tree_sync, xml_attr):
1361 # Check type
1362 if type(portage_tree_sync) != str:
1363 raise GLIException("PortageTreeSyncError", 'fatal', 'set_portage_tree_sync_type', "Must be a string!")
1364
1365 if string.lower(portage_tree_sync) not in ('sync', 'webrsync', 'custom', 'snapshot', 'none'):
1366 raise GLIException("PortageTreeSyncError", 'fatal', 'set_portage_tree_sync_type', "Invalid Input!")
1367
1368 self._portage_tree_sync_type = string.lower(portage_tree_sync)
1369
1370 ##
1371 # Returns portage_tree_sync
1372 def get_portage_tree_sync_type(self):
1373 return self._portage_tree_sync_type
1374
1375 ############################################################################
1376 #### Post-Install Script URI
1377
1378 ##
1379 # Sets the URI for the post install script
1380 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1381 # @param post_install_script_uri the URI
1382 # @param xml_attr Parameter description
1383 def set_post_install_script_uri(self, xml_path, post_install_script_uri, xml_attr):
1384 self._post_install_script_uri = post_install_script_uri
1385
1386 ##
1387 # Returns the URI for the post install script
1388 def get_post_install_script_uri(self):
1389 return self._post_install_script_uri
1390
1391 ############################################################################
1392 #### /etc/rc.conf Configuration
1393
1394 ##
1395 # Adds a variable set for the new system rc.conf
1396 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1397 # @param data a string that is the value of the variable name.
1398 # @param attr an xml attribute that contains the name of the variable
1399 def rc_conf_add_var(self, xml_path, data, attr):
1400 if 'name' not in attr.keys():
1401 raise GLIException("RCConfError", 'fatal', 'rc_conf_add_var', "Every value needs to have a variable name!")
1402
1403 varName = attr['name']
1404 if not "rc.conf" in self._etc_files:
1405 self._etc_files['rc.conf'] = {}
1406 self._etc_files[str(varName)] = str(data)
1407
1408 ##
1409 # rc_conf is a dictionary that will be set to _rc_conf
1410 # There is no checking that needs to be done, so please sure sure that the rc_conf dictionary
1411 # that is passed in is valid.Brief description of function
1412 # @param rc_conf dictionary in the format specified above.
1413 def set_rc_conf(self, rc_conf):
1414 self._etc_files['rc.conf'] = rc_conf
1415
1416 ##
1417 # Return a dictionary of the make.conf
1418 def get_rc_conf(self):
1419 if "rc.conf" in self._etc_files:
1420 return self._etc_files['rc.conf']
1421 else:
1422 return {}
1423
1424 ##
1425 # Serializes rc.conf (no longer used)
1426 def serialize_rc_conf(self):
1427 if self.get_rc_conf() != {}:
1428 self.xmldoc += "<rc-conf>"
1429
1430 rc_conf = self.get_rc_conf()
1431 for var in rc_conf:
1432 self.xmldoc += "<variable name=\"%s\">%s</variable>" % (var, rc_conf[var])
1433
1434 self.xmldoc += "</rc-conf>"
1435
1436 ############################################################################
1437 #### Root Password Hash
1438
1439 ##
1440 # root_pass_hash is a string containing an md5 password hash to be assinged as the password for the root user.
1441 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1442 # @param root_pass_hash Parameter description
1443 # @param xml_attr Parameter description
1444 def set_root_pass_hash(self, xml_path, root_pass_hash, xml_attr):
1445 # Check type
1446 if type(root_pass_hash) != str:
1447 raise GLIException("RootPassHashError", 'fatal', 'set_root_pass_hash', "Must be a string!")
1448 self._root_pass_hash = root_pass_hash
1449
1450 ##
1451 # Returns root_pass_hash
1452 def get_root_pass_hash(self):
1453 return self._root_pass_hash
1454
1455 ############################################################################
1456 #### RSYNC Proxy
1457
1458 ##
1459 # RSYNC proxy is a uri containing a proxy if needed for rsync traffic. (ie. 'rsync://myhost.mydomain:myport')
1460 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1461 # @param rsync_proxy the proxy address
1462 # @param xml_attr not used here
1463 def set_rsync_proxy(self, xml_path, rsync_proxy, xml_attr):
1464 # Check type
1465 if rsync_proxy and not GLIUtility.is_uri(rsync_proxy):
1466 raise GLIException("RSYNCProxyError", 'fatal', 'set_rsync_proxy', "Must be a uri!")
1467 self._rsync_proxy = rsync_proxy
1468
1469 ##
1470 # Returns RSYNC proxy
1471 def get_rsync_proxy(self):
1472 return self._rsync_proxy
1473
1474 ############################################################################
1475 #### Services
1476
1477 ##
1478 # Set the services to be started on bootup. Services should be
1479 # seperated by ','. WARNING: This used to be ' ' instead!
1480 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1481 # @param services comma-separated list of services
1482 # @param xml_attr Parameter description
1483 def set_services(self, xml_path, services, xml_attr):
1484 if type(services) == str:
1485 services = services.split(',')
1486 else:
1487 raise GLIException("ServicesError", 'fatal', 'set_services', "Invalid input!")
1488
1489 for service in services:
1490 if not GLIUtility.is_realstring(service):
1491 raise GLIException("ServicesError", 'fatal', 'set_services', service + " must be a valid string!")
1492 self._services = services
1493
1494 ##
1495 # This returns a list of the packages:
1496 def get_services(self):
1497 return self._services
1498
1499 ##
1500 # Serializes services
1501 def serialize_services(self):
1502 if self.get_services() != ():
1503 self.xmldoc += "<services>"
1504 self.xmldoc += string.join(self.get_services(), ',')
1505 self.xmldoc += "</services>"
1506
1507 ############################################################################
1508 #### Stage Tarball URI
1509
1510 ##
1511 # stage_tarball_uri is a string that is the full path to the tarball you
1512 # wish to use. (ie. 'file:///path/to/mytarball.tar.bz2')
1513 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1514 # @param stage_tarball_uri string of URI for stage tarball location.
1515 # @param xml_attr not used here.
1516 def set_stage_tarball_uri(self, xml_path, stage_tarball_uri, xml_attr):
1517 # Check type
1518 if type(stage_tarball_uri) != str:
1519 raise GLIException("StageTarballURIError", 'fatal', 'set_stage_tarball_uri', "Must be a string!")
1520
1521 # Check validity (now done in the FE)
1522 #if not stage_tarball_uri:
1523 # raise GLIException("CustomStage3TarballURIError", 'fatal', 'set_stage_tarball_uri', "Empty URI!")
1524
1525 self._stage_tarball_uri = stage_tarball_uri
1526
1527 ##
1528 # Returns stage_tarball_uri
1529 def get_stage_tarball_uri(self):
1530 return self._stage_tarball_uri
1531
1532 ############################################################################
1533 #### Timezone
1534
1535 ##
1536 # time_zone is a string defining the time zone to use.
1537 # Time zones are found in /usr/share/zoneinfo/. Syntax is 'UTC' or 'US/Eastern'.
1538 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1539 # @param time_zone string of the intended timezone
1540 # @param xml_attr not used here.
1541 def set_time_zone(self, xml_path, time_zone, xml_attr):
1542 # Check type
1543 if type(time_zone) != str:
1544 raise GLIException("TimeZoneError", 'fatal', 'set_time_zone', "Must be a string!")
1545 self._time_zone = time_zone
1546
1547 ##
1548 # Returns time_zone
1549 def get_time_zone(self):
1550 return self._time_zone
1551
1552 ############################################################################
1553 #### Users
1554
1555 ##
1556 # Adds a user to the list of users
1557 # @param xml_path Used internally by the XML parser. Should be None when calling directly
1558 # @param username name of user to be added
1559 # @param attr=None parameters for the user.
1560 def add_user(self, xml_path, username, attr=None):
1561 """
1562 This will take a username (that is a string) and a set of attributes and it will verify everything is valid
1563 and convert it into a 7-tuple set. Then it adds this tuple into the users list.
1564 username and hash are manditory. All other attributes are optional. Or this method will
1565 take a 7-tuple set, verify it's correctness and then append it to the _users list.
1566 All items are strings except <uid>, which is an integer, and groups, which is a tuple.
1567
1568 The finished tuples look like this:
1569 ( <user name>, <password hash>, (<tuple of groups>), <shell>, <home directory>, <user id>, <user comment> )
1570
1571 """
1572 hash = ''
1573 shell = None
1574 groups = None
1575 shell = None
1576 homedir = None
1577 uid = None
1578 comment = None
1579
1580 if type(username) == tuple:
1581 if len(username) != 7:
1582 raise GLIException("UserError", 'fatal', 'add_user', "Wrong format for user tuple!")
1583
1584 username_tmp = username[0]
1585 hash = username[1]
1586 groups = username[2]
1587 shell = username[3]
1588 homedir = username[4]
1589 uid = username[5]
1590 comment = username[6]
1591 username = username_tmp
1592
1593 if type(groups) != tuple:
1594 if groups != None:
1595 groups = tuple(groups.split(','))
1596 else:
1597 for attrName in attr.keys():
1598 if attrName == 'groups':
1599 groups = tuple(str(attr[attrName]).split(','))
1600 elif attrName == 'shell':
1601 shell = str(attr[attrName])
1602 elif attrName == 'hash':
1603 hash = str(attr[attrName])
1604 elif attrName == 'homedir':
1605 homedir = str(attr[attrName])
1606 elif attrName == 'uid':
1607 if attr[attrName]:
1608 uid = int(attr[attrName])
1609 elif attrName == 'comment':
1610 comment = str(attr[attrName])
1611
1612 allowable_nonalphnum_characters = '_-'
1613
1614 if not GLIUtility.is_realstring(username):
1615 raise GLIException("UserError", 'fatal', 'add_user', "username must be a non-empty string")
1616
1617 if username[0] not in (string.lowercase + string.uppercase):
1618 raise GLIException("UsersError", 'fatal', 'add_user', "A username must start with a letter!")
1619
1620 for x in username:
1621 if x not in (string.lowercase + string.uppercase + string.digits + allowable_nonalphnum_characters):
1622 raise GLIException("UsersError", 'fatal', 'add_user', "A username must contain only letters, numbers, or these symbols: " + allowable_nonalphnum_characters)
1623
1624 for user in self._users:
1625 if username == user[0]:
1626 raise GLIException("UserError", 'fatal', 'add_user', "This username already exists!")
1627
1628 if (hash == None) or (hash == ''):
1629 raise GLIException("UserError", 'fatal', 'add_user', "A password hash must be given for every user!")
1630
1631 self._users.append((username,hash,groups,shell,homedir,uid,comment))
1632
1633 ##
1634 # Remove "username" from the _users list.
1635 # @param username name of user to be removed
1636 def remove_user(self, username):
1637 for user in self._users:
1638 if username == user[0]:
1639 self._users.remove(user)
1640 break
1641
1642 ##
1643 # users is a tuple(user) of tuple's. This sets _users to this set of tuples.
1644 # @param users a tuple(user) of tuple's.
1645 def set_users(self, users):
1646 self._users = []
1647 if users != None:
1648 for user in users:
1649 self._users.append(user)
1650
1651 ##
1652 # Returns users
1653 def get_users(self):
1654 return self._users
1655
1656 ##
1657 # Serializes users
1658 def serialize_users(self):
1659 if self.get_users() != []:
1660 self.xmldoc += "<users>"
1661 users = self.get_users()
1662 for user in users:
1663 attrstr = ""
1664 username = user[0]
1665
1666 if user[1] != None:
1667 attrstr += "hash=\"%s\" " % user[1]
1668 if user[2] != None:
1669 attrstr += "groups=\"%s\" " % string.join(user[2],',')
1670 if user[3] != None:
1671 attrstr += "shell=\"%s\" " % user[3]
1672 if user[4] != None:
1673 attrstr += "homedir=\"%s\" " % user[4]
1674 if user[5] != None:
1675 attrstr += "uid=\"%s\" " % user[5]
1676 if user[6] != None:
1677 attrstr += "comment=\"%s\" " % user[6]
1678
1679 self.xmldoc += "<user %s>%s</user>" % (string.strip(attrstr), username)
1680 self.xmldoc += "</users>"

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20