diff options
author | Peter Schiffer <pschiffe@redhat.com> | 2013-07-18 14:16:42 +0200 |
---|---|---|
committer | Peter Schiffer <pschiffe@redhat.com> | 2013-07-18 14:16:42 +0200 |
commit | abfad7fa25dc0e8bd2102105b72b63109d481882 (patch) | |
tree | b3bef03324392eacda3506d169d785ff6be47203 /src | |
parent | 16a7166cba8a6ac2ae11f7dbc61dde9eb6177cd8 (diff) | |
parent | 7c5b2d12272abd8f9dd0057ea10a8578f492d2dd (diff) | |
download | openlmi-providers-abfad7fa25dc0e8bd2102105b72b63109d481882.tar.gz openlmi-providers-abfad7fa25dc0e8bd2102105b72b63109d481882.tar.xz openlmi-providers-abfad7fa25dc0e8bd2102105b72b63109d481882.zip |
Merge branch 'master'
Diffstat (limited to 'src')
-rw-r--r-- | src/account/test/TestAccount.py | 8 | ||||
-rw-r--r-- | src/account/test/TestIndications.py | 100 | ||||
-rw-r--r-- | src/account/test/TestMemberOfGroup.py | 4 | ||||
-rw-r--r-- | src/account/test/common.py | 158 | ||||
-rw-r--r-- | src/account/test/methods.py | 37 | ||||
-rw-r--r-- | src/indmanager/ind_manager.c | 3 | ||||
-rw-r--r-- | src/logicalfile/LMI_DirectoryContainsFileProvider.c | 12 | ||||
-rw-r--r-- | src/logicalfile/LMI_FileIdentityProvider.c | 26 | ||||
-rw-r--r-- | src/logicalfile/LMI_RootDirectoryProvider.c | 12 | ||||
-rw-r--r-- | src/logicalfile/LMI_UnixDirectoryProvider.c | 7 | ||||
-rw-r--r-- | src/logicalfile/LMI_UnixFileProvider.c | 1 | ||||
-rw-r--r-- | src/logicalfile/file.c | 141 | ||||
-rw-r--r-- | src/logicalfile/file.h | 1 | ||||
-rw-r--r-- | src/logicalfile/test/README | 6 | ||||
-rw-r--r-- | src/logicalfile/test/test_base.py | 9 | ||||
-rw-r--r-- | src/logicalfile/test/test_basic.py | 97 | ||||
-rw-r--r-- | src/pcp/README | 52 | ||||
-rw-r--r-- | src/pcp/lmi/pcp/__init__.py | 25 | ||||
-rw-r--r-- | src/pcp/lmi/pcp/metric.py | 167 | ||||
-rw-r--r-- | src/pcp/openlmi-pcp-generate | 68 | ||||
-rw-r--r-- | src/pcp/openlmi-pcp.cron | 3 | ||||
-rw-r--r-- | src/pcp/setup.py | 19 |
22 files changed, 852 insertions, 104 deletions
diff --git a/src/account/test/TestAccount.py b/src/account/test/TestAccount.py index e6f0c14..5763c4d 100644 --- a/src/account/test/TestAccount.py +++ b/src/account/test/TestAccount.py @@ -55,7 +55,7 @@ class TestAccount(AccountBase): self.wbemconnection.InvokeMethod("CreateAccount", lams.path, Name=self.user_name, System=computer_system.path) # The user now should be created, check it - subprocess.check_call(["id", self.user_name]) + self.assertTrue(user_exists(self.user_name)) # now delete that user clean_account(self.user_name) @@ -69,9 +69,7 @@ class TestAccount(AccountBase): 'select * from LMI_Account where Name = "%s"' % self.user_name)[0] self.wbemconnection.DeleteInstance(i.path) # check if it was really deleted - c = subprocess.Popen(["id", self.user_name]) - c.communicate() - self.assertEqual(c.returncode, 1) + self.assertFalse(user_exists(self.user_name)) clean_account(self.user_name) def test_modify_account(self): @@ -82,9 +80,7 @@ class TestAccount(AccountBase): i = self.wbemconnection.ExecQuery('WQL', 'select * from LMI_Account where Name = "%s"' % self.user_name)[0] # gecos - print i["ElementName"] i["ElementName"] = "GECOS" - print i["ElementName"] self.wbemconnection.ModifyInstance(i) self.assertEqual(field_in_passwd(self.user_name, 4), "GECOS") # login shell diff --git a/src/account/test/TestIndications.py b/src/account/test/TestIndications.py new file mode 100644 index 0000000..7b34b2e --- /dev/null +++ b/src/account/test/TestIndications.py @@ -0,0 +1,100 @@ +# Copyright (C) 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: Roman Rakus <rrakus@redhat.com> +# + +from common import AccountBase +import time +from methods import * + +class TestIndications(AccountBase): + """ + Class for testing LMI_Account indications + """ + def test_check_good_filter(self): + """ + Account: Test good indication filter + """ + filter_name = "test_good_filter_%d" % time.time() * 1000 + sub = self.subscribe(filter_name, "select * from LMI_AccountInstanceCreationIndication where SourceInstance isa LMI_Account") + self.assertIsNotNone(sub) + self.unsubscribe(filter_name); + + def test_check_bad_filter(self): + """ + Account: Test bad indication filter + """ + pass + + def test_group_deletion_indication(self): + """ + Account: Test indication of group deletion + """ + create_group(self.group_name) + filter_name = "test_delete_group_%d" % time.time() * 1000 + sub = self.subscribe(filter_name, "select * from LMI_AccountInstanceDeletionIndication where SourceInstance isa LMI_Group") + clean_group(self.group_name) + indication = self.get_indication(10) + self.assertEqual(indication.classname, "LMI_AccountInstanceDeletionIndication") + self.assertIn("SourceInstance", indication.keys()) + self.assertTrue(indication["SourceInstance"] is not None) + self.assertEqual(indication["SourceInstance"]["Name"], self.group_name) + + def test_group_creation_indication(self): + """ + Account: Test indication of group creation + """ + clean_group(self.group_name) + filter_name = "test_create_group_%d" % time.time() * 1000 + sub = self.subscribe(filter_name, "select * from LMI_AccountInstanceCreationIndication where SourceInstance isa LMI_Group") + create_group(self.group_name) + indication = self.get_indication(10) + self.assertEqual(indication.classname, "LMI_AccountInstanceCreationIndication") + self.assertIn("SourceInstance", indication.keys()) + self.assertTrue(indication["SourceInstance"] is not None) + self.assertEqual(indication["SourceInstance"]["Name"], self.group_name) + clean_group(self.group_name) + + def test_account_deletion_indication(self): + """ + Account: Test indication of account deletion + """ + create_account(self.user_name) + filter_name = "test_delete_account_%d" % time.time() * 1000 + sub = self.subscribe(filter_name, "select * from LMI_AccountInstanceDeletionIndication where SourceInstance isa LMI_Account") + clean_account(self.user_name) + indication = self.get_indication(10) + self.assertEqual(indication.classname, "LMI_AccountInstanceDeletionIndication") + self.assertIn("SourceInstance", indication.keys()) + self.assertTrue(indication["SourceInstance"] is not None) + self.assertEqual(indication["SourceInstance"]["Name"], self.user_name) + + def test_account_creation_indication(self): + """ + Account: Test indication of account creation + """ + clean_account(self.user_name) + filter_name = "test_create_account_%d" % time.time() * 1000 + sub = self.subscribe(filter_name, "select * from LMI_AccountInstanceCreationIndication where SourceInstance isa LMI_Account") + create_account(self.user_name) + indication = self.get_indication(10) + self.assertEqual(indication.classname, "LMI_AccountInstanceCreationIndication") + self.assertIn("SourceInstance", indication.keys()) + self.assertTrue(indication["SourceInstance"] is not None) + self.assertEqual(indication["SourceInstance"]["Name"], self.user_name) + clean_account(self.user_name) + diff --git a/src/account/test/TestMemberOfGroup.py b/src/account/test/TestMemberOfGroup.py index 635ac24..211244e 100644 --- a/src/account/test/TestMemberOfGroup.py +++ b/src/account/test/TestMemberOfGroup.py @@ -53,9 +53,7 @@ class TestMemberOfGroup(AccountBase): 'select * from LMI_Account where Name = "%s"' % self.user_name)[0] self.wbemconnection.DeleteInstance(i.path) # check if it was really deleted - c = subprocess.Popen(["id", self.user_name]) - c.communicate() - self.assertEqual(c.returncode, 1) + self.assertFalse(user_exists(self.user_name)) clean_account(self.user_name) def test_user_in_groups(self): diff --git a/src/account/test/common.py b/src/account/test/common.py index c56e94d..39442af 100644 --- a/src/account/test/common.py +++ b/src/account/test/common.py @@ -21,11 +21,56 @@ import pywbem import os import unittest +import Queue +import random +import BaseHTTPServer +import socket +import threading """ Base class for all tests """ +class CIMListener(object): + """ CIM Listener + """ + class CIMHandler(BaseHTTPServer.BaseHTTPRequestHandler): + def do_POST(self): + data = self.rfile.read(int(self.headers['Content-Length'])) + tt = pywbem.parse_cim(pywbem.xml_to_tupletree(data)) + # Get the instance from CIM-XML, copied from + # http://sf.net/apps/mediawiki/pywbem/?title=Indications_Tutorial + insts = [x[1] for x in tt[2][2][0][2][2]] + for inst in insts: + self.callback(inst) + self.send_response(200) + self.end_headers() + + def log_message(self, format, *p): + # suppress log messages + pass + + def __init__(self, callback, http_port=5988): + self.address = ('', http_port) + self.CIMHandler.callback = callback + self.thread = None + self.server = None + + def start(self): + BaseHTTPServer.HTTPServer.allow_reuse_address = True + self.server = BaseHTTPServer.HTTPServer(self.address, self.CIMHandler) + self.thread = threading.Thread(target=self.server.serve_forever) + self.thread.start() + + def stop(self): + if self.server is not None: + self.server.shutdown() + self.server.socket.close() + if self.thread is not None: + self.thread.join() + + def running(self): + return self.thread is not None class AccountBase(unittest.TestCase): @@ -44,3 +89,116 @@ class AccountBase(unittest.TestCase): self.wbemconnection = pywbem.WBEMConnection(self.url, (self.username, self.password)) + # for indications + self.indication_port = random.randint(12000, 13000) + self.indication_queue = Queue.Queue() + self.listener = CIMListener( + callback=self._process_indication, + http_port=self.indication_port) + + self.subscribed = {} + + def tearDown(self): + self.listener.stop() + if self.subscribed: + for name in self.subscribed.keys(): + self.unsubscribe(name) + + def get_indication(self, timeout): + """ Wait for an indication for given nr. of seconds and return it.""" + try: + indication = self.indication_queue.get(timeout=timeout) + except Queue.Empty: + raise AssertionError("Timeout when waiting for indicaiton") + self.indication_queue.task_done() + return indication + + def subscribe(self, filter_name, query=None, querylang="DMTF:CQL"): + """ + Create indication subscription for given filter name. + """ + namespace = "root/PG_interop" + hostname = socket.gethostname() + + if query is not None: + # Create filter first + filterinst = pywbem.CIMInstance('CIM_IndicationFilter') + filterinst['CreationClassName'] = 'CIM_IndicationFilter' + filterinst['SystemCreationClassName'] = 'CIM_ComputerSystem' + filterinst['SystemName'] = hostname + filterinst['Name'] = filter_name + filterinst['Query'] = query + filterinst['QueryLanguage'] = querylang + filterinst['SourceNamespace'] = "root/cimv2"#namespace + cop = pywbem.CIMInstanceName('CIM_IndicationFilter') + cop.keybindings = { 'CreationClassName': 'CIM_IndicationFilter', + 'SystemClassName': 'CIM_ComputerSystem', + 'SystemName': hostname, + 'Name': filter_name + } + cop.namespace=namespace + filterinst.path = cop + indfilter = self.wbemconnection.CreateInstance(filterinst) + else: + # the filter is already created, assemble its name + indfilter = pywbem.CIMInstanceName( + classname="CIM_IndicationFilter", + namespace=namespace, + keybindings={ + 'CreationClassName': 'CIM_IndicationFilter', + 'SystemClassName': 'CIM_ComputerSystem', + 'SystemName': hostname, + 'Name': filter_name}) + + # create destination + destinst = pywbem.CIMInstance('CIM_ListenerDestinationCIMXML') + destinst['CreationClassName'] = 'CIM_ListenerDestinationCIMXML' + destinst['SystemCreationClassName'] = 'CIM_ComputerSystem' + destinst['SystemName'] = hostname + destinst['Name'] = filter_name + destinst['Destination'] = "http://localhost:%d" % (self.indication_port) + destinst['PersistenceType'] = pywbem.Uint16(3) # Transient + cop = pywbem.CIMInstanceName('CIM_ListenerDestinationCIMXML') + cop.keybindings = { 'CreationClassName':'CIM_ListenerDestinationCIMXML', + 'SystemClassName':'CIM_ComputerSystem', + 'SystemName':hostname, + 'Name':filter_name } + cop.namespace = namespace + destinst.path = cop + destname = self.wbemconnection.CreateInstance(destinst) + + # create the subscription + subinst = pywbem.CIMInstance('CIM_IndicationSubscription') + subinst['Filter'] = indfilter + subinst['Handler'] = destname + cop = pywbem.CIMInstanceName('CIM_IndicationSubscription') + cop.keybindings = { 'Filter': indfilter, + 'Handler': destname } + cop.namespace = namespace + subinst.path = cop + subscription = self.wbemconnection.CreateInstance(subinst) + + self.subscribed[filter_name] = [subscription, destname] + + # start listening + if not self.listener.running(): + self._start_listening() + return subscription + + def unsubscribe(self, filter_name): + """ + Unsubscribe fron given filter. + """ + _list = self.subscribed.pop(filter_name) + for instance in _list: + self.wbemconnection.DeleteInstance(instance) + + def _start_listening(self): + """ Start listening for incoming indications. """ + self.listener.start() + + def _process_indication(self, indication): + """ Callback to process one indication.""" + self.indication_queue.put(indication) + + diff --git a/src/account/test/methods.py b/src/account/test/methods.py index c0407df..ffb9f7d 100644 --- a/src/account/test/methods.py +++ b/src/account/test/methods.py @@ -20,6 +20,20 @@ import subprocess +def user_exists(username): + """ + Return true/false if user does/does not exists + """ + got = field_in_passwd(username, 0) + return got == username + +def group_exists(groupname): + """ + Return true/false if user does/does not exists + """ + got = field_in_group(groupname, 0) + return got == groupname + def field_in_passwd(username, number): """ Return numberth field in /etc/passwd for given username @@ -48,33 +62,36 @@ def clean_account(user_name): """ Force to delete testing account and remove home dir """ - subprocess.call(["userdel", "-fr", user_name]) - # groups should be expicitely deleted - subprocess.call(["groupdel", user_name]) - subprocess.call(["rm", "-fr", "/home/%s" %user_name]) + if user_exists(user_name): + subprocess.check_call(["userdel", "-fr", user_name]) + if group_exists(user_name): + # groups should be expicitely deleted + subprocess.check_call(["groupdel", user_name]) def add_user_to_group(user_name, group_name): """ Will add user to group """ - subprocess.call(["usermod", "-a", "-G", group_name, user_name]) + subprocess.check_call(["usermod", "-a", "-G", group_name, user_name]) def create_account(user_name): """ Force to create account; run clean_account before creation """ - clean_account(user_name) - subprocess.call(["useradd", user_name]) + if not user_exists(user_name): + subprocess.check_call(["useradd", user_name]) def clean_group(group_name): """ Force to delete testing group """ - subprocess.call(["groupdel", group_name]) + if group_exists(group_name): + subprocess.check_call(["groupdel", group_name]) def create_group(group_name): """ Force to create group """ - clean_group(group_name) - subprocess.call(["groupadd", group_name]) + if not group_exists(group_name): + subprocess.check_call(["groupadd", group_name]) + diff --git a/src/indmanager/ind_manager.c b/src/indmanager/ind_manager.c index d3a73e8..7e2cda3 100644 --- a/src/indmanager/ind_manager.c +++ b/src/indmanager/ind_manager.c @@ -582,6 +582,9 @@ char *get_classname(CMPISelectExp *se) #else char *select = (char*)CMGetCharsPtr(CMGetSelExpString(se, NULL), NULL); char *rest = NULL, *token = NULL, *ptr = select; + if (!ptr) { + return NULL; + } for (; ptr || strcasecmp(token, "from") != 0; ptr = NULL) { token = strtok_r(ptr, " ", &rest); if (!token) { diff --git a/src/logicalfile/LMI_DirectoryContainsFileProvider.c b/src/logicalfile/LMI_DirectoryContainsFileProvider.c index 1794ea8..46db891 100644 --- a/src/logicalfile/LMI_DirectoryContainsFileProvider.c +++ b/src/logicalfile/LMI_DirectoryContainsFileProvider.c @@ -127,7 +127,6 @@ static CMPIStatus associators( CMPIObjectPath *o; CMPIInstance *ci; CMPIStatus st; - CMPIData pathd; const char *ns = KNameSpace(cop); st = lmi_check_required(_cb, cop, LOGICALFILE); @@ -139,8 +138,7 @@ static CMPIStatus associators( CMReturn(CMPI_RC_OK); } - pathd = CMGetKey(cop, "Name", &st); - const char *path = KChars(pathd.value.string); + const char *path = get_string_property_from_op(cop, "Name"); CMPIObjectPath *refs[MAX_REFS]; unsigned int count; @@ -200,8 +198,6 @@ static CMPIStatus references( { LMI_DirectoryContainsFile lmi_dcf; CMPIStatus st; - CMPIData pathd; - CMPIData cd; const char *ns = KNameSpace(cop); /* GroupComponent */ @@ -225,10 +221,8 @@ static CMPIStatus references( return st; } - cd = CMGetKey(cop, "CreationClassName", &st); - const char *ccname = KChars(cd.value.string); - pathd = CMGetKey(cop, "Name", &st); - const char *path = KChars(pathd.value.string); + const char *ccname = get_string_property_from_op(cop, "CreationClassName"); + const char *path = get_string_property_from_op(cop, "Name"); char *fsname; if (get_fsname_from_path(path, &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); diff --git a/src/logicalfile/LMI_FileIdentityProvider.c b/src/logicalfile/LMI_FileIdentityProvider.c index fe3324f..d31c305 100644 --- a/src/logicalfile/LMI_FileIdentityProvider.c +++ b/src/logicalfile/LMI_FileIdentityProvider.c @@ -65,8 +65,6 @@ static CMPIStatus associators( CMPIInstance *ci; CMPIObjectPath *o; const char *ns = KNameSpace(cop); - CMPIData pathd; - CMPIData cd; char fileclass[BUFLEN]; char *fsname; @@ -83,10 +81,8 @@ static CMPIStatus associators( return st; } - pathd = CMGetKey(cop, "LFName", &st); - cd = CMGetKey(cop, "LFCreationClassName", &st); - const char *path = KChars(pathd.value.string); - const char *ccname = KChars(cd.value.string); + const char *path = get_string_property_from_op(cop, "LFName"); + const char *ccname = get_string_property_from_op(cop, "LFCreationClassName"); get_class_from_path(path, fileclass); if (get_fsname_from_path(path, &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); @@ -111,9 +107,7 @@ static CMPIStatus associators( return st; } - pathd = CMGetKey(cop, "Name", &st); - cd = CMGetKey(cop, "CreationClassName", &st); - const char *path = KChars(pathd.value.string); + const char *path = get_string_property_from_op(cop, "Name"); get_class_from_path(path, fileclass); if (get_fsname_from_path(path, &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); @@ -152,8 +146,6 @@ static CMPIStatus references( { LMI_FileIdentity lmi_fi; CMPIStatus st, res; - CMPIData pathd; - CMPIData cd; const char *ns = KNameSpace(cop); CMPIInstance *ci; CMPIObjectPath *o; @@ -181,10 +173,8 @@ static CMPIStatus references( return st; } - pathd = CMGetKey(cop, "LFName", &st); - cd = CMGetKey(cop, "LFCreationClassName", &st); - const char *path = KChars(pathd.value.string); - const char *ccname = KChars(cd.value.string); + const char *path = get_string_property_from_op(cop, "LFName"); + const char *ccname = get_string_property_from_op(cop, "LFCreationClassName"); get_class_from_path(path, fileclass); if (get_fsname_from_path(path, &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); @@ -212,10 +202,8 @@ static CMPIStatus references( return st; } - pathd = CMGetKey(cop, "Name", &st); - cd = CMGetKey(cop, "CreationClassName", &st); - const char *path = KChars(pathd.value.string); - const char *ccname = KChars(cd.value.string); + const char *path = get_string_property_from_op(cop, "Name"); + const char *ccname = get_string_property_from_op(cop, "CreationClassName"); if (get_fsname_from_path(path, &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); } diff --git a/src/logicalfile/LMI_RootDirectoryProvider.c b/src/logicalfile/LMI_RootDirectoryProvider.c index dc6cd6b..600f7a5 100644 --- a/src/logicalfile/LMI_RootDirectoryProvider.c +++ b/src/logicalfile/LMI_RootDirectoryProvider.c @@ -59,9 +59,7 @@ static CMPIStatus associators( const char *ns = KNameSpace(cop); const char *comp_ccname = get_system_creation_class_name(); - CMPIData pathd; - pathd = CMGetKey(cop, "Name", &st); - const char *path = KChars(pathd.value.string); + const char *path = get_string_property_from_op(cop, "Name"); char *fsname; if (get_fsname_from_path("/", &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); @@ -128,12 +126,8 @@ static CMPIStatus references( const char *comp_ccname = get_system_creation_class_name(); const char *ns = KNameSpace(cop); - CMPIData pathd; - CMPIData cd; - pathd = CMGetKey(cop, "Name", &st); - cd = CMGetKey(cop, "CreationClassName", &st); - const char *path = KChars(pathd.value.string); - const char *ccname = KChars(cd.value.string); + const char *path = get_string_property_from_op(cop, "Name"); + const char *ccname = get_string_property_from_op(cop, "CreationClassName"); char *fsname; if (get_fsname_from_path("/", &fsname) < 0) { CMReturnWithChars(_cb, CMPI_RC_ERR_FAILED, "Can't get filesystem name"); diff --git a/src/logicalfile/LMI_UnixDirectoryProvider.c b/src/logicalfile/LMI_UnixDirectoryProvider.c index 2628982..7face91 100644 --- a/src/logicalfile/LMI_UnixDirectoryProvider.c +++ b/src/logicalfile/LMI_UnixDirectoryProvider.c @@ -78,8 +78,7 @@ static CMPIStatus LMI_UnixDirectoryCreateInstance( LMI_UnixDirectory_InitFromInstance(&lmi_ud, _cb, ci); CMPIStatus st; CMPIObjectPath *iop = CMGetObjectPath(ci, &st); - CMPIData pathd = CMGetKey(iop, "Name", &st); - const char *path = KChars(pathd.value.string); + const char *path = get_string_property_from_op(iop, "Name"); if (mkdir(path, 0777) < 0) { char errmsg[BUFLEN]; @@ -107,9 +106,7 @@ static CMPIStatus LMI_UnixDirectoryDeleteInstance( const CMPIResult* cr, const CMPIObjectPath* cop) { - CMPIStatus st; - CMPIData pathd = CMGetKey(cop, "Name", &st); - const char *path = KChars(pathd.value.string); + const char *path = get_string_property_from_op(cop, "Name"); if (rmdir(path) < 0) { char errmsg[BUFLEN]; diff --git a/src/logicalfile/LMI_UnixFileProvider.c b/src/logicalfile/LMI_UnixFileProvider.c index ff9423b..97f651e 100644 --- a/src/logicalfile/LMI_UnixFileProvider.c +++ b/src/logicalfile/LMI_UnixFileProvider.c @@ -121,6 +121,7 @@ static CMPIStatus LMI_UnixFileGetInstance( snprintf(aux, BUFLEN, "Can't stat file: %s", path); CMReturnWithChars(_cb, CMPI_RC_ERR_NOT_FOUND, aux); } + LMI_UnixFile_Set_Name(&lmi_file, path); sprintf(aux, "%u", sb.st_uid); LMI_UnixFile_Set_UserID(&lmi_file, aux); sprintf(aux, "%u", sb.st_gid); diff --git a/src/logicalfile/file.c b/src/logicalfile/file.c index 64b7d52..e3be07f 100644 --- a/src/logicalfile/file.c +++ b/src/logicalfile/file.c @@ -19,52 +19,112 @@ */ #include "file.h" -static const char *LOGICALFILE_REQUIRED_NAMES[] = { - "CSCreationClassName", - "CSName", - "CreationClassName", - "FSCreationClassName", - "FSName", - "Name", - NULL -}; - -static const char *UNIXFILE_REQUIRED_NAMES[] = { - "CSCreationClassName", - "CSName", - "LFCreationClassName", - "FSCreationClassName", - "FSName", - "LFName", - NULL -}; - CMPIStatus lmi_check_required( const CMPIBroker *b, const CMPIObjectPath *o, const enum RequiredNames rn) { - const char **names; - - switch (rn) { - case LOGICALFILE: - names = LOGICALFILE_REQUIRED_NAMES; - break; - case UNIXFILE: - names = UNIXFILE_REQUIRED_NAMES; - break; - default: + const char *prop; + const char *errmsg = NULL; + char *path = NULL; + + /* check computer system creation class name */ + if (CMIsNullValue(CMGetKey(o, "CSCreationClassName", NULL))) { + errmsg = "CSCreationClassName is empty"; + goto done; + } + prop = get_string_property_from_op(o, "CSCreationClassName"); + if (strcmp(prop, lmi_get_system_creation_class_name())) { + errmsg = "Wrong CSCreationClassName"; + goto done; + } + + /* check fqdn */ + if (CMIsNullValue(CMGetKey(o, "CSName", NULL))) { + errmsg = "CSName is empty"; + goto done; + } + prop = get_string_property_from_op(o, "CSName"); + if (strcmp(prop, lmi_get_system_name())) { + errmsg = "Wrong CSName"; + goto done; + } + + if (rn == UNIXFILE) { + /* check creation class name */ + char fileclass[BUFLEN]; + if (CMIsNullValue(CMGetKey(o, "LFCreationClassName", NULL))) { + errmsg = "LFCreationClassName is empty"; + goto done; + } + prop = get_string_property_from_op(o, "LFCreationClassName"); + if (get_class_from_path(get_string_property_from_op(o, "LFName"), fileclass) != 0) { + errmsg = "Can't get class from path"; + goto done; + } + if (strcmp(prop, fileclass)) { + errmsg = "LFCreationClassName doesn't match the file's type"; + goto done; + } + if (CMIsNullValue(CMGetKey(o, "LFName", NULL))) { + errmsg = "LFName is empty"; + goto done; + } + if (get_fsname_from_path(get_string_property_from_op(o, "LFName"), &path) < 0) { + errmsg = "Can't get FSName from path"; + goto done; + } + } else if (rn == LOGICALFILE) { + /* check creation class name */ + if (CMIsNullValue(CMGetKey(o, "CreationClassName", NULL))) { + errmsg = "CreationClassName is empty"; + goto done; + } + prop = get_string_property_from_op(o, "CreationClassName"); + if (!CMClassPathIsA(b, o, prop, NULL)) { + errmsg = "CreationClassName and the class name don't match"; + goto done; + } + if (CMIsNullValue(CMGetKey(o, "Name", NULL))) { + errmsg = "Name is empty"; + goto done; + } + if (get_fsname_from_path(get_string_property_from_op(o, "Name"), &path) < 0) { + errmsg = "Can't get FSName from path"; + goto done; + } + } else { /* not possible! */ assert(0); - break; } - for (int i = 0; names[i]; i++) { - if (CMIsNullValue(CMGetKey(o, names[i], NULL))) { - char errmsg[BUFLEN]; - snprintf(errmsg, BUFLEN, "No '%s' specified", names[i]); - CMReturnWithChars(b, CMPI_RC_ERR_FAILED, errmsg); - } + /* check fs creation class name and fsname */ + if (CMIsNullValue(CMGetKey(o, "FSCreationClassName", NULL))) { + errmsg = "FSCreationClassName is empty"; + goto done; + } + prop = get_string_property_from_op(o, "FSCreationClassName"); + if (strcmp(prop, FSCREATIONCLASSNAME)) { + errmsg = "Wrong FSCreationClassName"; + goto done; + } + + if (CMIsNullValue(CMGetKey(o, "FSName", NULL))) { + errmsg = "FSName is empty"; + goto done; + } + prop = get_string_property_from_op(o, "FSName"); + if (strcmp(prop, path)) { + errmsg = "Wrong FSName"; + goto done; + } + +done: + if (path) { + free(path); + } + if (errmsg) { + CMReturnWithChars(b, CMPI_RC_ERR_FAILED, errmsg); } CMReturn(CMPI_RC_OK); } @@ -137,6 +197,13 @@ int get_fsname_from_path(const char *path, char **fsname) return rc; } +const char *get_string_property_from_op(const CMPIObjectPath *o, const char *prop) +{ + CMPIData d; + d = CMGetKey(o, prop, NULL); + return KChars(d.value.string); +} + void _dump_objectpath(const CMPIObjectPath *o) { printf("OP: %s\n", CMGetCharsPtr(o->ft->toString(o, NULL), NULL)); diff --git a/src/logicalfile/file.h b/src/logicalfile/file.h index df906c2..b7f8c50 100644 --- a/src/logicalfile/file.h +++ b/src/logicalfile/file.h @@ -105,6 +105,7 @@ void get_class_from_stat(const struct stat *, char *); int get_class_from_path(const char *, char *); int get_fsname_from_stat(const struct stat *, char **); int get_fsname_from_path(const char *, char **); +const char *get_string_property_from_op(const CMPIObjectPath *, const char *); void _dump_objectpath(const CMPIObjectPath *); diff --git a/src/logicalfile/test/README b/src/logicalfile/test/README index 54c7c92..3c5a32e 100644 --- a/src/logicalfile/test/README +++ b/src/logicalfile/test/README @@ -9,6 +9,10 @@ associations-related methods, they should all be tested from both sides, meaning that the respective associations should be called twice with both of their "arguments". +Dependencies +------------ +$ yum install python-pyudev + Usage ----- The tests must be run on the same machine as the CIMOM! @@ -25,4 +29,4 @@ LMI_LOGICALFILE_TESTDIR - Testing directory where all the files and testing will Running the tests: LMI_CIMOM_PASSWORD=opensesame \ LMI_LOGICALFILE_TESTDIR="/home/user/my-testing-dir" \ - python test/test_basic.py
\ No newline at end of file + python test/test_basic.py diff --git a/src/logicalfile/test/test_base.py b/src/logicalfile/test/test_base.py index 6d2f2a1..5c71196 100644 --- a/src/logicalfile/test/test_base.py +++ b/src/logicalfile/test/test_base.py @@ -21,6 +21,7 @@ import os import socket import unittest import subprocess +import pyudev class LogicalFileTestBase(unittest.TestCase): """ @@ -43,6 +44,14 @@ class LogicalFileTestBase(unittest.TestCase): if rc != 0: cls.selinux_enabled = False except: cls.selinux_enabled = False + ctx = pyudev.Context() + sb = os.stat(os.path.realpath(cls.testdir + "/..")) + device = pyudev.Device.from_device_number(ctx, "block", sb.st_dev) + dev_name = device.get("ID_FS_UUID_ENC") + if not dev_name: + cls.fsname = "DEVICE=" + device.get("DEVNAME") + else: + cls.fsname = "UUID=" + dev_name def setUp(self): pass diff --git a/src/logicalfile/test/test_basic.py b/src/logicalfile/test/test_basic.py index f14de6e..fc4d336 100644 --- a/src/logicalfile/test/test_basic.py +++ b/src/logicalfile/test/test_basic.py @@ -71,7 +71,7 @@ class TestLogicalFile(LogicalFileTestBase): 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', - 'FSName':'NotImportant', + 'FSName':self.fsname, 'CreationClassName':'LMI_UnixDirectory', 'Name':self.testdir }) @@ -152,7 +152,7 @@ class TestLogicalFile(LogicalFileTestBase): 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', - 'FSName':'NotImportant', + 'FSName':self.fsname, 'CreationClassName':f['class'], 'Name':f['path'] }) @@ -179,7 +179,7 @@ class TestLogicalFile(LogicalFileTestBase): 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', - 'FSName':'NotImportant', + 'FSName':self.fsname, 'CreationClassName':f['class'], 'Name':f['path'] }) @@ -218,7 +218,7 @@ class TestLogicalFile(LogicalFileTestBase): 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', - 'FSName':'NotImportant', + 'FSName':self.fsname, 'LFCreationClassName':f['class'], 'LFName':f['path'] }) @@ -249,7 +249,7 @@ class TestLogicalFile(LogicalFileTestBase): 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', - 'FSName':'NotImportant', + 'FSName':self.fsname, 'LFCreationClassName':f['class'], 'LFName':f['path'] }) @@ -320,5 +320,92 @@ class TestLogicalFile(LogicalFileTestBase): rmdir, '/cant/remove/me') + def _test_missing_or_wrong_properties(self, is_unixfile): + testfile = self.files['data'] + if is_unixfile: + prefix = 'LF' + clsname = 'LMI_UnixFile' + else: + prefix = '' + clsname = 'LMI_DataFile' + cop = pywbem.CIMInstanceName(classname=clsname, + namespace='root/cimv2', + keybindings={}) + + prop = 'CSCreationClassName' + self.assertRaisesRegexp(pywbem.CIMError, + '%s is empty' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = 'BadClass' + self.assertRaisesRegexp(pywbem.CIMError, + 'Wrong %s' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = self.SYSTEM_CLASS_NAME + + prop = 'CSName' + self.assertRaisesRegexp(pywbem.CIMError, + '%s is empty' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = 'BadClass' + self.assertRaisesRegexp(pywbem.CIMError, + 'Wrong %s' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = self.SYSTEM_NAME + + prop = prefix + 'CreationClassName' + self.assertRaisesRegexp(pywbem.CIMError, + '%s is empty' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = testfile['class'] + prop = prefix + 'Name' + cop.keybindings[prop] = self.files['dir']['path'] + if is_unixfile: + self.assertRaisesRegexp(pywbem.CIMError, + 'LFCreationClassName doesn\'t match', + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = testfile['path'] + + prop = 'FSCreationClassName' + self.assertRaisesRegexp(pywbem.CIMError, + '%s is empty' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = 'BadFS' + self.assertRaisesRegexp(pywbem.CIMError, + 'Wrong %s' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = 'LMI_LocalFileSystem' + + prop = 'FSName' + self.assertRaisesRegexp(pywbem.CIMError, + '%s is empty' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = 'BadFSName' + self.assertRaisesRegexp(pywbem.CIMError, + 'Wrong %s' % prop, + self.wbemconnection.GetInstance, + cop) + cop.keybindings[prop] = self.fsname + + # finally, test GetInstance on the correct object path + try: + self.wbemconnection.GetInstance(cop) + except pywbem.CIMError as pe: + self.fail(pe[1]) + + def test_unixfile_missing_or_wrong_properties(self): + self._test_missing_or_wrong_properties(True) + + def test_logicalfile_missing_or_wrong_properties(self): + self._test_missing_or_wrong_properties(False) + if __name__ == '__main__': unittest.main() diff --git a/src/pcp/README b/src/pcp/README new file mode 100644 index 0000000..1f5e225 --- /dev/null +++ b/src/pcp/README @@ -0,0 +1,52 @@ +CIM <-> PCP (http://oss.sgi.com/projects/pcp) bridge +<fche@redhat.com> + +The idea of the bridge is to create a suite of CIM classes (derived from +CIM_StatisticsData), each of which represents one PCP metric. There are +hundreds of these. (Since PCP metrics can come and go, the MOF and REG +files may be regenerated by a simple shell script at any with an enclosed +shell script.) + +Install PCP and start the pmcd service to start. We assume you're +already running OpenLMI / Pegasus with a client like YAWN and are far +more familiar with this WBEM business than the author. Install the +CIM <-> PCP bridge thusly: + + vi PCP_pmns2mofreg.sh # to fix the path to pcp-metric.py + sh PCP_pmns2mofreg.sh mof > PCP_Metric_PMNS.mof + sh PCP_pmns2mofreg.sh reg > PCP_Metric_PMNS.reg + openlmi-mof-register register *.mof *.reg + +For example, whereas PCP command line tools may show these sorts of results: + + % pminfo -dTf hinv.machine + + hinv.machine + Data Type: string InDom: PM_INDOM_NULL 0xffffffff + Semantics: discrete Units: none + Help: + machine name, IP35 if SGI SNIA, else simply linux + value "linux" + + % pminfo -dTf network.interface.total.bytes + network.interface.total.bytes + Data Type: 64-bit unsigned int InDom: 60.3 0xf000003 + Semantics: counter Units: byte + Help: + network total (in+out) bytes from /proc/net/dev per network interface + inst [0 or "eth0"] value 585236365 + inst [1 or "lo"] value 85894766 + +These same metrics would show up in the CIM namespace as classes + + PCP_Metric_hinv__machine +and PCP_Metric_network__interface__total__bytes + +with instances with InstanceIDs such as + + PCP:hinv.machine + PCP:network.interface.total.bytes:lo + PCP:network.interface.total.bytes:eth0 + +These currently supply a string-formatted value of the respective +metric measurement, an accurate StatisticTime, and other metadata. diff --git a/src/pcp/lmi/pcp/__init__.py b/src/pcp/lmi/pcp/__init__.py new file mode 100644 index 0000000..81de2e5 --- /dev/null +++ b/src/pcp/lmi/pcp/__init__.py @@ -0,0 +1,25 @@ +# PCP bridge Providers +# +# Copyright (C) 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: Frank Ch. Eigler <fche@redhat.com> +# + +""" +CIM providers for PCP metrics. +Part of OpenLMI project. +""" 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 diff --git a/src/pcp/openlmi-pcp-generate b/src/pcp/openlmi-pcp-generate new file mode 100644 index 0000000..8c53512 --- /dev/null +++ b/src/pcp/openlmi-pcp-generate @@ -0,0 +1,68 @@ +#! /bin/sh + +# This script refreshes WBEM/CIM MOF & REG files from the current PCP PMNS, +# if necessary, and reloads the new MOF/REGs into the CIMMON. +# +# The PCP PMNS changes infrequently (when the sysadmin manuall installs or +# removes pcp PMDA (agent) modules in /var/lib/pcp/pmdas/*). +# +# This script encodes the PCP->CIM metric name-mapping convention of replacing +# dots with double-underscores, which lmi/pcp/metric.py will dutifully undo. + +_LOCALSTATEDIR=/var +_DATADIR=/usr/share +NAME=openlmi-providers +PYTHON2_SITELIB=/usr/lib/python2.7/site-packages + +PCP_PMNS=$_LOCALSTATEDIR/lib/pcp/pmns/root +PCP_HOST=${1-localhost} # or local:// for pcp 3.9+ +BASEMOFFILE=$_DATADIR/$NAME/60_LMI_PCP.mof +MOFREGDIR=$_LOCALSTATEDIR/lib/$NAME +STAMPFILE=$MOFREGDIR/stamp +MOFFILE=$MOFREGDIR/60_LMI_PCP_PMNS.mof +REGFILE=$MOFREGDIR/60_LMI_PCP_PMNS.reg +PROVIDER=$PYTHON2_SITELIB/lmi/pcp/metric.py + +if [ ! -f $PROVIDER ]; then + echo "Cannot find $PROVIDER" 1>&2 + exit 1 +fi + +set -e + +echo Refreshing PCP_Metric CIMMON classes from current PCP PMNS + +# quick liveness test +pcp -h $PCP_HOST + +if [ -s $PCP_PMNS -a $PCP_PMNS -nt $STAMPFILE ]; then + if [ -f $MOFFILE -a -f $REGFILE ]; then + echo Unregistering $BASEMOFFILE + echo Unregistering previous $MOFFILE + echo Unregistering previous $REGFILE + openlmi-mof-register unregister $BASEMOFFILE $MOFFILE $REGFILE || : + fi + + echo Generating $MOFFILE + pminfo -h $PCP_HOST | sed -e 's,\.,__,g' | + awk '{print "class PCP_Metric_" $1 " : PCP_MetricValue { } ;" }' > $MOFFILE + + echo Generating $REGFILE + pminfo -h $PCP_HOST | sed -e 's,\.,__,g' | + awk '{print "[PCP_Metric_" $1 "]" + print " provider: '$PROVIDER'" + print " location: pyCmpiProvider" + print " type: instance" + print " namespace: root/cimv2" + print " group: pcp" + print ""}' > $REGFILE + + echo Registering $BASEMOFFILE + echo Registering new $MOFFILE + echo Registering new $REGFILE + openlmi-mof-register register $BASEMOFFILE $MOFFILE $REGFILE 2>&1 | # filter out two noise diagnostics + egrep -v 'Warning: the instance already exists.|In this implementation, that means it cannot be changed.' || : + touch $STAMPFILE +else + echo Doing nothing, $PCP_PMNS older than $STAMPFILE +fi diff --git a/src/pcp/openlmi-pcp.cron b/src/pcp/openlmi-pcp.cron new file mode 100644 index 0000000..a9691f0 --- /dev/null +++ b/src/pcp/openlmi-pcp.cron @@ -0,0 +1,3 @@ +#! /bin/sh + +openlmi-pcp-generate localhost >/dev/null 2>&1 diff --git a/src/pcp/setup.py b/src/pcp/setup.py new file mode 100644 index 0000000..9ffa320 --- /dev/null +++ b/src/pcp/setup.py @@ -0,0 +1,19 @@ +from setuptools import setup +setup( + name='lmi-pcp', + description='PCP metric providers', + author='Frank Ch. Eigler', + author_email='fche@redhat.com', + url='https://fedorahosted.org/openlmi/', + version='0.1', + namespace_packages=['lmi'], + packages=[ + 'lmi.pcp'], + install_requires=['lmi', 'pcp'], + license="LGPLv2+", + classifiers=[ + 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)', + 'Operating System :: POSIX :: Linux', + 'Topic :: System :: Systems Administration', + ] + ) |