Ejemplo n.º 1
0
def AddCIMClasses(grph, rootNode, entity_host, nameSpace, className,
                  entity_id):
    # Maybe some of these servers are not able to display anything about this object.

    pairNameNodeWbem = None
    if wbemOk:
        if lib_wbem.ValidClassWbem(entity_host, className):
            pairNameNodeWbem = CreateWbemNode(grph, rootNode, entity_host,
                                              nameSpace, className, entity_id)

    pairNameNodeWmi = None
    if lib_wmi.ValidClassWmi(className):
        pairNameNodeWmi = CreateWmiNode(grph, rootNode, entity_host, nameSpace,
                                        className, entity_id)

    # Match the two inheritance trees.
    if pairNameNodeWbem and pairNameNodeWmi:
        for (baseClsNam, nodeWbem) in lib_util.six_iteritems(pairNameNodeWbem):
            try:
                nodeWmi = pairNameNodeWmi[baseClsNam]
            except KeyError:
                continue

            nodeClsAll = lib_util.EntityClassNode(baseClsNam, nameSpace,
                                                  entity_host, "WBEM ou WMI")
            grph.add((nodeClsAll, pc.property_wbem_data, nodeWbem))
            grph.add((nodeClsAll, pc.property_wmi_data, nodeWmi))
Ejemplo n.º 2
0
def _draw_from_this_base(root_node, wmi_namespace, cimom_url, cls_nam, grph,
                         cls_deriv):
    global _done_node
    wmi_node = _class_to_node(wmi_namespace, cimom_url, cls_nam)

    # The class is the starting point when displaying the class tree of the namespace.
    wmi_node_sub = _wmi_namespace_node(wmi_namespace, cimom_url, cls_nam)
    grph.add((wmi_node, pc.property_rdf_data_nolist1, wmi_node_sub))

    node_generalised_class = lib_util.EntityClassNode(cls_nam, wmi_namespace,
                                                      cimom_url, "WMI")
    grph.add((wmi_node, pc.property_rdf_data_nolist2, node_generalised_class))
    grph.add((wmi_node, pc.property_information, rdflib.Literal(cls_nam)))

    _done_node.add(cls_nam)

    previous_node = wmi_node

    # TODO: Collapse the two case into one, for cleanliness.
    if len(cls_deriv) == 0:
        grph.add((root_node, pc.property_cim_subclass, previous_node))
    else:
        for base_class_nam in cls_deriv:

            wmi_base_node = _class_to_node(wmi_namespace, cimom_url,
                                           base_class_nam)

            grph.add((wmi_base_node, pc.property_cim_subclass, previous_node))
            grph.add((wmi_base_node, pc.property_information,
                      rdflib.Literal(base_class_nam)))
            previous_node = wmi_base_node
            if base_class_nam in _done_node:
                break

            _done_node.add(base_class_nam)
Ejemplo n.º 3
0
def Main():
    # TODO: can_process_remote should be suppressed because it duplicates CanProcessRemote
    cgiEnv = lib_common.CgiEnv(can_process_remote=True)
    pid = int(cgiEnv.GetId())
    machine_name = cgiEnv.GetHost()

    grph = cgiEnv.GetGraph()

    cimom_url = lib_wbem.HostnameToWbemServer(machine_name)

    DEBUG(
        "wbem_process_info.py currentHostname=%s pid=%d machine_name=%s cimom_url=%s",
        lib_util.currentHostname, pid, machine_name, cimom_url)

    conn_wbem = lib_wbem.WbemConnection(cimom_url)

    name_space = "root/cimv2"
    try:
        inst_lists = conn_wbem.ExecQuery(
            "WQL", 'select * from CIM_Process  where Handle="%s"' % pid,
            name_space)
    except:
        lib_common.ErrorMessageHtml("Error:" + str(sys.exc_info()))

    class_name = "CIM_Process"
    dict_props = {"Handle": pid}

    root_node = lib_util.EntityClassNode(class_name, name_space, cimom_url,
                                         "WBEM")

    # There should be only one object, hopefully.
    for an_inst in inst_lists:
        dict_inst = dict(an_inst)

        host_only = lib_util.EntHostToIp(cimom_url)
        if lib_util.IsLocalAddress(host_only):
            uri_inst = lib_common.gUriGen.UriMakeFromDict(
                class_name, dict_props)
        else:
            uri_inst = lib_common.RemoteBox(host_only).UriMakeFromDict(
                class_name, dict_props)

        grph.add((root_node, lib_common.MakeProp(class_name), uri_inst))

        url_namespace = lib_wbem.NamespaceUrl(name_space, cimom_url,
                                              class_name)
        nod_namespace = lib_common.NodeUrl(url_namespace)
        grph.add((root_node, pc.property_cim_subnamespace, nod_namespace))

        # None properties are not printed.
        for iname_key in dict_inst:
            iname_val = dict_inst[iname_key]
            # TODO: If this is a reference, create a Node !!!!!!!
            if not iname_val is None:
                grph.add((uri_inst, lib_common.MakeProp(iname_key),
                          lib_common.NodeLiteral(iname_val)))

        # TODO: Call the method Associators(). Idem References().

    cgiEnv.OutCgiRdf()
Ejemplo n.º 4
0
def DrawFromThisBase(rootNode, wmiNamespace, cimomUrl, clsNam, grph, clsDeriv):
    global doneNode
    wmiNode = ClassToNode(wmiNamespace, cimomUrl, clsNam)

    # The class is the starting point when displaying the class tree of the namespace.
    wmiNodeSub = WmiNamespaceNode(wmiNamespace, cimomUrl, clsNam)
    grph.add((wmiNode, pc.property_rdf_data_nolist1, wmiNodeSub))

    nodeGeneralisedClass = lib_util.EntityClassNode(clsNam, wmiNamespace,
                                                    cimomUrl, "WMI")
    grph.add((wmiNode, pc.property_rdf_data_nolist2, nodeGeneralisedClass))

    doneNode.add(clsNam)

    previousNode = wmiNode

    # TODO: Collapse the two case into one, for cleanliness.
    if len(clsDeriv) == 0:
        grph.add((rootNode, pc.property_cim_subclass, previousNode))
    else:
        # sys.stderr.write("clsNam=%s clsDeriv=%s\n" % ( clsNam, str(clsDeriv) ))
        for baseClassNam in clsDeriv:

            wmiBaseNode = ClassToNode(wmiNamespace, cimomUrl, baseClassNam)

            grph.add((wmiBaseNode, pc.property_cim_subclass, previousNode))
            previousNode = wmiBaseNode
            if baseClassNam in doneNode:
                break

            doneNode.add(baseClassNam)
