D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
hc_python
/
lib
/
python3.8
/
site-packages
/
pyone
/
Filename :
util.py
back
Copy
# Copyright 2018 www.privaz.io Valletech AB # Copyright 2002-2023, OpenNebula Project, OpenNebula Systems # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import dict2xml import xmltodict from lxml.etree import tostring from collections import OrderedDict from aenum import IntEnum # this is a bit hackish way to avoid escaping <,> characters # by dict2xml, as it would break <!CDATA[]> which is injected before dict2xml.Node.entities = [] TEMPLATE_ALWAYS_LIST_ELEM = ['SNAPSHOT'] def add_cdata(d): ''' recursively traverse nested dict and add xml CDATA element to the leaves ''' if isinstance(d, list): return [ add_cdata(x) for x in d ] elif isinstance(d, dict): return { k: add_cdata(v) for (k,v) in d.items()} else: return f"<![CDATA[{str(d)}]]>" def cast2one(param): ''' This function will cast parameters to make them nebula friendly flat dictionaries will be turned into attribute=value vectors dictionaries with root dictionary will be serialized as XML Structures will be turned into strings before being submitted. :param param: the parameter to make nebula friendly :return: casted parameter ''' def is_nested_dict(dictionary): for val in dictionary.values(): if isinstance(val, dict): return True return False if isinstance(param, IntEnum): # if the param is a constant we return its value return param.value if isinstance(param, dict): # if this is a structured type # in case we passed a dictionary that is part of another if hasattr(param, '_root'): param = param._root # if the dictionary is not empty if bool(param): root = list(param.values())[0] if is_nested_dict(param): # We return this dictionary as XML return dict2xml.dict2xml(add_cdata(param), indent="", newlines=False) else: # We return this dictionary as attribute=value vector ret = u"" for (k, v) in param.items(): ret = u'''%s%s="%s"\n''' % (ret, k, v) return ret else: raise Exception("Cannot cast empty dictionary") else: return param def one2dict(element): ''' This function returns a dictionary from an anyType binding element The dictionary can then be used later as imput for an udpate This is now deprecated, included for backward compatibility. :param element: anyType element to be converted such as TEMLATE or USER_TEMPLATE :return: a dictionary representing the element ''' return element._root def none2emptystr(d): for k,v in d.items(): if type(v) == OrderedDict: none2emptystr(v) elif v == None: d[k] = "" def fix_dict(d, tag): if tag == 'TEMPLATE' and hasattr(d['TEMPLATE'], '__iter__'): tmpl = d['TEMPLATE'] # wrap single entry as a list for elem in TEMPLATE_ALWAYS_LIST_ELEM: if elem in tmpl and type(tmpl[elem]) != list: tmpl[elem] = [ tmpl[elem] ] def child2dict(element): ''' Creates a dictionary from the documentTree obtained from a binding Element. :param element: :return: ''' xml = tostring(element) ret = xmltodict.parse(xml, strip_whitespace=False) # process dict, do ad-hoc fixes fix_dict(ret, element.tag) # get the tag name and remove the ns attribute if present if "}" in element.tag: tagName = element.tag.split('}')[1] del ret[tagName]['@xmlns'] else: tagName = element.tag # Reemplace no-dictionary with empty dictionary if ret[tagName] == None: ret[tagName] = OrderedDict() # Replace 'None' values returned by xmltodict by "" none2emptystr(ret) if not isinstance(ret[tagName], OrderedDict) and isinstance(ret[tagName], dict): ret[tagName] = OrderedDict(ret[tagName]) # return the contents dictionary, but save a reference ret[tagName]._root = ret return ret[tagName] def build_template_node(obj,nodeName,child): ''' Utility function to build an anyType element that can be accessed as a dictionary :param obj: :param nodeName: :param child: :return: ''' if nodeName == "TEMPLATE": obj.TEMPLATE = child2dict(child) return True elif nodeName == "USER_TEMPLATE": obj.USER_TEMPLATE = child2dict(child) return True else: return False class TemplatedType(object): ''' Mixin class for Templated bindings ''' def _buildAttributes(self, node, attrs, already_processed): vars(self)['custom_attrs'] = dict(attrs) def _buildChildren(self, child_, node, nodeName_, fromsubclass_=False, gds_collector_=None): if not build_template_node(self, nodeName_, child_): super(TemplatedType, self)._buildChildren(child_,node,nodeName_,fromsubclass_,gds_collector_)