blob: 4097c6459cec81befe6c97ed4f42cc6d6de7f17f [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 McIntyre6d84ec12014-12-18 16:56:56 +000032from errors import 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
Steve McIntyredbe6aa52015-02-12 07:48:22 +000046class LoggingConfigClass:
47 """ Simple container for stuff to make for nicer syntax """
48
49 def __repr__(self):
50 return "<LoggingConfig: level: %s, filename: %s>" % (self.level, self.filename)
51
Steve McIntyre6f59b972014-12-10 16:43:37 +000052class SwitchConfigClass:
53 """ Simple container for stuff to make for nicer syntax """
54 def __repr__(self):
Steve McIntyrea9875062014-12-12 17:15:15 +000055 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 +000056
57class VlanConfig:
58 """VLANd config class"""
59 def __init__(self, filenames):
Steve McIntyred773cac2014-12-10 23:27:07 +000060
Steve McIntyre6f59b972014-12-10 16:43:37 +000061 config = ConfigParser.RawConfigParser({
62 # Set default values
63 'server': None,
64 'port': None,
65 'dbname': None,
66 'username': None,
67 'password': None,
68 'name': None,
69 'driver': None,
70 'enable_password': None
71 })
72
73 config.read(filenames)
74
75 # Parse out the config file
76 # Must have a [database] section
Steve McIntyrea9875062014-12-12 17:15:15 +000077 # May have a [vland] section
Steve McIntyre6f59b972014-12-10 16:43:37 +000078 # May have a [logging] section
79 # May have multiple [switch 'foo'] sections
80 if not config.has_section('database'):
81 raise ConfigError('No database configuration section found')
82
Steve McIntyrea9875062014-12-12 17:15:15 +000083 # No DB-specific defaults to set
Steve McIntyre6f59b972014-12-10 16:43:37 +000084 self.database = DBConfigClass()
Steve McIntyrea9875062014-12-12 17:15:15 +000085
Steve McIntyredbe6aa52015-02-12 07:48:22 +000086 # Set defaults logging details
87 self.logging = LoggingConfigClass()
88 self.logging.level = None
89 self.logging.filename = None
90
Steve McIntyrec12f6312014-12-15 15:00:12 +000091 # Set default port number and VLAN tag
Steve McIntyrea9875062014-12-12 17:15:15 +000092 self.vland = DaemonConfigClass()
93 self.vland.port = 3080
Steve McIntyrec12f6312014-12-15 15:00:12 +000094 self.vland.default_vlan_tag = 1
Steve McIntyrea9875062014-12-12 17:15:15 +000095
96 # No switch-specific defaults to set
Steve McIntyre6f59b972014-12-10 16:43:37 +000097 self.switches = {}
98
99 sw_regex = re.compile('(switch)\ (.*)', flags=re.I)
100 for section in config.sections():
101 if section == 'database':
102 try:
103 self.database.server = config.get(section, 'server')
Steve McIntyrea9875062014-12-12 17:15:15 +0000104 except ConfigParser.NoOptionError:
105 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000106 except:
107 raise ConfigError('Invalid database configuration (server)')
108
109 try:
Steve McIntyrea9875062014-12-12 17:15:15 +0000110 port = config.get(section, 'port')
111 if port is not None:
112 self.database.port = config.getint(section, 'port')
113 except ConfigParser.NoOptionError:
114 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000115 except:
116 raise ConfigError('Invalid database configuration (port)')
117
118 try:
Steve McIntyre6f59b972014-12-10 16:43:37 +0000119 self.database.dbname = config.get(section, 'dbname')
Steve McIntyrea9875062014-12-12 17:15:15 +0000120 except ConfigParser.NoOptionError:
121 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000122 except:
123 raise ConfigError('Invalid database configuration (dbname)')
124
125 try:
Steve McIntyre6f59b972014-12-10 16:43:37 +0000126 self.database.username = config.get(section, 'username')
Steve McIntyrea9875062014-12-12 17:15:15 +0000127 except ConfigParser.NoOptionError:
128 pass
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000129 except:
130 raise ConfigError('Invalid database configuration (username)')
131
132 try:
Steve McIntyre6f59b972014-12-10 16:43:37 +0000133 self.database.password = config.get(section, 'password')
Steve McIntyrea9875062014-12-12 17:15:15 +0000134 except ConfigParser.NoOptionError:
135 pass
Steve McIntyre6f59b972014-12-10 16:43:37 +0000136 except:
Steve McIntyre38a30eb2014-12-11 16:10:55 +0000137 raise ConfigError('Invalid database configuration (password)')
Steve McIntyrea9875062014-12-12 17:15:15 +0000138
139 # Other database config options are optional, but these are not
Steve McIntyre6f59b972014-12-10 16:43:37 +0000140 if self.database.dbname is None or self.database.username is None:
141 raise ConfigError('Database configuration section incomplete')
Steve McIntyrea9875062014-12-12 17:15:15 +0000142
Steve McIntyre6f59b972014-12-10 16:43:37 +0000143 elif section == 'logging':
Steve McIntyredbe6aa52015-02-12 07:48:22 +0000144 try:
145 self.logging.level = config.get(section, 'level')
146 except ConfigParser.NoOptionError:
147 pass
148 except:
149 raise ConfigError('Invalid logging configuration (level)')
150
151 try:
Steve McIntyre19e6b062015-02-12 08:05:08 +0000152 self.logging.filename = config.get(section, 'filename')
Steve McIntyredbe6aa52015-02-12 07:48:22 +0000153 except ConfigParser.NoOptionError:
154 pass
155 except:
156 raise ConfigError('Invalid logging configuration (filename)')
Steve McIntyrea9875062014-12-12 17:15:15 +0000157
158 elif section == 'vland':
159 try:
160 self.vland.port = config.getint(section, 'port')
161 except ConfigParser.NoOptionError:
162 pass
163 except:
164 raise ConfigError('Invalid vland configuration (port)')
165
Steve McIntyrec12f6312014-12-15 15:00:12 +0000166 try:
Steve McIntyrec6906982014-12-23 13:22:38 +0000167 self.vland.default_vlan_tag = config.getint(section, 'default_vlan_tag')
Steve McIntyrec12f6312014-12-15 15:00:12 +0000168 except ConfigParser.NoOptionError:
169 pass
170 except:
171 raise ConfigError('Invalid vland configuration (default_vlan_tag)')
172
Steve McIntyre6f59b972014-12-10 16:43:37 +0000173 else:
174 match = sw_regex.match(section)
175 if match:
176 # Constraint: switch names must be unique! See if
177 # there's already a switch with this name
178 name = config.get(section, 'name')
179 for key in self.switches.keys():
180 if name == key:
181 raise ConfigError('Found switches with the same name (%s)' % name)
182 self.switches[name] = SwitchConfigClass()
183 self.switches[name].name = name
184 self.switches[name].section = section
185 self.switches[name].driver = config.get(section, 'driver')
186 self.switches[name].username = config.get(section, 'username')
187 self.switches[name].password = config.get(section, 'password')
188 self.switches[name].enable_password = config.get(section, 'enable_password')
189 else:
190 raise ConfigError('Unrecognised config section %s' % section)
191
192 def __del__(self):
193 pass
194
195if __name__ == '__main__':
Steve McIntyre6d84ec12014-12-18 16:56:56 +0000196 c = VlanConfig(filenames=('./vland.cfg',))
197 print c.database
198 print c.vland
199 for switch in c.switches:
200 print c.switches[switch]
Steve McIntyre6f59b972014-12-10 16:43:37 +0000201