Ejemplo n.º 5
0
def AddCIMClasses(grph, root_node, entity_host, name_space, class_name,
                  entity_id):
    """entity_type = "CIM_Process", "Win32_Service" etc...
    This might happen at an intermediary level, with inheritance (To be implemented).
    Maybe some of these servers are not able to display anything about this object."""

    pair_name_node_wbem = None
    if wbem_ok:
        if lib_wbem.ValidClassWbem(class_name):
            pair_name_node_wbem = _create_wbem_node(grph, root_node,
                                                    entity_host, name_space,
                                                    class_name, entity_id)

    pair_name_node_wmi = None
    if lib_wmi.ValidClassWmi(class_name):
        pair_name_node_wmi = _create_wmi_node(grph, root_node, entity_host,
                                              name_space, class_name,
                                              entity_id)

    # Match the two inheritance trees.
    if pair_name_node_wbem and pair_name_node_wmi:
        for base_cls_nam, node_wbem in lib_util.six_iteritems(
                pair_name_node_wbem):
            try:
                nodeWmi = pair_name_node_wmi[base_cls_nam]
            except KeyError:
                continue

            node_cls_all = lib_util.EntityClassNode(base_cls_nam, name_space,
                                                    entity_host, "WBEM ou WMI")
            grph.add((node_cls_all, pc.property_wbem_data, node_wbem))
            grph.add((node_cls_all, pc.property_wmi_data, nodeWmi))
Ejemplo n.º 6
0
def PrintClassRecu(grph, rootNode, tree_classes, topclassNam, depth,
                   wbemNamespace, cimomUrl, maxDepth, withYawnUrls):
    # sys.stderr.write("topclassNam=%s depth=%d\n" % (topclassNam,depth))

    if depth > maxDepth:
        return
    depth += 1

    wbemUrl = lib_wbem.ClassUrl(wbemNamespace, cimomUrl, topclassNam)
    wbemNode = lib_common.NodeUrl(wbemUrl)

    grph.add((rootNode, pc.property_cim_subclass, wbemNode))

    # The class is the starting point when displaying the class tree of the namespace.
    wbemNodeSub = WbemNamespaceNode(wbemNamespace, cimomUrl, topclassNam)
    grph.add((wbemNode, pc.property_rdf_data_nolist1, wbemNodeSub))

    nodeGeneralisedClass = lib_util.EntityClassNode(topclassNam, wbemNamespace,
                                                    cimomUrl, "WBEM")
    grph.add((wbemNode, pc.property_rdf_data_nolist2, nodeGeneralisedClass))

    if withYawnUrls:
        AddYawnNode(cimomUrl, topclassNam, wbemNamespace, grph, wbemNode)

    try:
        # TODO: This should be indexed with a en empty string !
        if topclassNam == "":
            topclassNam = None
        for cl in tree_classes[topclassNam]:
            PrintClassRecu(grph, wbemNode, tree_classes, cl.classname, depth,
                           wbemNamespace, cimomUrl, maxDepth, withYawnUrls)
    except KeyError:
        pass  # No subclass.
Ejemplo n.º 7
0
def Main():
    cgiEnv = lib_common.CgiEnv()

    grph = cgiEnv.GetGraph()

    rootNode = lib_util.RootUri()

    # This assumes that we have no namespace.
    for entity_type in lib_util.ObjectTypes():

        tmpNode = rootNode
        idx = 0

        while idx >= 0:
            nextSlash = entity_type.find("/", idx + 1)
            if nextSlash == -1:
                intermedType = entity_type
            else:
                intermedType = entity_type[:nextSlash]

            entityNode = lib_util.EntityClassNode(intermedType)
            grph.add((tmpNode, pc.property_directory, entityNode))

            try:
                # This reloads all classes without cache because if it does not load
                # we want to see the error message.
                entity_module = lib_util.GetEntityModuleNoCatch(entity_type)
                entDoc = entity_module.__doc__
            except:
                exc = sys.exc_info()[1]
                entDoc = "Error:" + str(exc)

            if entDoc:
                entDoc = entDoc.strip()
                grph.add((entityNode, pc.property_information,
                          lib_common.NodeLiteral(entDoc)))

            # TODO: If this is a CIM class, add WMI or WBEM documentation, or add the link.

            tmpNode = entityNode
            idx = nextSlash

    cgiEnv.OutCgiRdf("LAYOUT_RECT")
Ejemplo n.º 8
0
def _print_class_recu(grph, root_node, tree_classes, topclass_nam, depth,
                      wbem_namespace, cimom_url, max_depth, with_yawn_urls):
    """topclassNam is None at first call."""

    if depth > max_depth:
        return
    depth += 1

    wbem_url = lib_wbem.ClassUrl(wbem_namespace, cimom_url, topclass_nam)
    wbem_node = lib_common.NodeUrl(wbem_url)

    grph.add((root_node, pc.property_cim_subclass, wbem_node))

    # The class is the starting point when displaying the class tree of the namespace.
    wbem_node_sub = _wbem_namespace_node(wbem_namespace, cimom_url,
                                         topclass_nam)
    grph.add((wbem_node, pc.property_rdf_data_nolist1, wbem_node_sub))

    node_generalised_class = lib_util.EntityClassNode(topclass_nam,
                                                      wbem_namespace,
                                                      cimom_url, "WBEM")
    grph.add((wbem_node, pc.property_rdf_data_nolist2, node_generalised_class))

    if with_yawn_urls:
        _add_yawn_node(cimom_url, topclass_nam, wbem_namespace, grph,
                       wbem_node)

    try:
        # TODO: This should be indexed with a en empty string !
        if topclass_nam == "":
            topclass_nam = None
        for cl in tree_classes[topclass_nam]:
            _print_class_recu(grph, wbem_node, tree_classes, cl.classname,
                              depth, wbem_namespace, cimom_url, max_depth,
                              with_yawn_urls)
    except KeyError:
        pass  # No subclass.
