import glob
import re
import os
+import copy
+from utils import utils
from iface import *
from template import templateEngine
hotplugs = {}
auto_ifaces = []
callbacks = {}
+ auto_all = False
_addrfams = {'inet' : ['static', 'manual', 'loopback', 'dhcp', 'dhcp6'],
'inet6' : ['static', 'manual', 'loopback', 'dhcp', 'dhcp6']}
else:
self.logger.error('%s: line%d: %s' %(filename, lineno, msg))
+ def _parse_warn(self, filename, lineno, msg):
+ if lineno == -1 or self._currentfile_has_template:
+ self.logger.warn('%s: %s' %(filename, msg))
+ else:
+ self.logger.warn('%s: line%d: %s' %(filename, lineno, msg))
+
def _validate_addr_family(self, ifaceobj, lineno=-1):
if ifaceobj.addr_family:
if not self._addrfams.get(ifaceobj.addr_family):
self.logger.debug('processing sourced line ..\'%s\'' %lines[cur_idx])
sourced_file = re.split(self._ws_split_regex, lines[cur_idx], 2)[1]
if sourced_file:
- for f in glob.glob(sourced_file):
+ filenames = glob.glob(sourced_file)
+ if not filenames:
+ self._parse_warn(self._currentfile, lineno,
+ 'cannot find source file %s' %sourced_file)
+ return 0
+ for f in filenames:
self.read_file(f)
else:
self._parse_error(self._currentfile, lineno,
self._parse_error(self._currentfile, lineno,
'invalid auto line \'%s\''%lines[cur_idx])
return 0
- [self.auto_ifaces.append(a) for a in auto_ifaces]
+ for a in auto_ifaces:
+ if a == 'all':
+ self.auto_all = True
+ break
+ r = utils.parse_iface_range(a)
+ if r:
+ for i in range(r[1], r[2]):
+ self.auto_ifaces.append('%s-%d' %(r[0], i))
+ self.auto_ifaces.append(a)
return 0
def _add_to_iface_config(self, ifacename, iface_config, attrname,
attrval, lineno):
newattrname = attrname.replace("_", "-")
try:
- if not self.callbacks.get('validateifaceattr')(newattrname, attrval):
+ if not self.callbacks.get('validateifaceattr')(newattrname,
+ attrval):
self._parse_error(self._currentfile, lineno,
'iface %s: unsupported keyword (%s)'
%(ifacename, attrname))
else:
iface_config[newattrname].append(attrval)
- def process_iface(self, lines, cur_idx, lineno):
+ def parse_iface(self, lines, cur_idx, lineno, ifaceobj):
lines_consumed = 0
line_idx = cur_idx
- ifaceobj = iface()
iface_line = lines[cur_idx].strip(whitespaces)
iface_attrs = re.split(self._ws_split_regex, iface_line)
ifacename = iface_attrs[1]
+ # in cases where mako is unable to render the template
+ # or incorrectly renders it due to user template
+ # errors, we maybe left with interface names with
+ # mako variables in them. There is no easy way to
+ # recognize and warn about these. In the below check
+ # we try to warn the user of such cases by looking for
+ # variable patterns ('$') in interface names.
+ if '$' in ifacename:
+ self._parse_warn(self._currentfile, lineno,
+ '%s: unexpected characters in interface name' %ifacename)
+
ifaceobj.raw_config.append(iface_line)
-
iface_config = collections.OrderedDict()
for line_idx in range(cur_idx + 1, len(lines)):
l = lines[line_idx].strip(whitespaces)
pass
self._validate_addr_family(ifaceobj, lineno)
- if ifaceobj.name in self.auto_ifaces:
+ if self.auto_all or (ifaceobj.name in self.auto_ifaces):
ifaceobj.auto = True
classes = self.get_allow_classes_for_iface(ifaceobj.name)
if classes:
[ifaceobj.set_class(c) for c in classes]
+
+ return lines_consumed # Return next index
+
+ def process_iface(self, lines, cur_idx, lineno):
+ ifaceobj = iface()
+ lines_consumed = self.parse_iface(lines, cur_idx, lineno, ifaceobj)
+
+ range_val = utils.parse_iface_range(ifaceobj.name)
+ if range_val:
+ for v in range(range_val[1], range_val[2]):
+ ifaceobj_new = copy.deepcopy(ifaceobj)
+ ifaceobj_new.realname = '%s' %ifaceobj.name
+ ifaceobj_new.name = '%s%d' %(range_val[0], v)
+ ifaceobj_new.flags = iface.IFACERANGE_ENTRY
+ if v == range_val[1]:
+ ifaceobj_new.flags |= iface.IFACERANGE_START
+ self.callbacks.get('iface_found')(ifaceobj_new)
+ else:
+ self.callbacks.get('iface_found')(ifaceobj)
- # Call iface found callback
- self.callbacks.get('iface_found')(ifaceobj)
return lines_consumed # Return next index
+ def process_vlan(self, lines, cur_idx, lineno):
+ ifaceobj = iface()
+ lines_consumed = self.parse_iface(lines, cur_idx, lineno, ifaceobj)
+
+ range_val = utils.parse_iface_range(ifaceobj.name)
+ if range_val:
+ for v in range(range_val[1], range_val[2]):
+ ifaceobj_new = copy.deepcopy(ifaceobj)
+ ifaceobj_new.realname = '%s' %ifaceobj.name
+ ifaceobj_new.name = '%s%d' %(range_val[0], v)
+ ifaceobj_new.type = ifaceType.BRIDGE_VLAN
+ ifaceobj_new.flags = iface.IFACERANGE_ENTRY
+ if v == range_val[1]:
+ ifaceobj_new.flags |= iface.IFACERANGE_START
+ self.callbacks.get('iface_found')(ifaceobj_new)
+ else:
+ ifaceobj.type = ifaceType.BRIDGE_VLAN
+ self.callbacks.get('iface_found')(ifaceobj)
+
+ return lines_consumed # Return next index
network_elems = { 'source' : process_source,
'allow' : process_allow,
'auto' : process_auto,
- 'iface' : process_iface}
+ 'iface' : process_iface,
+ 'vlan' : process_vlan}
def _is_keyword(self, str):
# The additional split here is for allow- keyword
return classes
def process_interfaces(self, filedata):
+
+ # process line continuations
+ filedata = ' '.join(d.strip() for d in filedata.split('\\'))
+
line_idx = 0
lines_consumed = 0
raw_config = filedata.split('\n')
def read_filedata(self, filedata):
self._currentfile_has_template = False
- # process line continuations
- filedata = ' '.join(d.strip() for d in filedata.split('\\'))
# run through template engine
try:
rendered_filedata = self._template_engine.render(filedata)
if rendered_filedata is filedata:
- self._currentfile_has_template = True
- else:
self._currentfile_has_template = False
+ else:
+ self._currentfile_has_template = True
except Exception, e:
self._parse_error(self._currentfile, -1,
'failed to render template (%s). ' %str(e) +
fp = open(filename)
ifacedicts = json.load(fp)
#object_hook=ifaceJsonDecoder.json_object_hook)
+
+ # we need to handle both lists and non lists formats (e.g. {{}})
+ if not isinstance(ifacedicts,list):
+ ifacedicts = [ifacedicts]
+
for ifacedict in ifacedicts:
ifaceobj = ifaceJsonDecoder.json_to_ifaceobj(ifacedict)
if ifaceobj: