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

Contents of /trunk/src/GLIInstallProfile.py

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1509 - (show annotations) (download) (as text)
Sat Sep 2 23:54:46 2006 UTC (11 years, 5 months ago) by codeman
File MIME type: text/x-python
File size: 67684 byte(s)
  Lots of internationalization fixes.  Point to a translation path called
  languages in the dialog directory.  Generated and added .pot files.
  Added gettext to GLIIP for package descriptions.

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

Properties

Name Value
svn:eol-style native

  ViewVC Help
Powered by ViewVC 1.1.20