Ejemplo n.º 9
0
def Main():

    cgiEnv = lib_common.ScriptEnvironment(can_process_remote=True)

    entity_id = cgiEnv.GetId()
    logging.debug("entity_id=%s", entity_id)
    if entity_id == "":
        lib_common.ErrorMessageHtml("No entity_id")

    # Just the path, shorter than cgiEnv.get_parameters("xid")
    cimom_url = cgiEnv.GetHost()

    name_space, class_name = cgiEnv.get_namespace_type()
    logging.debug("cimom_url=%s name_space=%s class_name=%s", cimom_url,
                  name_space, class_name)

    if name_space == "":
        name_space = "root/cimv2"
        logging.info("Setting namespace to default value.")

    if class_name == "":
        lib_common.ErrorMessageHtml("No class name. entity_id=%s" % entity_id)

    grph = cgiEnv.GetGraph()

    try:
        conn = lib_wbem.WbemConnection(cimom_url)
    except Exception as exc:
        lib_common.ErrorMessageHtml("Connecting to :" + cimom_url +
                                    " Caught:" + str(exc))

    root_node = lib_util.EntityClassNode(class_name, name_space, cimom_url,
                                         "WBEM")
    kla_descrip = lib_wbem.WbemClassDescription(conn, class_name, name_space)
    if not kla_descrip:
        kla_descrip = "Undefined class %s %s" % (name_space, class_name)
    grph.add((root_node, pc.property_information,
              lib_util.NodeLiteral(kla_descrip)))

    split_monik = cgiEnv.m_entity_id_dict

    logging.debug("entity_wbem.py name_space=%s class_name=%s cimom_url=%s",
                  name_space, class_name, cimom_url)

    # This works:
    # conn = pywbem.WBEMConnection("http://192.168.0.17:5988",("pegasus","toto"))
    # conn.ExecQuery("WQL","select * from CIM_System","root/cimv2")
    # conn.ExecQuery("WQL",'select * from CIM_Process  where Handle="4125"',"root/cimv2")
    #
    # select * from CIM_Directory or CIM_DataFile does not return anything.

    inst_lists = WbemPlainExecQuery(conn, class_name, split_monik, name_space)
    logging.debug("inst_lists=%s", str(inst_lists))
    if inst_lists is None:
        inst_lists = WbemNoQueryOneInst(conn, class_name, split_monik,
                                        name_space)
        if inst_lists is None:
            inst_lists = WbemNoQueryFilterInstances(conn, class_name,
                                                    split_monik, name_space)

    # TODO: Some objects are duplicated.
    # 'CSCreationClassName'   CIM_UnitaryComputerSystem Linux_ComputerSystem
    # 'CreationClassName'     PG_UnixProcess            TUT_UnixProcess
    num_insts = len(inst_lists)

    # If there are duplicates, adds a property which we hope is different.
    prop_discrim = "CreationClassName"

    # TODO!! WHAT OF THIS IS NOT THE RIGHT ORDER ???
    # Remove the double-quotes around the argument. WHAT IF THEY ARE NOT THERE ??

    for an_inst in inst_lists:

        # TODO: Use the right accessor for better performance.
        # On peut peut etre mettre tout ca dans une fonction sauf l execution de la query.
        dict_inst = dict(an_inst)

        # This differentiates several instance with the same properties.
        if num_insts > 1:
            # TODO: Should check if this property is different for all instances !!!
            with_extra_args = {prop_discrim: dict_inst[prop_discrim]}
            all_args = split_monik.copy()
            all_args.update(with_extra_args)
            dict_props = all_args
        else:
            dict_props = split_monik

        host_only = lib_util.EntHostToIp(cimom_url)
        uri_inst = lib_common.MachineBox(host_only).node_from_dict(
            class_name, dict_props)

        grph.add((root_node, lib_common.MakeProp(class_name), uri_inst))

        AddNamespaceLink(grph, root_node, name_space, cimom_url, class_name)

        # None properties are not printed.
        for iname_key in dict_inst:
            # Do not print twice values which are in the name.
            if iname_key in split_monik:
                continue
            iname_val = dict_inst[iname_key]
            # TODO: If this is a reference, create a Node !!!!!!!
            if not iname_val is None:
                grph.add((uri_inst, lib_common.MakeProp(iname_key),
                          lib_util.NodeLiteral(iname_val)))

        # TODO: Should call Associators(). Same for References().

    cgiEnv.OutCgiRdf()
Ejemplo n.º 10
0
def Main():
    paramkeyMaxInstances = "Max instances"
    paramkeyStartIndex = "Start index"

    # This can process remote hosts because it does not call any script, just shows them.
    cgiEnv = lib_common.CgiEnv(can_process_remote=True,
                               parameters={
                                   paramkeyMaxInstances: 80,
                                   paramkeyStartIndex: 0
                               })

    maxInstances = cgiEnv.get_parameters(paramkeyMaxInstances)
    startIndex = cgiEnv.get_parameters(paramkeyStartIndex)

    grph = cgiEnv.GetGraph()

    nameSpace, className = cgiEnv.get_namespace_type()
    DEBUG("nameSpace=%s className=%s", nameSpace, className)

    entity_host = cgiEnv.GetHost()

    rootNode = lib_util.EntityClassNode(className, nameSpace, entity_host,
                                        "WBEM")

    # Hard-coded default namespace.
    if nameSpace == "":
        nameSpace = "root/CIMV2"

    # This adds a link to the namespace of this WBEM class: It shows its inheritance graph.
    urlNamespace = lib_wbem.NamespaceUrl(nameSpace, entity_host, className)
    nodNamespace = lib_common.NodeUrl(urlNamespace)
    grph.add((rootNode, pc.property_cim_subnamespace, nodNamespace))

    try:
        connWbem = lib_wbem.WbemConnection(entity_host)
        wbemKlass = connWbem.GetClass(className,
                                      namespace=nameSpace,
                                      LocalOnly=False,
                                      IncludeQualifiers=True)
    except Exception:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml("EnumerateInstanceNames: entity_host=" +
                                    entity_host + " nameSpace=" + nameSpace +
                                    " className=" + className + ". Caught:" +
                                    str(exc))

    klaDescrip = lib_wbem.WbemClassDescrFromClass(wbemKlass)
    grph.add((rootNode, pc.property_information,
              lib_common.NodeLiteral("WBEM description: " + klaDescrip)))

    # Pour afficher du texte: Remplacer le help statique.
    # offset va etre un parametre. Helas ne pas se fairew d illusions sur "offset"

    # WBEM and WMI both have the annoying limitation that it is not possible to select only a range of instances.
    try:
        inst_names = connWbem.EnumerateInstanceNames(ClassName=className,
                                                     namespace=nameSpace)
    except Exception:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml("EnumerateInstanceNames: entity_host=" +
                                    entity_host + " nameSpace=" + nameSpace +
                                    " className=" + className + ". Caught:" +
                                    str(exc))

    try:
        isAssociation = wbemKlass.qualifiers['Association'].value
    except KeyError:
        isAssociation = False

    # It is possible to display an association like a normal class but it is useless.
    if isAssociation:
        if True:
            DisplayAssociatorsAsNetwork(grph, inst_names, rootNode, nameSpace,
                                        entity_host, maxInstances, startIndex)
        else:
            DisplayAssociatorsAsList(grph, inst_names, rootNode, nameSpace,
                                     entity_host, className, maxInstances,
                                     startIndex)
    else:
        DisplayPlainClass(grph, inst_names, rootNode, nameSpace, entity_host,
                          className, maxInstances, startIndex)

    numInstances = len(inst_names)
    DEBUG("numInstances=%d startIndex=%d", numInstances, startIndex)

    # This displays one link on the same page, with specific values of these parameters.
    # The other parameters are not changed.
    # TODO, BEWARE: What is the total number of elements ?
    if startIndex + maxInstances < numInstances:
        cgiEnv.add_parameterized_links(
            "Next", {paramkeyStartIndex: startIndex + maxInstances})
    if startIndex > 0:
        cgiEnv.add_parameterized_links(
            "Previous",
            {paramkeyStartIndex: max(startIndex - maxInstances, 0)})

    # TODO: On pourrait rassembler par classes,
    # et aussi afficher les liens d'heritages des classes.

    # cgiEnv.OutCgiRdf()
    cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_class_instance])
