aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPreston Cody <codeman@gentoo.org>2008-07-21 00:39:32 +0000
committerSebastian Pipping <sebastian@pipping.org>2014-06-22 00:21:25 +0200
commit3e854ae99194783fbaa9a15b3295227043cbfcdf (patch)
treec600d724c77f228647f2063039fac9098fe7745f
parentupdating todo (diff)
downloadgli-3e854ae99194783fbaa9a15b3295227043cbfcdf.tar.gz
gli-3e854ae99194783fbaa9a15b3295227043cbfcdf.tar.bz2
gli-3e854ae99194783fbaa9a15b3295227043cbfcdf.zip
adding a new module to create/parse quickstart profiles
it's about halfway done. svn path=/branches/qs/; revision=1911
-rw-r--r--src/GLIQSProfile.py980
1 files changed, 980 insertions, 0 deletions
diff --git a/src/GLIQSProfile.py b/src/GLIQSProfile.py
new file mode 100644
index 0000000..0219e48
--- /dev/null
+++ b/src/GLIQSProfile.py
@@ -0,0 +1,980 @@
+"""
+# Copyright 1999-2008 Gentoo Foundation
+# This source code is distributed under the terms of version 2 of the GNU
+# General Public License as published by the Free Software Foundation, a copy
+# of which can be found in the main directory of this project.
+Gentoo Linux Installer
+
+$Id $
+
+The QSProfile contains all information related to the new system to be
+installed.
+It is maintained in the class and writeable/loadable at any time in any state.
+"""
+
+import string
+import os
+import GLIUtility
+from GLIException import *
+import gettext
+try:
+ gettext.install('GLIQSProfile', './languages')
+ translator = gettext.translation('GLIQSProfile', './languages')
+ _ = translator.gettext
+except:
+ _ = gettext.gettext
+
+##
+# This class contains all the settings used during the install
+class QSProfile:
+ """
+ An object representation of a profile.
+ QSProfile is an object representation of a parsed quickstart installation
+ config file.
+ """
+
+ ##
+ # Initializes all variables to default values and adds handlers.
+ def __init__(self):
+
+ # Configuration information - profile data
+ # All variables must be declared here with a default value to ensure
+ # the XML will correctly serialize.
+
+ self._boot_device = ""
+ self._boot_loader_mbr = True
+ self._boot_loader_pkg = "grub"
+ self._bootloader_kernel_args = ""
+ self._cron_daemon_pkg = "vixie-cron"
+ self._kernel_source_pkg = "livecd-kernel"
+ self._logging_daemon_pkg = "syslog-ng"
+ self._users = []
+ self._root_pass_hash = ""
+ self._time_zone = "UTC"
+ self._portage_tree = GLIUtility.get_cd_snapshot_uri()
+ self._domainname = "localdomain"
+ self._hostname = "localhost"
+ self._mounts = []
+ self._network_mounts = []
+ self._network_interfaces = {}
+ self._make_conf = {}
+ self._dns_servers = ()
+ self._default_gateway = ()
+ self._install_packages = ()
+ self._services = ()
+ self._etc_files = {}
+ self._temp_etc_file = {}
+ self._verbose = True
+
+ # This is the root mount point
+ self._root_mount_point = "/mnt/gentoo"
+
+ ##
+ # Parses the given filename populating the profile configuration
+ # @param filename Parameter description
+ def load_profile(self, filename):
+ fh = open(filename)
+ while (line = fh.readline()):
+ type = line.split(' ')[0]
+ rest = line.split(' ')[1:]
+ if (type == "###STOP"):
+ break
+ if (type == "bootloader_install_device"): self.set_boot_device(rest) #includes mbr setting?
+ if (type == "bootloader"): self.set_boot_loader_pkg(rest)
+ if (type == "bootloader_kernel_args"): self.set_bootloader_kernel_args(rest)
+ if (type == "chroot_dir"): self.set_root_mount_point(rest)
+ if (type == "cron"): self.set_cron_daemon_pkg(rest)
+ if (type == "domainname"): self.set_domainname(rest)
+ if (type == "extra_packages"): self.set_install_packages(rest)
+ if (type == "hostname"): self.set_hostname(rest)
+ #if (type == "distcc"
+ if (type == "logger"): self.set_logging_daemon_pkg(rest)
+ if (type == "mountfs"): self.add_mount(rest)
+ if (type == "net"): self.add_network_interface(rest)
+ if (type == "netmount"): self.add_netmount(rest)
+ if (type == "nisdomainname"): self.set_nisdomainname(rest)
+ if (type == "rcadd"): self.add_service(rest)
+ if (type == "rootpw_crypt"): self.set_root_pass_hash(rest)
+ if (type == "timezone"): self.set_time_zone(rest)
+ if (type == "tree_type"): self.set_portage_tree(rest)
+ #if (type == "users"
+ if (type == "verbose"): self.set_verbose(rest)
+ if (type == "###Make.conf###"):
+ pass
+ if (type == "###etc/portage###"):
+ pass
+ fh.close()
+
+ ##
+ # This method writes out the profile of the configuration data.
+ def write_profile(self):
+ output = ""
+ if self.get_boot_device(): output += "bootloader_install_device\t" + self.get_boot_device() + "\n"
+ if self.get_bootloader(): output += "bootloader\t" + self.get_boot_loader_pkg() + "\n"
+ if self.get_bootloader_kernel_args(): output += "bootloader_kernel_args\t" + self.get_bootloader_kernel_args() + "\n"
+ if self.get_root_mount_point(): output += "chroot_dir\t" + self.get_root_mount_point() + "\n"
+ if self.get_cron_daemon_pkg(): output += "cron\t" + self.get_cron_daemon_pkg() + "\n"
+ if self.get_domainname(): output += "domainname\t" + self.get_domainname() + "\n"
+ if self.get_install_packages(): output += "extra_packages\t" + self.get_install_packages() + "\n"
+ if self.get_hostname(): output += "hostname\t" + self.get_hostname() + "\n"
+ if self.get_logging_daemon_pkg(): output += "logger\t" + self.get_logging_daemon_pkg() + "\n"
+ if self.get_mounts():
+ for mount in self.get_mounts():
+ output += "mountfs\t" + mount + "\n"
+
+ if self.get_network_interfaces():
+ for net_iface in self.get_network_interfaces():
+ output += "net\t" + net_iface + "\n"
+ if self.get_network_mounts():
+ for mount in self.get_network_mounts():
+ output += "netmount\t" + mount + "\n"
+
+ if self.get_nisdomainname(): output += "nisdomainname\t" + self.get_nisdomainname() + "\n"
+ if self.get_services():
+ for service in self.get_services():
+ output += "rcadd\t" + service
+
+ if self.get_root_pass_hash(): output += "rootpw_crypt\t" + self.get_root_pass_hash() + "\n"
+ if self.get_time_zone(): output += "timezone\t" + self.get_time_zone() + "\n"
+ if self.get_portage_tree(): output += "tree_type\t" + self.get_portage_tree() + "\n"
+ if self.get_verbose(): output += "verbose\t" + self.get_verbose() + "\n"
+
+
+
+
+
+ return output
+ ############################################################################
+ ############################################################################
+ #### Boot Device Selection
+
+ ##
+ # boot_device is a string to decide which device to install the bootloader to
+ # @param boot_loader_pkg boot device with full /dev
+ def set_boot_device(self, boot_device):
+ #check data type
+ if type(boot_device) != str:
+ raise GLIException("BootDevice", 'fatal', 'set_boot_device', "Input must be type 'string'!")
+ self._boot_device = boot_device
+
+ ##
+ # returns boot_device
+ def get_boot_device(self):
+ return self._boot_device
+
+ ############################################################################
+ #### Bootloader Package Selection
+
+ ##
+ # boot_loader_pkg is a string to decide which boot loader to install. (ie. 'grub')
+ # @param boot_loader_pkg bootloader package name (like grub or lilo)
+ def set_boot_loader_pkg(self, boot_loader_pkg):
+ # Check data type
+ if type(boot_loader_pkg) != str:
+ raise GLIException("BootLoaderPKG", 'fatal', 'set_boot_loader_pkg', "Input must be type 'string'!")
+ self._boot_loader_pkg = boot_loader_pkg
+
+ ##
+ # returns boot_loader_pkg
+ def get_boot_loader_pkg(self):
+ return self._boot_loader_pkg
+
+ ############################################################################
+ #### Bootloader Kernel Arguments
+
+ ##
+ # FIXME: agaffney, what error checking needs to be done here?
+ # kernel_args are the arguments to pass the kernel at boot from the bootloader.
+ # @param bootloader_kernel_args FIXME no idea.
+ def set_bootloader_kernel_args(self, bootloader_kernel_args):
+ self._bootloader_kernel_args = bootloader_kernel_args
+
+ ##
+ # Returns kernel arguments
+ def get_bootloader_kernel_args(self):
+ return self._bootloader_kernel_args
+
+ ############################################################################
+ #### Cron Daemon Package
+
+ ##
+ # cron_daemon_pkg is a string to determine which cron daemon to install and configure (ie. 'vixie-cron')
+ # @param cron_daemon_pkg package name
+ def set_cron_daemon_pkg(self, cron_daemon_pkg):
+ # Check data type
+ if type(cron_daemon_pkg) != str:
+ raise GLIException("CronDaemonPKGError", 'fatal', 'set_cron_daemon_pkg', "Input must be type 'string'!")
+ self._cron_daemon_pkg = cron_daemon_pkg
+
+ ##
+ # Returns the cron daemon pkg name
+ def get_cron_daemon_pkg(self):
+ return self._cron_daemon_pkg
+
+
+ ############################################################################
+ #### Network Gateway
+
+ ##
+ # Set the default gateway for the post-installed system.
+ # The format of the input is: <default-gateway interface="interface name">ip of gateway</default-gateway>
+ # It saves this information in the following format: (<interface>, <ip of gateway>)
+ # @param gateway gateway ip address
+ def set_default_gateway(self, gateway):
+ if not GLIUtility.is_realstring(gateway):
+ raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', "The gateway must be a non-empty string!")
+
+ if not GLIUtility.is_eth_device(interface):
+ raise GLIException('DefaultGatewayError', 'fatal', 'set_default_gateway', "Invalid device!")
+ if not GLIUtility.is_ip(gateway):
+ raise GLIException("DefaultGateway", 'fatal', 'set_default_gateway', "The IP Provided is not valid!")
+ self._default_gateway = (interface, gateway)
+
+ ##
+ # Returns the default gateway
+ def get_default_gateway(self):
+ return self._default_gateway
+
+ ############################################################################
+ #### DNS Servers
+
+ ##
+ # Set the DNS servers for the post-installed system.
+ # @param dns_servers a tuple or space-separated list of dns servers
+ def set_dns_servers(self, dns_servers):
+ if type(dns_servers) == tuple:
+ dns_servers = dns_servers[0:3]
+ elif type(dns_servers) == str:
+ dns_servers = string.split(dns_servers)
+ else:
+ raise GLIException("DnsServersError", 'fatal', 'set_dns_servers', "Invalid input!")
+
+ for server in dns_servers:
+ if not GLIUtility.is_ip(server):
+ raise GLIException("DnsServersError", 'fatal', 'set_dns_servers', server + " must be a valid IP address!")
+
+ self._dns_servers = dns_servers
+
+ ##
+ # This returns a tuple of the form: (<nameserver 1>, <nameserver 2>, <nameserver 3>)
+ def get_dns_servers(self):
+ return self._dns_servers
+
+ ############################################################################
+ #### Domainname
+
+ ##
+ # domainname is a string containing the domainname for the new system. (ie. 'mydomain.com'; NOT FQDN)
+ # @param domainname string of the domain name
+ def set_domainname(self, domainname):
+ # Check type
+ if type(domainname) != str:
+ raise GLIException("DomainnameError", 'fatal', 'set_domainname', "Must be a string!")
+ self._domainname = domainname
+
+ ##
+ # Returns domainname
+ def get_domainname(self):
+ return self._domainname
+
+ ##
+ # Used internally for XML parsing...adds an entry to a file
+ # @param xml_path Used internally by the XML parser. Should be None when calling directly
+ # @param value uhh...the value
+ # @param attr used for XML parsing
+ def add_etc_files_file_entry(self, xml_path, value, attr):
+ if 'name' in attr.getNames():
+ if not self._temp_etc_file:
+ self._temp_etc_file = {}
+ self._temp_etc_file[attr['name']] = value
+ else:
+ if not self._temp_etc_file:
+ self._temp_etc_file = []
+ self._temp_etc_file.append(value)
+
+ ##
+ # Used internally for XML parsing...adds a file
+ # @param xml_path Used internally by the XML parser. Should be None when calling directly
+ # @param unused this should be obvious
+ # @param attr used for XML parsing
+ def add_etc_files_file(self, xml_path, unused, attr):
+ self._etc_files[attr['name']] = self._temp_etc_file
+ self._temp_etc_file = None
+
+ ##
+ # Returns etc_files structure
+ def get_etc_files(self):
+ return self._etc_files
+
+ ##
+ # Replaces etc_files structure with one passed in
+ # @param etc_files new etc_files structure
+ def set_etc_files(self, etc_files):
+ self._etc_files = etc_files
+
+ ##
+ # Serializes the etc_files structure
+ def serialize_etc_files(self):
+ self.xmldoc += "<etc-files>"
+ for etc_file in self._etc_files:
+ self.xmldoc += "<file name=\"%s\">" % etc_file
+ for entry in self._etc_files[etc_file]:
+ self.xmldoc += "<entry"
+ if isinstance(self._etc_files[etc_file], dict):
+ self.xmldoc += " name=\"%s\">%s" % (entry, self._etc_files[etc_file][entry])
+ else:
+ self.xmldoc += ">%s" % entry
+ self.xmldoc += "</entry>"
+ self.xmldoc += "</file>"
+ self.xmldoc += "</etc-files>"
+
+
+
+ ############################################################################
+ #### Hostname
+
+ ##
+ # Hostname is a string containing the hostname for the new system. (ie. 'myhost'; NOT 'myhost.mydomain.com')
+ # @param hostname string of hostname
+ def set_hostname(self, hostname):
+ # Check type
+ if type(hostname) != str:
+ raise GLIException("HostnameError", 'fatal', 'set_hostname', "Must be a string!")
+ self._hostname = hostname
+
+ ##
+ # Returns hostname
+ def get_hostname(self):
+ return self._hostname
+
+
+ ############################################################################
+ #### Install Distcc
+
+ ##
+ # This tells the installer whether or not to install the distcc package
+ # @param install_distcc boolean
+ def set_install_distcc(self, install_distcc):
+ if type(install_distcc) != bool:
+ if type(install_distcc) == str:
+ install_distcc = GLIUtility.strtobool(install_distcc)
+ else:
+ raise GLIException("InstallDistcc", 'fatal', 'set_install_distcc', "Input must be type 'bool' or equiv string!")
+
+ self._install_distcc = install_distcc
+
+ ##
+ # Returns the boolean _install_distcc
+ def get_install_distcc(self):
+ return self._install_distcc
+
+ ############################################################################
+ #### Install Package List
+ ##
+ # Returns the list of packages to include in the Extra Packages screens.
+ def get_install_package_list(self):
+ install_package_list = {
+ 'Desktop': (_(u"Popular Desktop Applications"),
+ {"media-sound/audacious": _(u"GTK+ music player"),
+ "media-sound/alsa-utils": _(u"Utilities for ALSA, useful for enabling sound"),
+ "media-sound/easytag": _(u"A GTK+ tagging program for MP3, OGG, FLAC, and more"),
+ "mail-client/evolution": _(u"A GNOME groupware application, a Microsoft Outlook workalike"),
+ "net-im/gaim": _(u"GTK+ Instant Messenger client"),
+ "net-ftp/gftp": _(u"GTK+ FTP Client"),
+ "media-gfx/gimp": _(u"GNU Image Manipulation Program"),
+ "app-cdr/gnomebaker": _(u"GNOME CD Writing Software"),
+ "media-gfx/gtkam": _(u"GTK+ application for transferring pictures from a digital camera"),
+ "media-gfx/inkscape": _(u"A SVG based generic vector-drawing program"),
+ "app-cdr/k3b": _(u"KDE CD Writing Software"),
+ "app-office/koffice": _(u"An integrated office suite for KDE, the K Desktop Environment"),
+ "www-client/mozilla-firefox": _(u"The Mozilla Firefox Web Browser"),
+ "mail-client/mozilla-thunderbird": _(u"Thunderbird Mail Client"),
+ "media-video/mplayer": _(u"Media Player for Linux"),
+ "app-office/openoffice": _(u"OpenOffice.org, a full office productivity suite."),
+ "app-office/openoffice-bin": _(u"Same as OpenOffice but a binary package (no compiling!)"),
+ "net-nntp/pan": _(u"GTK news reader"),
+ "media-sound/rhythmbox": _(u"Music management and playback software for GNOME"),
+ "www-client/seamonkey": _(u"Open replacement for the Mozilla Suite"),
+ "mail-client/sylpheed": _(u"A light weight email client and news reader"),
+ "mail-client/sylpheed-claws": _(u"A light weight email client and news reader"),
+ "media-video/vlc": _(u"VLC media player - Video player and streamer"),
+ "net-irc/xchat": _(u"GTK+ Graphical IRC Client"),
+ "media-video/xine-ui": _(u"Xine movie player") }),
+ 'Servers': (_(u"Applications often found on servers."),
+ {"net-www/apache": _(u"Apache Web Server"),
+ "net-print/cups": _(u"The Common Unix Printing System"),
+ "mail-mta/exim": _(u"A highly configurable, drop-in replacement for sendmail"),
+ "net-firewall/iptables": _(u"Linux kernel (2.4+) firewall, NAT and packet mangling tools"),
+ "dev-db/mysql": _(u"A fast, multi-threaded, multi-user SQL database server"),
+ "dev-lang/php": _(u"The PHP scripting language"),
+ "mail-mta/postfix": _(u"A fast and secure drop-in replacement for sendmail"),
+ "dev-db/postgresql": _(u"sophisticated Object-Relational DBMS"),
+ "net-ftp/proftpd": _(u"ProFTP Server"),
+ "net-fs/samba": _(u"SAMBA client/server programs for UNIX"),
+ "mail-mta/sendmail": _(u"Widely-used Mail Transport Agent (MTA)"), }),
+ 'X11': (_(u"Window managers and X selection."),
+ {"x11-themes/gentoo-artwork-livecd": _(u"Desktop background used on this disk"),
+ "gnome-base/gnome": _(u"The Gnome Desktop Environment"),
+ "kde-base/kde-meta": _(u"The K Desktop Environment"),
+ "x11-wm/blackbox": _(u"A small, fast, full-featured window manager for X"),
+ "x11-wm/enlightenment": _(u"Enlightenment Window Manager"),
+ "x11-wm/fluxbox": _(u"Fluxbox is an X11 window manager featuring tabs and an iconbar"),
+ "x11-wm/icewm": _(u"IceWM is designed for speed, size, and simplicity"),
+ "x11-wm/windowmaker": _(u"Windowmaker is a window manager featuring the look and feel of NEXTSTEP"),
+ "xfce-base/xfce4": _(u"XFCE Desktop Environment"),
+ "x11-apps/xdm": _(u"X Display Manager"),
+ "gnome-base/gdm": _(u"GNOME Display Manager"),
+ "kde-base/kdm": _(u"KDE Display Manager"),
+ "x11-base/xorg-x11": _(u"An X11 implementation maintained by the X.Org Foundation") }),
+ 'Misc': (_(u"Miscellaneous Applications you may want."),
+ {"net-p2p/bittorrent": _(u"tool for distributing files via a distributed network of nodes"),
+ "app-editors/bluefish": _(u"GTK+ Web IDE"),
+ "app-editors/emacs": _(u"An incredibly powerful, extensible text editor"),
+ "app-admin/gkrellm": _(u"Single process stack of various system monitors"),
+ "app-editors/gvim": _(u"GUI version of the Vim text editor"),
+ "net-misc/keychain": _(u"ssh-agent manager"),
+ "app-admin/logrotate": _(u"Rotates, compresses, and mails system logs"),
+ "net-misc/ntp": _(u"Network Time Protocol suite/programs"),
+ "net-misc/rdesktop": _(u"A Remote Desktop Protocol Client"),
+ "sys-apps/slocate": _(u"Secure way to index and quickly search for files on your system"),
+ "net-analyzer/traceroute": _(u"Utility to trace the route of IP packets"),
+ "app-portage/ufed": _(u"Gentoo Linux USE flags editor"),
+ "app-editors/vim": _(u"Vim, an improved vi-style text editor"),
+ "net-analyzer/wireshark": _(u"A commercial-quality network protocol analyzer") }),
+ 'Recommended': (_(u"Applications recommended by the GLI Team."),
+ {"dev-util/anjuta": _(u"A versatile IDE for GNOME"),
+ "app-forensics/chkrootkit": _(u"a tool to locally check for signs of a rootkit"),
+ "games-arcade/crack-attack": _(u"Addictive OpenGL-based block game"),
+ "app-crypt/gnupg": _(u"The GNU Privacy Guard, a GPL PGP replacement"),
+ "net-analyzer/net-snmp": _(u"Software for generating and retrieving SNMP data"),
+ "net-analyzer/netcat": _(u"the network swiss army knife"),
+ "net-analyzer/nmap": _(u"A utility for network exploration or security auditing"),
+ "app-misc/screen": _(u"full-screen window manager that multiplexes between several processes"),
+ "app-text/xpdf": _(u"An X Viewer for PDF Files") })
+ }
+ return install_package_list
+
+ ############################################################################
+ #### Install Packages
+
+ ##
+ # Sets up the list of packages to be installed for the new system.
+ # @param install_packages The space-separated list of packages to install.
+ def set_install_packages(self, install_packages):
+ if type(install_packages) == str:
+ install_packages = string.split(install_packages)
+ else:
+ raise GLIException("InstallPackagesError", 'fatal', 'set_install_packages', "Invalid input!")
+
+ for install_package in install_packages:
+ if not GLIUtility.is_realstring(install_package):
+ raise GLIException("InstallPackagesError", 'fatal', 'set_install_packages', install_package + " must be a valid string!")
+ self._install_packages = install_packages
+
+ ##
+ # This returns a list of the packages
+ def get_install_packages(self):
+ return self._install_packages
+
+
+ ############################################################################
+ #### Logging Daemon Package
+
+ ##
+ # logging_daemon_pkg is a string to determine which logging daemon to install and configure (ie. 'sysklogd')
+ # @param logging_daemon_pkg package name of logging daemon to be emerged
+ def set_logging_daemon_pkg(self, logging_daemon_pkg):
+ # Check data type
+ if type(logging_daemon_pkg) != str:
+ raise GLIException("LoggingDaemonPKGError", 'fatal', 'set_logging_daemon_pkg', "Input must be type 'string'!")
+ self._logging_daemon_pkg = logging_daemon_pkg
+
+ ##
+ # Returns logging daemon pkg name
+ def get_logging_daemon_pkg(self):
+ return self._logging_daemon_pkg
+
+ ############################################################################
+ #### /etc/make.conf Configuration
+
+ ##
+ # Adds a variable to the new system make.conf
+ # @param xml_path Used internally by the XML parser. Should be None when calling directly
+ # @param data a string that is the value of the variable name.
+ # @param attr an xml attribute that contains the name of the variable
+ # OR attr is a variable name, like 'USE'. This makes it easier for front-end designers.
+ def make_conf_add_var(self, xml_path, data, attr):
+ if 'name' not in attr.keys():
+ raise GLIException("MakeConfError", 'fatal', 'make_conf_add_var', "Every value needs to have a variable name!")
+
+ varName = attr['name']
+ if not "make.conf" in self._etc_files:
+ self._etc_files['make.conf'] = {}
+ self._make_conf[str(varName)] = str(data)
+
+ ##
+ # make_conf is a dictionary that will be set to _make_conf
+ # There is no checking that needs to be done, so please sure sure that the make_conf dictionary
+ # that is passed in is valid.
+ # @param make_conf a dictionary that will be set to _make_conf
+ def set_make_conf(self, make_conf):
+ self._etc_files['make.conf'] = make_conf
+
+ ##
+ # Return a dictionary of the make.conf
+ def get_make_conf(self):
+ if "make.conf" in self._etc_files:
+ return self._etc_files['make.conf']
+ else:
+ return {}
+
+ ##
+ # Serializes make.conf (no longer used)
+ def serialize_make_conf(self):
+ if self.get_make_conf() != {}:
+ self.xmldoc += "<make-conf>"
+
+ # keys should always be in the same order!
+ make_conf = self.get_make_conf()
+ make_conf_keys = make_conf.keys()
+ make_conf_keys.sort()
+
+ for var in make_conf_keys:
+ self.xmldoc += "<variable name=\"%s\">%s</variable>" % (var, make_conf[var])
+
+ self.xmldoc += "</make-conf>"
+
+
+
+ ############################################################################
+ #### Mounts
+
+ ##
+ # Mounts used during the installation and for fstab and bootloader config.
+ # @param mount_entry the entry info, in a tuple, i guess.
+ def add_mount(self, mount_entry):
+ #mount_entry = {'devnode': '', 'mountopts': '', 'mountpoint': '', 'type': ''}
+ if type(attr) == tuple:
+ mount_entry['devnode'] = attr[0]
+ mount_entry['mountopts'] = attr[1]
+ mount_entry['mountpoint'] = attr[2]
+ mount_entry['type'] = attr[3]
+ self._mounts.append(mount_entry)
+
+ ##
+ # Sets Mounts given a mounts found probably in the config file. Not sure if used.
+ # @param netmounts Parameter description
+ def set_mounts(self, mounts):
+ self._mounts = mounts
+
+ ##
+ # Returns the mounts.
+ def get_mounts(self):
+ return self._mounts
+
+ ############################################################################
+ #### MTA Selection
+
+ ##
+ # Sets the intended MTA package
+ # @param mta package name of mta
+ def set_mta_pkg(self, mta_pkg):
+ if type(mta_pkg) != str:
+ raise GLIException("MTAError", 'fatal', 'set_mta_pkg', "The MTA must be a string!")
+ self._mta_pkg = mta_pkg
+
+ ##
+ # returns the MTA
+ def get_mta_pkg(self):
+ return self._mta_pkg
+
+ ############################################################################
+ #### Network Interface Selection
+
+ ##
+ # This adds an ethernet device to the _network_interfaces dictionary.
+ # The format of this dictionary is:
+ # { <eth_device> : (options tuple), ... }
+ #
+ # eth_device can be a valid ethernet device eth0, eth1, wlan*... OR
+ # it can be a valid MAC address.
+ #
+ # The format of the options tuple is for a static IP:
+ # ( <ip address>, <broadcast>, <netmask> )
+ #
+ # For DHCP, the format of the options tuple is:
+ # ( 'dhcp', <dhcp options>, None )
+ #
+ # We keep the None as a placeholder, to not break anything that uses this
+ # in other parts of the installer.
+ #
+ # Aliases are no longer needed in the tuple because they can be treated like
+ # an individual interface. GLIUtility.is_eth_device will recognize
+ # @param xml_path Used internally by the XML parser. Should be None when calling directly
+ # @param device the type and name of the device
+ # @param attr should be dhcp or a tuple of the ip addresses.
+ def add_network_interface(self, xml_path, device, attr):
+ options = None
+ ip = broadcast = netmask = dhcp_options = None
+ dhcp = True
+
+ if type(device) != str:
+ raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "Invalid or unimplimented device type (" + device + ")!")
+
+ if not GLIUtility.is_eth_device(device):
+ device = GLIUtility.format_mac(device)
+ if not GLIUtility.is_mac(device):
+ raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "Invalid or unimplimented device type (" + device + ")!")
+
+ if type(attr) == tuple:
+ ip = attr[0]
+ dhcp_options = broadcast = attr[1]
+ netmask = attr[2]
+ if ip != 'dhcp':
+ dhcp = False
+ else:
+ for attrName in attr.keys():
+ if attrName == 'ip':
+ ip = str(attr[attrName])
+ elif attrName == 'broadcast':
+ broadcast = str(attr[attrName])
+ elif attrName == 'netmask':
+ netmask = str(attr[attrName])
+ elif attrName == 'options':
+ dhcp_options = str(attr[attrName])
+
+ if ip != 'dhcp' and ip != None:
+ dhcp = False
+
+ if not dhcp:
+ if not GLIUtility.is_ip(ip):
+ raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The ip address you specified for " + device + " is not valid!")
+ if not GLIUtility.is_ip(broadcast):
+ raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The broadcast address you specified for " + device + " is not valid!")
+ if not GLIUtility.is_ip(netmask):
+ raise GLIException("NetworkInterfacesError", 'fatal', 'add_network_interface', "The netmask address you specified for " + device + " is not valid!")
+ options = (ip, broadcast, netmask)
+ else:
+ options = ('dhcp', dhcp_options, None)
+
+ self._network_interfaces[device] = options
+
+ ##
+ # This method sets the network interfaces diction to network_interfaces.
+ # This method uses the function add_network_interfaces to do all of the real work.
+ # @param network_interfaces a dict with all the networking info. see add_ for specification.
+ def set_network_interfaces(self, network_interfaces):
+ # Check type
+ if type(network_interfaces) != dict:
+ raise GLIException("NetworkInterfacesError", 'fatal', 'set_network_interfaces', "Must be a dictionary!")
+
+ self._network_interfaces = {}
+ for device in network_interfaces:
+ self.add_network_interface(None, device, network_interfaces[device])
+
+ ##
+ # Returns network_interfaces
+ def get_network_interfaces(self):
+ return self._network_interfaces
+
+ ##
+ # Serialize Network Interfaces
+ def serialize_network_interfaces(self):
+ if self.get_network_interfaces() != {}:
+ self.xmldoc += "<network-interfaces>"
+ interfaces = self.get_network_interfaces()
+ for iface in interfaces:
+ if interfaces[iface][0] == 'dhcp':
+ attrs = "ip=\"dhcp\""
+ if interfaces[iface][1] != None:
+ dhcp_options = "options=\"%s\"" % interfaces[iface][1]
+ attrs = attrs + " " + dhcp_options
+ self.xmldoc += "<device %s>%s</device>" % (attrs, iface)
+ else:
+ self.xmldoc += "<device ip=\"%s\" broadcast=\"%s\" netmask=\"%s\">%s</device>" % (interfaces[iface][0], interfaces[iface][1], interfaces[iface][2], iface)
+ self.xmldoc += "</network-interfaces>"
+
+ ############################################################################
+ #### Network Mounts
+
+ ##
+ # FIXME: agaffney: Brief description of function
+ # @param netmount_entry the entry info, in a tuple, i guess
+ def add_netmount(self, netmount_entry):
+ #netmount_entry = {'export': '', 'host': '', 'mountopts': '', 'mountpoint': '', 'type': ''}
+ if type(attr) == tuple:
+ netmount_entry['export'] = attr[0]
+ netmount_entry['host'] = attr[1]
+ netmount_entry['mountopts'] = attr[2]
+ netmount_entry['mountpoint'] = attr[3]
+ netmount_entry['type'] = attr[4]
+ else:
+ if "export" in attr.getNames():
+ for attrName in attr.getNames():
+ netmount_entry[attrName] = str(attr.getValue(attrName))
+ self._network_mounts.append(netmount_entry)
+
+ ##
+ # Sets Network Mounts given a netmounts found probably in the config file. Not sure if used.
+ # @param netmounts Parameter description
+ def set_network_mounts(self, netmounts):
+ self._network_mounts = netmounts
+
+ ##
+ # Returns the network mounts.
+ def get_network_mounts(self):
+ return self._network_mounts
+
+ ############################################################################
+ #### NIS Domain Name
+
+ ##
+ # nisdomainname is a string containing the NIS domainname for the new system.
+ # @param nisdomainname the name. is a string.
+ def set_nisdomainname(self, nisdomainname):
+ # Check type
+ if type(nisdomainname) != str:
+ raise GLIException("NISDomainnameError", 'fatal', 'set_nisdomainname', "Must be a string!")
+
+ self._nisdomainname = nisdomainname
+
+ ##
+ # Returns nisdomainname
+ def get_nisdomainname(self):
+ return self._nisdomainname
+
+
+
+ ############################################################################
+ #### Portage Snapshot URI
+
+ ##
+ # portage_tree_snapshot_uri is a string defining the path to a portage tree
+ # snapshot. (ie. 'file:///mnt/cdrom/snapshots/portage-*.tar.bz2')
+ # @param portage_tree_snapshot_uri URI of the portage tree shapshot location
+ def set_portage_tree_snapshot_uri(self, portage_tree_snapshot_uri):
+ # Check type
+ if type(portage_tree_snapshot_uri) != str:
+ raise GLIException("PortageTreeSnapshotURIError", 'fatal', 'set_portage_tree_snapshot_uri', "Must be a string!")
+
+ self._portage_tree_snapshot_uri = portage_tree_snapshot_uri
+
+ ##
+ # Returns portage_tree_snapshot_uri
+ def get_portage_tree_snapshot_uri(self):
+ return self._portage_tree_snapshot_uri
+
+
+ ############################################################################
+ #### Root Mount Point For New System
+
+ ##
+ # Sets the root_mount_point for the new system to be installed to
+ # @param root_mount_point new location for the root mount point
+ def set_root_mount_point(self, root_mount_point):
+ self._root_mount_point = root_mount_point
+
+ ##
+ # Returns the root_mount_point
+ def get_root_mount_point(self):
+ return self._root_mount_point
+
+ ############################################################################
+ #### Root Password Hash
+
+ ##
+ # root_pass_hash is a string containing an md5 password hash to be assinged as the password for the root user.
+ # @param root_pass_hash Parameter description
+ def set_root_pass_hash(self, root_pass_hash):
+ # Check type
+ if type(root_pass_hash) != str:
+ raise GLIException("RootPassHashError", 'fatal', 'set_root_pass_hash', "Must be a string!")
+ self._root_pass_hash = root_pass_hash
+
+ ##
+ # Returns root_pass_hash
+ def get_root_pass_hash(self):
+ return self._root_pass_hash
+
+ ############################################################################
+ #### Services
+
+ ##
+ # Set the services to be started on bootup. Services should be
+ # seperated by ','. WARNING: This used to be ' ' instead!
+ # @param services comma-separated list of services
+ def set_services(self, services):
+ if type(services) == str:
+ services = services.split(',')
+ else:
+ raise GLIException("ServicesError", 'fatal', 'set_services', "Invalid input!")
+
+ for service in services:
+ if not GLIUtility.is_realstring(service):
+ raise GLIException("ServicesError", 'fatal', 'set_services', service + " must be a valid string!")
+ self._services = services
+
+ ##
+ # This returns a list of the packages:
+ def get_services(self):
+ return self._services
+
+ ############################################################################
+ #### Timezone
+
+ ##
+ # time_zone is a string defining the time zone to use.
+ # Time zones are found in /usr/share/zoneinfo/. Syntax is 'UTC' or 'US/Eastern'.
+ # @param time_zone string of the intended timezone
+ def set_time_zone(self, time_zone):
+ # Check type
+ if type(time_zone) != str:
+ raise GLIException("TimeZoneError", 'fatal', 'set_time_zone', "Must be a string!")
+ self._time_zone = time_zone
+
+ ##
+ # Returns time_zone
+ def get_time_zone(self):
+ return self._time_zone
+
+ ############################################################################
+ #### Users
+
+ ##
+ # Adds a user to the list of users
+ # @param username name of user to be added
+ # @param attr=None parameters for the user.
+ def add_user(self, username, attr=None):
+ """
+ This will take a username (that is a string) and a set of attributes and it will verify everything is valid
+ and convert it into a 7-tuple set. Then it adds this tuple into the users list.
+ username and hash are manditory. All other attributes are optional. Or this method will
+ take a 7-tuple set, verify it's correctness and then append it to the _users list.
+ All items are strings except <uid>, which is an integer, and groups, which is a tuple.
+
+ The finished tuples look like this:
+ ( <user name>, <password hash>, (<tuple of groups>), <shell>, <home directory>, <user id>, <user comment> )
+
+ """
+ hash = ''
+ shell = None
+ groups = None
+ shell = None
+ homedir = None
+ uid = None
+ comment = None
+
+ if type(username) == tuple:
+ if len(username) != 7:
+ raise GLIException("UserError", 'fatal', 'add_user', "Wrong format for user tuple!")
+
+ username_tmp = username[0]
+ hash = username[1]
+ groups = username[2]
+ shell = username[3]
+ homedir = username[4]
+ uid = username[5]
+ comment = username[6]
+ username = username_tmp
+
+ if type(groups) != tuple:
+ if groups != None:
+ groups = tuple(groups.split(','))
+ else:
+ for attrName in attr.keys():
+ if attrName == 'groups':
+ groups = tuple(str(attr[attrName]).split(','))
+ elif attrName == 'shell':
+ shell = str(attr[attrName])
+ elif attrName == 'hash':
+ hash = str(attr[attrName])
+ elif attrName == 'homedir':
+ homedir = str(attr[attrName])
+ elif attrName == 'uid':
+ if attr[attrName]:
+ uid = int(attr[attrName])
+ elif attrName == 'comment':
+ comment = str(attr[attrName])
+
+ allowable_nonalphnum_characters = '_-'
+
+ if not GLIUtility.is_realstring(username):
+ raise GLIException("UserError", 'fatal', 'add_user', "username must be a non-empty string")
+
+ if username[0] not in (string.lowercase + string.uppercase):
+ raise GLIException("UsersError", 'fatal', 'add_user', "A username must start with a letter!")
+
+ for x in username:
+ if x not in (string.lowercase + string.uppercase + string.digits + allowable_nonalphnum_characters):
+ raise GLIException("UsersError", 'fatal', 'add_user', "A username must contain only letters, numbers, or these symbols: " + allowable_nonalphnum_characters)
+
+ for user in self._users:
+ if username == user[0]:
+ raise GLIException("UserError", 'fatal', 'add_user', "This username already exists!")
+
+ if (hash == None) or (hash == ''):
+ raise GLIException("UserError", 'fatal', 'add_user', "A password hash must be given for every user!")
+
+ self._users.append((username,hash,groups,shell,homedir,uid,comment))
+
+ ##
+ # Remove "username" from the _users list.
+ # @param username name of user to be removed
+ def remove_user(self, username):
+ for user in self._users:
+ if username == user[0]:
+ self._users.remove(user)
+ break
+
+ ##
+ # users is a tuple(user) of tuple's. This sets _users to this set of tuples.
+ # @param users a tuple(user) of tuple's.
+ def set_users(self, users):
+ self._users = []
+ if users != None:
+ for user in users:
+ self._users.append(user)
+
+ ##
+ # Returns users
+ def get_users(self):
+ return self._users
+
+ ##
+ # Serializes users
+ def serialize_users(self):
+ if self.get_users() != []:
+ self.xmldoc += "<users>"
+ users = self.get_users()
+ for user in users:
+ attrstr = ""
+ username = user[0]
+
+ if user[1] != None:
+ attrstr += "hash=\"%s\" " % user[1]
+ if user[2] != None:
+ attrstr += "groups=\"%s\" " % string.join(user[2],',')
+ if user[3] != None:
+ attrstr += "shell=\"%s\" " % user[3]
+ if user[4] != None:
+ attrstr += "homedir=\"%s\" " % user[4]
+ if user[5] != None:
+ attrstr += "uid=\"%s\" " % user[5]
+ if user[6] != None:
+ attrstr += "comment=\"%s\" " % user[6]
+
+ self.xmldoc += "<user %s>%s</user>" % (string.strip(attrstr), username)
+ self.xmldoc += "</users>"
+
+ ##
+ # Sets the Verbose mode (DEBUG mode)
+ # @param verbose flag. boolean.
+ def set_verbose(self, verbose):
+ if type(verbose) == str:
+ verbose = GLIUtility.strtobool(verbose)
+ self._verbose = verbose
+
+ ##
+ # Returns the verbose (DEBUG) flag
+ def get_verbose(self):
+ return self._verbose