def __init__( self, yang_content=None, yang_file_path=None, search_path=None, doctype="config", keep_tmp_files=False, ): self._yang_file_path = yang_file_path self._yang_content = yang_content self._doctype = doctype self._keep_tmp_files = keep_tmp_files self._pyang_exec_path = find_file_in_path("pyang") self._plugindir = unfrackpath(YANG_SPEC_DIR_PATH) makedirs_safe(self._plugindir) if search_path is None: if yang_file_path: search_path = os.path.dirname(yang_file_path) else: search_path = YANG_SPEC_DIR_PATH if yang_file_path is None: content_tmp_file_path = os.path.join( YANG_SPEC_DIR_PATH, "%s.%s" % (str(uuid.uuid4()), "yang") ) content_tmp_file_path = os.path.realpath( os.path.expanduser(content_tmp_file_path) ) with open(content_tmp_file_path, 'w') as opened_file: opened_file.write(yang_content) self._yang_file_path = content_tmp_file_path self._search_path = search_path
def _set_pyang_executables(self): if not HAS_PYANG: raise ValueError(missing_required_lib("pyang")) if not HAS_LXML: raise ValueError(missing_required_lib("lxml")) base_pyang_path = sys.modules["pyang"].__file__ self._pyang_exec_path = find_file_in_path("pyang") self._pyang_module = load_from_source(self._pyang_exec_path, "pyang") sys.modules["pyang"].__file__ = base_pyang_path
def __init__( self, yang_content=None, yang_file_path=None, search_path=None, doctype="config", keep_tmp_files=False, tmp_dir_path=YANG_SPEC_DIR_PATH, ): if not HAS_PYANG: raise ImportError(missing_required_lib("pyang")) yang_file_path = to_list(yang_file_path) if yang_file_path else [] self._yang_file_path = [] self._yang_content = yang_content self._doctype = doctype self._keep_tmp_files = keep_tmp_files self._pyang_exec_path = find_file_in_path("pyang") self._tmp_dir_path = tmp_dir_path self._handle_yang_file_path(yang_file_path) self._handle_search_path(search_path)
def json_to_xml(self, json_data): """ The method translates JSON data encoded as per YANG model (RFC 7951) to XML payload :param json_data: JSON data that should to translated to XML :return: XML data in string format. """ saved_arg = deepcopy(sys.argv) saved_stdout = sys.stdout saved_stderr = sys.stderr sys.stdout = sys.stderr = StringIO() plugin_instance = str(uuid.uuid4()) plugindir = unfrackpath(JSON2XML_DIR_PATH) makedirs_safe(plugindir) makedirs_safe(os.path.join(plugindir, plugin_instance)) jtox_file_path = os.path.join( JSON2XML_DIR_PATH, plugin_instance, "%s.%s" % (str(uuid.uuid4()), "jtox"), ) xml_file_path = os.path.join( JSON2XML_DIR_PATH, plugin_instance, "%s.%s" % (str(uuid.uuid4()), "xml"), ) jtox_file_path = os.path.realpath(os.path.expanduser(jtox_file_path)) xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path)) yang_metada_dir = os.path.join( os.path.dirname(os.path.abspath(__file__)), "files/yang") yang_metadata_path = os.path.join(yang_metada_dir, "nc-op.yang") self._search_path += ":%s" % yang_metada_dir # fill in the sys args before invoking pyang sys.argv = ([ self._pyang_exec_path, "-f", "jtox", "-o", jtox_file_path, "-p", self._search_path, "--lax-quote-checks", ] + self._yang_files + [yang_metadata_path]) try: self._pyang_exec.run() except SystemExit: pass except Exception as e: temp_dir = os.path.join(JSON2XML_DIR_PATH, plugin_instance) shutil.rmtree( os.path.realpath(os.path.expanduser(temp_dir)), ignore_errors=True, ) raise AnsibleError( "Error while generating intermediate (jtox) file: %s" % e) finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: temp_dir = os.path.join(JSON2XML_DIR_PATH, plugin_instance) shutil.rmtree( os.path.realpath(os.path.expanduser(temp_dir)), ignore_errors=True, ) raise AnsibleError( "Error while generating intermediate (jtox) file: %s" % err) json2xml_exec_path = find_file_in_path("json2xml") json2xml_exec = imp.load_source("json2xml", json2xml_exec_path) # fill in the sys args before invoking json2xml sys.argv = [ json2xml_exec_path, "-t", self._doctype, "-o", xml_file_path, jtox_file_path, json_data, ] try: json2xml_exec.main() with open(xml_file_path, "r+") as fp: content = fp.read() except SystemExit: pass finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: temp_dir = os.path.join(JSON2XML_DIR_PATH, plugin_instance) shutil.rmtree( os.path.realpath(os.path.expanduser(temp_dir)), ignore_errors=True, ) raise AnsibleError("Error while translating to xml: %s" % err) sys.argv = saved_arg sys.stdout = saved_stdout sys.stderr = saved_stderr try: content = re.sub(r"<\? ?xml .*\? ?>", "", content) root = etree.fromstring(content) except Exception as e: raise AnsibleError("Error while reading xml document: %s" % e) finally: if not self._keep_tmp_files: temp_dir = os.path.join(JSON2XML_DIR_PATH, plugin_instance) shutil.rmtree( os.path.realpath(os.path.expanduser(temp_dir)), ignore_errors=True, ) return etree.tostring(root)
def _set_pyang_executables(self): base_pyang_path = sys.modules["pyang"].__file__ self._pyang_exec_path = find_file_in_path("pyang") self._pyang_exec = imp.load_source("pyang", self._pyang_exec_path) sys.modules["pyang"].__file__ = base_pyang_path
def xml_to_json(self, xml_data): """ The method translates XML data to JSON data encoded as per YANG model (RFC 7951) :param xml_data: XML data or file path containing xml data that should to translated to JSON :return: data in JSON format. """ plugindir = unfrackpath(XM2JSONL_DIR_PATH) makedirs_safe(plugindir) if os.path.isfile(xml_data): # input is xml file path xml_file_path = os.path.realpath(os.path.expanduser(xml_data)) else: # input is xml string, copy it to file in temporary location xml_file_path = os.path.join(XM2JSONL_DIR_PATH, "%s.%s" % (str(uuid.uuid4()), "xml")) xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path)) with open(xml_file_path, "w") as f: if not xml_data.startswith("<?xml version"): xml_data = ('<?xml version="1.0" encoding="UTF-8"?>\n' + xml_data) data = xml_data f.write(data) xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path)) try: # validate xml etree.parse(xml_file_path) display.vvvv("Parsing xml data from temporary file: %s" % xml_file_path) except Exception as exc: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True, ) raise AnsibleError("Failed to load xml data: %s" % (to_text(exc, errors="surrogate_or_strict"))) base_pyang_path = sys.modules["pyang"].__file__ pyang_exec_path = find_file_in_path("pyang") pyang_exec = imp.load_source("pyang", pyang_exec_path) saved_arg = deepcopy(sys.argv) sys.modules["pyang"].__file__ = base_pyang_path saved_stdout = sys.stdout saved_stderr = sys.stderr sys.stdout = sys.stderr = StringIO() xsl_file_path = os.path.join(XM2JSONL_DIR_PATH, "%s.%s" % (str(uuid.uuid4()), "xsl")) json_file_path = os.path.join(XM2JSONL_DIR_PATH, "%s.%s" % (str(uuid.uuid4()), "json")) xls_file_path = os.path.realpath(os.path.expanduser(xsl_file_path)) json_file_path = os.path.realpath(os.path.expanduser(json_file_path)) # fill in the sys args before invoking pyang sys.argv = [ pyang_exec_path, "-f", "jsonxsl", "-o", xls_file_path, "-p", self._search_path, "--lax-quote-checks", ] + self._yang_files display.display( "Generating xsl file '%s' by executing command '%s'" % (xls_file_path, " ".join(sys.argv)), log_only=True, ) try: pyang_exec.run() except SystemExit: pass except Exception as e: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True, ) raise AnsibleError( "Error while generating intermediate (xsl) file: %s" % e) finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: shutil.rmtree( os.path.realpath( os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True, ) raise AnsibleError( "Error while generating (xsl) intermediate file: %s" % err) xsltproc_exec_path = find_file_in_path("xsltproc") # fill in the sys args before invoking xsltproc sys.argv = [ xsltproc_exec_path, "-o", json_file_path, xsl_file_path, xml_file_path, ] display.display( "Generating json data in temp file '%s' by executing command '%s'" % (json_file_path, " ".join(sys.argv)), log_only=True, ) time.sleep(5) try: os.system(" ".join(sys.argv)) except SystemExit: pass finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: shutil.rmtree( os.path.realpath( os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True, ) raise AnsibleError("Error while translating to json: %s" % err) sys.argv = saved_arg sys.stdout = saved_stdout sys.stderr = saved_stderr try: display.vvvv("Reading output json data from temporary file: %s" % json_file_path) with open(json_file_path, "r") as fp: raw_content = fp.read() content = json.loads(raw_content) except Exception as e: raise AnsibleError( "Error while reading json document %s with content %s" % (e, raw_content)) finally: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(XM2JSONL_DIR_PATH)), ignore_errors=True, ) return content
def xml_to_json(self, xml_data, tmp_dir_path): """ The method translates XML data to JSON data encoded as per YANG model (RFC 7951) :param xml_data: XML data or file path containing xml data that should to translated to JSON :param tmp_dir_path: Temporary directory path to copy intermediate files :return: data in JSON format. """ try: etree.fromstring(xml_data) # input is xml string, copy it to file in temporary location xml_file_path = os.path.join(tmp_dir_path, "%s.%s" % (str(uuid.uuid4()), "xml")) xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path)) with open(xml_file_path, "w") as f: if not xml_data.startswith("<?xml version"): xml_data = ('<?xml version="1.0" encoding="UTF-8"?>\n' + xml_data) data = xml_data f.write(data) except etree.XMLSyntaxError: if os.path.isfile(xml_data): # input is xml file path xml_file_path = os.path.realpath(os.path.expanduser(xml_data)) else: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError("Unable to create file or read XML data %s" % xml_data) xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path)) if os.path.isfile(xml_data): try: # validate xml etree.parse(xml_file_path) if self._debug: self._debug("Parsing xml data from temporary file: %s" % xml_file_path) except Exception as exc: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError("Failed to load xml data: %s" % (to_text(exc, errors="surrogate_or_strict"))) base_pyang_path = sys.modules["pyang"].__file__ pyang_exec_path = find_file_in_path("pyang") saved_arg = deepcopy(sys.argv) sys.modules["pyang"].__file__ = base_pyang_path saved_stdout = sys.stdout saved_stderr = sys.stderr sys.stdout = sys.stderr = StringIO() jsonxsl_relative_dirpath = os.path.join("yang", "xslt") jsonxsl_dir_path = find_share_path( os.path.join(jsonxsl_relative_dirpath, "jsonxsl-templates.xsl")) if jsonxsl_dir_path is None: raise ValueError( "Could not find jsonxsl-templates.xsl in environment path") os.environ["PYANG_XSLT_DIR"] = os.path.join(jsonxsl_dir_path, jsonxsl_relative_dirpath) xsl_file_path = os.path.join(tmp_dir_path, "%s.%s" % (str(uuid.uuid4()), "xsl")) json_file_path = os.path.join(tmp_dir_path, "%s.%s" % (str(uuid.uuid4()), "json")) xls_file_path = os.path.realpath(os.path.expanduser(xsl_file_path)) json_file_path = os.path.realpath(os.path.expanduser(json_file_path)) # fill in the sys args before invoking pyang sys.argv = [ pyang_exec_path, "-f", "jsonxsl", "-o", xls_file_path, "-p", self._search_path, "--lax-quote-checks", ] + self._yang_files if self._debug: self._debug("Generating xsl file '%s' by executing command '%s'" % (xls_file_path, " ".join(sys.argv))) try: self._pyang_module.run() except SystemExit: pass except Exception as e: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError( "Error while generating intermediate (xsl) file: %s" % e) finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError( "Error while generating (xsl) intermediate file: %s" % err) xsltproc_exec_path = find_file_in_path("xsltproc") if not xsltproc_exec_path: raise ValueError( "xsltproc executable not found." " Install 'libxml2-dev' and 'libxslt-dev' packages") # fill in the sys args before invoking xsltproc sys.argv = [ xsltproc_exec_path, "-o", json_file_path, xsl_file_path, xml_file_path, ] if self._debug: self._debug( "Generating json data in temp file '%s' by executing command '%s'" % (json_file_path, " ".join(sys.argv))) time.sleep(5) try: os.system(" ".join(sys.argv)) except SystemExit: pass finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError("Error while translating to json: %s" % err) sys.argv = saved_arg sys.stdout = saved_stdout sys.stderr = saved_stderr try: if self._debug: self._debug( "Reading output json data from temporary file: %s" % json_file_path) with open(json_file_path, "r") as fp: raw_content = fp.read() content = json.loads(raw_content) except Exception as e: raise ValueError( "Error while reading json document %s from path %s" % (e, json_file_path)) finally: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) return content
def json_to_xml(self, json_data, tmp_dir_path): """ The method translates JSON data encoded as per YANG model (RFC 7951) to XML payload :param json_data: JSON data that should to translated to XML :param tmp_dir_path: Temporary directory path to copy intermediate files :return: XML data in string format. """ saved_arg = deepcopy(sys.argv) saved_stdout = sys.stdout saved_stderr = sys.stderr sys.stdout = sys.stderr = StringIO() if isinstance(json_data, dict): # input is in json format, copy it to file in temporary location json_file_path = os.path.join( tmp_dir_path, "%s.%s" % (str(uuid.uuid4()), "json")) json_file_path = os.path.realpath( os.path.expanduser(json_file_path)) with open(json_file_path, "w") as f: f.write(json.dumps(json_data)) json_file_path = os.path.realpath( os.path.expanduser(json_file_path)) elif os.path.isfile(json_data): json_file_path = json_data else: raise ValueError("unable to create/find temporary json file %s" % json_data) try: # validate json with open(json_file_path) as fp: json.load(fp) except Exception as exc: raise ValueError("Failed to load json configuration: %s" % (to_text(exc, errors="surrogate_or_strict"))) jtox_file_path = os.path.join(tmp_dir_path, "%s.%s" % (str(uuid.uuid4()), "jtox")) xml_file_path = os.path.join(tmp_dir_path, "%s.%s" % (str(uuid.uuid4()), "xml")) jtox_file_path = os.path.realpath(os.path.expanduser(jtox_file_path)) xml_file_path = os.path.realpath(os.path.expanduser(xml_file_path)) yang_metada_dir = os.path.join( os.path.dirname(os.path.abspath(__file__)), "files/yang") yang_metadata_path = os.path.join(yang_metada_dir, "nc-op.yang") self._search_path += ":%s" % yang_metada_dir # fill in the sys args before invoking pyang sys.argv = ([ self._pyang_exec_path, "-f", "jtox", "-o", jtox_file_path, "-p", self._search_path, "--lax-quote-checks", ] + self._yang_files + [yang_metadata_path]) if self._debug: self._debug("Generating jtox file '%s' by executing command '%s'" % (jtox_file_path, " ".join(sys.argv))) try: self._pyang_module.run() except SystemExit: pass except Exception as e: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError( "Error while generating intermediate (jtox) file: %s" % e) finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError( "Error while generating intermediate (jtox) file: %s" % err) json2xml_exec_path = find_file_in_path("json2xml") json2xml_module = load_from_source(json2xml_exec_path, "json2xml") # fill in the sys args before invoking json2xml sys.argv = [ json2xml_exec_path, "-t", self._doctype, "-o", xml_file_path, jtox_file_path, json_file_path, ] if self._debug: self._debug("Generating xml file '%s' by executing command '%s'" % (xml_file_path, " ".join(sys.argv))) try: json2xml_module.main() with open(xml_file_path, "r+") as fp: b_content = fp.read() content = to_text(b_content, errors="surrogate_or_strict") except UnicodeError as uni_error: raise ValueError("Error while translating to text: %s" % str(uni_error)) except SystemExit: pass finally: err = sys.stderr.getvalue() if err and "error" in err.lower(): if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) raise ValueError("Error while translating to xml: %s" % err) sys.argv = saved_arg sys.stdout = saved_stdout sys.stderr = saved_stderr try: content = re.sub(r"<\? ?xml .*\? ?>", "", content) root = etree.fromstring(content) except Exception as e: raise ValueError("Error while reading xml document: %s" % e) finally: if not self._keep_tmp_files: shutil.rmtree( os.path.realpath(os.path.expanduser(tmp_dir_path)), ignore_errors=True, ) return etree.tostring(root).decode("utf-8")