diff options
author | Preston Cody <codeman@gentoo.org> | 2008-07-21 00:39:32 +0000 |
---|---|---|
committer | Sebastian Pipping <sebastian@pipping.org> | 2014-06-22 00:21:25 +0200 |
commit | 3e854ae99194783fbaa9a15b3295227043cbfcdf (patch) | |
tree | c600d724c77f228647f2063039fac9098fe7745f | |
parent | updating todo (diff) | |
download | gli-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.py | 980 |
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 |