Ejemplo n.º 11
0
def Main():
    global dictClassToNode

    dictClassToNode = dict()

    paramkeyMaxDepth = "Maximum depth"

    cgiEnv = lib_common.CgiEnv(can_process_remote=True,
                               parameters={paramkeyMaxDepth: 3})

    maxDepth = int(cgiEnv.GetParameters(paramkeyMaxDepth))

    (wmiNamespace, entity_type,
     entity_namespace_type) = cgiEnv.GetNamespaceType()

    sys.stderr.write("wmiNamespace=%s entity_type=%s\n" %
                     (wmiNamespace, entity_type))

    cimomUrl = cgiEnv.GetHost()

    if str(wmiNamespace) == "":
        lib_common.ErrorMessageHtml(
            "WMI namespace should not be empty. entity_namespace_type=" +
            entity_namespace_type)

    grph = cgiEnv.GetGraph()

    try:
        connWmi = lib_wmi.WmiConnect(cimomUrl, wmiNamespace)
    except:
        exc = sys.exc_info()[1]
        # wmiNamespace=root\directory\\LDAP Caught:
        # x_wmi: Unexpected COM Error (-2147217375, 'OLE error 0x80041021', None, None)
        lib_common.ErrorMessageHtml("wmiNamespace=%s Caught:%s" %
                                    (wmiNamespace, str(exc)))

    rootNode = ClassToNode(wmiNamespace, cimomUrl, entity_type)

    # rootNodeNameSpace = WmiNamespaceNode(entity_type)
    # grph.add( ( rootNode, pc.property_rdf_data_nolist2, lib_common.NodeLiteral(rootNodeNameSpace) ) )
    # def EntityClassNode(entity_type, entity_namespace = "", entity_host = "", category = ""):
    rootGeneralisedClass = lib_util.EntityClassNode(entity_type, wmiNamespace,
                                                    cimomUrl, "WMI")
    grph.add((rootNode, pc.property_rdf_data_nolist2, rootGeneralisedClass))

    # CA MARCHE PAS QUAND ON VIENT D ICI:
    # http://127.0.0.1/Survol/survol/objtypes_wmi.py?xid=\\rchateau-HP\root\CIMV2%3ACIM_LogicalDevice.
    #
    # KO:
    # http://127.0.0.1/Survol/survol/class_type_all.py?xid=\\rchateau-HP\root\CIMV2%3ACIM_LogicalDevice.
    # OK:
    # http://127.0.0.1/Survol/survol/class_type_all.py?xid=http%3A%2F%2F192.168.1.83%3A5988%2Froot%2Fcimv2%3ACIM_LogicalDevice.

    # CA AUSSI NE MARCHE PAS !!!!!!!!!!!!!!!
    # http://127.0.0.1:8000/survol/class_type_all.py?xid=http%3A%2F%2F192.168.1.88%3A5988%2Froot%2Fcimv2%3A.

    # FAIRE LA MEME CHOSE DANS objtypes_wbem
    # AUSSI, il faut que wbem_classes aient des liens en plus.
    # Et CGIPROP doit au moins contenir le nom du script.
    # Et eviter les repetiions dans les tables.[

    # TODO: Commencer a afficher a partir de entity_type si il est la.
    # TODO: Pour la classe d'en haut, ajouter un lien pour remonter d'une position.
    if entity_type == "":
        for clsNam in connWmi.classes:
            clsDeriv = GetDerivation(connWmi, clsNam)

            # Pour limiter la profondeur, on part de la classe X et on n'en descend pas a plus de N niveaux.
            if len(clsDeriv) < maxDepth:
                DrawFromThisBase(rootNode, wmiNamespace, cimomUrl, clsNam,
                                 grph, clsDeriv)
    else:
        # Normally this cache contains nodes to classes, but this is the top one.
        dictClassToNode[entity_type] = rootNode

        # This also points to its closest base class or to the namespace.
        topClsDeriv = GetDerivation(connWmi, entity_type)
        if len(topClsDeriv) == 0:
            topNode = WmiNamespaceNode(wmiNamespace, cimomUrl, "")
        else:
            topNode = WmiNamespaceNode(wmiNamespace, cimomUrl, topClsDeriv[0])
        grph.add((topNode, pc.property_cim_subclass, rootNode))

        for clsNam in connWmi.subclasses_of(entity_type):
            clsDeriv = GetDerivation(connWmi, clsNam)

            #sys.stderr.write("entity_type=%s clsNam=%s clsDeriv=%s\n" % (entity_type, clsNam, str(clsDeriv)))
            idxClass = clsDeriv.index(entity_type)
            invertIdx = len(clsDeriv) - idxClass
            # sys.stderr.write("clsNam=%s idxClass=%d invertIdx=%d clsDeriv=%s\n" % (clsNam, idxClass, invertIdx, str(clsDeriv)))
            # Pour limiter la profondeur, on part de la classe X et on en descend pas a plus de N niveaux.
            if len(clsDeriv) < maxDepth + invertIdx:
                # derivation starts by the lowest level to the top.
                DrawFromThisBase(rootNode, wmiNamespace, cimomUrl, clsNam,
                                 grph, clsDeriv[:idxClass])

    cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_cim_subclass])
