From b04d75b0200b2af845f993e3d5d861b0f91118c0 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Fri, 12 Apr 2013 10:24:27 +0200 Subject: Synchronize JobManager with storage. JobManager here is older version of the one in openlmi-storage. Let's sync it with the storage so I can use it from there. The patch includes: Fixed job expiration under SFCB. Added LMI_StorageJob.JobInParameters and .JobOutParameters properties. Allow python to exit the provider even if there are threads running. Fixed job returning an error Added possibility to set AffectedElements when a job finishes. Added workaround for rhbz#920763 --- src/python/openlmi/common/JobManager.py | 115 ++++++++++++++++++++++---------- 1 file changed, 80 insertions(+), 35 deletions(-) diff --git a/src/python/openlmi/common/JobManager.py b/src/python/openlmi/common/JobManager.py index a923f29..122fc7c 100644 --- a/src/python/openlmi/common/JobManager.py +++ b/src/python/openlmi/common/JobManager.py @@ -49,6 +49,7 @@ import pywbem import openlmi.common.cmpi_logging as cmpi_logging from pywbem.cim_provider2 import CIMProvider2 import socket +import traceback # Too many instance attributes # pylint: disable-msg=R0902 @@ -208,7 +209,7 @@ class Job(object): @cmpi_logging.trace_method def finish_method(self, new_state, return_value=None, return_type=None, - output_arguments=None, error=None): + output_arguments=None, error=None, affected_elements=None): """ Mark the job as finished, with given return value, output parameters and error. @@ -224,12 +225,18 @@ class Job(object): any output parameters. :param error: (``CIMError``) Error raised by the job. Can be None, when the job finished successfully. + :param affected_elements: (``array of CIMInstanceName``) New list of + affected elements to generate LMI_JobAffectedElement + association. If None, the old list, passed to constructor, remains + untouched. """ self.lock() self.return_value = return_value self.return_value_type = return_type self.output_arguments = output_arguments self.error = error + if affected_elements is not None: + self.affected_elements = affected_elements self.change_state(new_state, 100) self.unlock() @@ -310,14 +317,13 @@ class Job(object): self._restart_timer() self.unlock() - @cmpi_logging.trace_method def _expire(self): """ Callback when a Job completes and time_before_removal second passed. The job gets removed from its JobManager. """ - cmpi_logging.logger.debug("Got timeout for job %s: '%s', removing" - " the job" % (self.the_id, self.job_name)) + # We cannot log here, this method is executed in job's Timer thread, + # which is not registered at the cimom. self.job_manager.remove_job(self) @cmpi_logging.trace_method @@ -370,8 +376,16 @@ class Job(object): try: self._execute(*(self._execargs), **(self._execkwargs)) except pywbem.CIMError, error: + cmpi_logging.logger.trace_warn("Job.execute caught an CIMError %s", + str(error)) + cmpi_logging.logger.trace_verbose("traceback: %s", + traceback.format_exc()) self.finish_method(Job.STATE_FAILED, error=error) except Exception, ex: + cmpi_logging.logger.trace_warn("Job.execute caught an Exception %s", + str(ex)) + cmpi_logging.logger.trace_verbose("traceback: %s", + traceback.format_exc()) error = pywbem.CIMError(pywbem.CIM_ERR_FAILED, str(ex)) self.finish_method(Job.STATE_FAILED, error=error) @@ -455,18 +469,14 @@ class Job(object): namespace=self.job_manager.namespace) inst = pywbem.CIMInstance( classname="CIM_InstMethodCall", - path=path, - properties={ - 'MethodName' : self.method_name, - 'MethodParameters' : pywbem.CIMProperty( - name="MethodParameters", - type='instance', - value=self._get_method_params(False)), - 'PreCall' : True, - }) + path=path) src_instance = self._get_cim_instance() inst['SourceInstance'] = src_instance inst['SourceInstanceModelPath'] = str(src_instance.path) + inst['MethodName'] = self.method_name + inst['MethodParameters'] = self.get_method_params( + '__MethodParameters', True, False) + inst['PreCall'] = True return inst @cmpi_logging.trace_method @@ -484,22 +494,31 @@ class Job(object): namespace=self.job_manager.namespace) inst = pywbem.CIMInstance( classname="CIM_InstMethodCall", - path=path, - properties={ - 'MethodName' : self.method_name, - 'MethodParameters' : self._get_method_params(True), - 'PreCall' : False - }) + path=path) + src_instance = self._get_cim_instance() inst['SourceInstance'] = src_instance inst['SourceInstanceModelPath'] = str(src_instance.path) + inst['MethodName'] = self.method_name + inst['MethodParameters'] = self.get_method_params( + '__MethodParameters', True, True) + inst['PreCall'] = False if self.return_value_type is not None: inst['ReturnValueType'] = self.return_value_type if self.return_value is not None: - inst['ReturnValue'] = self.return_value + inst['ReturnValue'] = str(self.return_value) if self.error is not None: - inst['Error'] = self.error + path = pywbem.CIMInstanceName( + classname="CIM_Error", + host=socket.gethostname(), + namespace=self.job_manager.namespace) + err = pywbem.CIMInstance( + classname="CIM_Error", + path=path) + err['CIMStatusCode'] = pywbem.Uint32(self.error[0]) + err['Message'] = self.error[1] + inst['Error'] = [err, ] return inst @cmpi_logging.trace_method @@ -512,20 +531,31 @@ class Job(object): return self.job_manager.get_job_instance(self) @cmpi_logging.trace_method - def _get_method_params(self, output=True): + def get_method_params(self, class_name, include_input, include_output): """ - Assemble __MethodParameters for CIM_InstMethodCall indication. - - :rtype: CIMInstance of __MethodParameters. + Create a class of given name with all input or output parameters + of the asynchronous method. Typically used to assemble + CIM_ConcreteJob.JobInParameters or CIM_InstMethodCall.MethodParameters + values. + + :param class_name: (``string``) Name of the class to create. + :param input: (``boolean``) Whether input parameters should be + included in the returned class + :param output: (``boolean``) Whether output parameters should be + included in the returned class + :rtype: CIMInstance of the created class. """ + # TODO: this is workaround for bug #920763, use class_name + # when it's fixed + clsname = "CIM_ManagedElement" path = pywbem.CIMInstanceName( - classname="__MethodParameters", + classname=clsname, namespace=self.job_manager.namespace, - keybindings={}) - inst = pywbem.CIMInstance(classname="__MethodParameters", path=path) - for (name, value) in self.input_arguments.iteritems(): - inst[name] = value - if output: + inst = pywbem.CIMInstance(classname=clsname, path=path) + if include_input and self.input_arguments: + for (name, value) in self.input_arguments.iteritems(): + inst[name] = value + if include_output and self.output_arguments: # overwrite any input parameter for (name, value) in self.output_arguments.iteritems(): inst[name] = value @@ -633,7 +663,7 @@ class JobManager(object): # Start the worker thread (don't forget to register it at CIMOM) self.worker = threading.Thread(target=self._worker_main) - self.worker.daemon=True + self.worker.daemon = True self.worker.start() # Various classnames for job-related classes, with correct infixes. @@ -765,7 +795,6 @@ class JobManager(object): self.indication_manager.send_instmodification(prev_instance, current_instance, _id) - @cmpi_logging.trace_method def remove_job(self, job): """ Remove existing job. Note that jobs are removed automatically after a @@ -773,8 +802,8 @@ class JobManager(object): :param job: (``Job``) Job to remove. """ - cmpi_logging.logger.debug("Removing job %s: '%s'" - % (job.the_id, job.job_name)) + # We cannot log here, this method is executed in job's Timer thread, + # which is not registered at the cimom. del self.jobs[job.the_id] # The job may still be in the queue! # There is no way, how to remove it, it will be skipped by the @@ -964,6 +993,17 @@ class LMI_ConcreteJob(CIMProvider2): value=None, type='datetime') + if job.input_arguments: + model['JobInParameters'] = job.get_method_params( + "__JobInParameters", True, False) + + if job.job_state in Job.FINAL_STATES: + # assemble output parameters with return value + outparams = job.get_method_params("__JobOutParameters", False, True) + if job.return_value is not None: + outparams['__ReturnValue'] = job.return_value + model['JobOutParameters'] = outparams + model['TimeSubmitted'] = pywbem.CIMDateTime(job.time_submitted) # set correct state jobstate, opstate = self.get_job_states(job) @@ -1383,6 +1423,9 @@ class LMI_AffectedJobElement(CIMProvider2): raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "AffectingElement not found.") + if job.affected_elements is None: + raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, + "The AffectingElement has no AffectedElement.") if model['AffectedElement'] not in job.affected_elements: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "AffectedElement is not associated to AffectingElement.") @@ -1394,6 +1437,8 @@ class LMI_AffectedJobElement(CIMProvider2): """Enumerate instances.""" model.path.update({'AffectingElement': None, 'AffectedElement': None}) for job in self.job_manager.jobs.values(): + if job.affected_elements is None: + continue for element in job.affected_elements: model['AffectingElement'] = job.get_name() model['AffectedElement'] = element -- cgit From f128220b0d690f06d04816e8d217619a0c978091 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Fri, 12 Apr 2013 10:44:10 +0200 Subject: Updated the filter queries to match those in software provider. Both Storage and Software providers should use the same CQL filters for all job-realted indications. --- src/python/openlmi/common/JobManager.py | 41 ++++++++++++++++----------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/python/openlmi/common/JobManager.py b/src/python/openlmi/common/JobManager.py index 122fc7c..b4b7bb1 100644 --- a/src/python/openlmi/common/JobManager.py +++ b/src/python/openlmi/common/JobManager.py @@ -629,11 +629,11 @@ class JobManager(object): timeout. """ - IND_JOB_PERCENT_UPDATED = "JobPercentUpdated" - IND_JOB_SUCCEEDED = "JobSucceeded" - IND_JOB_FAILED = "JobFailed" - IND_JOB_CHANGED = "JobChanged" - IND_JOB_CREATED = "JobCreated" + IND_JOB_PERCENT_UPDATED = "PercentUpdated" + IND_JOB_SUCCEEDED = "Succeeded" + IND_JOB_FAILED = "Failed" + IND_JOB_CHANGED = "Changed" + IND_JOB_CREATED = "Created" @cmpi_logging.trace_method def __init__(self, name, namespace, indication_manager): @@ -686,7 +686,7 @@ class JobManager(object): filters = { self.IND_JOB_PERCENT_UPDATED: { "Query" : "SELECT * FROM CIM_InstModification WHERE " - "SourceInstance ISA CIM_ConcreteJob AND " + "SourceInstance ISA %(classname)s AND " "SourceInstance.CIM_ConcreteJob::PercentComplete <> " "PreviousInstance.CIM_ConcreteJob::PercentComplete", "Description" : "Modification of Percentage Complete for a " @@ -694,36 +694,35 @@ class JobManager(object): }, self.IND_JOB_SUCCEEDED: { "Query" : "SELECT * FROM CIM_InstModification WHERE " - "SourceInstance ISA CIM_ConcreteJob AND ANY " - "SourceInstance.CIM_ConcreteJob::OperationalStatus[*] = 17 " - "AND ANY " - "SourceInstance.CIM_ConcreteJob::OperationalStatus[*] = 2", - "Description": "Modification of Operational Status for a " - "Concrete Job to 'Complete' and 'OK'.", + "SourceInstance ISA %(classname)s AND " + "SourceInstance.CIM_ConcreteJob::JobState = 17", + "Description": "Modification of Job State for a " + "Concrete Job to 'Complete'.", }, self.IND_JOB_FAILED: { "Query" : "SELECT * FROM CIM_InstModification WHERE " - "SourceInstance ISA CIM_ConcreteJob AND ANY " - "SourceInstance.CIM_ConcreteJob::OperationalStatus[*] = 17 " - "AND ANY " - "SourceInstance.CIM_ConcreteJob::OperationalStatus[*] = 6", - "Description": "Modification of Operational Status for a " - "Concrete Job to 'Complete' and 'Error'.", + "SourceInstance ISA %(classname)s AND " + "SourceInstance.CIM_ConcreteJob::JobState = 10", + "Description": "Modification of Job State for a " + "Concrete Job to 'Exception'.", }, self.IND_JOB_CHANGED: { "Query" : "SELECT * FROM CIM_InstModification WHERE " - "SourceInstance ISA CIM_ConcreteJob AND " + "SourceInstance ISA %(classname)s AND " "SourceInstance.CIM_ConcreteJob::JobState <> " "PreviousInstance.CIM_ConcreteJob::JobState", "Description": "Modification of Job State for a ConcreteJob.", }, self.IND_JOB_CREATED: { "Query" : "SELECT * FROM CIM_InstCreation WHERE " - "SourceInstance ISA CIM_ConcreteJob", + "SourceInstance ISA %(classname)s", "Description": "Creation of a ConcreteJob.", }, } - self.indication_manager.add_filters(filters) + # add class name + for f in filters.itervalues(): + f['Query'] = f['Query'] % {"classname" : self.job_classname } + self.indication_manager.add_filters(self.job_classname, filters) @cmpi_logging.trace_method def get_providers(self): -- cgit From eb8ce5ef425908fee47b246e5b965746a4901060 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Fri, 12 Apr 2013 10:48:53 +0200 Subject: Added a log decorator to IndicationManager.__init__ --- src/python/openlmi/common/IndicationManager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/python/openlmi/common/IndicationManager.py b/src/python/openlmi/common/IndicationManager.py index dbe25f3..dda6b8e 100644 --- a/src/python/openlmi/common/IndicationManager.py +++ b/src/python/openlmi/common/IndicationManager.py @@ -252,6 +252,7 @@ class IndicationManager(singletonmixin.Singleton): """ SEVERITY_INFO = pywbem.Uint16(2) # CIM_Indication.PerceivedSeverity + @cmpi_logging.trace_method def __init__(self, env, nameprefix, namespace, ns_interop=None, queue=None): """ -- cgit From d84aedd0b4fa768b36a17fe39ef3d1c64a41eb45 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Fri, 12 Apr 2013 10:50:00 +0200 Subject: Removed logging from indication sender thread. When the method starts, the indication thread is not yet registered at CIMOM, that's done inside the method using AttachThread(). Therefore we should not log anything. --- src/python/openlmi/common/IndicationManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/python/openlmi/common/IndicationManager.py b/src/python/openlmi/common/IndicationManager.py index dda6b8e..b517373 100644 --- a/src/python/openlmi/common/IndicationManager.py +++ b/src/python/openlmi/common/IndicationManager.py @@ -669,7 +669,6 @@ class IndicationManager(singletonmixin.Singleton): return ( class_name in self._filters and fltr_id in self._filters[class_name]) - @cmpi_logging.trace_method def _send_indications_loop(self, broker): """ This method runs in its own thread. It just sends all enqueued -- cgit From 3cdf801f4f269a50fb1f55cfbf99bbd6810334db Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Fri, 12 Apr 2013 12:12:03 +0200 Subject: Fixed subscription check, the new IndicationManager has additional parameter. --- src/python/openlmi/common/JobManager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/python/openlmi/common/JobManager.py b/src/python/openlmi/common/JobManager.py index b4b7bb1..71c2df9 100644 --- a/src/python/openlmi/common/JobManager.py +++ b/src/python/openlmi/common/JobManager.py @@ -774,7 +774,8 @@ class JobManager(object): self.jobs[job.the_id] = job self.queue.put(job) # send indication - if self.indication_manager.is_subscribed(self.IND_JOB_CREATED): + if self.indication_manager.is_subscribed( + self.job_classname, self.IND_JOB_CREATED): job_instance = self.get_job_instance(job) self.indication_manager.send_instcreation( job_instance, self.IND_JOB_CREATED) -- cgit From 1b8ac75de453d41f5cc78695cb7f5cec476cf674 Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Tue, 16 Apr 2013 09:51:07 +0200 Subject: Fixed missing brace. --- src/python/openlmi/common/JobManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python/openlmi/common/JobManager.py b/src/python/openlmi/common/JobManager.py index 71c2df9..bb6fed8 100644 --- a/src/python/openlmi/common/JobManager.py +++ b/src/python/openlmi/common/JobManager.py @@ -550,7 +550,7 @@ class Job(object): clsname = "CIM_ManagedElement" path = pywbem.CIMInstanceName( classname=clsname, - namespace=self.job_manager.namespace, + namespace=self.job_manager.namespace) inst = pywbem.CIMInstance(classname=clsname, path=path) if include_input and self.input_arguments: for (name, value) in self.input_arguments.iteritems(): -- cgit From c14bd833b7b1b3b1283d116a87b6f293377f129b Mon Sep 17 00:00:00 2001 From: Radek Novacek Date: Mon, 8 Apr 2013 11:09:53 +0200 Subject: Support for using libopenlmicommon by external providers * add FindOpenLMI.cmake module * add pkgconfig for OpenLMI * add openlmi.c/h with exported functions * add symlink with major version to openlmicommon library Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=948948 --- CMakeLists.txt | 1 + cmake/modules/FindOpenLMI.cmake | 21 +++++ src/CMakeLists.txt | 16 +++- src/fan/LMI_FanAssociatedSensorProvider.c | 2 +- src/fan/LMI_FanSensorProvider.c | 2 +- src/globals.c | 98 --------------------- src/globals.h | 19 ++-- src/hardware/cpuinfo.h | 1 - src/hardware/dmidecode.h | 1 - src/hardware/lscpu.h | 1 - src/hardware/sysfs.h | 1 - src/openlmi.c | 139 ++++++++++++++++++++++++++++++ src/openlmi.h | 80 +++++++++++++++++ src/openlmi.pc.in | 10 +++ 14 files changed, 273 insertions(+), 119 deletions(-) create mode 100644 cmake/modules/FindOpenLMI.cmake delete mode 100644 src/globals.c create mode 100644 src/openlmi.c create mode 100644 src/openlmi.h create mode 100644 src/openlmi.pc.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 230ed26..b42debc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,3 +39,4 @@ install(PROGRAMS openlmi-register-pegasus DESTINATION libexec) install(FILES cmake/modules/OpenLMIMacros.cmake DESTINATION share/cmake/Modules) install(FILES cmake/modules/FindCMPI.cmake DESTINATION share/cmake/Modules) install(FILES cmake/modules/FindKonkretCMPI.cmake DESTINATION share/cmake/Modules) +install(FILES cmake/modules/FindOpenLMI.cmake DESTINATION share/cmake/Modules) diff --git a/cmake/modules/FindOpenLMI.cmake b/cmake/modules/FindOpenLMI.cmake new file mode 100644 index 0000000..d4338ca --- /dev/null +++ b/cmake/modules/FindOpenLMI.cmake @@ -0,0 +1,21 @@ + +find_path(OPENLMI_INCLUDE_DIR + NAMES openlmi.h + HINTS $ENV{OPENLMI_INCLUDE_DIR} + PATH_SUFFIXES include/openlmi + PATHS /usr /usr/local +) + +find_library(OPENLMICOMMON_LIBRARY + NAMES openlmicommon + HINTS $ENV{OPENLMI_LIB_DIR} + PATH_SUFFIXES lib64 lib + PATHS /usr /usr/local +) + +set(OPENLMI_LIBRARIES ${OPENLMICOMMON_LIBRARY}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OPENLMI DEFAULT_MSG OPENLMI_LIBRARIES OPENLMI_INCLUDE_DIR) + +mark_as_advanced(OPENLMI_INCLUDE_DIR OPENLMI_LIBRARIES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7318911..d5335a6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,13 +1,21 @@ -include_directories(.) +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMPI_INCLUDE_DIR}) add_library(openlmicommon SHARED - globals.c + openlmi.c ) -set_target_properties(openlmicommon PROPERTIES SOVERSION 0.0.1) +set(OPENLMICOMMON_VERSION_MAJOR 0) +set(OPENLMICOMMON_VERSION_MINOR 0) +set(OPENLMICOMMON_VERSION_PATCH 1) +set(OPENLMICOMMON_VERSION "${OPENLMICOMMON_VERSION_MAJOR}.${OPENLMICOMMON_VERSION_MINOR}.${OPENLMICOMMON_VERSION_PATCH}") + +set_target_properties(openlmicommon PROPERTIES VERSION ${OPENLMICOMMON_VERSION}) +set_target_properties(openlmicommon PROPERTIES SOVERSION ${OPENLMICOMMON_VERSION_MAJOR}) install(TARGETS openlmicommon DESTINATION lib${LIB_SUFFIX}) -install(FILES globals.h DESTINATION include/openlmi) +install(FILES openlmi.h DESTINATION include/openlmi) +configure_file(openlmi.pc.in openlmi.pc @ONLY) +install(FILES openlmi.pc DESTINATION lib${LIB_SUFFIX}/pkgconfig) if (WITH-FAN) add_subdirectory(fan) diff --git a/src/fan/LMI_FanAssociatedSensorProvider.c b/src/fan/LMI_FanAssociatedSensorProvider.c index d75bf5c..b462e83 100644 --- a/src/fan/LMI_FanAssociatedSensorProvider.c +++ b/src/fan/LMI_FanAssociatedSensorProvider.c @@ -21,7 +21,7 @@ #include #include "LMI_FanAssociatedSensor.h" #include "fan.h" -#include +#include "globals.h" static const CMPIBroker* _cb; diff --git a/src/fan/LMI_FanSensorProvider.c b/src/fan/LMI_FanSensorProvider.c index 47bd9d5..e63d266 100644 --- a/src/fan/LMI_FanSensorProvider.c +++ b/src/fan/LMI_FanSensorProvider.c @@ -22,7 +22,7 @@ #include #include "LMI_FanSensor.h" #include "fan.h" -#include +#include "globals.h" static const CMPIBroker* _cb = NULL; diff --git a/src/globals.c b/src/globals.c deleted file mode 100644 index 7e58817..0000000 --- a/src/globals.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: Radek Novacek - */ - -#include "globals.h" - -#include -#include -#include -#include -#include -#include -#include - -static char *_fqdn = NULL; -static int _log_level = DEBUG; - -char *getFQDN(void) -{ - struct utsname uts; - if ((uname(&uts) > 0) && (uts.nodename != NULL)) { - return strdup(uts.nodename); - } - char hostname[256]; - hostname[255] = '\0'; - if (gethostname(hostname, 255) == -1) { - // FIXME: what to do, if we can't use gethostname? - return NULL; - } - - struct addrinfo hints; - struct addrinfo *info = NULL, *p; - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; // either IPV4 or IPV6 - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = AI_CANONNAME; - - if (getaddrinfo(hostname, "http", &hints, &info) == 0) { - for (p = info; p != NULL; p = p->ai_next) { - if (p->ai_canonname && strstr(p->ai_canonname, "localhost") == NULL) { - char *dn = strdup(p->ai_canonname); - freeaddrinfo(info); - return dn; - } - } - } - if (info != NULL) { - freeaddrinfo(info); - } - return strdup(hostname); -} - -const char *get_system_name() -{ - if (_fqdn == NULL) { - _fqdn = getFQDN(); - } - return _fqdn; -} - -const char *get_system_creation_class_name() -{ - return "Linux_ComputerSystem"; -} - -void _debug(int level, const char *file, int line, const char *format, ...) -{ - if (level > _log_level) { - return; - } - FILE *trace_file = stderr; - const char *lvl[] = { "NONE", "ERROR", "WARNING", "DEBUG" }; - // TODO: use logger from sfcbd and pegasus - fprintf(trace_file, "[%s] %s:%d\t", lvl[level], file, line); - - va_list args; - va_start(args, format); - vfprintf(stderr, format, args); - va_end(args); - - fprintf(stderr, "\n"); -} diff --git a/src/globals.h b/src/globals.h index a1cb18c..094602f 100644 --- a/src/globals.h +++ b/src/globals.h @@ -21,19 +21,16 @@ #ifndef GLOBALS_H #define GLOBALS_H -const char *get_system_name(); +#include "openlmi.h" -const char *get_system_creation_class_name(); - -int log_level(void); -void set_log_level(int level); - -enum { NONE=0, ERROR, WARN, DEBUG }; -void _debug(int level, const char *file, int line, const char *format, ...); -#define debug(...) _debug(DEBUG, __FILE__, __LINE__, __VA_ARGS__) -#define warn(...) _debug(WARN, __FILE__, __LINE__, __VA_ARGS__) -#define error(...) _debug(ERROR, __FILE__, __LINE__, __VA_ARGS__) +// Shortcuts for functions and macros from openlmicommon library +#define get_system_creation_class_name lmi_get_system_creation_class_name +#define get_system_name lmi_get_system_name +#define debug lmi_debug +#define warn lmi_warn +#define error lmi_error #define ORGID "LMI" + #endif diff --git a/src/hardware/cpuinfo.h b/src/hardware/cpuinfo.h index 5ec5dd5..0b2f9ab 100644 --- a/src/hardware/cpuinfo.h +++ b/src/hardware/cpuinfo.h @@ -24,7 +24,6 @@ #include #include #include -#include "globals.h" #include "utils.h" diff --git a/src/hardware/dmidecode.h b/src/hardware/dmidecode.h index 9190ea4..a627553 100644 --- a/src/hardware/dmidecode.h +++ b/src/hardware/dmidecode.h @@ -24,7 +24,6 @@ #include #include #include -#include "globals.h" #include "utils.h" diff --git a/src/hardware/lscpu.h b/src/hardware/lscpu.h index 5dc5bd5..39c85b6 100644 --- a/src/hardware/lscpu.h +++ b/src/hardware/lscpu.h @@ -24,7 +24,6 @@ #include #include #include -#include "globals.h" #include "utils.h" diff --git a/src/hardware/sysfs.h b/src/hardware/sysfs.h index 0e0b523..028b559 100644 --- a/src/hardware/sysfs.h +++ b/src/hardware/sysfs.h @@ -27,7 +27,6 @@ #include #include #include -#include "globals.h" #include "utils.h" #define SYSFS_CPU_PATH "/sys/devices/system/cpu" diff --git a/src/openlmi.c b/src/openlmi.c new file mode 100644 index 0000000..786bdd2 --- /dev/null +++ b/src/openlmi.c @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Radek Novacek + */ + +#include "openlmi.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static char *_fqdn = NULL; +static int _log_level = _LMI_DEBUG_DEBUG; +static const CMPIBroker *_cb = NULL; +static char *_log_id = NULL; + +static char *getFQDN(void) +{ + struct utsname uts; + if ((uname(&uts) > 0) && (uts.nodename != NULL)) { + return strdup(uts.nodename); + } + char hostname[256]; + hostname[255] = '\0'; + if (gethostname(hostname, 255) == -1) { + // FIXME: what to do, if we can't use gethostname? + return NULL; + } + + struct addrinfo hints; + struct addrinfo *info = NULL, *p; + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; // either IPV4 or IPV6 + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_CANONNAME; + + if (getaddrinfo(hostname, "http", &hints, &info) == 0) { + for (p = info; p != NULL; p = p->ai_next) { + if (p->ai_canonname && strstr(p->ai_canonname, "localhost") == NULL) { + char *dn = strdup(p->ai_canonname); + freeaddrinfo(info); + return dn; + } + } + } + if (info != NULL) { + freeaddrinfo(info); + } + return strdup(hostname); +} + +const char *lmi_get_system_name() +{ + if (_fqdn == NULL) { + _fqdn = getFQDN(); + } + return _fqdn; +} + +const char *lmi_get_system_creation_class_name() +{ + return "Linux_ComputerSystem"; +} + +void lmi_init_logging(const char *log_id, const CMPIBroker *cb) +{ + if (_log_id != NULL) { + free(_log_id); + } + _log_id = strdup(log_id); + _cb = cb; +} + +int lmi_log_level(void) +{ + return _log_level; +} + +void lmi_set_log_level(int level) +{ + _log_level = level; +} + +void _lmi_debug(int level, const char *file, int line, const char *format, ...) +{ + const char *lvl[] = { "NONE", "ERROR", "INFO", "WARNING", "DEBUG" }; + if (level > 4) { + level = 4; + } + if (level < 1) { + level = 1; + } + + char *message, *text; + va_list args; + va_start(args, format); + vasprintf(&message, format, args); + va_end(args); + asprintf(&text, "[%s] %s:%d\t%s", lvl[level], file, line, message); + free(message); + + CMPIStatus rc; + rc.rc = CMPI_RC_OK; + if (_cb != NULL) { + // try to use standard CMPI logging + rc = _cb->eft->trace(_cb, CMPI_LEV_INFO, _log_id, text, NULL); + } + + if (_cb == NULL || rc.rc != CMPI_RC_OK) { + // Fallback to stderr + if (level > _log_level) { + free(text); + return; + } + + fprintf(stderr, "%s\n", text); + } + free(text); +} diff --git a/src/openlmi.h b/src/openlmi.h new file mode 100644 index 0000000..9b27d07 --- /dev/null +++ b/src/openlmi.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2012-2013 Red Hat, Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: Radek Novacek + */ + +#ifndef OPENLMI_H +#define OPENLMI_H + +#include + +/** + * This function returns FQDN (fully qualified domain name) of the machine + * + * @note Use this in the SystemName property of all provider created instances. + * + * @return The scoping System's Name. + */ +const char *lmi_get_system_name(); + +/** + * This function returns system creation class name + * + * @note Use this in the SystemCreationClassName property of all provider + * created instances. + * + * @return The scoping System's Creation class name. + */ +const char *lmi_get_system_creation_class_name(); + +/** + * To use standard CIMOM logging facility, broker must be assigned. Without + * calling this function, logging will go to stderr. + * + * \p log_id Identification of log messages + * \p cb CMPIBroker + */ +void lmi_init_logging(const char *log_id, const CMPIBroker *cb); + +/** + * Get currently set logging level + * + * @return logging level + */ +int lmi_log_level(void); + +/** + * Set logging level + * + * @param level new logging level + */ +void lmi_set_log_level(int level); + +enum { + _LMI_DEBUG_NONE=0, _LMI_DEBUG_ERROR, _LMI_DEBUG_WARN, + _LMI_DEBUG_INFO, _LMI_DEBUG_DEBUG +}; + +void _lmi_debug(int level, const char *file, int line, const char *format, ...); + +#define lmi_debug(...) _lmi_debug(_LMI_DEBUG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#define lmi_info(...) _lmi_debug(_LMI_DEBUG_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define lmi_warn(...) _lmi_debug(_LMI_DEBUG_WARN, __FILE__, __LINE__, __VA_ARGS__) +#define lmi_error(...) _lmi_debug(_LMI_DEBUG_ERROR, __FILE__, __LINE__, __VA_ARGS__) + +#endif diff --git a/src/openlmi.pc.in b/src/openlmi.pc.in new file mode 100644 index 0000000..939d672 --- /dev/null +++ b/src/openlmi.pc.in @@ -0,0 +1,10 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +includedir=${prefix}/include +libdir=${exec_prefix}/lib@LIB_SUFFIX@ + +Name: openlmi +Description: OpenLMI provider support +Version: @OPENLMICOMMON_VERSION@ +Libs: -L${libdir} -lopenlmicommon +CFlags: -I${includedir}/openlmi -- cgit