blob: 4cf06c284522eb5bf6950a043424d4cb2d725dc7 [file] [log] [blame]
Steve McIntyre6f59b972014-12-10 16:43:37 +00001#! /usr/bin/python
2
3# Copyright 2014 Linaro Limited
4# Author: Steve McIntyre <steve.mcintyre@linaro.org>
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19# MA 02110-1301, USA.
20#
21# VLANd simple config parser
22#
23
24import ConfigParser
25import os, sys, re
26
27if __name__ == '__main__':
28 vlandpath = os.path.abspath(os.path.normpath(os.path.dirname(sys.argv[0])))
29 sys.path.insert(0, vlandpath)
30 sys.path.insert(0, "%s/.." % vlandpath)
31
Steve McIntyre29980352014-12-10 19:16:51 +000032from errors import CriticalError, InputError, ConfigError
Steve McIntyre6f59b972014-12-10 16:43:37 +000033
Steve McIntyrea9875062014-12-12 17:15:15 +000034class DaemonConfigClass:
35 """ Simple container for stuff to make for nicer syntax """
36
37 def __repr__(self):
38 return "<DaemonConfig: port: %s>" % (self.port)
39
Steve McIntyre6f59b972014-12-10 16:43:37 +000040class DBConfigClass:
41 """ Simple container for stuff to make for nicer syntax """
42
43 def __repr__(self):
Steve McIntyrea9875062014-12-12 17:15:15 +000044 return "<DBConfig: server: %s, port: %s, dbname: %s, username: %s, password: %s>" % (self.server, self.port, self.dbname, self.username, self.password)
Steve McIntyre6f59b972014-12-10 16:43:37 +000045
46class SwitchConfigClass:
47 """ Simple container for stuff to make for nicer syntax """
48 def __repr__(self):
Steve McIntyrea9875062014-12-12 17:15:15 +000049 return "<SwitchConfig: name: %s, section: %s, driver: %s, username: %s, password: %s, enable_password: %s>" % (self.name, self.section, self.driver, self.username, self.password, self.enable_password)
Steve McIntyre6f59b972014-12-10 16:43:37 +000050
51class VlanConfig:
52 """VLANd config class"""
53 def __init__(self, filenames):
Steve McIntyred773cac2014-12-10 23:27:07 +000054
Steve McIntyre6f59b972014-12-10 16:43:37 +000055 config = ConfigParser.RawConfigParser({
56 # Set default values
57 'server': None,
58 'port': None,
59 'dbname': None,
60 'username': None,
61 'password': None,
62 'name': None,
63 'driver': None,
64 'enable_password': None
65 })
66
67 config.read(filenames)
68
69 # Parse out the config file
70 # Must have a [database] section
Steve McIntyrea9875062014-12-12 17:15:15 +000071 # May have a [vland] section
Steve McIntyre6f59b972014-12-10 16:43:37 +000072 # May have a [logging] section
73 # May have multiple [switch 'foo'] sections
74 if not config.has_section('database'):
75 raise ConfigError('No database configuration section found')
76
Steve McIntyrea9875062014-12-12 17:15:15 +000077 # No DB-specific defaults to set
Steve McIntyre6f59b972014-12-10 16:43:37 +000078 self.database = DBConfigClass()
Steve McIntyrea9875062014-12-12 17:15:15 +000079
Steve McIntyrec12f6312014-12-15 15:00:12 +000080 # Set default port number and VLAN tag
Steve McIntyrea9875062014-12-12 17:15:15 +000081 self.vland = DaemonConfigClass()
82 self.vland.port = 3080
Steve McIntyrec12f6312014-12-15 15:00:12 +000083 self.vland.default_vlan_tag = 1
Steve McIntyrea9875062014-12-12 17:15:15 +000084
85 # No switch-specific defaults to set
Steve McIntyre6f59b972014-12-10 16:43:37 +000086 self.switches = {}
87
88 sw_regex = re.compile('(switch)\ (.*)', flags=re.I)
89 for section in config.sections():
90 if section == 'database':
91 try:
92 self.database.server = config.get(section, 'server')
Steve McIntyrea9875062014-12-12 17:15:15 +000093 except ConfigParser.NoOptionError:
94 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +000095 except:
96 raise ConfigError('Invalid database configuration (server)')
97
98 try:
Steve McIntyrea9875062014-12-12 17:15:15 +000099 port = config.get(section, 'port')
100 if port is not None:
101 self.database.port = config.getint(section, 'port')
102 except ConfigParser.NoOptionError:
103 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000104 except:
105 raise ConfigError('Invalid database configuration (port)')
106
107 try:
Steve McIntyre6f59b972014-12-10 16:43:37 +0000108 self.database.dbname = config.get(section, 'dbname')
Steve McIntyrea9875062014-12-12 17:15:15 +0000109 except ConfigParser.NoOptionError:
110 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000111 except:
112 raise ConfigError('Invalid database configuration (dbname)')
113
114 try:
Steve McIntyre6f59b972014-12-10 16:43:37 +0000115 self.database.username = config.get(section, 'username')
Steve McIntyrea9875062014-12-12 17:15:15 +0000116 except ConfigParser.NoOptionError:
117 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000118 except:
119 raise ConfigError('Invalid database configuration (username)')
120
121 try:
Steve McIntyre6f59b972014-12-10 16:43:37 +0000122 self.database.password = config.get(section, 'password')
Steve McIntyrea9875062014-12-12 17:15:15 +0000123 except ConfigParser.NoOptionError:
124 pass
Steve McIntyre6f59b972014-12-10 16:43:37 +0000125 except:
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000126 raise ConfigError('Invalid database configuration (password)')
Steve McIntyrea9875062014-12-12 17:15:15 +0000127
128 # Other database config options are optional, but these are not
Steve McIntyre6f59b972014-12-10 16:43:37 +0000129 if self.database.dbname is None or self.database.username is None:
130 raise ConfigError('Database configuration section incomplete')
Steve McIntyrea9875062014-12-12 17:15:15 +0000131
Steve McIntyre6f59b972014-12-10 16:43:37 +0000132 elif section == 'logging':
133 pass # Fill this in later...
Steve McIntyrea9875062014-12-12 17:15:15 +0000134
135 elif section == 'vland':
136 try:
137 self.vland.port = config.getint(section, 'port')
138 except ConfigParser.NoOptionError:
139 pass
140 except:
141 raise ConfigError('Invalid vland configuration (port)')
142
Steve McIntyrec12f6312014-12-15 15:00:12 +0000143 try:
144 self.vland.port = config.getint(section, 'default_vlan_tag')
145 except ConfigParser.NoOptionError:
146 pass
147 except:
148 raise ConfigError('Invalid vland configuration (default_vlan_tag)')
149
Steve McIntyre6f59b972014-12-10 16:43:37 +0000150 else:
151 match = sw_regex.match(section)
152 if match:
153 # Constraint: switch names must be unique! See if
154 # there's already a switch with this name
155 name = config.get(section, 'name')
156 for key in self.switches.keys():
157 if name == key:
158 raise ConfigError('Found switches with the same name (%s)' % name)
159 self.switches[name] = SwitchConfigClass()
160 self.switches[name].name = name
161 self.switches[name].section = section
162 self.switches[name].driver = config.get(section, 'driver')
163 self.switches[name].username = config.get(section, 'username')
164 self.switches[name].password = config.get(section, 'password')
165 self.switches[name].enable_password = config.get(section, 'enable_password')
166 else:
167 raise ConfigError('Unrecognised config section %s' % section)
168
169 def __del__(self):
170 pass
171
172if __name__ == '__main__':
173 config = VlanConfig(filenames=('./vland.cfg',))
174 print config.database
Steve McIntyrea9875062014-12-12 17:15:15 +0000175 print config.vland
Steve McIntyre6f59b972014-12-10 16:43:37 +0000176 for switch in config.switches:
177 print config.switches[switch]
178