Ejemplo n.º 12
0
def Main():
    paramkeyEnumInstances = "Enumerate instances"

    cgiEnv = lib_common.CgiEnv(parameters={paramkeyEnumInstances: False})

    flagEnumInstances = bool(cgiEnv.get_parameters(paramkeyEnumInstances))

    grph = cgiEnv.GetGraph()

    nameSpace, className = cgiEnv.get_namespace_type()
    INFO("nameSpace=%s className=%s", nameSpace, className)

    # If nameSpace is not provided, it is set to "root/CIMV2" by default.
    if not className:
        lib_common.ErrorMessageHtml("Class name should not be empty")

    cimomUrl = cgiEnv.GetHost()

    rootNode = lib_util.EntityClassNode(className, nameSpace, cimomUrl, "WMI")

    AddExtraNodes(grph, rootNode)

    # Not sure why, but sometimes backslash replaced by slash, depending where we come from ?
    nameSpace = nameSpace.replace("/", "\\")

    try:
        connWmi = lib_wmi.WmiConnect(cimomUrl, nameSpace)
    except:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml(
            "WMI Connecting to cimomUrl=%s nameSpace=%s Caught:%s\n" %
            (cimomUrl, nameSpace, str(exc)))

    # http://rchateau-hp:8000/survol/class_wmi.py?xid=\\rchateau-HP\root\CIMV2%3ACIM_Directory.
    # http://rchateau-hp:8000/survol/class_wmi.py?xid=\rchateau-HP\root\CIMV2%3ACIM_Directory.&mode=html

    lib_wmi.WmiAddClassQualifiers(grph, connWmi, rootNode, className, True)

    # Inutilisable pour:
    # root/CIMV2/CIM_LogicalFile
    # car il y en a beaucoup trop.
    # TODO: pEUT-ETRE QUE wql POURRAQIT PERMETTRE UNE LIMITE ??
    # Ou bien arguments: De 1 a 100 etc... mais ca peut nous obliger de creer des liens bidons
    # pour aller aux elements suivants ou precedents. Notons que ca revient a creer des scripts artificiels.

    # Et aussi, revenir vers l'arborescence des classes dans ce namespace.

    try:
        wmiClass = getattr(connWmi, className)
    except Exception:
        exc = sys.exc_info()[1]
        lib_common.ErrorMessageHtml(
            "class_wmi.py cimomUrl=%s nameSpace=%s className=%s Caught:%s\n" %
            (cimomUrl, nameSpace, className, str(exc)))

    # wmiClass=[Abstract, Locale(1033): ToInstance, UUID("{8502C55F-5FBB-11D2-AAC1-006008C78BC7}"): ToInstance]
    # class CIM_Directory : CIM_LogicalFile
    # {
    # };
    DEBUG("wmiClass=%s", str(wmiClass))

    # Some examples of WMI queries.
    # http://timgolden.me.uk/python/wmi/tutorial.html
    #
    # logical_disk = wmi.WMI(moniker="//./root/cimv2:Win32_LogicalDisk")
    # c_drive = wmi.WMI(moniker='//./root/cimv2:Win32_LogicalDisk.DeviceID="C:"')
    # c = wmi.WMI("MachineB", user=r"MachineB\fred", password="******")
    #
    # A WMI class can be "called" with simple equal-to parameters to narrow down the list.
    # This filtering is happening at the WMI level.
    # for disk in c.Win32_LogicalDisk(DriveType=3):
    # for service in c.Win32_Service(Name="seclogon"):
    #
    # Arbitrary WQL queries can be run, but apparently WQL selects first all elements from WMI,
    # then only does its filtering:
    # for disk in wmi.WMI().query("SELECT Caption, Description FROM Win32_LogicalDisk WHERE DriveType <> 3"):
    #
    if flagEnumInstances:

        # Biggest difficulty is the impossibility to limit the numbers of results fetched by WMI.
        # Many classes have to many elements to display them.
        # This makes it virtually impossible to select their elements.
        if lib_wmi.WmiTooManyInstances(className):
            lib_common.ErrorMessageHtml("Too many elements in className=%s\n" %
                                        (className))

        try:
            lstObj = wmiClass()
        except Exception:
            exc = sys.exc_info()[1]
            lib_common.ErrorMessageHtml("Caught when getting list of %s\n" %
                                        className)

        numLstObj = len(lstObj)
        DEBUG("className=%s type(wmiClass)=%s len=%d", className,
              str(type(wmiClass)), numLstObj)

        if numLstObj == 0:
            grph.add((rootNode, pc.property_information,
                      lib_common.NodeLiteral("No instances in this class")))

        for wmiObj in lstObj:
            # Full natural path: We must try to merge it with WBEM Uris.
            # '\\\\RCHATEAU-HP\\root\\cimv2:Win32_Process.Handle="0"'
            # https://jdd:[email protected]:5959/cimv2:Win32_SoftwareFeature.Name="Havana",ProductName="Havana",Version="1.0"

            try:
                fullPth = str(wmiObj.path())
            except UnicodeEncodeError:
                # UnicodeEncodeError: 'ascii' codec can't encode characters in position 104-108: ordinal not in range(128)
                exc = sys.exc_info()[1]
                WARNING("Exception %s", str(exc))
                continue

            # sys.stderr.write("fullPth=%s\n" % fullPth)

            if fullPth == "":
                WARNING("Empty path wmiObj=%s", str(wmiObj))
                # The class Win32_PnPSignedDriver (Maybe others) generates dozens of these messages.
                # This is not really an issue as this class should be hidden from applications.
                # WARNING Empty path wmiObj=
                # instance of Win32_PnPSignedDriver
                # {
                # 		ClassGuid = NULL;
                # 		CompatID = NULL;
                # 		Description = NULL;
                # 		DeviceClass = "LEGACYDRIVER";
                # 		DeviceID = "ROOT\\LEGACY_LSI_FC\\0000";
                # 		DeviceName = "LSI_FC";
                # 		DevLoader = NULL;
                # 		DriverName = NULL;
                # 		DriverProviderName = NULL;
                # 		DriverVersion = NULL;
                # 		FriendlyName = NULL;
                # 		HardWareID = NULL;
                # 		InfName = NULL;
                # 		Location = NULL;
                # 		Manufacturer = NULL;
                # 		PDO = NULL;
                # };
                continue

            # fullPth=\\RCHATEAU-HP\root\CIMV2:Win32_SoundDevice.DeviceID="HDAUDIO\\FUNC_01&VEN_10EC&DEV_0221&SUBSYS_103C18E9&REV_1000\\4&3BC582&0&0001"
            fullPth = fullPth.replace("&", "&amp;")
            wmiInstanceUrl = lib_util.EntityUrlFromMoniker(fullPth)
            DEBUG("wmiInstanceUrl=%s", wmiInstanceUrl)

            wmiInstanceNode = lib_common.NodeUrl(wmiInstanceUrl)

            # infos = lib_wbem_cim.get_inst_info(iname, klass, include_all=True, keys_only=True)

            grph.add((rootNode, pc.property_class_instance, wmiInstanceNode))

    # TODO: On pourrait rassembler par classes, et aussi afficher les liens d'heritages des classes.

    cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_class_instance])
