# Abstracts out the config file format/access and holds # reasonable default settings. # # Michael DeHaan import api import util from msg import * import os import yaml import traceback class BootConfig: """ Constructor. This class maintains both the logical configuration for Boot and the file representation thereof. Creating the config object only loads the default values, users of this class need to call deserialize() to load config file values. """ def __init__(self,api): self.api = api self.settings_file = "/etc/bootconf.conf" self.state_file = "/var/bootconf/bootconf.conf" self.set_defaults() self.clear() def files_exist(self): return os.path.exists(self.settings_file) and os.path.exists(self.state_file) """ Establish an empty list of groups, distros, and systems. """ def clear(self): self.groups = api.Groups(self.api,None) self.distros = api.Distros(self.api,None) self.systems = api.Systems(self.api,None) """ Set some reasonable defaults in case no values are available """ def set_defaults(self): self.tftpboot = "/tftpboot" self.dhcpd_conf = "/etc/dhcpd.conf" self.tftpd_conf = "/etc/xinetd.d/tftp" self.pxelinux = "/usr/lib/syslinux/pxelinux.0" self.tftpd_bin = "/usr/sbin/in.tftpd" self.dhcpd_bin = "/usr/sbin/dhcpd" self.kernel_options = "append devfs=nomount ramdisk_size=16438 lang= vga=788 ksdevice=eth0 console=ttyS0,38400n8" #initrd and ks added programmatically """ Access the current groups list """ def get_groups(self): return self.groups """ Access the current distros list """ def get_distros(self): return self.distros """ Access the current systems list """ def get_systems(self): return self.systems """ Save all global config options in hash form (for serialization) """ def config_to_hash(self): # FIXME: this duplication NEEDS to go away. # idea: add list of properties to self.properties # and use method_missing to write accessors??? data = {} data['tftpboot'] = self.tftpboot data['dhcpd_conf'] = self.dhcpd_conf data['tftpd_conf'] = self.tftpd_conf data['pxelinux'] = self.pxelinux data['tftpd_bin'] = self.tftpd_bin data['dhcpd_bin'] = self.dhcpd_bin return data """ Load all global config options from hash form (for deserialization) """ def config_from_hash(self,hash): try: self.tftpboot = hash['tftpboot'] self.dhcpd_conf = hash['dhcpd_conf'] self.tftpd_conf = hash['tftpd_conf'] self.pxelinux = hash['pxelinux'] self.tftpd_bin = hash['tftpd_bin'] self.dhcpd_bin = hash['dhcpd_bin'] except: print "WARNING: config file error: %s" % (self.settings_file) self.set_defaults() """ Convert all items bootconfig knows about to a nested hash. There are seperate hashes for the /etc and /var portions. """ def to_hash(self,is_etc): world = {} if is_etc: world['config'] = self.config_to_hash() else: world['distros'] = self.get_distros().to_datastruct() world['groups'] = self.get_groups().to_datastruct() world['systems'] = self.get_systems().to_datastruct() #print "DEBUG: %s" % (world) return world """ Convert a hash representation of a bootconfig to 'reality' There are seperate hashes for the /etc and /var portions. """ def from_hash(self,hash,is_etc): #print "DEBUG: %s" % hash if is_etc: self.config_from_hash(hash['config']) else: self.distros = api.Distros(self.api, hash['distros']) self.groups = api.Groups(self.api, hash['groups']) self.systems = api.Systems(self.api, hash['systems']) # ------------------------------------------------------ # we don't care about file formats until below this line """ Save everything to the config file. This goes through an intermediate data format so we could use YAML later if we wanted. """ def serialize(self): settings = None state = None # ------ # dump global config (pathing, urls, etc)... try: settings = open(self.settings_file,"w+") except IOError: self.api.last_error = m("cant_create: %s" % self.settings_file) return False data = self.to_hash(True) settings.write(yaml.dump(data)) # ------ # dump internal state (distros, groups, systems...) if not os.path.isdir(os.path.dirname(self.state_file)): os.mkdir(os.path.dirname(self.state_file)) try: state = open(self.state_file,"w+") except: self.api.last_error = m("cant_create: %s" % self.state_file) data = self.to_hash(False) state.write(yaml.dump(data)) # all good return True """ Load everything from the config file. This goes through an intermediate data structure format so we could use YAML later if we wanted. """ def deserialize(self): #print "DEBUG: deserialize" # ----- # load global config (pathing, urls, etc)... try: settings = yaml.loadFile(self.settings_file) raw_data = settings.next() if raw_data is not None: self.from_hash(raw_data,True) else: print "WARNING: no %s data?" % self.settings_file except: self.api.last_error = m("parse_error") return False # ----- # load internal state(distros, systems, groups...) try: state = yaml.loadFile(self.state_file) raw_data = state.next() if raw_data is not None: self.from_hash(raw_data,False) else: print "WARNING: no %s data?" % self.state_file except: self.api.last_error = m("parse_error") return False # all good return True