"""Update Rougail XML file to new version Cadoles (http://www.cadoles.com) Copyright (C) 2021 distribued with GPL-2 or later license This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA """ from typing import List from os.path import join, isfile, basename from os import listdir from lxml.etree import DTD, parse, XMLParser, XMLSyntaxError # pylint: disable=E0611 from lxml.etree import Element, SubElement, tostring from ast import parse as ast_parse from .i18n import _ from .error import UpgradeError from .utils import normalize_family from .config import RougailConfig VERSIONS = {'creole': ['1'], 'rougail': ['0.9', '0.10'], } def get_function_name(root, version): version = version.replace('.', '_') return f'update_{root}_{version}' FUNCTION_VERSIONS = [(root, version, get_function_name(root, version)) for root, versions in VERSIONS.items() for version in versions] class RougailUpgrade: def __init__(self, test=False, upgrade_help=None, rougailconfig: RougailConfig=None, ) -> None: self.test = test if upgrade_help is None: upgrade_help = {} self.upgrade_help = upgrade_help if rougailconfig is None: rougailconfig = RougailConfig self.rougailconfig = rougailconfig def load_xml_from_folders(self, srcfolder: str, dstfolder: str, namespace: str, display: bool=True, ): """Loads all the XML files located in the xmlfolders' list :param xmlfolders: list of full folder's name """ filenames = [filename for filename in listdir(srcfolder) if filename.endswith('.xml')] filenames.sort() for filename in filenames: xmlsrc = join(srcfolder, filename) xmldst = join(dstfolder, filename) if isfile(xmldst): raise Exception(f'cannot update "{xmlsrc}" destination file "{xmldst}" already exists') try: parser = XMLParser(remove_blank_text=True) document = parse(xmlsrc, parser) except XMLSyntaxError as err: raise Exception(_(f'not a XML file: {err}')) from err root = document.getroot() search_function_name = get_function_name(root.tag, root.attrib.get('version', '1')) function_found = False for root_name, version, function_version in FUNCTION_VERSIONS: if function_found and hasattr(self, function_version): if display: print(f' - convert {filename} to version {version}') upgrade_help = self.upgrade_help.get(function_version, {}).get(filename, {}) if upgrade_help.get('remove') is True: continue root = getattr(self, function_version)(root, upgrade_help, namespace) if function_version == search_function_name: function_found = True root.attrib['version'] = version with open(xmldst, 'wb') as xmlfh: xmlfh.write(tostring(root, pretty_print=True, encoding="UTF-8", xml_declaration=True)) # if # if not self.dtd.validate(document): # dtd_error = self.dtd.error_log.filter_from_errors()[0] # msg = _(f'not a valid XML file: {dtd_error}') # raise DictConsistencyError(msg, 43, [xmlfile]) # yield xmlfile, document.getroot() def update_rougail_0_10(self, root: 'Element', upgrade_help: dict, namespace: str, ) -> 'Element': variables = root.find('variables') if variables is None: return root paths = self._get_path_variables(variables, namespace == self.rougailconfig['variable_namespace'], namespace, ) constraints = root.find('constraints') # convert schedule and schedulemod for variable in paths.values(): variable = variable['variable'] if variable.tag != 'variable': continue if 'type' in variable.attrib and variable.attrib['type'] in ['schedule', 'schedulemod']: if variable.attrib['type'] == 'schedule': choices = ('none', 'daily', 'weekly', 'monthly') else: choices = ('pre', 'post') variable.attrib['type'] = 'choice' has_value = False for value in variable: if value.tag == 'value': has_value = True break for name in choices: choice = SubElement(variable, 'choice') choice.text = name if not has_value: value = SubElement(variable, 'value') value.text = choices[0] variable.attrib['mandatory'] = 'True' # convert group to leadership groups = [] if constraints is not None: for constraint in constraints: if constraint.tag == 'group': constraints.remove(constraint) groups.append(constraint) for group in groups: if group.attrib['leader'] in paths: leader_obj = paths[group.attrib['leader']] #FIXME name peut avoir "." il faut le virer #FIXME si extra c'est un follower ! if 'name' in group.attrib: grpname = group.attrib['name'] if 'description' in group.attrib: description = group.attrib['description'] else: description = grpname else: grpname = leader_obj['variable'].attrib['name'] if '.' in grpname: grpname = grpname.rsplit('.', 1)[-1] if 'description' in group.attrib: description = group.attrib['description'] elif 'description' in leader_obj['variable'].attrib: description = leader_obj['variable'].attrib['description'] else: description = grpname family = SubElement(leader_obj['parent'], 'family', name=grpname, description=description, leadership="True") leader_obj['parent'].remove(leader_obj['variable']) family.append(leader_obj['variable']) else: # append in group follower = next(iter(group)) leader_name = group.attrib['leader'] if '.' in leader_name: leader_path = leader_name.rsplit('.', 1)[0] follower_path = leader_path + '.' + follower.text else: follower_path = follower.text obj = paths[follower_path] family = SubElement(obj['parent'], 'family', name=leader_name, leadership="True") grpname = leader_name for follower in group: leader_name = group.attrib['leader'] if '.' in leader_name: leader_path = leader_name.rsplit('.', 1)[0] follower_path = leader_path + '.' + follower.text else: follower_path = follower.text follower_obj = paths[follower_path] follower_obj['parent'].remove(follower_obj['variable']) family.append(follower_obj['variable']) if '.' in follower_path: new_path = follower_path.rsplit('.', 1)[0] + '.' + grpname + '.' + follower_path.rsplit('.', 1)[1] paths[new_path] = paths[follower_path] # convert choice option valid_enums = [] if constraints is not None: for constraint in constraints: if constraint.tag == 'check' and constraint.attrib['name'] == 'valid_enum': constraints.remove(constraint) valid_enums.append(constraint) for valid_enum in valid_enums: targets = [] for target in valid_enum: if target.tag != 'target': continue if target.text in paths: # not in paths if it's optional # but not check it targets.append(paths[target.text]['variable']) params = [] function_param = None for param in valid_enum: if param.tag != 'param': continue if 'type' in param.attrib and param.attrib['type'] == 'function': function_param = param.text continue params.append(param) first_choice = None for target in targets: if function_param is not None: function = SubElement(target, 'choice', type='function', name=function_param) for param in params: if function_param is not None: function.append(param) else: choice = SubElement(target, 'choice') if first_choice is None and ('type' not in param.attrib or param.attrib['type'] != 'variable'): first_choice = choice choice.text = param.text if 'type' not in param.attrib and param.text is None: choice_type = 'nil' elif 'type' in param.attrib: choice_type = param.attrib['type'] elif 'type' in target.attrib: choice_type = target.attrib['type'] else: choice_type = 'string' choice.attrib['type'] = choice_type has_value = False for target in targets: if 'remove_check' in target.attrib: target.attrib['remove_choice'] = target.attrib['remove_check'] for target in targets: for value in target: if value.tag == 'value': has_value = True if 'type' in target.attrib: value.attrib['type'] = target.attrib['type'] if first_choice is not None and not has_value: value = SubElement(target, 'value') value.attrib['type'] = first_choice.attrib['type'] value.text = first_choice.text for target in targets: if 'remove_choice' not in target.attrib or target.attrib['remove_choice'] != 'True': target.attrib['type'] = 'choice' return root def _get_path_variables(self, variables, is_variable_namespace, path, dico=None): if dico is None: dico = {} for variable in variables: if not is_variable_namespace and path: subpath = path + '.' else: subpath = '' if variable.tag not in ['variable', 'family']: continue subpath += variable.attrib['name'] if variable.tag == 'family': self._get_path_variables(variable, is_variable_namespace, subpath, dico) elif variable.tag == 'variable': dico[subpath] = {'variable': variable, 'parent': variables} return dico def update_rougail_0_9(self, root: 'Element', upgrade_help: dict, namespace: str, ) -> 'Element': # rename root root.tag = 'rougail' variables_auto_valid_enum = {} variables_help = {} families_help = {} variables = {} families = {} valid_enums = {} current_service = upgrade_help.get('services', {}).get('default', 'unknown') files = {current_service: {}} ips = {current_service: []} servicelists = {} test_unknowns_variables = set() autos = [] constraints_obj = None for subelement in root: if not isinstance(subelement.tag, str): # XML comment continue if subelement.tag == 'family_action': root.remove(subelement) continue for subsubelement in subelement: if not isinstance(subsubelement.tag, str): # XML comment continue for subsubsubelement in subsubelement: if not isinstance(subsubsubelement.tag, str): # XML comment continue if subsubsubelement.tag == 'variable': if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('remove', []): subsubelement.remove(subsubsubelement) continue if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('type', {}): subsubsubelement.attrib['type'] = upgrade_help['variables']['type'][subsubsubelement.attrib['name']] if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('hidden', {}).get('add', []): subsubsubelement.attrib['hidden'] = 'True' if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('hidden', {}).get('remove', []): self.remove(subsubsubelement, 'hidden', optional=True) if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('mandatory', {}).get('remove', []): self.remove(subsubsubelement, 'mandatory') if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('mandatory', {}).get('add', []): subsubsubelement.attrib['mandatory'] = 'True' if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('type', {}): subsubsubelement.attrib['type'] = upgrade_help.get('variables', {}).get('type', {})[subsubsubelement.attrib['name']] if namespace == self.rougailconfig['variable_namespace']: path = subsubsubelement.attrib['name'] npath = normalize_family(subsubsubelement.attrib['name']) else: path = namespace + '.' + subsubelement.attrib['name'] + '.' + subsubsubelement.attrib['name'] npath = normalize_family(namespace) + '.' + normalize_family(subsubelement.attrib['name']) + '.' + normalize_family(subsubsubelement.attrib['name']) variables[path] = subsubsubelement variables[npath] = subsubsubelement type = subsubsubelement.attrib.get('type') if type in ['oui/non', 'yes/no', 'on/off']: variables_auto_valid_enum.setdefault(subsubsubelement.attrib['type'], []).append(path) del subsubsubelement.attrib['type'] elif type == 'hostname_strict': subsubsubelement.attrib['type'] = 'hostname' elif type in ['domain', 'domain_strict']: subsubsubelement.attrib['type'] = 'domainname' elif type == 'string': del subsubsubelement.attrib['type'] if self.test and subsubsubelement.attrib.get('auto_freeze') == 'True': del subsubsubelement.attrib['auto_freeze'] #if self.test and subsubsubelement.attrib.get('redefine') == 'True': # subsubsubelement.attrib['exists'] = 'False' # del subsubsubelement.attrib['redefine'] if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('redefine', {}).get('remove', {}): del subsubsubelement.attrib['redefine'] if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('remove_check', []): subsubsubelement.attrib['remove_check'] = 'True' if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('mode', {}).get('modify', {}): subsubsubelement.attrib['mode'] = upgrade_help.get('variables', {}).get('mode', {}).get('modify', {})[subsubsubelement.attrib['name']] if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('type', {}).get('modify', {}): subsubsubelement.attrib['type'] = upgrade_help.get('variables', {}).get('type', {}).get('modify', {})[subsubsubelement.attrib['name']] type = subsubsubelement.attrib['type'] if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('test', {}): subsubsubelement.attrib['test'] = upgrade_help.get('variables', {}).get('test', {})[subsubsubelement.attrib['name']] if subsubsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('remove_value', []): for value in subsubsubelement: subsubsubelement.remove(value) if subsubsubelement.attrib['name'] != normalize_family(subsubsubelement.attrib['name']): if "description" not in subsubsubelement.attrib: subsubsubelement.attrib['description'] = subsubsubelement.attrib['name'] subsubsubelement.attrib['name'] = normalize_family(subsubsubelement.attrib['name']) elif subsubsubelement.tag == 'param': if subsubelement.tag == 'check' and subsubelement.attrib['target'] in upgrade_help.get('check', {}).get('remove', []): continue type = subsubsubelement.attrib.get('type') if type == 'eole': subsubsubelement.attrib['type'] = 'variable' type = 'variable' if type == 'python': subsubsubelement.attrib['type'] = 'function' if subsubsubelement.text.startswith('range('): func_ast = ast_parse(subsubsubelement.text) subsubsubelement.text = 'range' for arg in func_ast.body[0].value.args: SubElement(subsubelement, 'param', type='number').text = str(arg.value) else: raise Exception(f'{subsubsubelement.text} is not a supported function') type = 'function' elif type in ('container', 'context'): raise UpgradeError(_(f'cannot convert param with type "{type}"')) if subsubelement.attrib['name'] == 'valid_entier' and not 'type' in subsubsubelement.attrib: subsubsubelement.attrib['type'] = 'number' if (not type or type == 'variable') and subsubsubelement.text in upgrade_help.get('variables', {}).get('remove', []): subsubelement.remove(subsubsubelement) continue if subsubelement.attrib['name'] == 'valid_enum' and not type: if subsubsubelement.attrib.get('name') == 'checkval': if subsubelement.attrib['target'] in upgrade_help.get('check', {}).get('valid_enums', {}).get('checkval', {}).get('remove', []): subsubelement.remove(subsubsubelement) continue raise UpgradeError(_('checkval in valid_enum is no more supported')) if subsubsubelement.text.startswith('['): for val in eval(subsubsubelement.text): SubElement(subsubelement, 'param').text = str(val) subsubelement.remove(subsubsubelement) self.move(subsubsubelement, 'hidden', 'propertyerror', optional=True) if type == 'variable' and subsubsubelement.text in upgrade_help.get('variables', {}).get('rename', []): subsubsubelement.text = upgrade_help.get('variables', {}).get('rename', [])[subsubsubelement.text] up = upgrade_help.get('params', {}).get(subsubsubelement.text) if up: if 'text' in up: subsubsubelement.text = up['text'] if 'type' in up: subsubsubelement.attrib['type'] = up['type'] elif subsubsubelement.tag == 'target': type = subsubsubelement.attrib.get('type') if type in ['service_accesslist', 'service_restrictionlist', 'interfacelist', 'hostlist']: subsubelement.remove(subsubsubelement) elif (not type or type == 'variable') and subsubsubelement.text in upgrade_help.get('variables', {}).get('remove', []): subsubelement.remove(subsubsubelement) elif type == 'family' and subsubsubelement.text in upgrade_help.get('families', {}).get('remove', []): subsubelement.remove(subsubsubelement) elif type == 'actionlist': # for family in root.find('variables'): # family_list = SubElement(subsubelement, 'target') # family_list.attrib['type'] = 'family' # family_list.text = namespace + '.' + family.attrib['name'] subsubelement.remove(subsubsubelement) if upgrade_help.get('targets', {}).get(subsubsubelement.text, {}).get('optional'): subsubsubelement.attrib['optional'] = upgrade_help.get('targets', {}).get(subsubsubelement.text, {}).get('optional') has_target = False for target in subsubelement: if target.tag == 'target': has_target = True break if not has_target: subelement.remove(subsubelement) continue elif subsubsubelement.tag == 'slave': if subsubsubelement.text in upgrade_help.get('variables', {}).get('remove', []): subsubelement.remove(subsubsubelement) continue subsubsubelement.tag = 'follower' subsubsubelement.text = normalize_family(subsubsubelement.text) if subelement.tag == 'containers': current_service = self.upgrade_container(subsubsubelement, current_service, files, ips, servicelists, upgrade_help) subsubelement.remove(subsubsubelement) if subelement.tag == 'help': if subsubelement.tag == 'variable': if not subsubelement.attrib['name'] in upgrade_help.get('variables', {}).get('remove', []): variables_help[subsubelement.attrib['name']] = subsubelement.text elif subsubelement.tag == 'family': if subsubelement.attrib['name'] not in upgrade_help.get('families', {}).get('remove', []): families_help[subsubelement.attrib['name']] = subsubelement.text else: raise Exception(f'unknown help tag {subsubelement.tag}') subelement.remove(subsubelement) continue if subsubelement.tag == 'auto': if subsubelement.attrib['target'] in upgrade_help.get('variables', {}).get('remove', []): subelement.remove(subsubelement) continue autos.append(subsubelement.attrib['target']) subsubelement.tag = 'fill' if subsubelement.tag in ['fill', 'check']: if subsubelement.tag == 'check' and subsubelement.attrib['name'] == 'valid_enum': if subsubelement.attrib['target'] in upgrade_help.get('variables', {}).get('remove', []): subelement.remove(subsubelement) continue params = [] for param in subsubelement: if param.tag == 'param': params.append(param.text) key = '~'.join(params) if key in valid_enums: SubElement(valid_enums[key], 'target').text = subsubelement.attrib['target'] subelement.remove(subsubelement) continue valid_enums['~'.join(params)] = subsubelement if subsubelement.tag == 'fill' and subsubelement.attrib['target'] in upgrade_help.get('fills', {}).get('remove', []): subelement.remove(subsubelement) continue if subsubelement.tag == 'check' and subsubelement.attrib['target'] in upgrade_help.get('check', {}).get('remove', []): subelement.remove(subsubelement) continue if subsubelement.attrib['target'] in upgrade_help.get('variables', {}).get('remove', []): subelement.remove(subsubelement) continue if subsubelement.attrib['name'] == 'valid_networknetmask': subsubelement.attrib['name'] = 'valid_network_netmask' target = SubElement(subsubelement, 'target') target.text = subsubelement.attrib['target'] if self.test: target.attrib['optional'] = 'True' del subsubelement.attrib['target'] elif subsubelement.tag == 'separators': subelement.remove(subsubelement) elif subsubelement.tag == 'condition': if subsubelement.attrib['source'] in upgrade_help.get('variables', {}).get('remove', []): try: subelement.remove(subsubelement) except: pass else: if subsubelement.attrib['name'] == 'hidden_if_not_in': subsubelement.attrib['name'] = 'disabled_if_not_in' if subsubelement.attrib['name'] == 'hidden_if_in': subsubelement.attrib['name'] = 'disabled_if_in' if subsubelement.attrib['name'] == 'frozen_if_in': subsubelement.attrib['name'] = 'hidden_if_in' self.move(subsubelement, 'fallback', 'optional', optional='True') if subsubelement.attrib['source'] in upgrade_help.get('variables', {}).get('rename', []): subsubelement.attrib['source'] = upgrade_help.get('variables', {}).get('rename', [])[subsubelement.attrib['source']] elif subsubelement.tag == 'group': if subsubelement.attrib['master'] in upgrade_help.get('groups', {}).get('remove', []): subelement.remove(subsubelement) else: self.move(subsubelement, 'master', 'leader') for follower in subsubelement: if '.' in subsubelement.attrib['leader']: path = subsubelement.attrib['leader'].rsplit('.', 1)[0] + '.' + follower.text else: path = follower.text self.remove(variables[path], 'multi', optional=True) if subsubelement.attrib['leader'] in upgrade_help.get('groups', {}).get('reorder', {}): for follower in subsubelement: subsubelement.remove(follower) for follower in upgrade_help.get('groups', {}).get('reorder', {})[subsubelement.attrib['leader']]: SubElement(subsubelement, 'follower').text = follower if subelement.tag == 'files': current_service = self.upgrade_container(subsubelement, current_service, files, ips, servicelists, upgrade_help) subelement.remove(subsubelement) if subsubelement.tag == 'family': self.remove(subsubelement, 'icon', optional=True) if subsubelement.attrib['name'] in upgrade_help.get('families', {}).get('mode', {}).get('remove', []) and 'mode' in subsubelement.attrib: del subsubelement.attrib['mode'] if subsubelement.attrib['name'] in upgrade_help.get('families', {}).get('rename', {}): subsubelement.attrib['name'] = upgrade_help.get('families', {}).get('rename', {})[subsubelement.attrib['name']] if subsubelement.attrib['name'] in upgrade_help.get('families', {}).get('remove', []): subelement.remove(subsubelement) continue if subsubelement.attrib['name'] in upgrade_help.get('families', {}).get('hidden', {}).get('add', []): subsubelement.attrib['hidden'] = 'True' if subsubelement.attrib['name'] != normalize_family(subsubelement.attrib['name']): if "description" not in subsubelement.attrib: subsubelement.attrib['description'] = subsubelement.attrib['name'] subsubelement.attrib['name'] = normalize_family(subsubelement.attrib['name']) families[subsubelement.attrib['name']] = subsubelement # if empty, remove if is_empty(subelement) or subelement.tag in ['containers', 'files', 'help']: root.remove(subelement) continue # copy subelement if subelement.tag == 'constraints': constraints_obj = subelement services = None service_elt = {} for variable, obj in upgrade_help.get('variables', {}).get('add', {}).items(): family = next(iter(families.values())) variables[variable] = SubElement(family, 'variable', name=variable) if 'value' in obj: SubElement(variables[variable], 'value').text = obj['value'] for name in ['hidden', 'exists']: if name in obj: variables[variable].attrib[name] = obj[name] files_is_empty = True for lst in files.values(): if len(lst): files_is_empty = False break if not files_is_empty: services = Element('services') root.insert(0, services) for service_name, lst in files.items(): service = self.create_service(services, service_name, service_elt, servicelists, upgrade_help) for file_ in lst.values(): self.move(file_, 'name_type', 'file_type', optional=True) if 'file_type' in file_.attrib and file_.attrib['file_type'] == 'SymLinkOption': file_.attrib['file_type'] = 'variable' if variables[file_.text].attrib['type'] == 'string': variables[file_.text].attrib['type'] = 'filename' self.remove(file_, 'rm', optional=True) self.remove(file_, 'mkdir', optional=True) service.append(file_) ips_is_empty = True for lst in ips.values(): if len(lst): ips_is_empty = False break if not ips_is_empty: if services is None: services = Element('services') root.insert(0, services) for service_name, lst in ips.items(): service = self.create_service(services, service_name, service_elt, servicelists, upgrade_help) for ip in lst: if ip.text in upgrade_help.get('ips', {}).get('remove', []): continue for type in ['ip_type', 'netmask_type']: if type in ip.attrib and ip.attrib[type] == 'SymLinkOption': ip.attrib[type] = 'variable' if 'netmask' in ip.attrib: if ip.attrib['netmask'] == '255.255.255.255': del ip.attrib['netmask'] if ip.text in variables and 'type' not in variables[ip.text].attrib: variables[ip.text].attrib['type'] = 'ip' else: if ip.text in variables and 'type' not in variables[ip.text].attrib: variables[ip.text].attrib['type'] = 'network' if ip.attrib['netmask'] in variables and 'type' not in variables[ip.attrib['netmask']].attrib: variables[ip.attrib['netmask']].attrib['type'] = 'netmask' elif ip.text in variables and 'type' not in variables[ip.text].attrib: variables[ip.text].attrib['type'] = 'ip' self.remove(ip, 'interface') self.remove(ip, 'interface_type', optional=True) self.remove(ip, 'service_restrictionlist', optional=True) service.append(ip) if ips_is_empty and files_is_empty: for service_name in files: if services is None: services = Element('services') root.insert(0, services) if service_name != 'unknown': self.create_service(services, service_name, service_elt, servicelists, upgrade_help) if constraints_obj is None: constraints_obj = SubElement(root, 'constraints') if variables_auto_valid_enum: for type, variables_valid_enum in variables_auto_valid_enum.items(): valid_enum = SubElement(constraints_obj, 'check') valid_enum.attrib['name'] = 'valid_enum' for val in type.split('/'): param = SubElement(valid_enum, 'param') param.text = val for variable in variables_valid_enum: target = SubElement(valid_enum, 'target') target.text = variable for name, text in variables_help.items(): variables[name].attrib['help'] = text for name, text in families_help.items(): if name in upgrade_help.get('families', {}).get('rename', {}): name = upgrade_help.get('families', {}).get('rename', {})[name] families[normalize_family(name)].attrib['help'] = text for auto in autos: if auto in variables: variables[auto].attrib['hidden'] = 'True' else: # redefine value in first family family = next(iter(families.values())) variable = SubElement(family, 'variable', name=auto, redefine="True", hidden="True") if self.test: del variable.attrib['redefine'] return root @staticmethod def move(elt, src, dst, optional=False): if src == 'text': value = elt.text elt.text = None else: if optional and src not in elt.attrib: return value = elt.attrib[src] del elt.attrib[src] # if dst == 'text': elt.text = value else: elt.attrib[dst] = value @staticmethod def remove(elt, src, optional=False): if optional and src not in elt.attrib: return del elt.attrib[src] @staticmethod def create_service(services, service_name, service_elt, servicelists, upgrade_help): if service_name in service_elt: return service_elt[service_name] service = SubElement(services, 'service') service.attrib['name'] = service_name if service_name == 'unknown': service.attrib['manage'] = 'False' if service_name in upgrade_help.get('services', {}).get('unmanage', []): service.attrib['manage'] = 'False' service_elt[service_name] = service if upgrade_help.get('servicelists', {}).get(service_name): service.attrib['servicelist'] = upgrade_help.get('servicelists', {}).get(service_name) elif service_name in servicelists: service.attrib['servicelist'] = servicelists[service_name] return service def upgrade_container(self, elt, current_service, files, ips, servicelists, upgrade_help): if elt.tag == 'file': self.move(elt, 'name', 'text') self.remove(elt, 'del_comment', optional=True) elt.attrib['engine'] = 'creole_legacy' if (not 'instance_mode' in elt.attrib or elt.attrib['instance_mode'] != 'when_container') and \ elt.text not in upgrade_help.get('files', {}).get('remove', {}): if elt.attrib.get('filelist') in upgrade_help.get('services', {}).get('filelist_service', {}): elt_service = upgrade_help.get('services', {}).get('filelist_service', {})[elt.attrib['filelist']] if elt_service in files: service = elt_service else: service = current_service else: service = current_service files[service][elt.text] = elt elif elt.tag in ['host', 'disknod', 'fstab', 'interface', 'package', 'service_access']: pass elif elt.tag == 'service_restriction': for restriction in elt: if restriction.tag == 'ip' and restriction.text != '0.0.0.0': self.remove(restriction, 'ip_type', optional=True) self.remove(restriction, 'netmask_type', optional=True) if elt.attrib['service'] in upgrade_help.get('services', {}).get('rename', {}): elt_service = upgrade_help.get('services', {}).get('rename', {})[elt.attrib['service']] else: elt_service = elt.attrib['service'] if elt_service in ips: service = elt_service else: service = current_service ips[service].append(restriction) elif elt.tag == 'service': new_name = elt.text if current_service == 'unknown': if new_name in files: raise Exception('hu?') files[new_name] = files[current_service] del files[current_service] ips[new_name] = ips[current_service] del ips[current_service] elif new_name not in files: files[new_name] = {} ips[new_name] = [] current_service = new_name if 'servicelist' in elt.attrib: servicelists[current_service] = elt.attrib['servicelist'] else: raise Exception(f'unknown containers tag {elt.tag}') return current_service def is_empty(elt, not_check_attrib=False): if not not_check_attrib and elt.attrib: return False empty = True for file_ in elt: empty = False return empty def update_creole_1(): print('pfff')