Ejemplo n.º 13
0
def Main():

	cgiEnv = lib_common.CgiEnv(can_process_remote = True)

	entity_id = cgiEnv.GetId()
	DEBUG("entity_id=%s", entity_id)
	if entity_id == "":
		lib_common.ErrorMessageHtml("No entity_id")


	# Just the path, shorter than cgiEnv.get_parameters("xid")
	cimomUrl = cgiEnv.GetHost()

	nameSpace, className = cgiEnv.get_namespace_type()
	DEBUG("entity_wbem.py cimomUrl=%s nameSpace=%s className=%s", cimomUrl,nameSpace,className)

	if nameSpace == "":
		nameSpace = "root/cimv2"
		INFO("Setting namespace to default value\n")


	if className == "":
		lib_common.ErrorMessageHtml("No class name. entity_id=%s" % entity_id)

	grph = cgiEnv.GetGraph()

	conn = lib_wbem.WbemConnection(cimomUrl)

	rootNode = lib_util.EntityClassNode( className, nameSpace, cimomUrl, "WBEM" )
	klaDescrip = lib_wbem.WbemClassDescription(conn,className,nameSpace)
	if not klaDescrip:
		klaDescrip = "Undefined class %s %s" % ( nameSpace, className )
	grph.add( ( rootNode, pc.property_information, lib_common.NodeLiteral(klaDescrip ) ) )

	splitMonik = lib_util.SplitMoniker( cgiEnv.m_entity_id )

	DEBUG("entity_wbem.py nameSpace=%s className=%s cimomUrl=%s",nameSpace,className,cimomUrl)

	# This works:
	# conn = pywbem.WBEMConnection("http://192.168.0.17:5988",("pegasus","toto"))
	# conn.ExecQuery("WQL","select * from CIM_System","root/cimv2")
	# conn.ExecQuery("WQL",'select * from CIM_Process  where Handle="4125"',"root/cimv2")
	#
	# select * from CIM_Directory or CIM_DataFile does not return anything.


	instLists = WbemPlainExecQuery( conn, className, splitMonik, nameSpace )
	DEBUG("entity_wbem.py instLists=%s",str(instLists))
	if instLists is None:
		instLists = WbemNoQueryOneInst( conn, className, splitMonik, nameSpace )
		if instLists is None:
			instLists = WbemNoQueryFilterInstances( conn, className, splitMonik, nameSpace )

	# TODO: Some objects are duplicated.
	# 'CSCreationClassName'   CIM_UnitaryComputerSystem Linux_ComputerSystem
	# 'CreationClassName'     PG_UnixProcess            TUT_UnixProcess
	numInsts = len(instLists)

	# If there are duplicates, adds a property which we hope is different.
	propDiscrim = "CreationClassName"

	# TODO!! WHAT OF THIS IS NOT THE RIGHT ORDER ???
	# Remove the double-quotes around the argument. WHAT IF THEY ARE NOT THERE ??
	# arrVals = [ ChopEnclosingParentheses( splitMonik[qryKey] ) for qryKey in splitMonik ]

	for anInst in instLists:

		# TODO: Use the right accessor for better performance.
		# On peut peut etre mettre tout ca dans une fonction sauf l execution de la query.
		dictInst = dict(anInst)

		# This differentiates several instance with the same properties.


		if numInsts > 1:
			# TODO: Should check if this property is different for all instances !!!
			withExtraArgs = { propDiscrim : dictInst[ propDiscrim ] }
			allArgs = splitMonik.copy()
			allArgs.update(withExtraArgs)
			dictProps = allArgs
		else:
			dictProps = splitMonik

		hostOnly = lib_util.EntHostToIp(cimomUrl)
		if lib_util.IsLocalAddress(hostOnly):
			uriInst = lib_common.gUriGen.UriMakeFromDict(className, dictProps)
		else:
			uriInst = lib_common.RemoteBox(hostOnly).UriMakeFromDict(className, dictProps)

		grph.add( ( rootNode, lib_common.MakeProp(className), uriInst ) )

		AddNamespaceLink(grph, rootNode, nameSpace, cimomUrl, className)

		# None properties are not printed.
		for inameKey in dictInst:
			# Do not print twice values which are in the name.
			if inameKey in splitMonik:
				continue
			inameVal = dictInst[inameKey]
			# TODO: If this is a reference, create a Node !!!!!!!
			if not inameVal is None:
				grph.add( ( uriInst, lib_common.MakeProp(inameKey), lib_common.NodeLiteral(inameVal) ) )

		# TODO: Should call Associators(). Same for References().

	cgiEnv.OutCgiRdf()
