summaryrefslogtreecommitdiffstats
path: root/config.py
blob: cf932144a4a48a9b43a47fd6245d44df6a826052 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# Abstracts out the config file format/access and holds
# reasonable default settings.
#
# Michael DeHaan <mdehaan@redhat.com>

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