def _object_information_html_iterator(theCgi): if theCgi.m_entity_type: # WrtAsUtf('m_entity_id: %s<br>'%(theCgi.m_entity_id)) entity_module = lib_util.GetEntityModule(theCgi.m_entity_type) entDoc = entity_module.__doc__ if entDoc: entDoc = entDoc.strip() else: entDoc = "" urlClass = lib_util.EntityClassUrl(theCgi.m_entity_type) urlClass_with_mode = _url_in_html_mode(urlClass) yield ('<table class="table_script_information">') yield (""" <tr> <td><a href='%s'>%s</a></td> <td>%s</td> </tr> """ % (urlClass_with_mode, theCgi.m_entity_type, entDoc)) for dict_property_value in theCgi.m_entity_id_dict.items(): yield ("<tr><td>%s</td><td>%s</td></tr>" % dict_property_value) yield ('</table>')
def Main(): cgiEnv = lib_common.CgiEnv() entity_id = cgiEnv.m_entity_id entity_host = cgiEnv.GetHost() (nameSpace, entity_type, entity_namespace_type) = cgiEnv.GetNamespaceType() grph = cgiEnv.GetGraph() rootNode = lib_util.RootUri() entity_ids_arr = lib_util.EntityIdToArray(entity_type, entity_id) modeDisp = lib_util.GuessDisplayMode() sys.stderr.write("entity_mime.py entity_type=%s modeDisp=%s\n" % (entity_type, modeDisp)) if not entity_type: lib_common.ErrorMessageHtml("entity_mime.py needs an object") entity_module = lib_util.GetEntityModule(entity_type) if not entity_module: lib_common.ErrorMessageHtml( "entity_mime.py entity_type=%s needs a module" % (entity_type)) try: entity_module.DisplayAsMime(grph, rootNode, entity_ids_arr) except: exc = sys.exc_info()[1] sys.stderr.write("entity_mime.py No DisplayAsMime for %s %s: %s\n" % (entity_type, entity_id, str(exc))) lib_common.ErrorMessageHtml( "entity_mime.py No DisplayAsMime for %s %s: %s\n" % (entity_type, entity_id, str(exc)))
def Main(): cgiEnv = lib_common.ScriptEnvironment() entity_id = cgiEnv.m_entity_id name_space, entity_type = cgiEnv.get_namespace_type() grph = cgiEnv.GetGraph() root_node = lib_util.RootUri() entity_ids_arr = lib_util.EntityIdToArray(entity_type, entity_id) mode_disp = lib_util.GuessDisplayMode() logging.debug("entity_type=%s mode_disp=%s", entity_type, mode_disp) if not entity_type: lib_common.ErrorMessageHtml("entity_mime.py needs an object") entity_module = lib_util.GetEntityModule(entity_type) if not entity_module: lib_common.ErrorMessageHtml( "entity_mime.py entity_type=%s needs a module" % entity_type) try: entity_module.DisplayAsMime(grph, root_node, entity_ids_arr) except Exception as exc: lib_common.ErrorMessageHtml( __file__ + " DisplayAsMime fails: %s %s: %s. File=%s.\n" % (entity_type, entity_id, str(exc), entity_module.__file__))
def AddSurvolObjectFromWmi(grph, wmiInstanceNode, connWmi, className, objList): """ Must find the url of the object in the Survol terminoloy equivalent to this one in WMI. This does not care the namespace which is set to root/cimv2 anyway. The reason is that it is the most common one, and the others seem to be used for very technical purpose. """ # The first step is to iterate on the base classes until there is one of the Survol classes. (survolEquivalentClass, ontoKeys) = ImportSurvolModuleFromWmiClass(connWmi, className) # This class nor any of its base classes exists in Survol. if survolEquivalentClass is None: return setSurvolUrls = set() for objWmi in objList: # sys.stderr.write("objWmi=[%s]\n" % str(objWmi) ) propValuesArray = [] # For each property of the survol ontology, picks the value returned by WMI. # Replace missing values by an empty string. for survKey in ontoKeys: try: wmiVal = getattr(objWmi, survKey) except KeyError: sys.stderr.write( "AddSurvolObjectFromWmi className=%s no value for key=%s\n" % (className, survKey)) wmiVal = "" propValuesArray.append(wmiVal) entityModule = lib_util.GetEntityModule(survolEquivalentClass) # Maybe there is a special function for encoding these arguments. try: urlSurvol = entityModule.MakeUri(*propValuesArray) except: # Otherwise, general case. urlSurvol = lib_common.gUriGen.UriMake(survolEquivalentClass, *propValuesArray) setSurvolUrls.add(urlSurvol) # There might potentially be several Survol objects for these several WMI objects. # It depends on the properties, as Survol takes only a subset of them. # Prefixed by hyphens so that it comes first when sorted. propWmi2Survol = lib_common.MakeProp("--Survol equivalent object") for urlSurvol in setSurvolUrls: grph.add((wmiInstanceNode, propWmi2Survol, urlSurvol)) return
def AddInformation(grph, rootNode, entity_id, entity_type): entity_ids_arr = lib_util.EntityIdToArray(entity_type, entity_id) # Each entity type ("process","file" etc... ) can have a small library # of its own, for displaying a rdf node of this type. if entity_type: entity_module = lib_util.GetEntityModule(entity_type) if entity_module: try: # On veut garder uniquement les informations textuelles # qu'on peut afficher dans une table. Et en plus ce doit etre tres rapide. # En fait il faudrait virer rdflib, le remplacer # par un simple container. # On peut se roder en passant un pseudo-grph ? class FilterLiteralRdfGraph: #Init with a genuine rdflib graph. def __init__(self, grph, destNode): self.m_grph = grph self.m_node = destNode # If the information is not a literal, we could display the associated name. # Also, consider recursive tables. def Filter(self, subjRdf, objRdf): return (subjRdf == self.m_node) and lib_kbase.IsLiteral( (objRdf)) # This filters only literal properties which points to or from our node. # This also ensures that theere is one node only, no links, because # of the way json documents are generated. # THE WHOLE SCRIPT MUST BE REPLACED BY A REAL JSON DOCUMENT, # TRANSFORMED INTO HTML. def add(self, trpl): # sys.stderr.write("Trying %s %s %s\n"% trpl) if self.Filter(trpl[0], trpl[2]): # sys.stderr.write("Adding %s %s %s\n"%trpl) self.m_grph.add(trpl) if self.Filter(trpl[2], trpl[0]): # sys.stderr.write("Adding %s %s %s\n"%trpl) self.m_grph.add((trpl[2], trpl[1], trpl[0])) pseudoGraph = FilterLiteralRdfGraph(grph, rootNode) entity_module.AddInfo(pseudoGraph, rootNode, entity_ids_arr) except AttributeError: exc = sys.exc_info()[1] sys.stderr.write("No AddInfo for %s %s: %s\n" % (entity_type, entity_id, str(exc))) else: sys.stderr.write("No lib_entities for %s %s\n" % (entity_type, entity_id))
def Main(): # This can process remote hosts because it calls scripts which can access remote data. I hope. cgiEnv = lib_common.CgiEnv(can_process_remote=True) # entity_type = cgiEnv.m_entity_type (nameSpace, className, entity_type) = cgiEnv.GetNamespaceType() # UNE SEQUENCE QUI NE MARCHE PAS VRAIMENT # http://rchateau-hp:8000/survol/class_type_all.py?xid=CIM_ComputerSystem. OK bien que plein de "Undefined class CIM_ComputerSystem" # http://rchateau-hp:8000/survol/class_wbem.py?xid=http%3A%252F%252F192.168.0.17%3A5988%2FCIM_ComputerSystem. # http://rchateau-hp:8000/survol/class_type_all.py?xid=http%3A%2F%2F192.168.0.17%3A5988%2F%3ACIM_ComputerSystem. # CA NON PLUS: # http://192.168.0.17/Survol/survol/class_type_all.py?xid=http%3A%2F%2F192.168.0.17%3A5988%2Froot%2Fcimv2%3ACIM_Process. # Just in case ... if nameSpace == "/": nameSpace = "" entity_host = cgiEnv.GetHost() entity_id = cgiEnv.m_entity_id # QUERY_STRING=xid=http%3A%2F%2F192.168.1.88%3A5988%2Froot%2FPG_Internal%3APG_WBEMSLPTemplate sys.stderr.write("class_type_all entity_host=%s entity_id=%s\n" % (entity_host, entity_id)) grph = cgiEnv.GetGraph() # TODO: Utiliser la bonne fonction !!! rootNode = lib_util.RootUri() objtypeNode = lib_common.NodeUrl(lib_util.uriRoot + '/objtypes.py') grph.add((rootNode, pc.property_rdf_data_nolist2, objtypeNode)) # This displays the documentation of the Python module of this entity class. entity_module = lib_util.GetEntityModule(className) entDoc = entity_module.__doc__ if entDoc: grph.add((rootNode, pc.property_information, lib_common.NodeLiteral(entDoc))) CreateOurNode(grph, rootNode, entity_host, nameSpace, className, entity_id) # Do this for each intermediary entity type (Between slashes). AddCIMClasses(grph, rootNode, entity_host, nameSpace, className, entity_id) cgiEnv.OutCgiRdf("LAYOUT_RECT_TB")
def directory_usability_error_node(relative_dir, depth_call): # Maybe there is a usability test in the current module. # The goal is to control all scripts in the subdirectories, from here. try: entity_class = ".".join(relative_dir.split("/")[2:]) imported_module = lib_util.GetEntityModule(entity_class) if imported_module: error_msg = _test_usability(imported_module, entity_type, entity_ids_arr) if error_msg: # If set to True, the directory is displayed even if all its script are not usable. return lib_util.NodeLiteral(error_msg) except IndexError: # If we are at the top-level, no interest for the module. pass return None
def _concatenate_entity_documentation(self, full_title, entity_class, entity_id): """This appends to the title, the documentation of the class of the object, if there is one. """ if entity_id: # If there is an object to display. # Practically, we are in the script "entity.py" and the single doc string is "Overview" self.m_page_title += " " + full_title # We assume there is an object, and therefore a class and its description. # Similar code in objtypes.py # This is different of _get_calling_module, which takes the __doc__ of the script. entity_module = lib_util.GetEntityModule(entity_class) ent_doc = entity_module.__doc__ # The convention is the first line treated as a title. if ent_doc: ent_doc = ent_doc.strip() self.m_page_title += "\n" + ent_doc
def Main(): """This should be able to process remote hosts because it calls scripts which can access remote data.""" cgiEnv = lib_common.ScriptEnvironment(can_process_remote=True) name_space, class_name = cgiEnv.get_namespace_type() # If name_space is not provided, it is set to "root/CIMV2" by default. if not class_name: lib_common.ErrorMessageHtml("Class name should not be empty") # Just in case ... if name_space == "/": name_space = "" entity_host = cgiEnv.GetHost() entity_id = cgiEnv.m_entity_id # QUERY_STRING=xid=http%3A%2F%2F192.168.1.88%3A5988%2Froot%2FPG_Internal%3APG_WBEMSLPTemplate logging.debug("class_type_all entity_host=%s entity_id=%s", entity_host, entity_id) grph = cgiEnv.GetGraph() root_node = lib_util.RootUri() objtypeNode = lib_common.NodeUrl(lib_util.uriRoot + '/objtypes.py') grph.add((root_node, pc.property_rdf_data_nolist2, objtypeNode)) # This displays the documentation of the Python module of this entity class. entity_module = lib_util.GetEntityModule(class_name) ent_doc = entity_module.__doc__ if ent_doc: ent_doc = ent_doc.strip() grph.add((root_node, pc.property_information, lib_util.NodeLiteral(ent_doc))) _create_our_node(grph, root_node, entity_host, name_space, class_name, entity_id) # Do this for each intermediary entity type (Between slashes). AddCIMClasses(grph, root_node, entity_host, name_space, class_name, entity_id) cgiEnv.OutCgiRdf("LAYOUT_RECT_TB")
def _add_information(grph, root_node, entity_id, entity_type): """ This returns only literal information which can be displayed in a table. """ entity_ids_arr = lib_util.EntityIdToArray(entity_type, entity_id) # Each entity type ("process","file" etc... ) can have a small library # of its own, for displaying a rdf node of this type. if entity_type: entity_module = lib_util.GetEntityModule(entity_type) if entity_module: try: # On text information are kept. This must be very fast. class FilterLiteralRdfGraph: # Init with a genuine rdflib graph. def __init__(self, grph, destNode): self.m_grph = grph self.m_node = destNode # If the information is not a literal, we could display the associated name. # Also, consider recursive tables. def _filter_subject_object(self, subj_rdf, obj_rdf): return (subj_rdf == self.m_node ) and lib_kbase.IsLiteral(obj_rdf) # This filters only literal properties which points to or from our node. # This also ensures that there is one node only, no links, because json documents generation. # THE WHOLE SCRIPT MUST BE REPLACED BY A REAL JSON DOCUMENT, TRANSFORMED INTO HTML. def add(self, trpl): if self._filter_subject_object(trpl[0], trpl[2]): self.m_grph.add(trpl) if self._filter_subject_object(trpl[2], trpl[0]): self.m_grph.add((trpl[2], trpl[1], trpl[0])) pseudo_graph = FilterLiteralRdfGraph(grph, root_node) entity_module.AddInfo(pseudo_graph, root_node, entity_ids_arr) except AttributeError as exc: logging.error("No AddInfo for %s %s: %s", entity_type, entity_id, str(exc)) else: logging.warning("No lib_entities for %s %s", entity_type, entity_id)
def DirectoryUsabilityErrorNode(relative_dir, depthCall): # Maybe there is a usability test in the current module. # The goal is to control all scripts in the subdirectories, from here. try: entity_class = ".".join(relative_dir.split("/")[2:]) #DirMenuReport( depthCall, "entity_class=%s\n"%(entity_class)) importedMod = lib_util.GetEntityModule(entity_class) if importedMod: errorMsg = TestUsability(importedMod, entity_type, entity_ids_arr) # if flagShowAll and errorMsg ??? if errorMsg: DEBUG("IsDirectoryUsable errorMsg(1)=%s", errorMsg) # If set to True, the directory is displayed even if all its scripts # are not usable. Surprisingly, the message is not displayed as a subdirectory, but in a separate square. return lib_common.NodeLiteral(errorMsg) except IndexError: # If we are at the top-level, no interest for the module. pass return None
def Main(): # This can process remote hosts because it does not call any script, just shows them. cgiEnv = lib_common.ScriptEnvironment( can_process_remote=True, parameters={lib_util.paramkeyShowAll: False}) entity_id = cgiEnv.m_entity_id entity_host = cgiEnv.GetHost() logging.debug("entity_host=%s", entity_host) flag_show_all = int(cgiEnv.get_parameters(lib_util.paramkeyShowAll)) # This optional parameter must not be edited. # It contains the name of an associator, and the associated objects must be displayed. associator_attribute = cgiEnv.get_parameters("__associator_attribute__") logging.debug("associator_attribute=%s", associator_attribute) if associator_attribute and associator_attribute.find(".") <= 0: lib_common.ErrorMessageHtml( "Associator attribute '%s' should be 'associator.role'" % associator_attribute) name_space, entity_type = cgiEnv.get_namespace_type() grph = cgiEnv.GetGraph() root_node = lib_util.RootUri() logging.debug("root_node=%s", root_node) entity_ids_arr = lib_util.EntityIdToArray(entity_type, entity_id) # Each entity type ("process","file" etc... ) can have a small library # of its own, for displaying a rdf node of this type. if entity_type: entity_module = lib_util.GetEntityModule(entity_type) if entity_module: try: entity_module.AddInfo(grph, root_node, entity_ids_arr) except AttributeError as exc: logging.info("No AddInfo for %s %s: %s", entity_type, entity_id, str(exc)) except Exception as exc: logging.info("Unexpected exception for %s %s: %s", entity_type, entity_id, str(exc)) if associator_attribute: # Should we display the associated instances for this associator and role ? lib_associators.add_associated_instances(grph, root_node, entity_type, entity_id, associator_attribute) else: # This behaves as the top-level page, without instances to display. logging.info("No lib_entities for %s %s", entity_type, entity_id) # When displaying in json mode, the scripts are shown with a contextual menu, not with D3 modes.. if lib_util.GuessDisplayMode() not in ["json", "html"]: # This function is called for each script which applies to the given entity. # It receives a triplet: (subject,property,object) and the depth in the tree. # Here, this simply stores the scripts in a graph. The depth is not used yet, # but can help debugging. def callback_grph_add(tripl, depthCall): try: grph.add(tripl) except Exception as exc: logging.error("callback_grph_add: tripl=%s exception=%s" % (str(tripl), str(exc))) raise try: # This displays the scripts associated to this instance. entity_dirmenu_only.recursive_walk_on_scripts( callback_grph_add, root_node, entity_type, entity_id, entity_host, flag_show_all) except Exception as exc: logging.error("Caught in recursive_walk_on_scripts:%s. Trace=%s", exc, traceback.format_exc()) # This adds WBEM and WMI urls related to the current object. # They can display more information about this instance. if entity_type != "": # This solves the case where one of the values of the ontology predicates contains commas. # These commands were quoted, then separated of other arguments by a comma. # TODO: It would be probably be simpler to encode predicates values just like CGI arguments. _add_wbem_wmi_servers(grph, root_node, entity_host, name_space, entity_type, entity_id) _add_default_scripts(grph, root_node, entity_host) # Special case if the current entity we are displaying, is a machine, # we might as well try to connect to its WMI or WBEM server, running on this machine. if entity_type == "CIM_ComputerSystem": _add_default_scripts(grph, root_node, entity_id) _add_default_nodes(grph, root_node, entity_host) cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_directory, pc.property_script])
def Main(): cgiEnv = lib_common.ScriptEnvironment() grph = cgiEnv.GetGraph() sql_query = cgiEnv.m_entity_id_dict["Query"] # TODO: It would be nicer to use a new function CIM_Process.GetEnvArgs. process_id = cgiEnv.m_entity_id_dict["Handle"] node_process_query = embedded_sql_query.MakeUri(sql_query, process_id) # This returns the list of tables and views used by this query. # They will be associated to the databases possibly accessed by this process. # Then, another filtering is possible given the database content etc... # This is still experimental. list_of_tables = lib_sql.TableDependencies(sql_query) prop_type_db = lib_common.MakeProp("Database type") arr_props = [] #listModulesUsingSqlQueries = [ # ("sources_types.oracle","__init__.py"), # ... # ("sources_types.CIM_Process.memory_regex_search","search_connection_strings.py") ... for nam_db_type, script_nam in lib_sql.listModulesUsingSqlQueries: logging.debug("nam_db_type=%s script_nam=%s", nam_db_type, script_nam) # TODO: We should check if the syntax of the query is conformant to the database. # TODO: We should check if the process is linked with this database. module_db_type = lib_util.GetScriptModule(nam_db_type, script_nam) # This removes the ".py" file extension. node_type_db = lib_util.module_doc_string(module_db_type, script_nam[:-3]) # This creates a non-clickable node. TODO: DOES NOT WORK ?? prop_type_this_db = lib_common.MakeProp(nam_db_type) arr_props.append(prop_type_this_db) grph.add((node_process_query, prop_type_db, node_type_db)) try: # Now transforms the list of tables or views into nodes for this database. if not module_db_type: logging.debug("No module for nam_db_type=%s", nam_db_type) continue try: # This returns the possible database credentials for this database type. # This returns also a module name. Maybe a schema, in the future. # "oracle.DatabaseEnvParams()" defined in "oracle/__init__.py" db_tp_env_params = module_db_type.DatabaseEnvParams(process_id) except AttributeError as exc: # Maybe the function is not defined in this module or other error. logging.debug("Caught: %s", str(exc)) continue if not db_tp_env_params: continue query_entity = db_tp_env_params[0] module_query_entity = lib_util.GetEntityModule(query_entity) if not module_query_entity: # Should not happen, otherwise how can we get the parameters for this ? logging.debug("query_entity=%s. No module", query_entity) continue list_args = db_tp_env_params[1] # For example ( "oracle/query", ( { "Db":"XE" } ) ) for connection_kw in list_args: try: list_table_nodes = module_query_entity.QueryToNodesList( connection_kw, list_of_tables) except Exception as exc: logging.warning("query_entity=%s Caught %s", query_entity, str(exc)) continue if not list_table_nodes: logging.debug("No nodes") continue # We know this is a valid query for this connection, so we add a link to it. node_db_query = sql_query_module.MakeUri( sql_query, query_entity, **connection_kw) grph.add((node_type_db, prop_type_this_db, node_db_query)) except Exception as exc: lib_common.ErrorMessageHtml("Unexpected exception:%s" % str(exc)) cgiEnv.OutCgiRdf("LAYOUT_RECT", arr_props)
def UniversalAlias(entity_ids_arr, entity_host, entity_class): entity_module = lib_util.GetEntityModule(entity_class) return entity_module.EntityName(entity_ids_arr)
def DirToMenuAux(callbackGrphAdd,parentNode,curr_dir,relative_dir,entity_type,entity_ids_arr,encodedEntityId,entity_host,flagShowAll,depthCall = 1): # sys.stderr.write("DirToMenuAux entity_host=%s\n"%(entity_host) ) # DirMenuReport( depthCall, "curr_dir=%s relative_dir=%s\n"%(curr_dir,relative_dir)) # In case there is nothing. dirs = None for path, dirs, files in os.walk(curr_dir): break # Maybe this class is not defined in our ontology. if dirs == None: # sys.stderr.write("No content in "+curr_dir) return False # Will still be None if nothing is added. rdfNode = None sub_path = path[ len(curr_dir) : ] relative_dir_sub_path = relative_dir + sub_path argDir = relative_dir_sub_path.replace("/",".")[1:] # Maybe there is a usability test in the current module. # The goal is to control all scripts in the subdirectories, from here. try: entity_class = ".".join( relative_dir.split("/")[2:] ) # DirMenuReport( depthCall, "entity_class=%s\n"%(entity_class)) importedMod = lib_util.GetEntityModule(entity_class) if importedMod: errorMsg = TestUsability(importedMod,entity_type,entity_ids_arr) # if flagShowAll and errorMsg ??? if errorMsg: # If set to True, the directory is displayed even if all its scripts # are not usable. Surprisingly, the message is not displayed as a subdirectory, but in a separate square. if False: callbackGrphAdd( ( parentNode, lib_common.MakeProp("Usability"), lib_common.NodeLiteral(errorMsg) ),depthCall ) return False except IndexError: # If we are at the top-level, no interest for the module. pass containsSomething = False for dir in dirs: # DirMenuReport( depthCall, "dir=%s\n"%(dir)) # Might be generated by our Python interpreter. if dir == "__pycache__": continue full_sub_dir = curr_dir + "/" + dir full_sub_dir = full_sub_dir.replace("\\","/") currDirNode = lib_util.DirDocNode(argDir,dir) if not currDirNode: DirMenuReport( depthCall, "currDirNode NONE: argDir=%s dir=%s\n"%(argDir,dir)) continue sub_relative_dir = relative_dir + "/" + dir sub_entity_class = ".".join( sub_relative_dir.split("/")[2:] ) ontoKeys = lib_util.OntologyClassKeys(sub_entity_class) # DirMenuReport( depthCall, "Checked ontology of %s: ontoKeys=%s\n"%(sub_entity_class,str(ontoKeys))) # TODO: Beware, if not ontology, returns empty array. Why not returning None ? if ontoKeys != []: # DirMenuReport( depthCall, "Module %s has an ontology so it is a class. Skipping\n"%(sub_relative_dir)) # BEWARE: NO MORE DEFAULT ONTOLOGY ["Id"] continue somethingAdded = DirToMenuAux(callbackGrphAdd,currDirNode, full_sub_dir,sub_relative_dir,entity_type,entity_ids_arr,encodedEntityId,entity_host,flagShowAll,depthCall + 1) # This adds the directory name only if it contains a script. if somethingAdded: # CA MARCHE DANS LES DEUX CAS. SI PROPRIETE DIFFERENTE, ON AURA SIMPLEMENT DEUX PAVES, UN POUR LES DIR, L AUTRE POUR LES FICHIERS. # grph.add( ( parentNode, pc.property_directory, currDirNode ) ) callbackGrphAdd( ( parentNode, pc.property_script, currDirNode ), depthCall ) containsSomething = containsSomething | somethingAdded for fil in files: # We want to list only the usable Python scripts. if not fil.endswith(".py") or fil == "__init__.py": continue script_path = relative_dir_sub_path + "/" + fil # DirMenuReport( depthCall, "DirToMenu encodedEntityId=%s\n" % encodedEntityId) if entity_host: genObj = lib_common.RemoteBox(entity_host) else: genObj = lib_common.gUriGen url_rdf = genObj.MakeTheNodeFromScript( script_path, entity_type, encodedEntityId ) errorMsg = None try: importedMod = lib_util.GetScriptModule(argDir, fil) except Exception: errorMsg = sys.exc_info()[1] DirMenuReport( depthCall, "Cannot import=%s. Caught: %s\n" % (script_path, errorMsg ) ) importedMod = None if not flagShowAll: continue if not errorMsg: # Show only scripts which want to be shown. Each script can have an optional function # called Usable(): If it is there and returns False, the script is not displayed. errorMsg = TestUsability(importedMod,entity_type,entity_ids_arr) if not flagShowAll and errorMsg: continue # If the entity is on another host, does this work on remote entities ? if entity_host: try: # Script can be used on a remote entity. can_process_remote = importedMod.CanProcessRemote except AttributeError: can_process_remote = False can_process_remote = True if not can_process_remote: if not errorMsg: errorMsg = "%s is local" % ( entity_host ) DirMenuReport( depthCall, "Script %s %s cannot work on remote entities: %s at %s\n" % ( argDir, fil, encodedEntityId , entity_host ) ) if not flagShowAll: continue # Here, we are sure that the script is added. # TODO: If no script is added, should not add the directory? rdfNode = lib_common.NodeUrl(url_rdf) callbackGrphAdd( ( parentNode, pc.property_script, rdfNode ), depthCall ) # Default doc text is file name minus the ".py" extension. nodModu = lib_util.FromModuleToDoc(importedMod,fil[:-3]) callbackGrphAdd( ( rdfNode, pc.property_information, nodModu ), depthCall ) if errorMsg: callbackGrphAdd( ( rdfNode, lib_common.MakeProp("Error"), lib_common.NodeLiteral(errorMsg) ), depthCall ) # This tells if a script was added in this directory or one of the subdirs. return ( rdfNode is not None ) | containsSomething
def Main(): cgiEnv = lib_common.CgiEnv() grph = cgiEnv.GetGraph() sqlQuery = sql_query.GetEnvArgs(cgiEnv) # TODO: It would be nicer to use a new function CIM_Process.GetEnvArgs. Not urgent. processId = cgiEnv.m_entity_id_dict["Handle"] nodeProcessQuery = embedded_sql_query.MakeUri(sqlQuery,processId) list_of_tables = lib_sql.TableDependencies(sqlQuery) propTypeDb = lib_common.MakeProp("Database type") arrProps = [] #listModulesUsingSqlQueries = [ # ("sources_types.oracle","__init__.py"), # ... # ("sources_types.CIM_Process.memory_regex_search","search_connection_strings.py") ... for ( namDbType, scriptNam ) in lib_sql.listModulesUsingSqlQueries : sys.stderr.write("\nnamDbType=%s scriptNam=%s\n"%(namDbType,scriptNam)) # TODO: We should check if the syntax of the query is conformant to the database. # TODO: We should check if the process is linked with this database. moduleDbType = lib_util.GetScriptModule(namDbType, scriptNam) # This removes the ".py" file extension. nodeTypeDb = lib_util.FromModuleToDoc(moduleDbType,scriptNam[:-3]) # This creates a non-clickable node. TODO: DOES NOT WORK ?? propTypeThisDb = lib_common.MakeProp(namDbType) arrProps.append(propTypeThisDb) grph.add((nodeProcessQuery,propTypeDb,nodeTypeDb)) try: # Now transforms the list of tables or views into nodes for this database. if not moduleDbType: sys.stderr.write("No module for namDbType=%s\n"%namDbType) continue try: # This returns the possible database credentials for this database type. # This returns also a module name. Maybe a schema, in the future. # "oracle.DatabaseEnvParams()" defined in "oracle/__init__.py" dbTp_envParams = moduleDbType.DatabaseEnvParams(processId) except AttributeError: exc = sys.exc_info()[1] # Maybe the function is not defined in this module or other error. sys.stderr.write("Caught: %s\n"%str()) continue if not dbTp_envParams: continue queryEntity = dbTp_envParams[0] moduleQueryEntity = lib_util.GetEntityModule(queryEntity) if not moduleQueryEntity: # Should not happen, otherwise how can we get the parameters for this ? sys.stderr.write("queryEntity=%s. No module\n"%queryEntity) continue listArgs = dbTp_envParams[1] # For example ( "oracle/query", ( { "Db":"XE" } ) ) for connectionKW in listArgs: # sys.stderr.write("queryEntity=%s connectionKW=%s\n"%(queryEntity,connectionKW)) try: # HELAS ON FAIT LE TRAVAIL DEUX FOIS, DE TESTER SI LES SHEETS SONT DES TABLES OU DES VIEWS. # Il faudrait un mode degrade ou on ne fait que tester. # "oracle.query.QueryToNodesList()" defined in "oracle/query/__init__.py" # sys.stderr.write("queryEntity=%s moduleQueryEntity=%s\n"%(queryEntity,str(moduleQueryEntity))) listTableNodes = moduleQueryEntity.QueryToNodesList(sqlQuery,connectionKW,list_of_tables) except Exception: exc = sys.exc_info()[0] sys.stderr.write("queryEntity=%s Caught %s\n"%(queryEntity,str(exc))) continue if not listTableNodes: sys.stderr.write("No nodes\n") continue # We know this is a valid query for this connection, so we add a link to it. # Dans le lien on devra retester si vraiment valide. # C est la ou on voit qu il vaudrait mieux avoir des dict. nodeDbQuery = sql_query.MakeUri(sqlQuery,queryEntity,**connectionKW) grph.add((nodeTypeDb,propTypeThisDb,nodeDbQuery)) except Exception: exc = sys.exc_info()[0] lib_common.ErrorMessageHtml( "Unexpected exception:%s" % ( str(sys.exc_info()))) # cgiEnv.OutCgiRdf() cgiEnv.OutCgiRdf("LAYOUT_RECT",arrProps)
def __init__(self, parameters = {}, can_process_remote = False ): # TODO: This value is read again in OutCgiRdf, we could save time by making this object global. sys.stderr.write( "CgiEnv parameters=%s\n" % ( str(parameters) ) ) # TODO: When running from cgiserver.py, and if QUERY_STRING is finished by a dot ".", this dot # TODO: is removed. Workaround: Any CGI variable added after. # TODO: Also: Several slashes "/" are merged into one. # TODO: Example: "xid=http://192.168.1.83:5988/." becomes "xid=http:/192.168.1.83:5988/" # TODO: ... or "xx.py?xid=smbshr.Id=////WDMyCloudMirror///rchateau" become "xx.py?xid=smbshr.Id=/WDMyCloudMirror/rchateau" # TODO: Replace by "xid=http:%2F%2F192.168.1.83:5988/." # Maybe a bad collapsing of URL ? # sys.stderr.write("QUERY_STRING=%s\n" % os.environ['QUERY_STRING'] ) mode = lib_util.GuessDisplayMode() # Contains the optional arguments, needed by calling scripts. self.m_parameters = parameters self.m_parameterized_links = dict() # When in merge mode, the display parameters must be stored in a place accessible by the graph. docModuAll = GetCallingModuleDoc() # Take only the first non-empty line. See lib_util.FromModuleToDoc() docModuSplit = docModuAll.split("\n") self.m_page_title = docModuSplit[0] # Title page contains __doc__ plus object label. callingUrl = lib_util.RequestUri() self.m_calling_url = callingUrl sys.stderr.write("CgiEnv m_page_title=%s m_calling_url=%s\n"%(self.m_page_title,self.m_calling_url)) parsedEntityUri = lib_naming.ParseEntityUri(callingUrl,longDisplay=False,force_entity_ip_addr=None) if parsedEntityUri[2]: # If there is an object to display. # Practically, we are in the script "entity.py" and the single doc string is "Overview" fullTitle = parsedEntityUri[0] self.m_page_title += " " + fullTitle # We assume there is an object, and therefore a class and its description. entity_class = parsedEntityUri[1] # Similar code in objtypes.py entity_module = lib_util.GetEntityModule(entity_class) entDoc = entity_module.__doc__ # The convention is the first line treated as a title. if entDoc: self.m_page_title += "\n" + entDoc # If we can talk to a remote host to get the desired values. # Global CanProcessRemote has precedence over parameter can_process_remote # whcih should probably be deprecated, although they do not have exactly the same role: # * Global CanProcessRemote is used by entity.py to display scripts which have this capability. # * Parameter can_process_remote is used to inform, at execution time, of this capability. # Many scripts are not enumerated by entity.py so a global CanProcessRemote is not necessary. # For clarity, it might be fine to replace the parameter can_process_remote by the global value. # There cannot be nasty consequences except that some scripts might not be displayed # when they should be, and vice-versa. try: globalCanProcessRemote = globals()["CanProcessRemote"] except KeyError: globalCanProcessRemote = False if can_process_remote != globalCanProcessRemote: # sys.stderr.write("INCONSISTENCY CanProcessRemote\n") # ... which is not an issue. can_process_remote = True self.m_can_process_remote = can_process_remote self.m_arguments = cgi.FieldStorage() (self.m_entity_type,self.m_entity_id,self.m_entity_host) = self.GetXid() sys.stderr.write("CgiEnv m_entity_type=%s m_entity_id=%s m_entity_host=%s\n"%(self.m_entity_type,self.m_entity_id,self.m_entity_host)) self.m_entity_id_dict = lib_util.SplitMoniker(self.m_entity_id) # Depending on the caller module, maybe the arguments should be 64decoded. See "sql/query". # As the entity type is available, it is possible to import it and check if it encodes it arguments. # See presence of source_types.sql.query.DecodeCgiArg(keyWord,cgiArg) for example. # This is probably too generous to indicate a local host. self.TestRemoteIfPossible(can_process_remote) # TODO: HOW WILL WE RESTORE THE ORIGINAL DISPLAY MODE ? if mode == "edit": self.EditionMode()
def CallbackSelect(self, grph, class_name, predicate_prefix, filtered_where_key_values): DEBUG( "SurvolCallbackSelect class_name=%s predicate_prefix=%s where_key_values=%s", class_name, predicate_prefix, str(filtered_where_key_values)) # Maybe there is a script: predicate_prefix="survol:CIM_DataFile/mapping_processes" prefix, colon, script_nickname = predicate_prefix.partition(":") DEBUG("SurvolCallbackSelect script_nickname=%s", script_nickname) if script_nickname: # For example: script_nickname="CIM_DataFile/mapping_processes" # Wildcards or directories are not accepted yet. script_name = "sources_types/" + script_nickname + ".py" DEBUG( "SurvolCallbackSelect script_name=%s filtered_where_key_values=%s", script_name, str(filtered_where_key_values)) # TODO: Check that there are enough parameters for this script ? my_source = lib_client.SourceLocal(script_name, class_name, **filtered_where_key_values) DEBUG("SurvolCallbackSelect my_source=%s", my_source) my_triplestore = my_source.get_triplestore() # This is returned anyway, as a triplestore that rdflib Sparql can work on. my_triplestore.copy_to_graph(grph) list_instances = my_triplestore.get_instances() # TODO: We filter only the objects of the right type, # TODO: ... but we lose all the other objects which could be stored in the output triplestore !!... DEBUG("SurvolCallbackSelect tp=%s class_name=%s", type(list_instances), class_name) DEBUG("SurvolCallbackSelect list_instances=%s", str(list_instances)) for one_instance in list_instances: WARNING( "SurvolCallbackSelect one_instance.__class__.__name__=%s", one_instance.__class__.__name__) if one_instance.__class__.__name__ == class_name: # 'CIM_DataFile.Name=/usr/lib/systemd/systemd-journald' instance_url = one_instance.__class__.__name__ + "." + one_instance.m_entity_id one_instance.m_key_value_pairs[ lib_kbase. PredicateIsDefinedBy] = lib_common.NodeLiteral( predicate_prefix) # Add it again, so the original Sparql query will work. one_instance.m_key_value_pairs[ lib_kbase.PredicateSeeAlso] = lib_common.NodeLiteral( predicate_prefix) DEBUG("SurvolCallbackSelect instance_url=%s", instance_url) yield (instance_url, one_instance.m_key_value_pairs) else: entity_module = lib_util.GetEntityModule(class_name) if not entity_module: raise Exception( "SurvolCallbackSelect: No module for class:%s" % class_name) try: enumerate_function = entity_module.SelectFromWhere except AttributeError: exc = sys.exc_info()[1] WARNING("No Enumerate for %s:%s", class_name, str(exc)) return iter_enumeration = enumerate_function(filtered_where_key_values) # for one_key_value_dict in iter_enumeration: for one_key_value_dict_nodes in iter_enumeration: class_ontology = lib_util.OntologyClassKeys(class_name) ontology_key_values = {} for key_node, value_node in one_key_value_dict_nodes.items(): key_str = lib_properties.PropToQName(key_node) if key_str in class_ontology: ontology_key_values[key_str] = str(value_node) # This reorders the attributes if needed. key_value_path = lib_util.KWArgsToEntityId( class_name, **ontology_key_values) # key_value_path = ".".join( '%s="%s"' % ( lib_properties.PropToQName(key), str(value) ) for key, value in one_key_value_dict_nodes.items() ) object_path = "SurvolLocalHost:" + class_name + "." + key_value_path one_key_value_dict_nodes[ lib_kbase.PredicateIsDefinedBy] = lib_common.NodeLiteral( predicate_prefix) # Add it again, so the original Sparql query will work. one_key_value_dict_nodes[ lib_kbase.PredicateSeeAlso] = lib_common.NodeLiteral( predicate_prefix) yield (object_path, one_key_value_dict_nodes)
def Main(): # This can process remote hosts because it does not call any script, just shows them. cgiEnv = lib_common.CgiEnv(can_process_remote=True, parameters={lib_util.paramkeyShowAll: False}) entity_id = cgiEnv.m_entity_id entity_host = cgiEnv.GetHost() flagShowAll = int(cgiEnv.GetParameters(lib_util.paramkeyShowAll)) (nameSpace, entity_type, entity_namespace_type) = cgiEnv.GetNamespaceType() grph = cgiEnv.GetGraph() rootNode = lib_util.RootUri() entity_ids_arr = lib_util.EntityIdToArray(entity_type, entity_id) # entity_info_only.AddInformation(grph,rootNode,entity_id, entity_type) # Each entity type ("process","file" etc... ) can have a small library # of its own, for displaying a rdf node of this type. if entity_type: entity_module = lib_util.GetEntityModule(entity_type) if entity_module: try: entity_module.AddInfo(grph, rootNode, entity_ids_arr) except AttributeError: exc = sys.exc_info()[1] sys.stderr.write("No AddInfo for %s %s: %s\n" % (entity_type, entity_id, str(exc))) else: sys.stderr.write("No lib_entities for %s %s\n" % (entity_type, entity_id)) # When displaying in json mode, the scripts are shown with a contextual menu, not with D3 modes.. if lib_util.GuessDisplayMode() not in ["json", "html"]: # This function is called for each script which applies to the given entity. # It receives a triplet: (subject,property,object) and the depth in the tree. # Here, this simply stores the scripts in a graph. The depth is not used yet, # but can help debugging. def CallbackGrphAdd(tripl, depthCall): grph.add(tripl) entity_dirmenu_only.DirToMenu(CallbackGrphAdd, rootNode, entity_type, entity_id, entity_host, flagShowAll) # This adds WBEM and WMI urls related to the current object. if entity_type != "": CIM_ComputerSystem.AddWbemWmiServers(grph, rootNode, entity_host, nameSpace, entity_type, entity_id) AddDefaultScripts(grph, rootNode, entity_host) # Special case if the currententity we are displaying, is a machine, # we might as well try to connect to its WMI or WBEM server, running on this machine. if entity_type == "CIM_ComputerSystem": AddDefaultScripts(grph, rootNode, entity_id) AddDefaultNodes(grph, rootNode, entity_host) cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_directory, pc.property_script])
def WriteScriptInformation(theCgi, gblCgiEnvList): """ This displays general information about this script and the object if there is one. """ sys.stderr.write("WriteScriptInformation entity_type=%s\n" % (theCgi.m_entity_type)) # This is already called in lib_common, when creating CgiEnv. # It does not matter because this is very fast. callingUrl = lib_util.RequestUri() (entity_label, entity_graphic_class, entity_id) = lib_naming.ParseEntityUri(callingUrl, longDisplay=True) sys.stderr.write("entity_label=%s entity_graphic_class=%s entity_id=%s\n" % (entity_label, entity_graphic_class, entity_id)) # WrtAsUtf('<table class="list_of_merged_scripts">') WrtAsUtf('<table border="0">') if len(gblCgiEnvList): sys.stderr.write("gblCgiEnvList=%s\n" % str(gblCgiEnvList)) # This step is dedicated to the merging of several scripts. WrtAsUtf( "<tr align=left><td colspan=2 align=left><h2>Fusion of data from %d scripts</h2></td></tr>" % len(gblCgiEnvList)) for aCgiEnv in gblCgiEnvList: sys.stderr.write("aCgiEnv=%s\n" % str(aCgiEnv)) sys.stderr.write("aCgiEnv.m_page_title=%s\n" % str(aCgiEnv.m_page_title)) sys.stderr.write("aCgiEnv.m_calling_url=%s\n" % str(aCgiEnv.m_calling_url)) (page_title_first, page_title_rest) = lib_util.SplitTextTitleRest( aCgiEnv.m_page_title) WrtAsUtf( "<tr><td><a href='%s'>%s</td><td><i>%s</i></td></tr>" % (aCgiEnv.m_calling_url, page_title_first, page_title_rest)) else: (page_title_first, page_title_rest) = lib_util.SplitTextTitleRest(theCgi.m_page_title) WrtAsUtf("<tr><td colspan=2><h2>%s</h2></td></tr>" % (page_title_first)) if page_title_rest: WrtAsUtf("<tr><td colspan=2>%s</td></tr>" % (page_title_rest)) WrtAsUtf('</table>') if theCgi.m_entity_type: # WrtAsUtf('m_entity_id: %s<br>'%(theCgi.m_entity_id)) WrtAsUtf('<table class="table_script_information">') entity_module = lib_util.GetEntityModule(theCgi.m_entity_type) entDoc = entity_module.__doc__ if not entDoc: entDoc = "" urlClass = lib_util.EntityClassUrl(theCgi.m_entity_type) urlClass_with_mode = UrlInHtmlMode(urlClass) WrtAsUtf(""" <tr> <td><a href='%s'>%s</a></td> <td>%s</td> </tr> """ % (urlClass_with_mode, theCgi.m_entity_type, entDoc)) for keyProp in theCgi.m_entity_id_dict: keyVal = theCgi.m_entity_id_dict[keyProp] WrtAsUtf(""" <tr> <td>%s</td> <td>%s</td> </tr> """ % (keyProp, keyVal)) WrtAsUtf('</table>')