Ejemplo n.º 14
0
def Main():
    paramkey_enum_instances = "Enumerate instances"

    cgiEnv = lib_common.ScriptEnvironment(
        parameters={paramkey_enum_instances: False})

    flag_enum_instances = bool(cgiEnv.get_parameters(paramkey_enum_instances))

    grph = cgiEnv.GetGraph()

    name_space, class_name = cgiEnv.get_namespace_type()
    logging.info("name_space=%s class_name=%s", name_space, class_name)

    # 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")

    cimom_url = cgiEnv.GetHost()

    root_node = lib_util.EntityClassNode(class_name, name_space, cimom_url,
                                         "WMI")

    _add_extra_nodes(grph, root_node)

    # Not sure why, but sometimes backslash replaced by slash, depending where we come from ?
    name_space = name_space.replace("/", "\\")

    try:
        conn_wmi = lib_wmi.WmiConnect(cimom_url, name_space)
    except Exception as exc:
        lib_common.ErrorMessageHtml(
            "WMI Connecting to cimom_url=%s name_space=%s Caught:%s\n" %
            (cimom_url, name_space, str(exc)))

    # http://mymachine:8000/survol/class_wmi.py?xid=\\mymachine\root\CIMV2%3ACIM_Directory.
    # http://mymachine:8000/survol/class_wmi.py?xid=\mymachine\root\CIMV2%3ACIM_Directory.&mode=html

    lib_wmi.WmiAddClassQualifiers(grph, conn_wmi, root_node, class_name, True)

    try:
        wmi_class = getattr(conn_wmi, class_name)
    except Exception as exc:
        lib_common.ErrorMessageHtml(
            "class_wmi.py cimom_url=%s name_space=%s class_name=%s Caught:%s\n"
            % (cimom_url, name_space, class_name, str(exc)))

    # wmi_class=[Abstract, Locale(1033): ToInstance, UUID("{8502C55F-5FBB-11D2-AAC1-006008C78BC7}"): ToInstance]
    # class CIM_Directory : CIM_LogicalFile
    # {
    # };
    logging.debug("wmi_class=%s", str(wmi_class))

    # Some examples of WMI queries.
    # http://timgolden.me.uk/python/wmi/tutorial.html
    #
    # logical_disk = wmi.WMI(moniker="//./root/cimv2:Win32_LogicalDisk")
    # c_drive = wmi.WMI(moniker='//./root/cimv2:Win32_LogicalDisk.DeviceID="C:"')
    # c = wmi.WMI("MachineB", user=r"MachineB\fred", password="******")
    #
    # A WMI class can be "called" with simple equal-to parameters to narrow down the list.
    # This filtering is happening at the WMI level.
    # for disk in c.Win32_LogicalDisk(DriveType=3):
    # for service in c.Win32_Service(Name="seclogon"):
    #
    # Arbitrary WQL queries can be run, but apparently WQL selects first all elements from WMI,
    # then only does its filtering:
    # for disk in wmi.WMI().query("SELECT Caption, Description FROM Win32_LogicalDisk WHERE DriveType <> 3"):
    #
    if flag_enum_instances:
        # Biggest difficulty is the impossibility to limit the numbers of results fetched by WMI.
        # Many classes have to many elements to display them.
        # This makes it virtually impossible to select their elements.
        if lib_wmi.WmiTooManyInstances(class_name):
            lib_common.ErrorMessageHtml(
                "Too many elements in class_name=%s\n" % class_name)

        try:
            lst_obj = wmi_class()
        except Exception as exc:
            lib_common.ErrorMessageHtml("Caught when getting list of %s\n" %
                                        class_name)

        num_lst_obj = len(lst_obj)
        logging.debug("class_name=%s type(wmi_class)=%s len=%d", class_name,
                      str(type(wmi_class)), num_lst_obj)

        if num_lst_obj == 0:
            grph.add((root_node, pc.property_information,
                      lib_util.NodeLiteral("No instances in this class")))

        for wmi_obj in lst_obj:
            # Full natural path: We must try to merge it with WBEM Uris.
            # '\\\\MYMACHINE\\root\\cimv2:Win32_Process.Handle="0"'
            # https://jdd:[email protected]:5959/cimv2:Win32_SoftwareFeature.Name="Havana",ProductName="Havana",Version="1.0"

            try:
                full_pth = str(wmi_obj.path())
            except UnicodeEncodeError as exc:
                # UnicodeEncodeError: 'ascii' codec can't encode characters in position 104-108: ordinal not in range(128)
                logging.warning("Exception %s", str(exc))
                continue

            if full_pth == "":
                logging.warning("Empty path wmi_obj=%s", str(wmi_obj))
                # The class Win32_PnPSignedDriver (Maybe others) generates dozens of these messages.
                # This is not really an issue as this class should be hidden from applications.
                # logging.warning Empty path wmi_obj=
                # instance of Win32_PnPSignedDriver
                # {
                #         ClassGuid = NULL;
                #         CompatID = NULL;
                #         Description = NULL;
                #         DeviceClass = "LEGACYDRIVER";
                #         DeviceID = "ROOT\\LEGACY_LSI_FC\\0000";
                #         DeviceName = "LSI_FC";
                #         DevLoader = NULL;
                #         DriverName = NULL;
                #         DriverProviderName = NULL;
                #         DriverVersion = NULL;
                #         FriendlyName = NULL;
                #         HardWareID = NULL;
                #         InfName = NULL;
                #         Location = NULL;
                #         Manufacturer = NULL;
                #         PDO = NULL;
                # };
                continue

            # full_pth=\\MYMACHINE\root\CIMV2:Win32_SoundDevice.DeviceID="HDAUDIO\\FUNC_01&VEN_10EC&DEV_0221&SUBSYS_103C18E9&REV_1000\\4&3BC582&0&0001"
            full_pth = full_pth.replace("&", "&amp;")
            wmi_instance_url = lib_util.EntityUrlFromMoniker(full_pth)
            logging.debug("wmi_instance_url=%s", wmi_instance_url)

            wmi_instance_node = lib_common.NodeUrl(wmi_instance_url)

            grph.add(
                (root_node, pc.property_class_instance, wmi_instance_node))

    # TODO: On pourrait rassembler par classes, et aussi afficher les liens d'heritages des classes.

    cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_class_instance])
Ejemplo n.º 15
0
(nameSpace, className, entity_namespace_type) = cgiEnv.GetNamespaceType()
sys.stderr.write("entity_wbem.py cimomUrl=%s nameSpace=%s className=%s\n" %
                 (cimomUrl, nameSpace, className))

if nameSpace == "":
    nameSpace = "root/cimv2"
    sys.stderr.write("Setting namespace to default value\n")

if className == "":
    lib_common.ErrorMessageHtml("No class name. entity_id=%s" % entity_id)

grph = cgiEnv.GetGraph()

conn = lib_wbem.WbemConnection(cimomUrl)

rootNode = lib_util.EntityClassNode(className, nameSpace, cimomUrl, "WBEM")
klaDescrip = lib_wbem.WbemClassDescription(conn, className, nameSpace)
if not klaDescrip:
    klaDescrip = "Undefined class %s %s" % (nameSpace, className)
grph.add(
    (rootNode, pc.property_information, lib_common.NodeLiteral(klaDescrip)))

splitMonik = lib_util.SplitMoniker(cgiEnv.m_entity_id)

sys.stderr.write("entity_wbem.py nameSpace=%s className=%s cimomUrl=%s\n" %
                 (nameSpace, className, cimomUrl))

