creole/creole/loader.py

874 lines
38 KiB
Python

"""creole loader
flattened XML specific
"""
from os.path import join, isfile, isdir
from os import listdir
#from ast import literal_eval
from lxml.etree import parse, DTD
from tiramisu.option import (UnicodeOption, OptionDescription, PortOption,
IntOption, ChoiceOption, BoolOption, SymLinkOption, IPOption,
NetworkOption, NetmaskOption, DomainnameOption, BroadcastOption,
URLOption, EmailOption, FilenameOption, UsernameOption, DateOption,
PasswordOption, BoolOption, Leadership)
from tiramisu import Config, MetaConfig, MixConfig
from tiramisu.setting import groups
from tiramisu.error import ConfigError
from tiramisu.setting import owners
from tiramisu import Params, ParamOption, ParamValue, ParamContext
from .config import (FLATTENED_CREOLE_DIR, dtdfilename, eoledirs, eoleextradico, forbiddenextra,
configeol, eoleextraconfig)
from .i18n import _
from .var_loader import convert_tiramisu_value, modes_level, MACOption # FIXME YO
from .loader1 import load_config_eol, load_extras, _list_extras
#For compatibility
from .loader1 import config_save_values, config_load_store, config_get_values, add_eol_version
from .loader1 import load_store, load_config_store, load_values
from .xmlreflector import HIGH_COMPATIBILITY
#from . import eosfunc
from .objspace import CreoleObjSpace
import imp
class CreoleLoaderError(Exception):
pass
CONVERT_OPTION = {'number': dict(opttype=IntOption),
'choice': dict(opttype=ChoiceOption),
'string': dict(opttype=UnicodeOption),
'password': dict(opttype=PasswordOption),
'mail': dict(opttype=EmailOption),
'boolean': dict(opttype=BoolOption),
'symlink': dict(opttype=SymLinkOption),
'filename': dict(opttype=FilenameOption),
'date': dict(opttype=DateOption),
'unix_user': dict(opttype=UsernameOption),
'ip': dict(opttype=IPOption, initkwargs={'allow_reserved': True}),
'local_ip': dict(opttype=IPOption, initkwargs={'private_only': True, 'warnings_only': True}),
'netmask': dict(opttype=NetmaskOption),
'network': dict(opttype=NetworkOption),
'broadcast': dict(opttype=BroadcastOption),
'netbios': dict(opttype=DomainnameOption, initkwargs={'type_': 'netbios', 'warnings_only': True}),
'domain': dict(opttype=DomainnameOption, initkwargs={'type_': 'domainname', 'allow_ip': True, 'allow_without_dot': True}),
'domain_strict': dict(opttype=DomainnameOption, initkwargs={'type_': 'domainname', 'allow_ip': False}),
'hostname': dict(opttype=DomainnameOption, initkwargs={'type_': 'hostname', 'allow_ip': True}),
'hostname_strict': dict(opttype=DomainnameOption, initkwargs={'type_': 'hostname', 'allow_ip': False}),
'web_address': dict(opttype=URLOption, initkwargs={'allow_ip': True, 'allow_without_dot': True}),
'port': dict(opttype=PortOption, initkwargs={'allow_private': True}),
'mac': dict(opttype=MACOption) # FIXME YO
}
REMOVED_ATTRIB = ['path', 'type']
class Elt(object):
def __init__(self, attrib):
self.attrib = attrib
class PopulateTiramisuObjects(object):
def __init__(self):
self.storage = ElementStorage()
self.booleans = []
self.force_store_values = set()
self.separators = {}
self.groups = {}
def parse_dtd(self, dtdfilename):
"""Loads the Creole DTD
:raises IOError: if the DTD is not found
:param dtdfilename: the full filename of the Creole DTD
"""
if not isfile(dtdfilename):
raise IOError(_("no such DTD file: {}").format(dtdfilename))
with open(dtdfilename, 'r') as dtdfd:
dtd = DTD(dtdfd)
for elt in dtd.iterelements():
if elt.name == 'variable':
for attr in elt.iterattributes():
if set(attr.itervalues()) == set(['True', 'False']):
self.booleans.append(attr.name)
def make_tiramisu_objects(self, xmlroot, creolefunc_file, load_extra=True):
elt = Elt({'name': 'baseoption'})
family = Family(elt, self.booleans)
self.storage.add('.', family)
self.eosfunc = imp.load_source('eosfunc', creolefunc_file)
elts = {}
for elt in xmlroot:
elts.setdefault(elt.tag, []).append(elt)
list_elts = list(elts.keys())
if 'family' in list_elts:
list_elts.remove('family')
list_elts.insert(0, 'family')
for elt in list_elts:
xmlelts_ = elts[elt]
if elt == 'family':
xmlelts = []
actions = None
# `creole` family has to be loaded before any other family
# because `extra` family could use `creole` variables.
# `actions` family has to be loaded at the very end
# because it may use `creole` or `extra` variables
for xml in xmlelts_:
if not load_extra and xml.attrib['name'] not in ['creole', 'containers']:
continue
if xml.attrib['name'] == 'creole':
xmlelts.insert(0, xml)
elif xml.attrib['name'] == 'actions':
actions = xml
else:
xmlelts.append(xml)
if actions is not None:
xmlelts.append(actions)
else:
xmlelts = xmlelts_
for xmlelt in xmlelts:
if xmlelt.tag == 'family':
self._iter_family(xmlelt, family=family)
elif xmlelt.tag == 'help':
self._iter_help(xmlelt)
elif xmlelt.tag == 'constraints':
self._iter_constraints(xmlelt, load_extra)
else:
raise CreoleLoaderError(_('unknown tag {}').format(xmlelt.tag))
def _populate_variable(self, elt, subpath, is_slave, is_master):
variable = Variable(elt, self.booleans, self.storage, is_slave, is_master, self.eosfunc)
path = self._build_path(subpath, elt)
properties = variable.attrib.get('properties', [])
if 'force_store_value' in properties or "auto_freeze" in properties:
self.force_store_values.add(path)
self.storage.add(path, variable)
return variable
def _populate_family(self, elt, subpath):
if subpath is None:
force_icon = False
else:
force_icon = not subpath.startswith('containers') and not subpath.startswith('actions')
family = Family(elt, self.booleans, force_icon)
path = self._build_path(subpath, elt)
self.storage.add(path, family)
return family
def _build_path(self, subpath, elt):
if subpath is None:
subpath = elt.attrib['name']
else:
subpath += '.' + elt.attrib['name']
return subpath
def _iter_constraints(self, xmlelt, load_extra):
for elt in xmlelt:
if elt.tag == 'fill':
self._parse_fill(elt, load_extra)
elif elt.tag == 'condition':
self._parse_condition(elt, load_extra)
elif elt.tag == 'check':
self._parse_check(elt, load_extra)
else:
raise CreoleLoaderError(_('unknown constraint {}').format(elt.tag))
def _check_extra(self, variable, load_extra):
if load_extra:
return True
return variable.startswith('creole.') or variable.startswith('containers.')
def _parse_fill(self, elt, load_extra):
if not self._check_extra(elt.attrib['target'], load_extra):
return
callback = getattr(self.eosfunc, elt.attrib['name'])
callback_params = {}
for param in elt:
name = param.attrib.get('name', '')
if param.attrib['type'] == 'string':
value = str(param.text)
elif param.attrib['type'] == 'eole':
hidden = param.attrib['hidden']
if hidden == 'True':
hidden = False
elif hidden == 'False':
hidden = True
else:
raise CreoleLoaderError(_('unknown hidden boolean {}').format(hidden))
if not self._check_extra(param.text, load_extra):
return
value = [self.storage.get(param.text), hidden]
elif param.attrib['type'] == 'number':
value = int(param.text)
elif param.attrib['type'] == 'context':
value = (None,)
else:
raise CreoleLoaderError(_('unknown param type {} in fill to {}').format(param.attrib['type'], elt.attrib['target']))
callback_params.setdefault(name, []).append(value)
if callback_params == {}:
callback_params = None
self.storage.add_callback(elt.attrib['target'], callback, callback_params)
def _parse_check(self, elt, load_extra):
if not self._check_extra(elt.attrib['target'], load_extra):
return
all_param_eole = True
for param in elt:
if param.attrib.get('type') != 'eole':
all_param_eole = False
break
if elt.attrib['name'] == 'valid_enum':
# only for valid_enum with checkval to True
if len(elt) != 1:
raise CreoleLoaderError(_('valid_enum cannot have more than one param for {}').format(elt.attrib['target']))
if elt.attrib['probe'] == 'True':
proposed = elt[0].text
type_ = 'string'
elif elt[0].attrib['type'] == 'eole':
proposed = elt[0].text
type_ = 'eole'
else:
#proposed_value = literal_eval(elt[0].text)
proposed_value = eval(elt[0].text)
proposed = tuple(proposed_value)
type_ = 'string'
self.storage.add_information(elt.attrib['target'], 'proposed_value', {'value': proposed, 'type': type_})
validator = getattr(self.eosfunc, elt.attrib['name'])
elif elt.attrib['name'] == 'valid_differ' and all_param_eole:
if (HIGH_COMPATIBILITY and len(elt) not in [0, 1]) or (not HIGH_COMPATIBILITY and len(elt) != 1):
raise CreoleLoaderError(_('valid_differ length should be 1'))
if HIGH_COMPATIBILITY and len(elt) == 1:
if not self._check_extra(elt[0].text, load_extra):
return
variables = [self.storage.get(elt[0].text)]
else:
variables = []
self.storage.add_consistency(elt.attrib['target'],
'not_equal',
variables,
elt.attrib['warnings_only'],
elt.attrib['transitive'])
elif elt.attrib['name'] == 'valid_networknetmask':
if len(elt) != 1:
raise CreoleLoaderError(_('valid_networknetmask length should be 1'))
if not all_param_eole:
raise CreoleLoaderError(_('valid_networknetmask must have only eole variable'))
variables = [self.storage.get(elt[0].text)]
self.storage.add_consistency(elt.attrib['target'],
'network_netmask',
variables,
elt.attrib['warnings_only'],
elt.attrib['transitive'])
elif elt.attrib['name'] == 'valid_ipnetmask':
if len(elt) != 1:
raise CreoleLoaderError(_('valid_ipnetmask length should be 1'))
if not all_param_eole:
raise CreoleLoaderError(_('valid_ipnetmask must have only eole variable'))
if not self._check_extra(elt[0].text, load_extra):
return
variables = [self.storage.get(elt[0].text)]
self.storage.add_consistency(elt.attrib['target'],
'ip_netmask',
variables,
elt.attrib['warnings_only'],
elt.attrib['transitive'])
elif elt.attrib['name'] == 'valid_broadcast':
if len(elt) != 2:
raise CreoleLoaderError(_('valid_broadcast length should be 2'))
if not all_param_eole:
raise CreoleLoaderError(_('valid_broadcast must have only eole variable'))
if not self._check_extra(elt[0].text, load_extra):
return
variables = [self.storage.get(elt[0].text)]
if not self._check_extra(elt[1].text, load_extra):
return
variables.append(self.storage.get(elt[1].text))
self.storage.add_consistency(elt.attrib['target'],
'broadcast',
variables,
elt.attrib['warnings_only'],
elt.attrib['transitive'])
elif elt.attrib['name'] == 'valid_in_network':
if len(elt) != 2:
raise CreoleLoaderError(_('valid_in_network length should be 2'))
if not all_param_eole:
raise CreoleLoaderError(_('valid_in_network must have only eole variable'))
if not self._check_extra(elt[0].text, load_extra):
return
variables = [self.storage.get(elt[0].text)]
if not self._check_extra(elt[1].text, load_extra):
return
variables.append(self.storage.get(elt[1].text))
self.storage.add_consistency(elt.attrib['target'],
'in_network',
variables,
elt.attrib['warnings_only'],
elt.attrib['transitive'])
else:
validator = getattr(self.eosfunc, elt.attrib['name'])
validator_params = {}
for param in elt:
text = param.text
if param.attrib['type'] == 'eole':
hidden = param.attrib.get('hidden', 'True')
if hidden == 'True':
hidden = False
elif hidden == 'False':
hidden = True
else:
raise CreoleLoaderError(_('unknown hidden boolean {}').format(hidden))
if not self._check_extra(text, load_extra):
return
text = [self.storage.get(text), hidden]
validator_params.setdefault(param.attrib.get('name', ''), []).append(text)
self.storage.add_validator(elt.attrib['target'], validator, validator_params)
def _parse_condition(self, elt, load_extra):
if not self._check_extra(elt.attrib['source'], load_extra):
return
if elt.attrib['name'] == 'disabled_if_in':
actions = ['disabled']
inverse = False
elif elt.attrib['name'] == 'disabled_if_not_in':
actions = ['disabled']
inverse = True
elif elt.attrib['name'] == 'auto_frozen_if_in':
actions = ['frozen']
inverse = False
elif elt.attrib['name'] == 'frozen_if_in':
actions = ['frozen', 'hidden', 'force_default_on_freeze']
inverse = False
elif elt.attrib['name'] == 'frozen_if_not_in':
actions = ['frozen', 'hidden', 'force_default_on_freeze']
inverse = True
elif elt.attrib['name'] == 'mandatory_if_in':
actions = ['mandatory']
inverse = False
elif elt.attrib['name'] == 'mandatory_if_not_in':
actions = ['mandatory']
inverse = True
else:
raise CreoleLoaderError(_('unknown condition type {} for {}').format(elt.attrib['name'], elt.attrib['source']))
expected_values = []
options = []
for param in elt:
if param.tag == 'param':
expected_values.append(param.text)
elif param.tag == 'target':
if param.attrib['type'] in ['variable', 'family']:
if not self._check_extra(param.text, load_extra):
return
option = self.storage.get(param.text)
option_actions = actions
if 'force_store_value' in option.attrib.get('properties', []) and \
'force_default_on_freeze' in option_actions:
option_actions.remove('force_default_on_freeze')
options.append((param.text, option_actions))
source = self.storage.get(elt.attrib['source'])
for option, actions in options:
conditions = []
for action in actions:
for expected in expected_values:
conditions.append({'option': source, 'expected': expected,
'action': action, 'inverse': inverse})
self.storage.add_requires(option, conditions)
def _iter_help(self, xmlelt):
for elt in xmlelt:
self.storage.add_help(elt.attrib['name'], elt.text)
def _iter_master(self, master, subpath):
subpath = self._build_path(subpath, master)
family = Family(master, self.booleans)
family.set_master()
self.storage.add(subpath, family)
master_name = None
for var in master:
if master_name is None:
master_name = var.attrib['name']
self.groups[master_name] = []
else:
self.groups[master_name].append(var.attrib['name'])
self._iter_family(var, subpath=subpath, family=family)
return family
def _iter_family(self, child, subpath=None, family=None):
if child.tag not in ['family', 'variable', 'separators', 'master']:
raise CreoleLoaderError(_('unknown tag {}').format(child.tag))
if child.tag == 'family':
old_family = family
family = self._populate_family(child, subpath)
if old_family is not None:
old_family.add(family)
if child.tag == 'master':
master = self._iter_master(child, subpath)
family.add(master)
elif child.tag == 'separators':
self._parse_separators(child)
elif child.tag == 'variable':
if family is None:
raise CreoleLoaderError(_('variable without family'))
is_slave = False
is_master = False
if family.is_master:
if child.attrib['name'] != family.attrib['name']:
is_slave = True
else:
is_master = True
variable = self._populate_variable(child, subpath, is_slave, is_master)
family.add(variable)
elif len(child) != 0:
subpath = self._build_path(subpath, child)
for c in child:
self._iter_family(c, subpath, family)
def _parse_separators(self, separators):
for separator in separators:
elt = self.storage.get(separator.attrib['name'])
never_hidden = separator.attrib.get('never_hidden')
if never_hidden == 'True':
never_hidden = True
else:
never_hidden = None
info = (separator.text, never_hidden)
self.separators[separator.attrib['name']] = info
elt.add_information('separator', info)
def build(self, persistent=False, session_id=None, meta_config=False):
if meta_config:
optiondescription = self.storage.paths['.'].get()
config = MetaConfig([],
optiondescription=optiondescription,
persistent=persistent,
session_id=session_id)
mixconfig = MixConfig(children=[],
optiondescription=optiondescription,
persistent=persistent,
session_id='m_' + session_id)
config.config.add(mixconfig)
else:
config = Config(self.storage.paths['.'].get(),
persistent=persistent,
session_id=session_id)
config.information.set('force_store_vars', self.force_store_values)
config.information.set('force_store_values', list(self.force_store_values))
# XXX really usefull?
ro_append = frozenset(config.property.getdefault('read_only', 'append') - {'force_store_value'})
rw_append = frozenset(config.property.getdefault('read_write', 'append') - {'force_store_value'})
config.property.setdefault(ro_append, 'read_only', 'append')
config.property.setdefault(rw_append, 'read_write', 'append')
config.property.read_only()
_modes = list(modes_level)
_modes.append('hidden')
config.permissive.set(frozenset(_modes))
return config
class ElementStorage(object):
def __init__(self):
self.paths = {}
def add(self, path, elt):
if path in self.paths:
raise CreoleLoaderError(_('path already loaded {}').format(path))
self.paths[path] = elt
def add_help(self, path, text):
elt = self.get(path)
self.paths[path].add_information('help', text)
def add_callback(self, path, callback, callback_params):
elt = self.get(path)
elt.add_callback(callback, callback_params)
def add_information(self, path, name, information):
elt = self.get(path)
elt.add_information(name, information)
def add_validator(self, path, validator, validator_params):
elt = self.get(path)
elt.add_validator(validator, validator_params)
def add_consistency(self, path, consistence, variables, warnings_only, transitive):
elt = self.get(path)
elt.add_consistency(consistence, variables, warnings_only, transitive)
def add_requires(self, path, requires):
elt = self.get(path)
elt.add_requires(requires)
def get(self, path):
if path not in self.paths:
raise CreoleLoaderError(_('there is no element for path {}').format(path))
return self.paths[path]
class Variable(object):
def __init__(self, elt, booleans, storage, is_slave, is_master, eosfunc):
self.option = None
self.informations = {}
self.attrib = {}
self.callbacks = []
self.requires = []
self.validator = None
self.consistencies = []
self.attrib['properties'] = []
self.eosfunc = eosfunc
for key, value in elt.attrib.items():
if key in REMOVED_ATTRIB:
continue
#if key != 'name':
# value = unicode(value)
if key in booleans:
if value == 'True':
value = True
elif value == 'False':
value = False
else:
raise CreoleLoaderError(_('unknown value {} for {}').format(value, key))
self.attrib[key] = value
convert_option = CONVERT_OPTION[elt.attrib['type']]
self.object_type = convert_option['opttype']
if elt.attrib['type'] == 'choice':
if self.attrib.get('choice'):
self.attrib['values'] = getattr(self.eosfunc, self.attrib.get('choice'))
else:
self.attrib['values'] = []
for child in elt:
if child.tag == 'choice':
value = child.text
if 'type' in child.attrib and child.attrib['type'] == 'number':
value = int(value)
if value is None:
value = u''
self.attrib['values'].append(value)
self.attrib['values'] = tuple(self.attrib['values'])
for child in elt:
if "type" in child.attrib:
type_ = CONVERT_OPTION[child.attrib['type']]['opttype']
else:
type_ = self.object_type
if child.tag == 'property':
self.attrib['properties'].append(child.text)
elif child.tag == 'value':
if self.attrib['multi'] and not is_slave:
if 'default' not in self.attrib:
self.attrib['default'] = []
value = convert_tiramisu_value(child.text, type_)
self.attrib['default'].append(value)
if 'default_multi' not in self.attrib and not is_master:
self.attrib['default_multi'] = value
else:
if 'default' in self.attrib:
raise CreoleLoaderError(_('default value already set for {}'
'').format(self.attrib['path']))
value = convert_tiramisu_value(child.text, type_)
if value is None: # and (elt.attrib['type'] != 'choice' or value not in self.attrib['values']):
value = u''
if is_slave:
self.attrib['default_multi'] = value
else:
self.attrib['default'] = value
if 'initkwargs' in convert_option:
self.attrib.update(convert_option['initkwargs'])
self.attrib['properties'] = tuple(self.attrib['properties'])
if elt.attrib['type'] == 'symlink':
del self.attrib['properties']
del self.attrib['multi']
self.attrib['opt'] = storage.get(self.attrib['opt'])
def add_information(self, key, value):
if key in self.informations:
raise CreoleLoaderError(_('key already exists in information {}').format(key))
self.informations[key] = value
def add_callback(self, callback, callback_params):
self.callbacks.append((callback, callback_params))
def add_requires(self, requires):
self.requires.extend(requires)
def add_validator(self, validator, validator_params):
self.validator = (validator, validator_params)
def add_consistency(self, consistence, variables, warnings_only, transitive):
self.consistencies.append((consistence, variables, warnings_only, transitive))
def build_params(self, params):
if params != None:
new_params = Params()
for key, values in params.items():
new_values = []
for value in values:
if isinstance(value, list):
# retrieve object
value = ParamOption(value[0].get(), value[1])
elif value == (None,):
value = ParamContext()
else:
value = ParamValue(value)
if key == '':
args = list(new_params.args)
args.append(value)
new_params.args = tuple(args)
else:
new_params.kwargs[key] = value
return new_params
return params
def get(self):
if self.option is None:
if self.object_type is SymLinkOption:
self.attrib['opt'] = self.attrib['opt'].get()
for callback, callback_params in self.callbacks:
self.attrib['callback'] = callback
self.attrib['callback_params'] = self.build_params(callback_params)
for require in self.requires:
if isinstance(require['option'], Variable):
require['option'] = require['option'].get()
if self.requires != []:
self.attrib['requires'] = self.requires
if self.validator:
self.attrib['validator'] = self.validator[0]
self.attrib['validator_params'] = self.build_params(self.validator[1])
try:
option = self.object_type(**self.attrib)
except Exception as err:
import traceback
traceback.print_exc()
name = self.attrib['name']
raise CreoleLoaderError(_('cannot create option {}: {}').format(name, err))
for key, value in self.informations.items():
option.impl_set_information(key, value)
for consistency in self.consistencies:
options = []
for variable in consistency[1]:
options.append(variable.get())
try:
kwargs = {}
if consistency[2] == 'True':
kwargs['warnings_only'] = True
if consistency[3] == 'False':
kwargs['transitive'] = False
option.impl_add_consistency(consistency[0], *options, **kwargs)
except ConfigError as err:
name = self.attrib['name']
raise CreoleLoaderError(_('cannot load consistency for {}: {}').format(name, err))
self.option = option
return self.option
class Family(object):
def __init__(self, elt, booleans, force_icon=False):
self.requires = []
self.option = None
self.attrib = {}
self.is_master = False
if force_icon:
self.informations = {'icon': None}
else:
self.informations = {}
self.children = []
self.attrib['properties'] = []
for key, value in elt.attrib.items():
if key in REMOVED_ATTRIB:
continue
if key in booleans:
if value == 'True':
value = True
elif value == 'False':
value = False
else:
raise CreoleLoaderError(_('unknown value {} for {}').format(value, key))
if key == 'icon':
self.add_information('icon', value)
continue
elif key == 'hidden':
if value:
self.attrib['properties'].append(key)
elif key == 'mode':
self.attrib['properties'].append(value)
else:
self.attrib[key] = value
if 'doc' not in self.attrib:
self.attrib['doc'] = u''
self.attrib['properties'] = tuple(self.attrib['properties'])
def add(self, child):
self.children.append(child)
def add_information(self, key, value):
if key in self.informations and not (key == 'icon' and self.informations[key] is None):
raise CreoleLoaderError(_('key already exists in information {}').format(key))
self.informations[key] = value
def set_master(self):
self.is_master = True
def add_requires(self, requires):
self.requires.extend(requires)
def get(self):
if self.option is None:
self.attrib['children'] = []
for child in self.children:
self.attrib['children'].append(child.get())
for require in self.requires:
if isinstance(require['option'], Variable):
require['option'] = require['option'].get()
if self.requires != []:
self.attrib['requires'] = self.requires
try:
if not self.is_master:
option = OptionDescription(**self.attrib)
else:
option = Leadership(**self.attrib)
#option = OptionDescription(**self.attrib)
except Exception as err:
raise CreoleLoaderError(_('cannot create optiondescription {}: {}').format(self.attrib['name'], err))
for key, value in self.informations.items():
option.impl_set_information(key, value)
self.option = option
#if self.is_master:
# self.option.impl_set_group_type(groups.master)
return self.option
def _gen_eol_file(namespace):
if namespace == 'creole':
return configeol
else:
return join(eoleextraconfig, namespace, 'config.eol')
def creole_loader(load_values=True, rw=False, namespace='creole',
load_extra=False, reload_config=True, owner=None,
disable_mandatory=False, force_configeol=None,
try_upgrade=True, force_load_creole_owner=None,
force_dirs=None, warnings=None, force_instanciate=None,
force_dtdfile=None, force_flattened=None,
mandatory_permissive=True, from_zephir=None,
force_no_save=False, force_eoleextradico=None,
force_eoleextraconfig=None, only_load_flattened=False):
"""
Loads the Creole XML dictionnary files and return a tiramisu config object
:param bool load_values: Loads (or not) the :file:`config.eol` file
:param bool rw: Config's read/write flag
:param str namespace: Root's namespace for the config (example: "creole", "bacula", ...)
:param bool load_extra: Loads (or not) the extra dictionnaries (if `namespace='creole'`)
:param bool reload_config: This parameter is kept for compatibility reasons
:param str owner: forces the owner on a modified variable
:param bool disable_mandatory: disables the mandatory variables
:param str force_configeol: Forces the used configuration file
:param bool try_upgrade: tries to upgrade
:param force_load_creole_owner: Forces the owner for the loaded variables
:param str force_dirs: Forces the folder's name containing the dictionnaries
:param warnings: Shows the validation's warnings
:param bool force_instanciate: tells us if the server is already instanciated or not
:param force_dtdfile: None or dtd filename
:param force_flattened: None or flatened filename's name
:param only_load_flattened: boolean to desactivate generated of flattened file
"""
if namespace is not 'creole':
raise CreoleLoaderError(_('Only creole namespace is supported'))
#if reload_config is not True:
# raise CreoleLoaderError(_('Cannot reload the configuration'))
if force_flattened is None:
force_flattened = join(FLATTENED_CREOLE_DIR, 'flattened_creole.xml')
if force_dtdfile is None:
force_dtdfile = dtdfilename
if force_configeol is not None:
if not isfile(force_configeol):
raise CreoleLoaderError(_("Configuration file unexistent : {0}").format(
force_configeol))
if load_extra and force_eoleextraconfig is None:
# if force_configeol, cannot calculate extra configfile name
raise CreoleLoaderError(_('Unable to force_configeol with load_extra.'))
if force_dirs is not None and load_extra is True and force_eoleextradico is None:
raise CreoleLoaderError(_('If force_dirs is defined, namespace must be set to creole and '
'load_extra must be set to False.'))
if not only_load_flattened:
#should not load value now because create a Config
eolobj = CreoleObjSpace(force_dtdfile)
if force_dirs is not None:
dirs = force_dirs
else:
dirs = eoledirs
if from_zephir is not None and type(dirs) != list:
#if dirs is not a list, add subdirectory 'local'
#and 'variante'
orig_dir = dirs
dirs = [dirs]
for tdir in [join(orig_dir, 'local'),
join(orig_dir, 'variante')]:
if isdir(tdir):
dirs.append(tdir)
eolobj.create_or_populate_from_xml('creole', dirs, from_zephir=from_zephir)
if load_extra:
if force_eoleextradico == None:
force_eoleextradico = eoleextradico
extranames = _list_extras(force_eoleextradico)
extranames.sort()
if isdir(force_eoleextradico):
for directory in extranames:
if directory in forbiddenextra:
raise CreoleLoaderError(
_('Namespace {} for extra dictionary not allowed').format(directory))
dirname = join(force_eoleextradico, directory)
eolobj.create_or_populate_from_xml(directory, [dirname], from_zephir)
eolobj.space_visitor()
xmlroot = eolobj.save(force_flattened, force_no_save)
else:
with open(force_flattened, 'r') as fhd:
xmlroot = parse(fhd).getroot()
tiramisu_objects = PopulateTiramisuObjects()
tiramisu_objects.parse_dtd(force_dtdfile)
tiramisu_objects.make_tiramisu_objects(xmlroot)
config = tiramisu_objects.build()
if warnings is None:
# warnings is disabled in read-only mode and enabled in read-write mode by default
warnings = rw
if warnings is False:
config.cfgimpl_get_settings().remove('warnings')
if owner is not None:
if owner not in dir(owners):
owners.addowner(owner)
config.cfgimpl_get_settings().setowner(getattr(owners, owner))
#load values
if force_configeol is not None:
configfile = force_configeol
else:
configfile = _gen_eol_file(namespace)
if load_values and isfile(configfile):
disable_mandatory = False
load_config_eol(config, configfile=configfile, try_upgrade=try_upgrade,
force_load_owner=force_load_creole_owner,
force_instanciate=force_instanciate)
else:
config.impl_set_information(namespace, configfile)
if load_extra:
load_extras(config, load_values=load_values, mandatory_permissive=mandatory_permissive,
extradico=force_eoleextradico, force_eoleextraconfig=force_eoleextraconfig)
if rw:
config.read_write()
elif rw is False:
config.read_only()
if disable_mandatory:
config.cfgimpl_get_settings().remove('mandatory')
config.cfgimpl_get_settings().remove('empty')
if from_zephir is not None:
return tiramisu_objects.groups, tiramisu_objects.separators, config
else:
return config