summaryrefslogtreecommitdiffstats
path: root/src/pcp/lmi/pcp/metric.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/pcp/lmi/pcp/metric.py')
-rw-r--r--src/pcp/lmi/pcp/metric.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/src/pcp/lmi/pcp/metric.py b/src/pcp/lmi/pcp/metric.py
new file mode 100644
index 0000000..454f54a
--- /dev/null
+++ b/src/pcp/lmi/pcp/metric.py
@@ -0,0 +1,167 @@
+"""Python Provider for PCP_Metric_*
+Instruments the CIM class family PCP_Metric_*
+"""
+
+from pywbem.cim_provider2 import CIMProvider2
+import pywbem
+from pcp import pmapi
+import cpmapi as c_api
+import datetime
+
+context = None # persistent pcp context
+
+
+# Since we serve a whole slew of PCP_Metric_** subclasses, we can't
+# use a straight classname->provider-class dictionary.
+#
+#def get_providers(env):
+# return {'PCP_Metric_****': PCP_MetricProvider}
+#
+# Instead, we implement the one-hop-higher proxy-level function calls,
+# namely the IM_* functions at the bottom.
+
+
+# Undo mangling done by PCP_pmns2mofreg.sh
+def MOFname_to_PCPmetric (op):
+ assert (op.namespace == 'root/cimv2')
+ assert (op.classname[0:11] == 'PCP_Metric_')
+ return op.classname[11:].replace('__', '.')
+
+
+# Search the given PM_ResultSet for a given instance number (if any);
+# return formatted CIM of the value (or CIM None)
+def PCP_CIMValueString (context, result, desc, inst):
+ for i in range (0,result.contents.get_numval(0)):
+ value = result.contents.get_vlist(0,i)
+ iv = value.inst
+ if (inst is not None and inst != iv):
+ continue
+ atom = context.pmExtractValue (result.contents.get_valfmt(0),
+ value,
+ desc.contents.type,
+ desc.contents.type)
+ atomValue = atom.dref(desc.contents.type) # nb: atomValue could be numeric etc.
+ return pywbem.CIMProperty(name='ValueString',
+ value=str(atomValue), # stringify it here
+ type='string')
+
+ return pywbem.CIMProperty(name='ValueString',
+ value=None,
+ type='string')
+
+
+def PCP_CIMStatisticTime (result):
+ dt = datetime.datetime.fromtimestamp(float(str(result.contents.timestamp)))
+ return pywbem.CIMDateTime(dt)
+
+
+# generic payload generator, used for
+# - iterating across instance domains (keys_only=1)
+# - fetching metric values
+# - fetching metric metadata (for those model/filter fields set)
+def get_instance (env, op, model, keys_only):
+ metric = MOFname_to_PCPmetric (op)
+ global context
+
+ try:
+ if (context == None):
+ context = pmapi.pmContext() # localhost or equivalent
+ context.pmReconnectContext() # in case it was nuked recently
+ except pmapi.pmErr, e:
+ context = None
+ raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, "Unable to connect to local PMCD:" + str(e))
+
+ pmids = context.pmLookupName(metric)
+ pmid = pmids[0]
+ desc = context.pmLookupDesc(pmid)
+
+ if ('InstanceID' in model):
+ selected_instanceid = model['InstanceID']
+ else:
+ selected_instanceid = None
+
+ model.path.update({'InstanceID':None})
+
+ if (not keys_only):
+ model['PMID'] = pywbem.Uint32(pmid)
+ model['ElementName'] = metric
+ # must not fail, or else we have no metric value data worth sharing
+ try:
+ results = context.pmFetch(pmids)
+ except pmapi.pmErr, e:
+ # fatal
+ raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, "PCP pmFetch failed:" + str(e))
+ # cannot fail
+ model['Units'] = context.pmUnitsStr(desc.contents.units)
+ model['Type'] = context.pmTypeStr(desc.contents.type)
+ # these may fail, but not fatally
+ try:
+ model['Caption'] = context.pmLookupText(pmid)
+ except pmapi.pmErr:
+ pass
+ try:
+ model['Description'] = context.pmLookupText(pmid, c_api.PM_TEXT_HELP)
+ except pmapi.pmErr:
+ pass
+
+ try:
+ instL, nameL = context.pmGetInDom(desc)
+ for iL, nL in zip(instL, nameL):
+ new_instanceid = 'PCP:'+metric+':'+nL
+ if (selected_instanceid is None or
+ new_instanceid == selected_instanceid):
+ model['InstanceNumber'] = pywbem.Uint32(iL)
+ model['InstanceName'] = nL
+ model['InstanceID'] = new_instanceid
+ if (not keys_only):
+ model['StatisticTime'] = PCP_CIMStatisticTime (results)
+ model['ValueString'] = PCP_CIMValueString (context, results, desc, iL)
+ yield model
+ except pmapi.pmErr: # pmGetInDom is expected to fail for non-instance (PM_INDOM_NULL) metrics
+ new_instanceid = 'PCP:'+metric
+ if (selected_instanceid is None or
+ new_instanceid == selected_instanceid):
+ model['InstanceNumber'] = pywbem.CIMProperty(name='InstanceNumber',
+ value=None,type='uint32')
+ model['InstanceName'] = pywbem.CIMProperty(name='InstanceName',
+ value=None,type='string')
+ model['InstanceID'] = new_instanceid
+ if (not keys_only):
+ model['StatisticTime'] = PCP_CIMStatisticTime (results)
+ model['ValueString'] = PCP_CIMValueString (context, results, desc, None)
+ yield model
+
+# hooks for impersonating CIMProvider2 functions
+
+
+def MI_enumInstanceNames (env, op):
+ model = pywbem.CIMInstance(classname = op.classname, path=op)
+ for x in get_instance (env, op, model, True):
+ yield x.path
+
+def MI_enumInstances (env, op, plist):
+ model = pywbem.CIMInstance(classname = op.classname, path=op)
+ return get_instance (env, op, model, False)
+
+def MI_getInstance (env, op, plist):
+ proplist = None
+ if plist is not None:
+ proplist = [s.lower() for s in propertyList]
+ proplist+= [s.lower() for s in op.keybindings.keys()]
+ model = pywbem.CIMInstance(classname=op.classname, path=op,
+ property_list=proplist)
+ model.update(model.path.keybindings)
+ for x in get_instance (env, op, model, False):
+ return x # XXX: first one
+
+def MI_createInstance (env, pinst):
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED)
+
+def MI_modifyInstance (env, pinst, plist):
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED)
+
+def MI_deleteInstance (env, piname):
+ raise pywbem.CIMError(pywbem.CIM_ERR_NOT_SUPPORTED)
+
+# See also extra MI_* functions for associations, etc.;
+# cmpi-bindings.git swig/python/cmpi_pywbem_bindings.py