# This works:
# conn = pywbem.WBEMConnection("http://192.168.0.17:5988",("pegasus","toto"))
# conn.ExecQuery("WQL","select * from CIM_System","root/cimv2")
# conn.ExecQuery("WQL",'select * from CIM_Process  where Handle="4125"',"root/cimv2")
Ejemplo n.º 16
0
def Main():
    global dict_class_to_node

    dict_class_to_node = dict()

    paramkey_max_depth = "Maximum depth"

    cgiEnv = lib_common.ScriptEnvironment(can_process_remote=True,
                                          parameters={paramkey_max_depth: 3})

    max_depth = int(cgiEnv.get_parameters(paramkey_max_depth))

    wmi_namespace, entity_type = cgiEnv.get_namespace_type()

    logging.debug("wmi_namespace=%s entity_type=%s", wmi_namespace,
                  entity_type)

    cimom_url = cgiEnv.GetHost()

    # If wmi_namespace, this is not an issue, it is set to "root/CIMV2" by default.

    grph = cgiEnv.GetGraph()

    try:
        conn_wmi = lib_wmi.WmiConnect(cimom_url, wmi_namespace)
    except Exception as exc:
        # wmi_namespace=root\directory\\LDAP Caught:
        # x_wmi: Unexpected COM Error (-2147217375, 'OLE error 0x80041021', None, None)
        lib_common.ErrorMessageHtml("wmi_namespace=%s Caught:%s" %
                                    (wmi_namespace, str(exc)))

    root_node = _class_to_node(wmi_namespace, cimom_url, entity_type)

    # rootNodeNameSpace = _wmi_namespace_node(entity_type)
    # grph.add( ( root_node, pc.property_rdf_data_nolist2, lib_util.NodeLiteral(rootNodeNameSpace) ) )
    # def EntityClassNode(entity_type, entity_namespace = "", entity_host = "", category = ""):
    root_generalised_class = lib_util.EntityClassNode(entity_type,
                                                      wmi_namespace, cimom_url,
                                                      "WMI")
    grph.add((root_node, pc.property_rdf_data_nolist2, root_generalised_class))

    # TODO: Should add a link to the upper class.
    if entity_type == "":
        for cls_nam in conn_wmi.classes:
            cls_deriv = _get_derivation(conn_wmi, cls_nam)

            if len(cls_deriv) < max_depth:
                _draw_from_this_base(root_node, wmi_namespace, cimom_url,
                                     cls_nam, grph, cls_deriv)
    else:
        # Normally this cache contains nodes to classes, but this is the top one.
        dict_class_to_node[entity_type] = root_node

        # This also points to its closest base class or to the namespace.
        top_cls_deriv = _get_derivation(conn_wmi, entity_type)
        if len(top_cls_deriv) == 0:
            top_node = _wmi_namespace_node(wmi_namespace, cimom_url, "")
        else:
            top_node = _wmi_namespace_node(wmi_namespace, cimom_url,
                                           top_cls_deriv[0])
        grph.add((top_node, pc.property_cim_subclass, root_node))

        for cls_nam in conn_wmi.subclasses_of(entity_type):
            cls_deriv = _get_derivation(conn_wmi, cls_nam)

            idx_class = cls_deriv.index(entity_type)
            invert_idx = len(cls_deriv) - idx_class

            # This tree can be very deep so there is a maximum depth.
            if len(cls_deriv) < max_depth + invert_idx:
                # derivation starts by the lowest level to the top.
                _draw_from_this_base(root_node, wmi_namespace, cimom_url,
                                     cls_nam, grph, cls_deriv[:idx_class])

    cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_cim_subclass])
Ejemplo n.º 17
0
def Main():
    global dictClassToNode

    dictClassToNode = dict()

    paramkeyMaxDepth = "Maximum depth"

    cgiEnv = lib_common.CgiEnv(can_process_remote=True,
                               parameters={paramkeyMaxDepth: 3})

    maxDepth = int(cgiEnv.get_parameters(paramkeyMaxDepth))

    wmiNamespace, entity_type = cgiEnv.get_namespace_type()

    DEBUG("wmiNamespace=%s entity_type=%s", wmiNamespace, entity_type)

    cimomUrl = cgiEnv.GetHost()

    # If wmiNamespace, this is not an issue, it is set to "root/CIMV2" by default.

    grph = cgiEnv.GetGraph()

    try:
        connWmi = lib_wmi.WmiConnect(cimomUrl, wmiNamespace)
    except:
        exc = sys.exc_info()[1]
        # wmiNamespace=root\directory\\LDAP Caught:
        # x_wmi: Unexpected COM Error (-2147217375, 'OLE error 0x80041021', None, None)
        lib_common.ErrorMessageHtml("wmiNamespace=%s Caught:%s" %
                                    (wmiNamespace, str(exc)))

    rootNode = ClassToNode(wmiNamespace, cimomUrl, entity_type)

    # rootNodeNameSpace = WmiNamespaceNode(entity_type)
    # grph.add( ( rootNode, pc.property_rdf_data_nolist2, lib_common.NodeLiteral(rootNodeNameSpace) ) )
    # def EntityClassNode(entity_type, entity_namespace = "", entity_host = "", category = ""):
    rootGeneralisedClass = lib_util.EntityClassNode(entity_type, wmiNamespace,
                                                    cimomUrl, "WMI")
    grph.add((rootNode, pc.property_rdf_data_nolist2, rootGeneralisedClass))

    # TODO: Should add a link to the upper class.
    if entity_type == "":
        for clsNam in connWmi.classes:
            clsDeriv = GetDerivation(connWmi, clsNam)

            if len(clsDeriv) < maxDepth:
                DrawFromThisBase(rootNode, wmiNamespace, cimomUrl, clsNam,
                                 grph, clsDeriv)
    else:
        # Normally this cache contains nodes to classes, but this is the top one.
        dictClassToNode[entity_type] = rootNode

        # This also points to its closest base class or to the namespace.
        topClsDeriv = GetDerivation(connWmi, entity_type)
        if len(topClsDeriv) == 0:
            topNode = WmiNamespaceNode(wmiNamespace, cimomUrl, "")
        else:
            topNode = WmiNamespaceNode(wmiNamespace, cimomUrl, topClsDeriv[0])
        grph.add((topNode, pc.property_cim_subclass, rootNode))

        for clsNam in connWmi.subclasses_of(entity_type):
            clsDeriv = GetDerivation(connWmi, clsNam)

            #sys.stderr.write("entity_type=%s clsNam=%s clsDeriv=%s\n" % (entity_type, clsNam, str(clsDeriv)))
            idxClass = clsDeriv.index(entity_type)
            invertIdx = len(clsDeriv) - idxClass
            # sys.stderr.write("clsNam=%s idxClass=%d invertIdx=%d clsDeriv=%s\n" % (clsNam, idxClass, invertIdx, str(clsDeriv)))
            # This tree can be very deep so there is a maximum depth.
            if len(clsDeriv) < maxDepth + invertIdx:
                # derivation starts by the lowest level to the top.
                DrawFromThisBase(rootNode, wmiNamespace, cimomUrl, clsNam,
                                 grph, clsDeriv[:idxClass])

    cgiEnv.OutCgiRdf("LAYOUT_RECT", [pc.property_cim_subclass])