diff --git a/CONTRIBUTORS.wrs b/CONTRIBUTORS.wrs new file mode 100644 index 00000000..a1b906d8 --- /dev/null +++ b/CONTRIBUTORS.wrs @@ -0,0 +1,7 @@ +The following contributors from Wind River have developed the seed code in this +repository. We look forward to community collaboration and contributions for +additional features, enhancements and refactoring. + +Contributors: +============= +Tao Liu diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..13efe1ce --- /dev/null +++ b/README.rst @@ -0,0 +1,5 @@ +========= +stx-fault +========= + +StarlingX Fault Management diff --git a/fm-api/.gitignore b/fm-api/.gitignore new file mode 100644 index 00000000..d328101d --- /dev/null +++ b/fm-api/.gitignore @@ -0,0 +1,6 @@ +!.distro +.distro/centos7/rpmbuild/RPMS +.distro/centos7/rpmbuild/SRPMS +.distro/centos7/rpmbuild/BUILD +.distro/centos7/rpmbuild/BUILDROOT +.distro/centos7/rpmbuild/SOURCES/fm-api*tar.gz diff --git a/fm-api/LICENSE b/fm-api/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/fm-api/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fm-api/PKG-INFO b/fm-api/PKG-INFO new file mode 100644 index 00000000..358e81d8 --- /dev/null +++ b/fm-api/PKG-INFO @@ -0,0 +1,14 @@ +Metadata-Version: 1.1 +Name: fm-api +Version: 1.0 +Summary: CGTS Platform Fault Management Python API Package +Home-page: +Author: Windriver +Author-email: info@windriver.com +License: Apache-2.0 + +Description: CGTS platform Fault Management Client Library that provides APIs \ + for applications to raise/clear/update active alarms. + + +Platform: UNKNOWN diff --git a/fm-api/centos/build_srpm.data b/fm-api/centos/build_srpm.data new file mode 100755 index 00000000..c5375f07 --- /dev/null +++ b/fm-api/centos/build_srpm.data @@ -0,0 +1,5 @@ +SRC_DIR="." +COPY_LIST="$PKG_BASE/LICENSE" +EXCLUDE_FILES_FROM_TAR="centos" + +TIS_PATCH_VER=13 diff --git a/fm-api/centos/fm-api.spec b/fm-api/centos/fm-api.spec new file mode 100644 index 00000000..f741f403 --- /dev/null +++ b/fm-api/centos/fm-api.spec @@ -0,0 +1,66 @@ +Summary: CGTS Platform Fault Management Python API Package +Name: fm-api +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +Source0: %{name}-%{version}.tar.gz +Source1: LICENSE + +%define debug_package %{nil} + +BuildRequires: python-setuptools + +%description +CGTS platform Fault Management Client Library that provides APIs +for applications to raise/clear/update active alarms. + +%package -n fm-api-doc +Summary: fm-api deploy doc +Group: doc +Provides: fm-api-doc + +%description -n fm-api-doc +Contains contansts which is to be used by fm-doc package to validate +the Alarms & Logs Doc Yaml file + +%define pythonroot /usr/lib64/python2.7/site-packages +%define cgcs_doc_deploy_dir /opt/deploy/cgcs_doc + +%prep +%setup + +%build +%{__python} setup.py build + +%install +%{__python} setup.py install --root=$RPM_BUILD_ROOT \ + --install-lib=%{pythonroot} \ + --prefix=/usr \ + --install-data=/usr/share \ + --single-version-externally-managed + +CGCS_DOC_DEPLOY=$RPM_BUILD_ROOT/%{cgcs_doc_deploy_dir} +install -d $CGCS_DOC_DEPLOY +# install constants.py in CGCS_DOC_DEPLOY_DIR +# used by fm-doc package to validate the Alarms & Logs Doc Yaml file +install -m 644 fm_api/constants.py $CGCS_DOC_DEPLOY + +%clean +rm -rf $RPM_BUILD_ROOT + +# Note: RPM package name is fm-api but import package name is fm_api so can't +# use '%{name}'. +%files +%license LICENSE +%defattr(-,root,root,-) +%dir %{pythonroot}/fm_api +%{pythonroot}/fm_api/* +%dir %{pythonroot}/fm_api-%{version}.0-py2.7.egg-info +%{pythonroot}/fm_api-%{version}.0-py2.7.egg-info/* + +%files -n fm-api-doc +%defattr(-,root,root,-) +%{cgcs_doc_deploy_dir}/* diff --git a/fm-api/fm_api/__init__.py b/fm-api/fm_api/__init__.py new file mode 100644 index 00000000..2104d0c7 --- /dev/null +++ b/fm-api/fm_api/__init__.py @@ -0,0 +1,11 @@ +# +# Copyright (c) 2013-2014 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2014 Wind River Inc. +# All Rights Reserved. +# diff --git a/fm-api/fm_api/constants.py b/fm-api/fm_api/constants.py new file mode 100755 index 00000000..7d18def9 --- /dev/null +++ b/fm-api/fm_api/constants.py @@ -0,0 +1,498 @@ +# +# Copyright (c) 2013-2017 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# -*- encoding: utf-8 -*- +# +# +# Author: Tao Liu +# +# This file contains CGTS alarm definitions. The alarm ids that used by Python +# applications are defined here. For a completed alarm id list see the alarm ids +# that used by the C/C++ applications defined in +# fm-common/sources/fmAlarm.h + +################################################################################ +# +# Please make sure that all FM_ALARM_ID_xxx entries in this file +# have a corresponding Alarm record entry in file events.yaml +# +################################################################################ + +# alarm sub entity types +FM_ENTITY_TYPE_SYSTEM = 'system' +FM_ENTITY_TYPE_HOST = 'host' +FM_ENTITY_TYPE_PORT = 'port' +FM_ENTITY_TYPE_INTERFACE = 'interface' +FM_ENTITY_TYPE_SERVICE = 'service' +FM_ENTITY_TYPE_AGENT = 'agent' +FM_ENTITY_TYPE_PROVIDERNET = 'providernet' +FM_ENTITY_TYPE_INSTANCE = 'instance' +FM_ENTITY_TYPE_CLUSTER = 'cluster' +FM_ENTITY_TYPE_NTP = 'ntp' +FM_ENTITY_TYPE_ML2DRIVER = 'ml2driver' +FM_ENTITY_TYPE_PV = 'pv' +FM_ENTITY_TYPE_BGP_PEER = "bgp-peer" +FM_ENTITY_TYPE_STORAGE_BACKEND = 'storage_backend' +FM_ENTITY_TYPE_SUBCLOUD = 'subcloud' + +# alarm service sub entity values +FM_SERVICE_NETWORKING = 'networking' + +# alarm_id = . +# = 000 - 999 +# = 000 999 +ALARM_GROUP_GENERAL = "100" +ALARM_GROUP_MAINTENANCE = "200" +ALARM_GROUP_BACKUP_RESTORE = "210" +ALARM_GROUP_SYSCONFIG = "250" +ALARM_GROUP_HOST_SERVICES = "270" +ALARM_GROUP_HYPERVISOR = "275" +ALARM_GROUP_DISTRIBUTED_CLOUD = "280" +ALARM_GROUP_NETWORK = "300" +ALARM_GROUP_HA = "400" +ALARM_GROUP_SECURITY = "500" +ALARM_GROUP_LICENSING = "600" +ALARM_GROUP_VM = "700" +ALARM_GROUP_STORAGE = "800" +ALARM_GROUP_SW_MGMT = "900" + + +# Maintenance Log id +FM_LOG_ID_HOST_DISCOVERED = ALARM_GROUP_MAINTENANCE + ".020" + +# System Config Alarm id +FM_ALARM_ID_SYSCONFIG_OUT_OF_DATE = ALARM_GROUP_SYSCONFIG + ".001" + +# This CONFIG_REQD alarm ID is deprecated and commented out to avoid its +# alarm id .010 from being unintentinally reused for some unrelated purpose. +# Deprecation followed the removal of the compute-config-complete command. +# FM_ALARM_ID_CONFIG_REQD = ALARM_GROUP_SYSCONFIG + ".010" + +FM_ALARM_ID_CEPH_CACHE_TIER_CONFIG_OUT_OF_DATE = ALARM_GROUP_SYSCONFIG + ".002" + +# Backup/Restore Alarm id +FM_ALARM_ID_BACKUP_IN_PROGRESS = ALARM_GROUP_BACKUP_RESTORE + ".001" + +# Backup/Restore Log id +FM_LOG_ID_RESTORE_COMPLETE = ALARM_GROUP_BACKUP_RESTORE + ".101" + +# Network alarm id +FM_ALARM_ID_NETWORK_PORT = ALARM_GROUP_NETWORK + ".001" +FM_ALARM_ID_NETWORK_INTERFACE = ALARM_GROUP_NETWORK + ".002" +FM_ALARM_ID_NETWORK_AGENT = ALARM_GROUP_NETWORK + ".003" +FM_ALARM_ID_NETWORK_PROVIDERNET = ALARM_GROUP_NETWORK + ".004" +FM_ALARM_ID_NETWORK_PROVIDERNET_CONNECTIVITY = ALARM_GROUP_NETWORK + ".005" +FM_ALARM_ID_NETWORK_ML2_DRIVER = ALARM_GROUP_NETWORK + ".010" +FM_ALARM_ID_NETWORK_OPENFLOW_CONTROLLER = ALARM_GROUP_NETWORK + ".012" +FM_ALARM_ID_NETWORK_OVSDB_MANAGER = ALARM_GROUP_NETWORK + ".014" +FM_ALARM_ID_NETWORK_BGP_PEER = ALARM_GROUP_NETWORK + ".016" + +# Storage alarm id +FM_ALARM_ID_STORAGE_CEPH_CRITICAL = ALARM_GROUP_STORAGE + ".010" +FM_ALARM_ID_STORAGE_CEPH_MAJOR = ALARM_GROUP_STORAGE + ".011" +FM_ALARM_ID_STORAGE_CEPH = ALARM_GROUP_STORAGE + ".001" +FM_ALARM_ID_STORAGE_IMAGE = ALARM_GROUP_STORAGE + ".002" +FM_ALARM_ID_STORAGE_CEPH_FREE_SPACE = ALARM_GROUP_STORAGE + ".003" +FM_ALARM_ID_STORAGE_CINDER_IO_BUILDING = ALARM_GROUP_STORAGE + ".100" +FM_ALARM_ID_STORAGE_CINDER_IO_LIMITING = ALARM_GROUP_STORAGE + ".101" +FM_ALARM_ID_STORAGE_PV_FAILED = ALARM_GROUP_STORAGE + ".102" +# Alarm .103 is reserved for LVM thin pool metadata alarm +FM_ALARM_ID_STORAGE_BACKEND_FAILED = ALARM_GROUP_STORAGE + ".104" + +# Host-Services alarm id +FM_ALARM_ID_HOST_SERVICES_FAILED = ALARM_GROUP_HOST_SERVICES + ".001" + +# Host-Services log id +FM_LOG_ID_HOST_SERVICES_FAILED = ALARM_GROUP_HOST_SERVICES + ".101" +FM_LOG_ID_HOST_SERVICES_ENABLED = ALARM_GROUP_HOST_SERVICES + ".102" +FM_LOG_ID_HOST_SERVICES_DISABLED = ALARM_GROUP_HOST_SERVICES + ".103" + +# Hypervisor log id +FM_LOG_ID_HYPERVISOR_STATE_CHANGE = ALARM_GROUP_HYPERVISOR + ".001" + +# Distributed Cloud alarm id +FM_ALARM_ID_DC_SUBCLOUD_OFFLINE = ALARM_GROUP_DISTRIBUTED_CLOUD + ".001" +FM_ALARM_ID_DC_SUBCLOUD_RESOURCE_OUT_OF_SYNC = ALARM_GROUP_DISTRIBUTED_CLOUD + ".002" + + +# VM alarm id +FM_ALARM_ID_VM_FAILED = ALARM_GROUP_VM + ".001" +FM_ALARM_ID_VM_PAUSED = ALARM_GROUP_VM + ".002" +FM_ALARM_ID_VM_SUSPENDED = ALARM_GROUP_VM + ".003" +FM_ALARM_ID_VM_STOPPED = ALARM_GROUP_VM + ".004" +FM_ALARM_ID_VM_REBOOTING = ALARM_GROUP_VM + ".005" +FM_ALARM_ID_VM_REBUILDING = ALARM_GROUP_VM + ".006" +FM_ALARM_ID_VM_EVACUATING = ALARM_GROUP_VM + ".007" +FM_ALARM_ID_VM_LIVE_MIGRATING = ALARM_GROUP_VM + ".008" +FM_ALARM_ID_VM_COLD_MIGRATING = ALARM_GROUP_VM + ".009" +FM_ALARM_ID_VM_COLD_MIGRATED = ALARM_GROUP_VM + ".010" +FM_ALARM_ID_VM_COLD_MIGRATE_REVERTING = ALARM_GROUP_VM + ".011" +FM_ALARM_ID_VM_RESIZING = ALARM_GROUP_VM + ".012" +FM_ALARM_ID_VM_RESIZED = ALARM_GROUP_VM + ".013" +FM_ALARM_ID_VM_RESIZE_REVERTING = ALARM_GROUP_VM + ".014" +FM_ALARM_ID_VM_GUEST_HEARTBEAT = ALARM_GROUP_VM + ".015" +FM_ALARM_ID_VM_MULTI_NODE_RECOVERY_MODE = ALARM_GROUP_VM + ".016" +FM_ALARM_ID_VM_GROUP_POLICY_CONFLICT = ALARM_GROUP_VM + ".017" + +# VM log id +FM_LOG_ID_VM_ENABLED = ALARM_GROUP_VM + ".101" +FM_LOG_ID_VM_FAILED = ALARM_GROUP_VM + ".102" +FM_LOG_ID_VM_CREATE = ALARM_GROUP_VM + ".103" +FM_LOG_ID_VM_CREATING = ALARM_GROUP_VM + ".104" +FM_LOG_ID_VM_CREATE_REJECTED = ALARM_GROUP_VM + ".105" +FM_LOG_ID_VM_CREATE_CANCELLED = ALARM_GROUP_VM + ".106" +FM_LOG_ID_VM_CREATE_FAILED = ALARM_GROUP_VM + ".107" +FM_LOG_ID_VM_CREATED = ALARM_GROUP_VM + ".108" +FM_LOG_ID_VM_DELETE = ALARM_GROUP_VM + ".109" +FM_LOG_ID_VM_DELETING = ALARM_GROUP_VM + ".110" +FM_LOG_ID_VM_DELETE_REJECTED = ALARM_GROUP_VM + ".111" +FM_LOG_ID_VM_DELETE_CANCELLED = ALARM_GROUP_VM + ".112" +FM_LOG_ID_VM_DELETE_FAILED = ALARM_GROUP_VM + ".113" +FM_LOG_ID_VM_DELETED = ALARM_GROUP_VM + ".114" +FM_LOG_ID_VM_PAUSE = ALARM_GROUP_VM + ".115" +FM_LOG_ID_VM_PAUSING = ALARM_GROUP_VM + ".116" +FM_LOG_ID_VM_PAUSE_REJECTED = ALARM_GROUP_VM + ".117" +FM_LOG_ID_VM_PAUSE_CANCELLED = ALARM_GROUP_VM + ".118" +FM_LOG_ID_VM_PAUSE_FAILED = ALARM_GROUP_VM + ".119" +FM_LOG_ID_VM_PAUSED = ALARM_GROUP_VM + ".120" +FM_LOG_ID_VM_UNPAUSE = ALARM_GROUP_VM + ".121" +FM_LOG_ID_VM_UNPAUSING = ALARM_GROUP_VM + ".122" +FM_LOG_ID_VM_UNPAUSE_REJECTED = ALARM_GROUP_VM + ".123" +FM_LOG_ID_VM_UNPAUSE_CANCELLED = ALARM_GROUP_VM + ".124" +FM_LOG_ID_VM_UNPAUSE_FAILED = ALARM_GROUP_VM + ".125" +FM_LOG_ID_VM_UNPAUSED = ALARM_GROUP_VM + ".126" +FM_LOG_ID_VM_SUSPEND = ALARM_GROUP_VM + ".127" +FM_LOG_ID_VM_SUSPENDING = ALARM_GROUP_VM + ".128" +FM_LOG_ID_VM_SUSPEND_REJECTED = ALARM_GROUP_VM + ".129" +FM_LOG_ID_VM_SUSPEND_CANCELLED = ALARM_GROUP_VM + ".130" +FM_LOG_ID_VM_SUSPEND_FAILED = ALARM_GROUP_VM + ".131" +FM_LOG_ID_VM_SUSPENDED = ALARM_GROUP_VM + ".132" +FM_LOG_ID_VM_RESUME = ALARM_GROUP_VM + ".133" +FM_LOG_ID_VM_RESUMING = ALARM_GROUP_VM + ".134" +FM_LOG_ID_VM_RESUME_REJECTED = ALARM_GROUP_VM + ".135" +FM_LOG_ID_VM_RESUME_CANCELLED = ALARM_GROUP_VM + ".136" +FM_LOG_ID_VM_RESUME_FAILED = ALARM_GROUP_VM + ".137" +FM_LOG_ID_VM_RESUMED = ALARM_GROUP_VM + ".138" +FM_LOG_ID_VM_START = ALARM_GROUP_VM + ".139" +FM_LOG_ID_VM_STARTING = ALARM_GROUP_VM + ".140" +FM_LOG_ID_VM_START_REJECTED = ALARM_GROUP_VM + ".141" +FM_LOG_ID_VM_START_CANCELLED = ALARM_GROUP_VM + ".142" +FM_LOG_ID_VM_START_FAILED = ALARM_GROUP_VM + ".143" +FM_LOG_ID_VM_STARTED = ALARM_GROUP_VM + ".144" +FM_LOG_ID_VM_STOP = ALARM_GROUP_VM + ".145" +FM_LOG_ID_VM_STOPPING = ALARM_GROUP_VM + ".146" +FM_LOG_ID_VM_STOP_REJECTED = ALARM_GROUP_VM + ".147" +FM_LOG_ID_VM_STOP_CANCELLED = ALARM_GROUP_VM + ".148" +FM_LOG_ID_VM_STOP_FAILED = ALARM_GROUP_VM + ".149" +FM_LOG_ID_VM_STOPPED = ALARM_GROUP_VM + ".150" +FM_LOG_ID_VM_LIVE_MIGRATE = ALARM_GROUP_VM + ".151" +FM_LOG_ID_VM_LIVE_MIGRATING = ALARM_GROUP_VM + ".152" +FM_LOG_ID_VM_LIVE_MIGRATE_REJECTED = ALARM_GROUP_VM + ".153" +FM_LOG_ID_VM_LIVE_MIGRATE_CANCELLED = ALARM_GROUP_VM + ".154" +FM_LOG_ID_VM_LIVE_MIGRATE_FAILED = ALARM_GROUP_VM + ".155" +FM_LOG_ID_VM_LIVE_MIGRATED = ALARM_GROUP_VM + ".156" +FM_LOG_ID_VM_COLD_MIGRATE = ALARM_GROUP_VM + ".157" +FM_LOG_ID_VM_COLD_MIGRATING = ALARM_GROUP_VM + ".158" +FM_LOG_ID_VM_COLD_MIGRATE_REJECTED = ALARM_GROUP_VM + ".159" +FM_LOG_ID_VM_COLD_MIGRATE_CANCELLED = ALARM_GROUP_VM + ".160" +FM_LOG_ID_VM_COLD_MIGRATE_FAILED = ALARM_GROUP_VM + ".161" +FM_LOG_ID_VM_COLD_MIGRATED = ALARM_GROUP_VM + ".162" +FM_LOG_ID_VM_COLD_MIGRATE_CONFIRM = ALARM_GROUP_VM + ".163" +FM_LOG_ID_VM_COLD_MIGRATE_CONFIRMING = ALARM_GROUP_VM + ".164" +FM_LOG_ID_VM_COLD_MIGRATE_CONFIRM_REJECTED = ALARM_GROUP_VM + ".165" +FM_LOG_ID_VM_COLD_MIGRATE_CONFIRM_CANCELLED = ALARM_GROUP_VM + ".166" +FM_LOG_ID_VM_COLD_MIGRATE_CONFIRM_FAILED = ALARM_GROUP_VM + ".167" +FM_LOG_ID_VM_COLD_MIGRATE_CONFIRMED = ALARM_GROUP_VM + ".168" +FM_LOG_ID_VM_COLD_MIGRATE_REVERT = ALARM_GROUP_VM + ".169" +FM_LOG_ID_VM_COLD_MIGRATE_REVERTING = ALARM_GROUP_VM + ".170" +FM_LOG_ID_VM_COLD_MIGRATE_REVERT_REJECTED = ALARM_GROUP_VM + ".171" +FM_LOG_ID_VM_COLD_MIGRATE_REVERT_CANCELLED = ALARM_GROUP_VM + ".172" +FM_LOG_ID_VM_COLD_MIGRATE_REVERT_FAILED = ALARM_GROUP_VM + ".173" +FM_LOG_ID_VM_COLD_MIGRATE_REVERTED = ALARM_GROUP_VM + ".174" +FM_LOG_ID_VM_EVACUATE = ALARM_GROUP_VM + ".175" +FM_LOG_ID_VM_EVACUATING = ALARM_GROUP_VM + ".176" +FM_LOG_ID_VM_EVACUATE_REJECTED = ALARM_GROUP_VM + ".177" +FM_LOG_ID_VM_EVACUATE_CANCELLED = ALARM_GROUP_VM + ".178" +FM_LOG_ID_VM_EVACUATE_FAILED = ALARM_GROUP_VM + ".179" +FM_LOG_ID_VM_EVACUATED = ALARM_GROUP_VM + ".180" +FM_LOG_ID_VM_REBOOT = ALARM_GROUP_VM + ".181" +FM_LOG_ID_VM_REBOOTING = ALARM_GROUP_VM + ".182" +FM_LOG_ID_VM_REBOOT_REJECTED = ALARM_GROUP_VM + ".183" +FM_LOG_ID_VM_REBOOT_CANCELLED = ALARM_GROUP_VM + ".184" +FM_LOG_ID_VM_REBOOT_FAILED = ALARM_GROUP_VM + ".185" +FM_LOG_ID_VM_REBOOTED = ALARM_GROUP_VM + ".186" +FM_LOG_ID_VM_REBUILD = ALARM_GROUP_VM + ".187" +FM_LOG_ID_VM_REBUILDING = ALARM_GROUP_VM + ".188" +FM_LOG_ID_VM_REBUILD_REJECTED = ALARM_GROUP_VM + ".189" +FM_LOG_ID_VM_REBUILD_CANCELLED = ALARM_GROUP_VM + ".190" +FM_LOG_ID_VM_REBUILD_FAILED = ALARM_GROUP_VM + ".191" +FM_LOG_ID_VM_REBUILT = ALARM_GROUP_VM + ".192" +FM_LOG_ID_VM_RESIZE = ALARM_GROUP_VM + ".193" +FM_LOG_ID_VM_RESIZING = ALARM_GROUP_VM + ".194" +FM_LOG_ID_VM_RESIZE_REJECTED = ALARM_GROUP_VM + ".195" +FM_LOG_ID_VM_RESIZE_CANCELLED = ALARM_GROUP_VM + ".196" +FM_LOG_ID_VM_RESIZE_FAILED = ALARM_GROUP_VM + ".197" +FM_LOG_ID_VM_RESIZED = ALARM_GROUP_VM + ".198" +FM_LOG_ID_VM_RESIZE_CONFIRM = ALARM_GROUP_VM + ".199" +FM_LOG_ID_VM_RESIZE_CONFIRMING = ALARM_GROUP_VM + ".200" +FM_LOG_ID_VM_RESIZE_CONFIRM_REJECTED = ALARM_GROUP_VM + ".201" +FM_LOG_ID_VM_RESIZE_CONFIRM_CANCELLED = ALARM_GROUP_VM + ".202" +FM_LOG_ID_VM_RESIZE_CONFIRM_FAILED = ALARM_GROUP_VM + ".203" +FM_LOG_ID_VM_RESIZE_CONFIRMED = ALARM_GROUP_VM + ".204" +FM_LOG_ID_VM_RESIZE_REVERT = ALARM_GROUP_VM + ".205" +FM_LOG_ID_VM_RESIZE_REVERTING = ALARM_GROUP_VM + ".206" +FM_LOG_ID_VM_RESIZE_REVERT_REJECTED = ALARM_GROUP_VM + ".207" +FM_LOG_ID_VM_RESIZE_REVERT_CANCELLED = ALARM_GROUP_VM + ".208" +FM_LOG_ID_VM_RESIZE_REVERT_FAILED = ALARM_GROUP_VM + ".209" +FM_LOG_ID_VM_RESIZE_REVERTED = ALARM_GROUP_VM + ".210" +FM_LOG_ID_VM_GUEST_HEARTBEAT_ESTABLISHED = ALARM_GROUP_VM + ".211" +FM_LOG_ID_VM_GUEST_HEARTBEAT_DISCONNECTED = ALARM_GROUP_VM + ".212" +FM_LOG_ID_VM_GUEST_HEARTBEAT_FAILED = ALARM_GROUP_VM + ".213" +FM_LOG_ID_VM_RENAMED = ALARM_GROUP_VM + ".214" +FM_LOG_ID_VM_GUEST_HEALTH_CHECK_FAILED = ALARM_GROUP_VM + ".215" +FM_LOG_ID_VM_MULTI_NODE_RECOVERY_MODE_ENTER = ALARM_GROUP_VM + ".216" +FM_LOG_ID_VM_MULTI_NODE_RECOVERY_MODE_EXIT = ALARM_GROUP_VM + ".217" + + +# Patching alarm id +FM_ALARM_ID_PATCH_IN_PROGRESS = ALARM_GROUP_SW_MGMT + ".001" +FM_ALARM_ID_PATCH_HOST_INSTALL_FAILED = ALARM_GROUP_SW_MGMT + ".002" +FM_ALARM_ID_PATCH_OBS_IN_SYSTEM = ALARM_GROUP_SW_MGMT + ".003" + +# Upgrades alarm id +FM_ALARM_ID_HOST_VERSION_MISMATCH = ALARM_GROUP_SW_MGMT + ".004" +FM_ALARM_ID_UPGRADE_IN_PROGRESS = ALARM_GROUP_SW_MGMT + ".005" + +# Security log id +FM_LOG_ID_INVALID_PASSWORD = ALARM_GROUP_SECURITY + ".001" +FM_LOG_ID_USER_LOCKOUT = ALARM_GROUP_SECURITY + ".002" + + +# Security alarm id +FM_ALARM_ID_TPM_INIT = ALARM_GROUP_SECURITY + ".100" + +# Security nonstandard certificate in use for patching alarm id +FM_ALARM_ID_NONSTANDARD_CERT_PATCH = ALARM_GROUP_SECURITY + ".101" + +# Software Update Orchestration +FM_ALARM_ID_SW_PATCH_AUTO_APPLY_INPROGRESS = ALARM_GROUP_SW_MGMT + ".101" +FM_ALARM_ID_SW_PATCH_AUTO_APPLY_ABORTING = ALARM_GROUP_SW_MGMT + ".102" +FM_ALARM_ID_SW_PATCH_AUTO_APPLY_FAILED = ALARM_GROUP_SW_MGMT + ".103" + +FM_LOG_ID_SW_PATCH_AUTO_APPLY_START = ALARM_GROUP_SW_MGMT + ".111" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_INPROGRESS = ALARM_GROUP_SW_MGMT + ".112" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_REJECTED = ALARM_GROUP_SW_MGMT + ".113" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_CANCELLED = ALARM_GROUP_SW_MGMT + ".114" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_FAILED = ALARM_GROUP_SW_MGMT + ".115" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_COMPLETED = ALARM_GROUP_SW_MGMT + ".116" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_ABORT = ALARM_GROUP_SW_MGMT + ".117" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_ABORTING = ALARM_GROUP_SW_MGMT + ".118" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_ABORT_REJECTED = ALARM_GROUP_SW_MGMT + ".119" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_ABORT_FAILED = ALARM_GROUP_SW_MGMT + ".120" +FM_LOG_ID_SW_PATCH_AUTO_APPLY_ABORTED = ALARM_GROUP_SW_MGMT + ".121" + +FM_ALARM_ID_SW_UPGRADE_AUTO_APPLY_INPROGRESS = ALARM_GROUP_SW_MGMT + ".201" +FM_ALARM_ID_SW_UPGRADE_AUTO_APPLY_ABORTING = ALARM_GROUP_SW_MGMT + ".202" +FM_ALARM_ID_SW_UPGRADE_AUTO_APPLY_FAILED = ALARM_GROUP_SW_MGMT + ".203" + +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_START = ALARM_GROUP_SW_MGMT + ".211" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_INPROGRESS = ALARM_GROUP_SW_MGMT + ".212" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_REJECTED = ALARM_GROUP_SW_MGMT + ".213" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_CANCELLED = ALARM_GROUP_SW_MGMT + ".214" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_FAILED = ALARM_GROUP_SW_MGMT + ".215" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_COMPLETED = ALARM_GROUP_SW_MGMT + ".216" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_ABORT = ALARM_GROUP_SW_MGMT + ".217" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_ABORTING = ALARM_GROUP_SW_MGMT + ".218" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_ABORT_REJECTED = ALARM_GROUP_SW_MGMT + ".219" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_ABORT_FAILED = ALARM_GROUP_SW_MGMT + ".220" +FM_LOG_ID_SW_UPGRADE_AUTO_APPLY_ABORTED = ALARM_GROUP_SW_MGMT + ".221" + + +FM_ALARM_STATE_SET = 'set' +FM_ALARM_STATE_CLEAR = 'clear' +FM_ALARM_STATE_MSG = 'msg' + +FM_ALARM_TYPE_0 = 'other' +FM_ALARM_TYPE_1 = 'communication' +FM_ALARM_TYPE_2 = 'qos' +FM_ALARM_TYPE_3 = 'processing-error' +FM_ALARM_TYPE_4 = 'equipment' +FM_ALARM_TYPE_5 = 'environmental' +FM_ALARM_TYPE_6 = 'integrity-violation' +FM_ALARM_TYPE_7 = 'operational-violation' +FM_ALARM_TYPE_8 = 'physical-violation' +FM_ALARM_TYPE_9 = 'security-service-or-mechanism-violation' +FM_ALARM_TYPE_10 = 'time-domain-violation' + +FM_ALARM_SEVERITY_CLEAR = 'clear' +FM_ALARM_SEVERITY_WARNING = 'warning' +FM_ALARM_SEVERITY_MINOR = 'minor' +FM_ALARM_SEVERITY_MAJOR = 'major' +FM_ALARM_SEVERITY_CRITICAL = 'critical' + +FM_ALARM_OK_STATUS = "OK" +FM_ALARM_DEGRADED_STATUS = "degraded" +FM_ALARM_CRITICAL_STATUS = "critical" + +ALARM_CRITICAL_REPLICATION = 'Potential data loss. No available OSDs in storage replication group ' +ALARM_MAJOR_REPLICATION = 'Loss of replication in replication group ' + +ALARM_PROBABLE_CAUSE_1 = 'adaptor-error' +ALARM_PROBABLE_CAUSE_2 = 'application-subsystem-failure' +ALARM_PROBABLE_CAUSE_3 = 'bandwidth-reduced' +ALARM_PROBABLE_CAUSE_4 = 'call-establishment-error' +ALARM_PROBABLE_CAUSE_5 = 'communication-protocol-error' +ALARM_PROBABLE_CAUSE_6 = 'communication-subsystem-failure' +ALARM_PROBABLE_CAUSE_7 = 'configuration-or-customization-error' +ALARM_PROBABLE_CAUSE_8 = 'congestion' +ALARM_PROBABLE_CAUSE_9 = 'corrupt-data' +ALARM_PROBABLE_CAUSE_10 = 'cpu-cycles-limit-exceeded' +ALARM_PROBABLE_CAUSE_11 = 'dataset-or-modem-error' +ALARM_PROBABLE_CAUSE_12 = 'degraded-signal' +ALARM_PROBABLE_CAUSE_13 = 'dte-dce-interface-error' +ALARM_PROBABLE_CAUSE_14 = 'enclosure-door-open' +ALARM_PROBABLE_CAUSE_15 = 'equipment-malfunction' +ALARM_PROBABLE_CAUSE_16 = 'excessive-vibration' +ALARM_PROBABLE_CAUSE_17 = 'file-error' +ALARM_PROBABLE_CAUSE_18 = 'fire-detected' +ALARM_PROBABLE_CAUSE_19 = 'flood-detected' +ALARM_PROBABLE_CAUSE_20 = 'framing-error' +ALARM_PROBABLE_CAUSE_21 = 'heating-ventilation-cooling-system-problem' +ALARM_PROBABLE_CAUSE_22 = 'humidity-unacceptable' +ALARM_PROBABLE_CAUSE_23 = 'io-device-error' +ALARM_PROBABLE_CAUSE_24 = 'input-device-error' +ALARM_PROBABLE_CAUSE_25 = 'lan-error' +ALARM_PROBABLE_CAUSE_26 = 'leak-detected' +ALARM_PROBABLE_CAUSE_27 = 'local-node-transmission-error' +ALARM_PROBABLE_CAUSE_28 = 'loss-of-frame' +ALARM_PROBABLE_CAUSE_29 = 'loss-of-signal' +ALARM_PROBABLE_CAUSE_30 = 'material-supply-exhausted' +ALARM_PROBABLE_CAUSE_31 = 'multiplexer-problem' +ALARM_PROBABLE_CAUSE_32 = 'out-of-memory' +ALARM_PROBABLE_CAUSE_33 = 'output-device-error' +ALARM_PROBABLE_CAUSE_34 = 'performance-degraded' +ALARM_PROBABLE_CAUSE_35 = 'power-problem' +ALARM_PROBABLE_CAUSE_36 = 'processor-problem' +ALARM_PROBABLE_CAUSE_37 = 'pump-failure' +ALARM_PROBABLE_CAUSE_38 = 'queue-size-exceeded' +ALARM_PROBABLE_CAUSE_39 = 'receive-failure' +ALARM_PROBABLE_CAUSE_40 = 'receiver-failure' +ALARM_PROBABLE_CAUSE_41 = 'remote-node-transmission-error' +ALARM_PROBABLE_CAUSE_42 = 'resource-at-or-nearing-capacity' +ALARM_PROBABLE_CAUSE_43 = 'response-time-excessive' +ALARM_PROBABLE_CAUSE_44 = 'retransmission-rate-excessive' +ALARM_PROBABLE_CAUSE_45 = 'software-error' +ALARM_PROBABLE_CAUSE_46 = 'software-program-abnormally-terminated' +ALARM_PROBABLE_CAUSE_47 = 'software-program-error' +ALARM_PROBABLE_CAUSE_48 = 'storage-capacity-problem' +ALARM_PROBABLE_CAUSE_49 = 'temperature-unacceptable' +ALARM_PROBABLE_CAUSE_50 = 'threshold-crossed' +ALARM_PROBABLE_CAUSE_51 = 'timing-problem' +ALARM_PROBABLE_CAUSE_52 = 'toxic-leak-detected' +ALARM_PROBABLE_CAUSE_53 = 'transmit-failure' +ALARM_PROBABLE_CAUSE_54 = 'transmitter-failure' +ALARM_PROBABLE_CAUSE_55 = 'underlying-resource-unavailable' +ALARM_PROBABLE_CAUSE_56 = 'version-mismatch' +ALARM_PROBABLE_CAUSE_57 = 'duplicate-information' +ALARM_PROBABLE_CAUSE_58 = 'information-missing' +ALARM_PROBABLE_CAUSE_59 = 'information-modification-detected' +ALARM_PROBABLE_CAUSE_60 = 'information-out-of-sequence' +ALARM_PROBABLE_CAUSE_61 = 'unexpected-information' +ALARM_PROBABLE_CAUSE_62 = 'denial-of-service' +ALARM_PROBABLE_CAUSE_63 = 'out-of-service' +ALARM_PROBABLE_CAUSE_64 = 'procedural-error' +ALARM_PROBABLE_CAUSE_65 = 'unspecified-reason' +ALARM_PROBABLE_CAUSE_66 = 'cable-tamper' +ALARM_PROBABLE_CAUSE_67 = 'intrusion-detection' +ALARM_PROBABLE_CAUSE_68 = 'authentication-failure' +ALARM_PROBABLE_CAUSE_69 = 'breach-of-confidentiality' +ALARM_PROBABLE_CAUSE_70 = 'non-repudiation-failure' +ALARM_PROBABLE_CAUSE_71 = 'unauthorized-access-attempt' +ALARM_PROBABLE_CAUSE_72 = 'delayed-information' +ALARM_PROBABLE_CAUSE_73 = 'key-expired' +ALARM_PROBABLE_CAUSE_74 = 'out-of-hours-activity' +ALARM_PROBABLE_CAUSE_75 = 'configuration-out-of-date' +ALARM_PROBABLE_CAUSE_76 = 'configuration-provisioning-required' +ALARM_PROBABLE_CAUSE_UNKNOWN = 'unknown' + +ALARM_STATE = [FM_ALARM_STATE_SET, FM_ALARM_STATE_CLEAR, FM_ALARM_STATE_MSG] + +ALARM_TYPE = [FM_ALARM_TYPE_0, FM_ALARM_TYPE_1, FM_ALARM_TYPE_2, + FM_ALARM_TYPE_3, FM_ALARM_TYPE_4, FM_ALARM_TYPE_5, + FM_ALARM_TYPE_6, FM_ALARM_TYPE_7, FM_ALARM_TYPE_8, + FM_ALARM_TYPE_9, FM_ALARM_TYPE_10] + +ALARM_SEVERITY = [FM_ALARM_SEVERITY_CLEAR, FM_ALARM_SEVERITY_WARNING, + FM_ALARM_SEVERITY_MINOR, FM_ALARM_SEVERITY_MAJOR, + FM_ALARM_SEVERITY_CRITICAL] + +ALARM_STATUS = [FM_ALARM_OK_STATUS, FM_ALARM_DEGRADED_STATUS, + FM_ALARM_CRITICAL_STATUS] + +ALARM_PROBABLE_CAUSE = [ALARM_PROBABLE_CAUSE_1, ALARM_PROBABLE_CAUSE_2, + ALARM_PROBABLE_CAUSE_3, ALARM_PROBABLE_CAUSE_4, + ALARM_PROBABLE_CAUSE_5, ALARM_PROBABLE_CAUSE_6, + ALARM_PROBABLE_CAUSE_7, ALARM_PROBABLE_CAUSE_8, + ALARM_PROBABLE_CAUSE_9, ALARM_PROBABLE_CAUSE_10, + ALARM_PROBABLE_CAUSE_11, ALARM_PROBABLE_CAUSE_12, + ALARM_PROBABLE_CAUSE_13, ALARM_PROBABLE_CAUSE_14, + ALARM_PROBABLE_CAUSE_15, ALARM_PROBABLE_CAUSE_16, + ALARM_PROBABLE_CAUSE_17, ALARM_PROBABLE_CAUSE_18, + ALARM_PROBABLE_CAUSE_19, ALARM_PROBABLE_CAUSE_20, + ALARM_PROBABLE_CAUSE_21, ALARM_PROBABLE_CAUSE_22, + ALARM_PROBABLE_CAUSE_23, ALARM_PROBABLE_CAUSE_24, + ALARM_PROBABLE_CAUSE_25, ALARM_PROBABLE_CAUSE_26, + ALARM_PROBABLE_CAUSE_27, ALARM_PROBABLE_CAUSE_28, + ALARM_PROBABLE_CAUSE_29, ALARM_PROBABLE_CAUSE_30, + ALARM_PROBABLE_CAUSE_31, ALARM_PROBABLE_CAUSE_32, + ALARM_PROBABLE_CAUSE_33, ALARM_PROBABLE_CAUSE_34, + ALARM_PROBABLE_CAUSE_35, ALARM_PROBABLE_CAUSE_36, + ALARM_PROBABLE_CAUSE_37, ALARM_PROBABLE_CAUSE_38, + ALARM_PROBABLE_CAUSE_39, ALARM_PROBABLE_CAUSE_40, + ALARM_PROBABLE_CAUSE_41, ALARM_PROBABLE_CAUSE_42, + ALARM_PROBABLE_CAUSE_43, ALARM_PROBABLE_CAUSE_44, + ALARM_PROBABLE_CAUSE_45, ALARM_PROBABLE_CAUSE_46, + ALARM_PROBABLE_CAUSE_47, ALARM_PROBABLE_CAUSE_48, + ALARM_PROBABLE_CAUSE_49, ALARM_PROBABLE_CAUSE_50, + ALARM_PROBABLE_CAUSE_51, ALARM_PROBABLE_CAUSE_52, + ALARM_PROBABLE_CAUSE_53, ALARM_PROBABLE_CAUSE_54, + ALARM_PROBABLE_CAUSE_55, ALARM_PROBABLE_CAUSE_56, + ALARM_PROBABLE_CAUSE_57, ALARM_PROBABLE_CAUSE_58, + ALARM_PROBABLE_CAUSE_59, ALARM_PROBABLE_CAUSE_60, + ALARM_PROBABLE_CAUSE_61, ALARM_PROBABLE_CAUSE_62, + ALARM_PROBABLE_CAUSE_63, ALARM_PROBABLE_CAUSE_64, + ALARM_PROBABLE_CAUSE_65, ALARM_PROBABLE_CAUSE_66, + ALARM_PROBABLE_CAUSE_67, ALARM_PROBABLE_CAUSE_68, + ALARM_PROBABLE_CAUSE_69, ALARM_PROBABLE_CAUSE_70, + ALARM_PROBABLE_CAUSE_71, ALARM_PROBABLE_CAUSE_72, + ALARM_PROBABLE_CAUSE_73, ALARM_PROBABLE_CAUSE_74, + ALARM_PROBABLE_CAUSE_75, ALARM_PROBABLE_CAUSE_76, + ALARM_PROBABLE_CAUSE_UNKNOWN] + + +FM_CLIENT_SET_FAULT = "/usr/local/bin/fmClientCli -c " +FM_CLIENT_CLEAR_FAULT = "/usr/local/bin/fmClientCli -d " +FM_CLIENT_GET_FAULT = "/usr/local/bin/fmClientCli -g " +FM_CLIENT_GET_FAULTS = "/usr/local/bin/fmClientCli -G " +FM_CLIENT_GET_FAULTS_BY_ID = "/usr/local/bin/fmClientCli -A " +FM_CLIENT_CLEAR_ALL = "/usr/local/bin/fmClientCli -D " +FM_CLIENT_STR_SEP = "###" + +FM_UUID_INDEX = 0 +FM_ALARM_ID_INDEX = 1 +FM_ALARM_STATE_INDEX = 2 +FM_ENT_TYPE_ID_INDEX = 3 +FM_ENT_INST_ID_INDEX = 4 +FM_TIMESTAMP_INDEX = 5 +FM_SEVERITY_INDEX = 6 +FM_REASON_TEXT_INDEX = 7 +FM_ALARM_TYPE_INDEX = 8 +FM_CAUSE_INDEX = 9 +FM_REPAIR_ACTION_INDEX = 10 +FM_SERVICE_AFFECTING_INDEX = 11 +FM_SUPPRESSION_INDEX = 12 +FM_INHIBIT_ALARMS_INDEX = 13 +MAX_ALARM_ATTRIBUTES = 14 diff --git a/fm-api/fm_api/fm_api.py b/fm-api/fm_api/fm_api.py new file mode 100755 index 00000000..11b45727 --- /dev/null +++ b/fm-api/fm_api/fm_api.py @@ -0,0 +1,247 @@ +# +# Copyright (c) 2013-2014 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# -*- encoding: utf-8 -*- +# +# +# Author: +# + +import copy +import subprocess +import constants +import six + + +class ClientException(Exception): + pass + +# Fields explanation: +# +# alarm_id: a text string of the alarm identifier +# alarm_state: see ALARM_STATE +# entity_type_id: type of the object raising alarm. +# entity_instance_id: instance information of the object raising alarm. +# severity: see ALARM_SEVERITY +# reason_text: free-format string providing description and additional details +# on the alarm. Optional. +# alarm_type: see ALARM_TYPE +# probable_cause: see ALARM_PROBABLE_CAUSE +# proposed_repair_action:free-format string providing additional details on how to +# clear the alarm. Optional. +# service_affecting: true/false, default to false +# suppression: true/false (allowed/not-allowed), default to false +# uuid: unique identifier of an active alarm instance, filled by FM system +# Timestamp: when the alarm has been raised/updated, filled by FM system +# See CGCS FM Guide for the alarm model specification +class Fault(object): + + def __init__(self, alarm_id, alarm_state, entity_type_id, + entity_instance_id, severity, reason_text, + alarm_type, probable_cause, proposed_repair_action, + service_affecting=False, suppression=False, + uuid=None, timestamp=None): + self.alarm_id = alarm_id + self.alarm_state = alarm_state + self.entity_type_id = self._unicode(entity_type_id) + self.entity_instance_id = self._unicode(entity_instance_id) + self.severity = severity + self.reason_text = self._unicode(reason_text) + self.alarm_type = alarm_type + self.probable_cause = probable_cause + self.proposed_repair_action = self._unicode(proposed_repair_action) + self.service_affecting = service_affecting + self.suppression = suppression + self.uuid = uuid + self.timestamp = timestamp + + def as_dict(self): + return copy.copy(self.__dict__) + + @staticmethod + def _unicode(value): + if isinstance(value, str): + return six.text_type(value.decode('utf-8')) + else: + return value + + +class FaultAPIs(object): + + def set_fault(self, data): + self._check_required_attributes(data) + self._validate_attributes(data) + buff = self._alarm_to_str(data) + cmd = constants.FM_CLIENT_SET_FAULT + '"' + buff + '"' + resp = self._run_cmd_and_get_resp(cmd) + if (resp[0] == "Ok") and (len(resp) > 1): + return resp[1] + else: + return None + + def clear_fault(self, alarm_id, entity_instance_id): + sep = constants.FM_CLIENT_STR_SEP + buff = (sep + self._check_val(alarm_id) + sep + + self._check_val(entity_instance_id) + sep) + cmd = constants.FM_CLIENT_CLEAR_FAULT + '"' + buff + '"' + + resp = self._run_cmd_and_get_resp(cmd) + if resp[0] == "Ok": + return True + else: + return False + + def get_fault(self, alarm_id, entity_instance_id): + sep = constants.FM_CLIENT_STR_SEP + buff = (sep + self._check_val(alarm_id) + sep + + self._check_val(entity_instance_id) + sep) + cmd = constants.FM_CLIENT_GET_FAULT + '"' + buff + '"' + resp = self._run_cmd_and_get_resp(cmd) + if (resp[0] == "Ok") and (len(resp) > 1): + return self._str_to_alarm(resp[1]) + else: + return None + + def clear_all(self, entity_instance_id): + cmd = constants.FM_CLIENT_CLEAR_ALL + '"' + entity_instance_id + '"' + resp = self._run_cmd_and_get_resp(cmd) + if resp[0] == "Ok": + return True + else: + return False + + def get_faults(self, entity_instance_id): + cmd = constants.FM_CLIENT_GET_FAULTS + '"' + entity_instance_id + '"' + resp = self._run_cmd_and_get_resp(cmd) + data = [] + if resp[0] == "Ok": + for i in range(1, len(resp)): + alarm = self._str_to_alarm(resp[i]) + data.append(alarm) + return data + else: + return None + + def get_faults_by_id(self, alarm_id): + cmd = constants.FM_CLIENT_GET_FAULTS_BY_ID + '"' + alarm_id + '"' + resp = self._run_cmd_and_get_resp(cmd) + data = [] + if resp[0] == "Ok": + for i in range(1, len(resp)): + alarm = self._str_to_alarm(resp[i]) + data.append(alarm) + return data + else: + return None + + @staticmethod + def _check_val(data): + if data is None: + return " " + else: + return data + + def _alarm_to_str(self, data): + sep = constants.FM_CLIENT_STR_SEP + return (sep + self._check_val(data.uuid) + sep + data.alarm_id + sep + + data.alarm_state + sep + data.entity_type_id + sep + + data.entity_instance_id + sep + self._check_val(data.timestamp) + + sep + data.severity + sep + self._check_val(data.reason_text) + + sep + data.alarm_type + sep + data.probable_cause + sep + + self._check_val(data.proposed_repair_action) + sep + + str(data.service_affecting) + sep + str(data.suppression) + sep) + + @staticmethod + def _str_to_alarm(alarm_str): + l = alarm_str.split(constants.FM_CLIENT_STR_SEP) + if len(l) < constants.MAX_ALARM_ATTRIBUTES: + return None + else: + data = Fault(l[constants.FM_ALARM_ID_INDEX], + l[constants.FM_ALARM_STATE_INDEX], + l[constants.FM_ENT_TYPE_ID_INDEX], + l[constants.FM_ENT_INST_ID_INDEX], + l[constants.FM_SEVERITY_INDEX], + l[constants.FM_REASON_TEXT_INDEX], + l[constants.FM_ALARM_TYPE_INDEX], + l[constants.FM_CAUSE_INDEX], + l[constants.FM_REPAIR_ACTION_INDEX], + l[constants.FM_SERVICE_AFFECTING_INDEX], + l[constants.FM_SUPPRESSION_INDEX], + l[constants.FM_UUID_INDEX], + l[constants.FM_TIMESTAMP_INDEX]) + return data + + @staticmethod + def _run_cmd_and_get_resp(cmd): + resp = [] + cmd = cmd.encode('utf-8') + pro = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE) + output = pro.communicate()[0] + lines = output.split('\n') + for line in lines: + if line != '': + resp.append(line) + if len(resp) == 0: + resp.append("Unknown") + + return resp + + @staticmethod + def _check_required_attributes(data): + if data.alarm_id is None: + raise ClientException("Alarm id is is required.") + if data.alarm_state is None: + raise ClientException("Alarm state is required.") + if data.severity is None: + raise ClientException("Severity is required.") + if data.alarm_type is None: + raise ClientException("Alarm type is required.") + if data.probable_cause is None: + raise ClientException("Probable Cause is required.") + if data.entity_type_id is None: + raise ClientException("Entity type id is required.") + if data.entity_instance_id is None: + raise ClientException("Entity instance id is required.") + + @staticmethod + def _validate_attributes(data): + """ Validate the attributes + only applies to Telco specific attributes""" + if data.alarm_state not in constants.ALARM_STATE: + raise ClientException("Invalid Fault State: %s" % + data.alarm_state) + if data.severity not in constants.ALARM_SEVERITY: + raise ClientException("Invalid Fault Severity: %s" % + data.severity) + if data.alarm_type not in constants.ALARM_TYPE: + raise ClientException("Invalid Fault Type: %s" % + data.alarm_type) + if data.probable_cause not in constants.ALARM_PROBABLE_CAUSE: + raise ClientException("Invalid Fault Probable Cause: %s" % + data.probable_cause) + + @staticmethod + def alarm_allowed(alarm_severity, threshold): + def severity_to_int(severity): + if severity == 'none': + return 5 + elif severity == constants.FM_ALARM_SEVERITY_CRITICAL: + return 4 + elif severity == constants.FM_ALARM_SEVERITY_MAJOR: + return 3 + elif severity == constants.FM_ALARM_SEVERITY_MINOR: + return 2 + elif severity == constants.FM_ALARM_SEVERITY_WARNING: + return 1 + + given = severity_to_int(alarm_severity) + threshold = severity_to_int(threshold) + if given < threshold: + return True + return False + + diff --git a/fm-api/fm_api_test.py b/fm-api/fm_api_test.py new file mode 100644 index 00000000..e748dfdb --- /dev/null +++ b/fm-api/fm_api_test.py @@ -0,0 +1,105 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2014 Wind River Systems, Inc. +# +# Author: +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sys +from fm_api import * +from fm_api import constants + + +def print_alarm(alarm): + alarm_str = "alarm_id: " + alarm.alarm_id + ", " + "uuid: " + alarm.uuid + ", " + alarm_str += "alarm_type: " + alarm.alarm_type + "\n" + alarm_str += "state: " + alarm.alarm_state + ", ""severity: " + alarm.severity + ", " \ + + "entity_type_id: " + alarm.entity_type_id + ", timestamp: "+ alarm.timestamp + "\n" + alarm_str += "entity_instance_id: " + alarm.entity_instance_id + ", " + alarm_str += "probable cause:" + alarm.probable_cause + "\n" + print alarm_str + + +def create(): + ser = FaultAPIs() + fault = Fault(alarm_id=constants.FM_ALARM_ID_VM_RESCUED, + alarm_state=constants.FM_ALARM_STATE_SET, + entity_type_id=constants.FM_ENTITY_TYPE_INSTANCE, + entity_instance_id=constants.FM_ENTITY_TYPE_INSTANCE + '=' + 'a4e4cdb7-2ee6-4818-84c8-5310fcd67b5d', + severity = constants.FM_ALARM_SEVERITY_CRITICAL, + reason_text = "Unknown", + alarm_type = constants.FM_ALARM_TYPE_5, + probable_cause = constants.ALARM_PROBABLE_CAUSE_8, + proposed_repair_action = None, + service_affecting = False, + suppression = False) + uuid =ser.set_fault(fault) + print uuid + + +def delete(alarm_id, instance_id): + ser=FaultAPIs() + ret = ser.clear_fault(alarm_id,instance_id) + print "Delete fault return %s" % str(ret) + + +def del_all(instance_id): + ser=FaultAPIs() + ret= ser.clear_all(instance_id) + print "Delete faults return: %s" % str(ret) + + +def get(alarm_id, instance_id): + ser=FaultAPIs() + a = ser.get_fault(alarm_id, instance_id) + if a is not None: + print_alarm(a) + else: + print "Alarm not found" + + +def get_all(instance_id): + ser=FaultAPIs() + ll= ser.get_faults(instance_id) + if ll is not None: + print "Total alarm returned: %d\n" % len(ll) + for i in ll: + print_alarm(i) + else: + print "No alarm returned" + + +def get_list(alarm_id): + ser=FaultAPIs() + ll= ser.get_faults_by_id(alarm_id) + if ll is not None: + print "Total alarm returned: %d\n" % len(ll) + for i in ll: + print_alarm(i) + else: + print "No alarm returned" + +if __name__ == "__main__": + if sys.argv[1] == "create": + sys.exit(create()) + elif sys.argv[1] == "del": + sys.exit(delete(sys.argv[2],sys.argv[3])) + elif sys.argv[1] == "get": + sys.exit(get(sys.argv[2],sys.argv[3])) + elif sys.argv[1] == "get_all": + sys.exit(get_all(sys.argv[2])) + elif sys.argv[1] == "del_all": + sys.exit(del_all(sys.argv[2])) + elif sys.argv[1] == "get_list": + sys.exit(get_list(sys.argv[2])) diff --git a/fm-api/setup.py b/fm-api/setup.py new file mode 100644 index 00000000..3b55e8c0 --- /dev/null +++ b/fm-api/setup.py @@ -0,0 +1,17 @@ +# +# Copyright (c) 2013-2014 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import setuptools + +setuptools.setup( + name='fm_api', + description='CGCS FM Python API', + version='1.0.0', + license='Apache-2.0', + packages=['fm_api'], + entry_points={ + } +) diff --git a/fm-common/.gitignore b/fm-common/.gitignore new file mode 100644 index 00000000..84ba375e --- /dev/null +++ b/fm-common/.gitignore @@ -0,0 +1,6 @@ +!.distro +.distro/centos7/rpmbuild/RPMS +.distro/centos7/rpmbuild/SRPMS +.distro/centos7/rpmbuild/BUILD +.distro/centos7/rpmbuild/BUILDROOT +.distro/centos7/rpmbuild/SOURCES/fm-common*tar.gz diff --git a/fm-common/PKG-INFO b/fm-common/PKG-INFO new file mode 100644 index 00000000..1c372a2c --- /dev/null +++ b/fm-common/PKG-INFO @@ -0,0 +1,14 @@ +Metadata-Version: 1.1 +Name: fm-common +Version: 1.0 +Summary: Titanium Cloud Platform Fault Management Common Package +Home-page: +Author: Windriver +Author-email: info@windriver.com +License: Apache-2.0 + +Description: CGTS platform Fault Management Client Library that provides APIs + for applications to raise/clear/update active alarms." + + +Platform: UNKNOWN diff --git a/fm-common/centos/build_srpm.data b/fm-common/centos/build_srpm.data new file mode 100644 index 00000000..7dfb9b30 --- /dev/null +++ b/fm-common/centos/build_srpm.data @@ -0,0 +1,2 @@ +SRC_DIR="sources" +TIS_PATCH_VER=8 diff --git a/fm-common/centos/fm-common.spec b/fm-common/centos/fm-common.spec new file mode 100644 index 00000000..2e562ed6 --- /dev/null +++ b/fm-common/centos/fm-common.spec @@ -0,0 +1,85 @@ +%define local_dir /usr/local +%define local_bindir %{local_dir}/bin +%define cgcs_doc_deploy_dir /opt/deploy/cgcs_doc + +Summary: CGTS Platform Fault Management Common Package +Name: fm-common +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +Source0: %{name}-%{version}.tar.gz +BuildRequires: util-linux +BuildRequires: postgresql-devel +BuildRequires: libuuid-devel +BuildRequires: python-devel + +%package -n fm-common-dev +Summary: CGTS Platform Fault Management Common Package - Development files +Group: devel +Requires: fm-common = %{version}-%{release} + +%description +Titanium Cloud platform Fault Management Client Library that provides APIs for +applications to raise/clear/update active alarms. + +%description -n fm-common-dev +Titanium Cloud platform Fault Management Client Library that provides APIs for +applications to raise/clear/update active alarms. This package contains +symbolic links, header files, and related items necessary for software +development. + +%package -n fm-common-doc +Summary: fm-common deploy doc +Group: doc + +%description -n fm-common-doc +Contains fmAlarm.h which is to be used by fm-doc package to validate +the Alarms & Logs Doc Yaml file + +%prep +%setup + +%build +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +make MAJOR=$MAJOR MINOR=$MINOR %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +make DEST_DIR=$RPM_BUILD_ROOT BIN_DIR=%{local_bindir} LIB_DIR=%{_libdir} INC_DIR=%{_includedir} MAJOR=$MAJOR MINOR=$MINOR install_non_bb + +install -d $RPM_BUILD_ROOT/usr/bin +install -m 755 fm_db_sync_event_suppression.py $RPM_BUILD_ROOT/usr/bin/fm_db_sync_event_suppression.py + +CGCS_DOC_DEPLOY=$RPM_BUILD_ROOT/%{cgcs_doc_deploy_dir} +install -d $CGCS_DOC_DEPLOY +# install fmAlarm.h in CGCS_DOC_DEPLOY_DIR +# used by fm-doc package to validate the Alarms & Logs Doc Yaml file +install -m 644 fmAlarm.h $CGCS_DOC_DEPLOY + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%defattr(-,root,root,-) +%doc LICENSE +%{local_bindir}/* +%{_libdir}/*.so.* +/usr/bin/fm_db_sync_event_suppression.py + +%files -n fm-common-dev +%defattr(-,root,root,-) +%{_includedir}/* +%{_libdir}/*.so + +%files -n fm-common-doc +%defattr(-,root,root,-) +%{cgcs_doc_deploy_dir}/* diff --git a/fm-common/sources/LICENSE b/fm-common/sources/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/fm-common/sources/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fm-common/sources/Makefile b/fm-common/sources/Makefile new file mode 100755 index 00000000..fc3b9a2d --- /dev/null +++ b/fm-common/sources/Makefile @@ -0,0 +1,40 @@ +SRCS = fmAPI.cpp fmFile.cpp fmLog.cpp fmMsgServer.cpp fmMutex.cpp fmSocket.cpp fmThread.cpp fmTime.cpp \ + fmAlarmUtils.cpp fmDb.cpp fmDbUtils.cpp fmDbAlarm.cpp fmSnmpUtils.cpp \ + fmDbEventLog.cpp fmEventSuppression.cpp +CLI_SRCS = fm_cli.cpp +OBJS = $(SRCS:.cpp=.o) +CLI_OBJS = fm_cli.o +LDLIBS = -lstdc++ -lrt -luuid -lpq -lpthread -lpython2.7 +INCLUDES = -I./ +CCFLAGS = -g -O2 -Wall -Werror -fPIC + +LIBFMCOMMON_SO := libfmcommon.so +build: lib fmClientCli + +.cpp.o: + $(CXX) $(CCFLAGS) $(INCLUDES) $(EXTRACCFLAGS) -c $< -o $@ + +lib: $(OBJS) + $(CXX) -Wl,-soname,$(LIBFMCOMMON_SO).$(MAJOR) -o $(LIBFMCOMMON_SO).$(MAJOR).$(MINOR) -shared $(OBJS) $(EXTRAARFLAGS) ${LDLIBS} + ln -sf $(LIBFMCOMMON_SO).$(MAJOR).$(MINOR) $(LIBFMCOMMON_SO).$(MAJOR) + ln -sf $(LIBFMCOMMON_SO).$(MAJOR).$(MINOR) $(LIBFMCOMMON_SO) + +fmClientCli: $(CLI_OBJS) lib + $(CXX) -o $@ $(CLI_OBJS) -L./ -lfmcommon + +clean: + @rm -f $(OBJ) *.o *.so fmClientCli + +install_non_bb: + install -m 755 -d $(DEST_DIR)$(BIN_DIR) + install -m 755 -d $(DEST_DIR)$(LIB_DIR) + install -m 755 -d $(DEST_DIR)$(INC_DIR) + install -m 755 fmClientCli $(DEST_DIR)$(BIN_DIR) + install -m 644 fmDbAPI.h $(DEST_DIR)$(INC_DIR) + install -m 644 fmAPI.h $(DEST_DIR)$(INC_DIR) + install -m 644 fmThread.h $(DEST_DIR)$(INC_DIR) + install -m 644 fmAlarm.h $(DEST_DIR)$(INC_DIR) + install -m 755 $(LIBFMCOMMON_SO).$(MAJOR).$(MINOR) $(DEST_DIR)$(LIB_DIR) + ln -s $(LIBFMCOMMON_SO).$(MAJOR).$(MINOR) $(DEST_DIR)$(LIB_DIR)/$(LIBFMCOMMON_SO).$(MAJOR) + ln -s $(LIBFMCOMMON_SO).$(MAJOR).$(MINOR) $(DEST_DIR)$(LIB_DIR)/$(LIBFMCOMMON_SO) + diff --git a/fm-common/sources/fmAPI.cpp b/fm-common/sources/fmAPI.cpp new file mode 100644 index 00000000..be14af20 --- /dev/null +++ b/fm-common/sources/fmAPI.cpp @@ -0,0 +1,514 @@ +// +// Copyright (c) 2017 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fmAPI.h" +#include "fmMsg.h" +#include "fmLog.h" +#include "fmSocket.h" +#include "fmMutex.h" +#include "fmThread.h" +#include "fmAlarmUtils.h" + + +#define FM_MGR_HOST_NAME "controller" +#define MAX_PENDING_REQUEST 1000 + +#define HANDLE_SERVER_RC(hdr) \ + if ((hdr)->msg_rc!=FM_ERR_OK) return (EFmErrorT) (hdr)->msg_rc + +#define CHECK_RESPONSE(hdr,neededstruct) \ + if (!fm_valid_srv_msg(hdr,sizeof(neededstruct))) \ + return FM_ERR_COMMUNICATIONS + +#define CHECK_LIST_FULL(l) \ + if (l.size() == MAX_PENDING_REQUEST) \ + return FM_ERR_NOT_ENOUGH_SPACE + +#define CHECK_LIST_NOT_EMPTY(l) \ + if (l.size() != 0) \ + return FM_ERR_REQUEST_PENDING + +static CFmSocket m_client; +static bool m_connected = false; +static bool m_thread = false; + +typedef std::list FmRequestListT; +static FmRequestListT & GetListOfFmRequests(){ + static FmRequestListT reqs; + return reqs; +} + +static CFmMutex & getListMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +static CFmMutex & getThreadMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +CFmMutex & getAPIMutex(){ + static pthread_mutex_t ml = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + static CFmMutex *m = NULL; + if (m == NULL){ + pthread_mutex_lock(&ml); + m = new CFmMutex; + pthread_mutex_unlock(&ml); + } + return *m; +} + +static void enqueue(fm_buff_t &req){ + CFmMutexGuard m(getListMutex()); + GetListOfFmRequests().push_back(req); +} + +static bool dequeue(fm_buff_t &req){ + CFmMutexGuard m(getListMutex()); + if (GetListOfFmRequests().size() == 0){ + return false; + } + FmRequestListT::iterator it = GetListOfFmRequests().begin(); + req.clear(); + req = (*it); + GetListOfFmRequests().pop_front(); + return true; +} + +static bool fm_lib_reconnect() { + char addr[INET6_ADDRSTRLEN]; + + while (!m_connected) { + struct addrinfo hints; + struct addrinfo *result=NULL, *rp; + memset(&hints,0,sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ + hints.ai_flags = 0; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + int rc = getaddrinfo(FM_MGR_HOST_NAME,NULL, + &hints, + &result); + if (rc!=0) { + FM_ERROR_LOG("controller lookup failed... errno:%d",errno); + break; + } else { + for (rp = result; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family==AF_INET||rp->ai_family==AF_INET6) { + if(rp->ai_family==AF_INET) { + inet_ntop(AF_INET, &(((sockaddr_in*)rp->ai_addr)->sin_addr), addr, sizeof(addr)); + } else if (rp->ai_family==AF_INET6) { + inet_ntop(AF_INET6, &(((sockaddr_in6*)rp->ai_addr)->sin6_addr), addr, sizeof(addr)); + } + m_connected=m_client.connect(addr,8001,rp->ai_family); + if (m_connected==true) { + FM_INFO_LOG("Connected to FM Manager."); + break; + } else { + FM_WARNING_LOG("Failed to connect to FM Manager."); + } + } + } + freeaddrinfo(result); + } + break; + } + + return (m_connected); +} + +EFmErrorT fm_msg_utils_prep_requet_msg(fm_buff_t &buff, + EFmMsgActionsT act, + const void * data, + uint32_t len) { + + try { + buff.resize(sizeof(SFmMsgHdrT) + len); + } catch (...) { + FM_ERROR_LOG("Buff resize failed: errno:%d",errno); + return FM_ERR_NOMEM; + } + SFmMsgHdrT *hdr = ptr_to_hdr(buff); + hdr->action = act; + hdr->msg_size = len; + hdr->version = EFmMsgV1; + hdr->msg_rc = 0; + memcpy(ptr_to_data(buff),data,len); + return FM_ERR_OK; +} + +static void fmApiJobHandlerThread(void *context){ + + while (true){ + fm_buff_t buff; + buff.clear(); + while (dequeue(buff)){ + while (true) { + while (!fm_lib_reconnect()){ + fmThreadSleep(200); + } + fm_log_request(buff); + // protect from other sync APIs to access the same socket + CFmMutexGuard m(getAPIMutex()); + if(m_client.write_packet(buff)) { + fm_buff_t in_buff; + in_buff.clear(); + if(!m_client.read_packet(in_buff)) { + // retry after read failure + fm_log_response(buff, in_buff, true); + m_connected = false; + continue; + } + else { + fm_log_response(buff, in_buff); + break; + } + }else{ + //retry after write failure + fm_log_request(buff, true); + m_connected = false; + continue; + } + } + } + fmThreadSleep(50); + } +} + +static bool fm_lib_thread(){ + CFmMutexGuard m(getThreadMutex()); + if (!m_thread){ + FM_INFO_LOG("Creating thread"); + if (!fmCreateThread(fmApiJobHandlerThread,NULL)) { + FM_ERROR_LOG("Fail to create API job thread"); + } + else { + m_thread = true; + } + } + return m_thread; +} + +static EFmErrorT fm_check_thread_pending_request(){ + CFmMutexGuard m(getThreadMutex()); + if (m_thread){ + CHECK_LIST_NOT_EMPTY(GetListOfFmRequests()); + } + return FM_ERR_OK; +} + +extern "C" { + +EFmErrorT fm_init_lib() { + signal(SIGINT,SIG_IGN); + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) { + FM_ERROR_LOG("Socket connection failed\n"); + return FM_ERR_NOCONNECT; + } + return FM_ERR_OK; +} + +EFmErrorT fm_set_fault(const SFmAlarmDataT *alarm, + fm_uuid_t *uuid){ + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT; + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmCreateFault, + alarm,sizeof(*alarm)); + if (erc!=FM_ERR_OK) return erc; + + if(m_client.write_packet(buff)) { + if(!m_client.read_packet(buff)) { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + HANDLE_SERVER_RC(ptr_to_hdr(buff)); + CHECK_RESPONSE(ptr_to_hdr(buff),fm_uuid_t); + if (uuid != NULL) + memcpy(*uuid,ptr_to_data(buff),sizeof(*uuid)-1); + } else { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + return FM_ERR_OK; +} + +EFmErrorT fm_clear_fault(AlarmFilter *filter){ + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT; + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmDeleteFault, + filter,sizeof(*filter)); + if (erc!=FM_ERR_OK) return erc; + + if(m_client.write_packet(buff)) { + if(!m_client.read_packet(buff)) { + m_connected = false; + return FM_ERR_NOCONNECT; + } + HANDLE_SERVER_RC(ptr_to_hdr(buff)); + } else { + m_connected = false; + return FM_ERR_NOCONNECT; + } + return FM_ERR_OK; +} + +EFmErrorT fm_clear_all(fm_ent_inst_t *inst_id){ + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT; + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmDeleteFaults, + (*inst_id), sizeof(*inst_id)); + if (erc!=FM_ERR_OK) return erc; + + if(m_client.write_packet(buff)) { + if(!m_client.read_packet(buff)) { + m_connected = false; + FM_ERROR_LOG("Read ERR: return FM_ERR_NOCONNECT"); + return FM_ERR_NOCONNECT; + } + HANDLE_SERVER_RC(ptr_to_hdr(buff)); + } else { + m_connected = false; + FM_ERROR_LOG("Write ERR: return FM_ERR_NOCONNECT"); + return FM_ERR_NOCONNECT; + } + return FM_ERR_OK; +} + + +EFmErrorT fm_get_fault(AlarmFilter *filter, SFmAlarmDataT *alarm ){ + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT; + fm_check_thread_pending_request(); + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmGetFault, + filter,sizeof(*filter)); + if (erc!=FM_ERR_OK) return erc; + + if(m_client.write_packet(buff)) { + if(!m_client.read_packet(buff)) { + m_connected = false; + return FM_ERR_NOCONNECT; + } + HANDLE_SERVER_RC(ptr_to_hdr(buff)); + CHECK_RESPONSE(ptr_to_hdr(buff),SFmAlarmDataT); + SFmAlarmDataT * data = (SFmAlarmDataT * ) ptr_to_data(buff); + *alarm = *data; + } else { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + return FM_ERR_OK; +} + +EFmErrorT fm_get_faults(fm_ent_inst_t *inst_id, + SFmAlarmDataT *alarm, unsigned int *max_alarms_to_get) { + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT; + fm_check_thread_pending_request(); + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmGetFaults, + (*inst_id),sizeof(*inst_id)); + if (erc!=FM_ERR_OK) return erc; + + if(m_client.write_packet(buff)) { + if(!m_client.read_packet(buff)) { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + if (ptr_to_hdr(buff)->msg_rc != FM_ERR_OK){ + *max_alarms_to_get = 0; + EFmErrorT rc = (EFmErrorT)ptr_to_hdr(buff)->msg_rc; + return rc; + } + + uint32_t pkt_size = ptr_to_hdr(buff)->msg_size; + if (pkt_size < sizeof(uint32_t)) { + FM_ERROR_LOG("Received invalid pkt size: %u\n",pkt_size ); + m_connected = false; + return FM_ERR_COMMUNICATIONS; + } + pkt_size-=sizeof(uint32_t); + + char *dptr = (char*)ptr_to_data(buff); + + uint32_t *len = (uint32_t*)dptr; + dptr+=sizeof(uint32_t); + if (*max_alarms_to_get < *len) { + return FM_ERR_NOT_ENOUGH_SPACE; + } + if (pkt_size < (*len*sizeof(SFmAlarmDataT)) ) { + return FM_ERR_COMMUNICATIONS; + } + *max_alarms_to_get = *len; + memcpy(alarm,dptr,pkt_size); + } else { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + return FM_ERR_OK; +} + +EFmErrorT fm_get_faults_by_id(fm_alarm_id *alarm_id, SFmAlarmDataT *alarm, + unsigned int *max_alarms_to_get){ + + CFmMutexGuard m(getAPIMutex()); + if (!fm_lib_reconnect()) return FM_ERR_NOCONNECT; + fm_check_thread_pending_request(); + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmGetFaultsById, + (*alarm_id),sizeof(*alarm_id)); + if (erc!=FM_ERR_OK) return erc; + + if(m_client.write_packet(buff)) { + if(!m_client.read_packet(buff)) { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + if (ptr_to_hdr(buff)->msg_rc != FM_ERR_OK){ + *max_alarms_to_get = 0; + EFmErrorT rc = (EFmErrorT)ptr_to_hdr(buff)->msg_rc; + return rc; + } + + uint32_t pkt_size = ptr_to_hdr(buff)->msg_size; + if (pkt_size < sizeof(uint32_t)) { + FM_ERROR_LOG("Received invalid pkt size: %u\n",pkt_size ); + m_connected = false; + return FM_ERR_COMMUNICATIONS; + } + pkt_size-=sizeof(uint32_t); + + char *dptr = (char*)ptr_to_data(buff); + + uint32_t *len = (uint32_t*)dptr; + dptr+=sizeof(uint32_t); + if (*max_alarms_to_get < *len) { + return FM_ERR_NOT_ENOUGH_SPACE; + } + if (pkt_size < (*len*sizeof(SFmAlarmDataT)) ) { + return FM_ERR_COMMUNICATIONS; + } + *max_alarms_to_get = *len; + memcpy(alarm,dptr,pkt_size); + } else { + m_connected = false; + return FM_ERR_NOCONNECT; + } + + return FM_ERR_OK; +} + +/* + * APIs that enqueue the request and return ok for acknowledgment. + * A backgroup thread will pick up the request and send it to the FM Manager + */ +EFmErrorT fm_set_fault_async(const SFmAlarmDataT *alarm, fm_uuid_t *uuid){ + + if ( !fm_lib_thread()) return FM_ERR_RESOURCE_UNAVAILABLE; + CHECK_LIST_FULL(GetListOfFmRequests()); + + fm_uuid_t id; + fm_buff_t buff; + buff.clear(); + fm_uuid_create(id); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmCreateFault, + alarm,sizeof(*alarm)); + if (erc!=FM_ERR_OK) return erc; + memcpy(ptr_to_data(buff), id, sizeof(fm_uuid_t)-1); + + FM_INFO_LOG("Enqueue raise alarm request: UUID (%s) alarm id (%s) instant id (%s)", + id, alarm->alarm_id, alarm->entity_instance_id); + enqueue(buff); + + if (uuid != NULL){ + memcpy(*uuid,id,sizeof(*uuid)-1); + } + return FM_ERR_OK; +} + +EFmErrorT fm_clear_fault_async(AlarmFilter *filter){ + + if ( !fm_lib_thread()) return FM_ERR_RESOURCE_UNAVAILABLE; + CHECK_LIST_FULL(GetListOfFmRequests()); + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmDeleteFault, + filter,sizeof(*filter)); + if (erc!=FM_ERR_OK) return erc; + + FM_INFO_LOG("Enqueue clear alarm request: alarm id (%s), instant id (%s)", + filter->alarm_id, filter->entity_instance_id); + enqueue(buff); + + return FM_ERR_OK; +} + +EFmErrorT fm_clear_all_async(fm_ent_inst_t *inst_id){ + + if ( !fm_lib_thread()) return FM_ERR_RESOURCE_UNAVAILABLE; + CHECK_LIST_FULL(GetListOfFmRequests()); + + fm_buff_t buff; + buff.clear(); + EFmErrorT erc = fm_msg_utils_prep_requet_msg(buff,EFmDeleteFaults, + (*inst_id), sizeof(*inst_id)); + if (erc!=FM_ERR_OK) return erc; + + FM_INFO_LOG("Enqueue clear all alarm request: instant id (%s)", *inst_id); + enqueue(buff); + return FM_ERR_OK; +} + +} diff --git a/fm-common/sources/fmAPI.h b/fm-common/sources/fmAPI.h new file mode 100644 index 00000000..bb128bbd --- /dev/null +++ b/fm-common/sources/fmAPI.h @@ -0,0 +1,224 @@ +// +// Copyright (c) 2017 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef _FM_API_H +#define _FM_API_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#define FM_MAX_BUFFER_LENGTH 255 + +/* unsigned 64-bit data, 8-byte alignment, Time in microsecond */ +typedef unsigned long long int FMTimeT __attribute__((__aligned__(8))); + +typedef unsigned char FMBoolTypeT; + +#define FM_TRUE 1 //any non-zero value is also considered to be True + +#define FM_FALSE 0 + +typedef enum{ + FM_ALARM_STATE_CLEAR = 0, + FM_ALARM_STATE_SET = 1, + FM_ALARM_STATE_MSG = 2, + FM_ALARM_STATE_LOG = 3, // Use only for SNMP Agent + FM_ALARM_STATE_MAX = 4 +}EFmAlarmStateT; + +typedef enum{ + FM_ALARM_SEVERITY_CLEAR = 0, + FM_ALARM_SEVERITY_WARNING = 1, + FM_ALARM_SEVERITY_MINOR = 2, + FM_ALARM_SEVERITY_MAJOR = 3, + FM_ALARM_SEVERITY_CRITICAL = 4, + FM_ALARM_SEVERITY_MAX = 5 +}EFmAlarmSeverityT; + +typedef enum{ + FM_ALARM_TYPE_UNKNOWN = 0, + FM_ALARM_COMM = 1, //communication + FM_ALARM_QOS = 2, //qos + FM_ALARM_PROCESSING_ERROR = 3, //processing-error + FM_ALARM_EQUIPMENT = 4 , //equipment + FM_ALARM_ENVIRONMENTAL = 5, //environmental + FM_ALARM_INTERGRITY = 6, //integrity-violation + FM_ALARM_OPERATIONAL = 7, //operational-violation + FM_ALARM_PHYSICAL = 8, //physical-violation + FM_ALARM_SECURITY = 9, //security-service-or-mechanism-violation + FM_ALARM_TIME = 10, //time-domain-violation + FM_ALARM_TYPE_MAX = 11 +}EFmAlarmTypeT; + +typedef enum{ + FM_ALARM_CAUSE_UNKNOWN = 0, + FM_ALARM_ADAPTOR_ERROR = 1, //adaptor-error + FM_ALARM_APP_SUBSYS_FAILURE = 2, //application-subsystem-failure + FM_ALARM_BANDWIDTH_REDUCED = 3, //bandwidth-reduced + FM_ALARM_CALL_ERROR = 4 , //call-establishment-error + FM_ALARM_COMM_PROTOCOL_ERROR = 5, //communication-protocol-error + FM_ALARM_COMM_SUBSYS_FAILURE = 6, //communication-subsystem-failure + FM_ALARM_CONFIG_ERROR = 7, //configuration-or-customization-error + FM_ALARM_CONGESTION = 8, //congestion + FM_ALARM_CORRUPT_DATA = 9, //corrupt-data + FM_ALARM_CPU_LIMITED_EXCEEDED = 10, //cpu-cycles-limit-exceeded + FM_ALARM_DATASET_ERROR = 11, //dataset-or-modem-error + FM_ALARM_DEGRADED_SIGNAL = 12, //degraded-signal + FM_ALARM_DTE_DCE_INTERFACE_ERROR = 13, //dte-dce-interface-error + FM_ALARM_DOOR_OPEN = 14, //enclosure-door-open', + FM_ALARM_EQUIPMENT_MALFUNCTION = 15, //equipment-malfunction + FM_ALARM_EXCESSIVE_VIBRATION = 16, //excessive-vibration' + FM_ALARM_FILE_ERROR = 17, //file-error + FM_ALARM_FIRE_DETECTED = 18, //fire-detected + FM_ALARM_FLOOD_DETECTED = 19, //flood-detected + FM_ALARM_FRAMING_ERROR = 20, //framing-error + FM_ALARM_COOLING_PROBLEM = 21, //heating-ventilation-cooling-system-problem + FM_ALARM_HUMIDITY_UNACCEPTABLE = 22, //humidity-unacceptable + FM_ALARM_IO_DEVICE_ERROR = 23, //io-device-error + FM_ALARM_INPUT_DEVICE_ERROR = 24, //input-device-error + FM_ALARM_LAN_ERROR = 25, //lan-error + FM_ALARM_LEAK_DETECTED = 26, //leak-detected + FM_ALARM_LOCAL_TX_ERROR = 27, //local-node-transmission-error + FM_ALARM_LOSS_OF_FRAME = 28, //loss-of-frame + FM_ALARM_LOSS_OF_SIGNAL = 29, //loss-of-signal + FM_ALARM_MATERIAL_SUPPlY_EXHAUSTED = 30, //material-supply-exhausted + FM_ALARM_MULTIPLEXER_PROBLEM = 31, //multiplexer-problem + FM_ALARM_OUT_OF_MEMORY = 32, //out-of-memory', + FM_ALARM_OUTPUT_DEVICE_ERROR = 33, //output-device-error + FM_ALARM_PERMFORMANCE_DEGRADED = 34, //performance-degraded + FM_ALARM_POWER_PROBLEM = 35, //power-problem + FM_ALARM_PROCESSOR_PROBLEM = 36, //processor-problem + FM_ALARM_PUMP_FAILURE = 37, //pump-failure + FM_ALARM_Q_SIZE_EXCEEDED = 38, //queue-size-exceeded + FM_ALARM_RX_FAILURE = 39, //receive-failure + FM_ALARM_RXER_FAILURE = 40, //receiver-failure + FM_ALARM_REMOTE_TX_ERROR = 41, //remote-node-transmission-error + FM_ALARM_RESOURCE_NEAR_CAPACITY = 42, //resource-at-or-nearing-capacity + FM_ALARM_RESPONSE_TIME_EXCESSIVE = 43, //response-time-excessive + FM_ALARM_RETX_RATE_EXCESSIVE = 44, //retransmission-rate-excessive + FM_ALARM_SOFTWARE_ERROR = 45, //software-error + FM_ALARM_PROGRAM_TERMINATED = 46, //software-program-abnormally-terminated + FM_ALARM_PROGRAM_ERROR = 47, //software-program-error + FM_ALARM_STORAGE_PROBLEM = 48, //storage-capacity-problem + FM_ALARM_TEMP_UNACCEPTABLE = 49, //temperature-unacceptable + FM_ALARM_THRESHOLD_CROSSED = 50, //threshold-crossed + FM_ALARM_TIMING_PROBLEM = 51, //timing-problem + FM_ALARM_TOXIC_LEAK_DETECTED = 52, //toxic-leak-detected + FM_ALARM_TRANSMIT_FAILURE = 53, //transmit-failure + FM_ALARM_TRANSMITTER_FAILURE = 54, //transmitter-failure + FM_ALARM_UNDERLYING_RESOURCE_UNAVAILABLE = 55,//underlying-resource-unavailable + FM_ALARM_VERSION_MISMATCH = 56, //version-mismatch + FM_ALARM_DUPLICATE_INFO = 57, //duplicate-information + FM_ALARM_INFO_MISSING = 58, //information-missing + FM_ALARM_INFO_MODIFICATION = 59, //information-modification-detected + FM_ALARM_INFO_OUT_OF_SEQ = 60, //information-out-of-sequence + FM_ALARM_UNEXPECTED_INFO = 61, //unexpected-information + FM_ALARM_DENIAL_OF_SERVICE = 62, //denial-of-service + FM_ALARM_OUT_OF_SERVICE = 63, //out-of-service + FM_ALARM_PROCEDURAL_ERROR = 64, //procedural-error + FM_ALARM_UNSPECIFIED_REASON = 65, //unspecified-reason + FM_ALARM_CABLE_TAMPER = 66, //cable-tamper + FM_ALARM_INTRUSION_DETECTION = 67, //intrusion-detection + FM_ALARM_AUTH_FAILURE = 68, //authentication-failure + FM_ALARM_BREACH_CONFIDENT = 69, //breach-of-confidentiality + FM_ALARM_NON_REPUD_FAILURE = 70, //non-repudiation-failure + FM_ALARM_UNAUTH_ACCESS_ATTEMP = 71, //unauthorized-access-attempt + FM_ALARM_DELAYED_INFO = 72, //delayed-information + FM_ALARM_KEY_EXPIRED = 73, //key-expired + FM_ALARM_OUT_OF_HR_ACTIVITY = 74, //out-of-hours-activity + FM_ALARM_CAUSE_MAX = 75 +}EFmAlarmProbableCauseT; + + +typedef char fm_uuid_t[FM_MAX_BUFFER_LENGTH]; +typedef char fm_ent_inst_t[FM_MAX_BUFFER_LENGTH]; +typedef char fm_alarm_id[FM_MAX_BUFFER_LENGTH]; + +typedef struct{ + fm_uuid_t uuid; //generated by FM system + char alarm_id[FM_MAX_BUFFER_LENGTH]; //structured id for the fault + EFmAlarmStateT alarm_state; //state of the fault + char entity_type_id[FM_MAX_BUFFER_LENGTH];//type of the object raising fault + char entity_instance_id[FM_MAX_BUFFER_LENGTH];//instance information of the object raising fault + FMTimeT timestamp; //time in UTC at which the fault state is last updated + EFmAlarmSeverityT severity; //severity of the fault + char reason_text[FM_MAX_BUFFER_LENGTH]; + EFmAlarmTypeT alarm_type; + EFmAlarmProbableCauseT probable_cause; + char proposed_repair_action[FM_MAX_BUFFER_LENGTH]; + FMBoolTypeT service_affecting; + FMBoolTypeT suppression; //'allowed' or 'not-allowed' + FMBoolTypeT inhibit_alarms; //hierarchical suppression of alarms if it is set to true +}SFmAlarmDataT; + +typedef enum{ + FM_ERR_OK = 0, + FM_ERR_ALARM_EXISTS = 1, + FM_ERR_INVALID_ATTRIBUTE = 2, + FM_ERR_NOCONNECT=3, + FM_ERR_NOMEM=4, + FM_ERR_COMMUNICATIONS=5, + FM_ERR_NOT_ENOUGH_SPACE=6, + FM_ERR_INVALID_REQ=7, + FM_ERR_SERVER_NO_MEM=8, + FM_ERR_SCRIPT_FAILURE=9, + FM_ERR_ENTITY_NOT_FOUND = 10, + FM_ERR_DB_OPERATION_FAILURE = 11, + FM_ERR_DB_CONNECT_FAILURE = 12, + FM_ERR_INVALID_PARAMETER = 13, + FM_ERR_RESOURCE_UNAVAILABLE = 14, + FM_ERR_REQUEST_PENDING = 15, + FM_ERR_MAX +}EFmErrorT; + + +typedef struct { + char alarm_id[FM_MAX_BUFFER_LENGTH]; + fm_ent_inst_t entity_instance_id; +}AlarmFilter ; + + +EFmErrorT fm_set_fault(const SFmAlarmDataT *alarm, fm_uuid_t *uuid); + +EFmErrorT fm_clear_fault(AlarmFilter *filter); + +EFmErrorT fm_clear_all(fm_ent_inst_t *inst_id); + +EFmErrorT fm_get_fault(AlarmFilter *filter, SFmAlarmDataT *alarm); + +EFmErrorT fm_get_faults(fm_ent_inst_t *inst_id, SFmAlarmDataT *alarm, + unsigned int *max_alarms_to_get); + +EFmErrorT fm_get_faults_by_id(fm_alarm_id *alarm_id, SFmAlarmDataT *alarm, + unsigned int *max_alarms_to_get); + + +/* + * APIs that enqueue the request and return ok for acknowledgment. + * It is up to the client to query and find out whether + * the alarm is raised or cleared successfully + */ +EFmErrorT fm_set_fault_async(const SFmAlarmDataT *alarm, fm_uuid_t *uuid); + +EFmErrorT fm_clear_fault_async(AlarmFilter *filter); + +EFmErrorT fm_clear_all_async(fm_ent_inst_t *inst_id); + +//used by fmManager +EFmErrorT fm_server_create(const char *fn) ; + + +#ifdef __cplusplus +} +#endif + +#endif /* _FM_API_H */ diff --git a/fm-common/sources/fmAlarm.h b/fm-common/sources/fmAlarm.h new file mode 100644 index 00000000..6454af34 --- /dev/null +++ b/fm-common/sources/fmAlarm.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +/* This file contains CGTS alarm definitions. The alarm ids that used by + * C/C++ applications are defined here. For a completed alarm id list see + * the alarm ids that used by the Python applications defined in + * fm-api/fm_api/constants.py + */ + +#ifndef _FM_ALARM_H +#define _FM_ALARM_H + +/* alarm sub entity types*/ +#define FM_ENTITY_TYPE_SYSTEM "system" +#define FM_ENTITY_TYPE_HOST "host" +#define FM_ENTITY_TYPE_PORT "port" +#define FM_ENTITY_TYPE_INTERFACE "interface" +#define FM_ENTITY_TYPE_DISK "disk" +#define FM_ENTITY_TYPE_SERVICE "service" +#define FM_ENTITY_TYPE_AGENT "agent" +#define FM_ENTITY_TYPE_PROVIDERNET "providernet" +#define FM_ENTITY_TYPE_INSTANCE "instance" + +/* alarm_id = . */ +/* = 000 - 999 */ +/* = 000 999 */ + +#define ALARM_GROUP_GENERAL "100" +#define ALARM_GROUP_MAINTENANCE "200" +#define ALARM_GROUP_NETWORK "300" +#define ALARM_GROUP_HA "400" +#define ALARM_GROUP_SECURITY "500" +#define ALARM_GROUP_LICENSING "600" +#define ALARM_GROUP_VM "700" +#define ALARM_GROUP_STORAGE "800" +#define ALARM_GROUP_SW_MGMT "900" + + +/* Maintenance group alarm id */ +#define FM_ALARM_ID_MTC_LOCK (ALARM_GROUP_MAINTENANCE ".001") +#define FM_ALARM_ID_MTC_CONFIG (ALARM_GROUP_MAINTENANCE ".004") +#define FM_ALARM_ID_MTC_HB (ALARM_GROUP_MAINTENANCE ".005") +#define FM_ALARM_ID_MTC_PMOND (ALARM_GROUP_MAINTENANCE ".006") +#define FM_ALARM_ID_MTC_RESMON (ALARM_GROUP_MAINTENANCE ".007") + +/* HA alarm id */ +#define FM_ALARM_ID_SERVICE_GROUP_STATE (ALARM_GROUP_HA ".001") +#define FM_ALARM_ID_SERVICE_GROUP_REDUNDANCY (ALARM_GROUP_HA ".002") + +/* Patching alarm id */ +#define FM_ALARM_ID_PATCH_IN_PROGRESS (ALARM_GROUP_SW_MGMT ".001") +#define FM_ALARM_ID_PATCH_HOST_INSTALL_FAILED (ALARM_GROUP_SW_MGMT ".002") +#define FM_ALARM_ID_PATCH_OBS_IN_SYSTEM (ALARM_GROUP_SW_MGMT ".003") + +#endif /* _FM_ALARM_H */ diff --git a/fm-common/sources/fmAlarmUtils.cpp b/fm-common/sources/fmAlarmUtils.cpp new file mode 100644 index 00000000..37813113 --- /dev/null +++ b/fm-common/sources/fmAlarmUtils.cpp @@ -0,0 +1,580 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include + +#include "fmAlarmUtils.h" +#include "fmDbUtils.h" +#include "fmLog.h" + + +typedef std::map itos_t; +typedef std::map stoi_t; +typedef std::vector strvect_t; + +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +static itos_t state_to_str; +static itos_t severity_to_str; +static itos_t type_to_str; +static itos_t cause_to_str; +static itos_t bool_to_str; +static itos_t err_to_str; + + +static stoi_t state_to_int; +static stoi_t severity_to_int; +static stoi_t type_to_int; +static stoi_t cause_to_int; +static stoi_t bool_to_int; +static stoi_t err_to_int; + + +#define STRCP_TO(charb,str)\ + if (((str).length()==0) || \ + ((str).length()==1 && ((str).c_str())[0]==' ')) { \ + memset(charb,0,sizeof(charb)); \ + } else { \ + strncpy((charb),str.c_str(),sizeof(charb)); \ + } + +void add_both_tables(int id, const char *str, itos_t &t1,stoi_t &t2 ) { + t1[id]=str; + t2[str]=id; +} + +static void init_tables() { + pthread_mutex_lock(&mutex); + static bool has_inited=false; + + while (!has_inited) { + add_both_tables(FM_ALARM_STATE_CLEAR,"clear",state_to_str,state_to_int); + add_both_tables(FM_ALARM_STATE_SET,"set",state_to_str,state_to_int); + add_both_tables(FM_ALARM_STATE_MSG,"msg",state_to_str,state_to_int); + add_both_tables(FM_ALARM_STATE_LOG,"log",state_to_str,state_to_int); + + add_both_tables(FM_ALARM_SEVERITY_CLEAR,"not-applicable",severity_to_str,severity_to_int); + add_both_tables(FM_ALARM_SEVERITY_WARNING,"warning",severity_to_str,severity_to_int); + add_both_tables(FM_ALARM_SEVERITY_MINOR,"minor",severity_to_str,severity_to_int); + add_both_tables(FM_ALARM_SEVERITY_MAJOR,"major",severity_to_str,severity_to_int); + add_both_tables(FM_ALARM_SEVERITY_CRITICAL,"critical",severity_to_str,severity_to_int); + + add_both_tables(FM_ALARM_TYPE_UNKNOWN,"other",type_to_str,type_to_int); + add_both_tables(FM_ALARM_COMM,"communication",type_to_str,type_to_int); + add_both_tables(FM_ALARM_QOS,"qos",type_to_str,type_to_int); + add_both_tables(FM_ALARM_PROCESSING_ERROR,"processing-error",type_to_str,type_to_int); + add_both_tables(FM_ALARM_EQUIPMENT,"equipment",type_to_str,type_to_int); + add_both_tables(FM_ALARM_ENVIRONMENTAL,"environmental",type_to_str,type_to_int); + add_both_tables(FM_ALARM_INTERGRITY,"integrity-violation",type_to_str,type_to_int); + add_both_tables(FM_ALARM_OPERATIONAL,"operational-violation",type_to_str,type_to_int); + add_both_tables(FM_ALARM_PHYSICAL,"physical-violation",type_to_str,type_to_int); + add_both_tables(FM_ALARM_SECURITY,"security-service-or-mechanism-violation",type_to_str,type_to_int); + add_both_tables(FM_ALARM_TIME,"time-domain-violation",type_to_str,type_to_int); + + add_both_tables( FM_ALARM_CAUSE_UNKNOWN ,"not-applicable",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_ADAPTOR_ERROR ,"adaptor-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_APP_SUBSYS_FAILURE ,"application-subsystem-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_BANDWIDTH_REDUCED ,"bandwidth-reduced",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_CALL_ERROR ,"call-establishment-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_COMM_PROTOCOL_ERROR ,"communication-protocol-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_COMM_SUBSYS_FAILURE ,"communication-subsystem-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_CONFIG_ERROR ,"configuration-or-customization-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_CONGESTION ,"congestion",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_CORRUPT_DATA ,"corrupt-data",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_CPU_LIMITED_EXCEEDED ,"cpu-cycles-limit-exceeded",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DATASET_ERROR ,"dataset-or-modem-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DEGRADED_SIGNAL ,"degraded-signal",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DTE_DCE_INTERFACE_ERROR ,"dte-dce-interface-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DOOR_OPEN ,"enclosure-door-open",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_EQUIPMENT_MALFUNCTION ,"equipment-malfunction",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_EXCESSIVE_VIBRATION ,"excessive-vibration'",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_FILE_ERROR ,"file-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_FIRE_DETECTED ,"fire-detected",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_FLOOD_DETECTED ,"flood-detected",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_FRAMING_ERROR ,"framing-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_COOLING_PROBLEM ,"heating-ventilation-cooling-system-problem",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_HUMIDITY_UNACCEPTABLE ,"humidity-unacceptable",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_IO_DEVICE_ERROR ,"io-device-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_INPUT_DEVICE_ERROR ,"input-device-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_LAN_ERROR ,"lan-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_LEAK_DETECTED ,"leak-detected",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_LOCAL_TX_ERROR ,"local-node-transmission-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_LOSS_OF_FRAME ,"loss-of-frame",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_LOSS_OF_SIGNAL ,"loss-of-signal",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_MATERIAL_SUPPlY_EXHAUSTED ,"material-supply-exhausted",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_MULTIPLEXER_PROBLEM ,"multiplexer-problem",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_OUT_OF_MEMORY ,"out-of-memory",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_OUTPUT_DEVICE_ERROR ,"output-device-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_PERMFORMANCE_DEGRADED ,"performance-degraded",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_POWER_PROBLEM ,"power-problem",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_PROCESSOR_PROBLEM ,"processor-problem",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_PUMP_FAILURE ,"pump-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_Q_SIZE_EXCEEDED ,"queue-size-exceeded",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_RX_FAILURE ,"receive-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_RXER_FAILURE ,"receiver-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_REMOTE_TX_ERROR ,"remote-node-transmission-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_RESOURCE_NEAR_CAPACITY ,"resource-at-or-nearing-capacity",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_RESPONSE_TIME_EXCESSIVE ,"response-time-excessive",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_RETX_RATE_EXCESSIVE ,"retransmission-rate-excessive",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_SOFTWARE_ERROR ,"software-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_PROGRAM_TERMINATED ,"software-program-abnormally-terminated",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_PROGRAM_ERROR ,"software-program-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_STORAGE_PROBLEM ,"storage-capacity-problem",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_TEMP_UNACCEPTABLE ,"temperature-unacceptable",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_THRESHOLD_CROSSED ,"threshold-crossed",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_TIMING_PROBLEM ,"timing-problem",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_TOXIC_LEAK_DETECTED ,"toxic-leak-detected",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_TRANSMIT_FAILURE ,"transmit-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_TRANSMITTER_FAILURE ,"transmitter-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_UNDERLYING_RESOURCE_UNAVAILABLE ,"underlying-resource-unavailable",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_VERSION_MISMATCH ,"version-mismatch",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DUPLICATE_INFO ,"duplicate-information",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_INFO_MISSING ,"information-missing",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_INFO_MODIFICATION ,"information-modification-detected",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_INFO_OUT_OF_SEQ ,"information-out-of-sequence",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_UNEXPECTED_INFO ,"unexpected-information",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DENIAL_OF_SERVICE ,"denial-of-service",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_OUT_OF_SERVICE ,"out-of-service",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_PROCEDURAL_ERROR ,"procedural-error",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_UNSPECIFIED_REASON ,"unspecified-reason",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_CABLE_TAMPER ,"cable-tamper",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_INTRUSION_DETECTION ,"intrusion-detection",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_AUTH_FAILURE ,"authentication-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_BREACH_CONFIDENT ,"breach-of-confidentiality",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_NON_REPUD_FAILURE ,"non-repudiation-failure",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_UNAUTH_ACCESS_ATTEMP ,"unauthorized-access-attempt",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_DELAYED_INFO ,"delayed-information",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_KEY_EXPIRED ,"key-expired",cause_to_str,cause_to_int); + add_both_tables( FM_ALARM_OUT_OF_HR_ACTIVITY ,"out-of-hours-activity",cause_to_str,cause_to_int); + + add_both_tables( FM_ERR_OK, "Ok", err_to_str, err_to_int); + add_both_tables( FM_ERR_ALARM_EXISTS, "FM_ERR_ALARM_EXISTS", err_to_str, err_to_int); + add_both_tables( FM_ERR_INVALID_ATTRIBUTE, "FM_ERR_INVALID_ATTRIBUTE", err_to_str, err_to_int); + add_both_tables( FM_ERR_ENTITY_NOT_FOUND, "FM_ERR_ENTITY_NOT_FOUND", err_to_str, err_to_int); + add_both_tables( FM_ERR_DB_OPERATION_FAILURE, "FM_ERR_DB_OPERATION_FAILURE", err_to_str, err_to_int); + add_both_tables( FM_ERR_SCRIPT_FAILURE, "FM_ERR_SCRIPT_FAILURE",err_to_str, err_to_int); + add_both_tables( FM_ERR_NOCONNECT, "FM_ERR_NOCONNECT", err_to_str, err_to_int); + add_both_tables( FM_ERR_NOMEM, "FM_ERR_NOMEM", err_to_str, err_to_int); + add_both_tables( FM_ERR_COMMUNICATIONS, "FM_ERR_COMMUNICATIONS", err_to_str, err_to_int); + add_both_tables( FM_ERR_NOT_ENOUGH_SPACE, "FM_ERR_NOT_ENOUGH_SPACE", err_to_str, err_to_int); + add_both_tables( FM_ERR_INVALID_REQ, "FM_ERR_INVALID_REQ", err_to_str, err_to_int); + add_both_tables( FM_ERR_SERVER_NO_MEM, "FM_ERR_SERVER_NO_MEM", err_to_str, err_to_int); + add_both_tables( FM_ERR_INVALID_PARAMETER, "FM_ERR_INVALID_PARAMETER",err_to_str, err_to_int); + add_both_tables( FM_ERR_RESOURCE_UNAVAILABLE, "FM_ERR_RESOURCE_UNAVAILABLE",err_to_str, err_to_int); + + add_both_tables( 0 ,"False",bool_to_str,bool_to_int); + add_both_tables( 1 ,"True",bool_to_str,bool_to_int); + + has_inited=true; + } + pthread_mutex_unlock(&mutex); +} + +static void add_s(std::string &s) { s+="###"; }; + +static std::string tostr(int id, const itos_t &t ){ + itos_t::const_iterator it = t.find(id); + if (it!=t.end()) return it->second; + return "unknown"; +} +static int toint(const std::string &s, const stoi_t &t) { + stoi_t::const_iterator it = t.find(s); + if (it!=t.end()) return it->second ; + return 0; +} + +static std::string chkstr(const std::string &s) { + if (s.length()==0) return " "; + return s; +} + +static void str_to_vector(const std::string &s, std::vector &alarm) { + size_t offset = 0; + alarm.clear(); + while (true) { + size_t beg = (offset==0) ? 0 : s.find("###",offset); + if (beg==std::string::npos) break; + size_t e = s.find("###",beg+3); + std::string cont = s.substr(beg+3,e-(beg+3)); + alarm.push_back(cont); + offset=e; + } +} + +static void fm_set_uuid(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = chkstr(a->uuid); + else STRCP_TO(a->uuid,s); +} + +static void fm_tr_alarm_id(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = chkstr(a->alarm_id); + else STRCP_TO(a->alarm_id,s); +} + +static void fm_alarm_state(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = tostr(a->alarm_state,state_to_str); + else a->alarm_state = (EFmAlarmStateT)toint(s,state_to_int); +} + +static void fm_entity_id(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = chkstr(a->entity_type_id); + else STRCP_TO(a->entity_type_id,s); +} + +static void fm_instance_id(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = chkstr(a->entity_instance_id); + else STRCP_TO(a->entity_instance_id,s); +} + +static void fm_timestamp(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) { + fm_db_util_make_timestamp_string(s, a->timestamp); + } else { + fm_db_util_get_timestamp(s.c_str(), a->timestamp); + } +} + +static void fm_alarm_severity(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = tostr(a->severity,severity_to_str); + else a->severity = (EFmAlarmSeverityT)toint(s,severity_to_int); +} + +static void fm_reason_text(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = chkstr(a->reason_text); + else STRCP_TO(a->reason_text,s); +} + +static void fm_alarm_type(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s =tostr(a->alarm_type,type_to_str); + else a->alarm_type = (EFmAlarmTypeT)toint(s,type_to_int); +} + +static void fm_prop_cause(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = tostr(a->probable_cause,cause_to_str); + else a->probable_cause = (EFmAlarmProbableCauseT)toint(s,cause_to_int); +} + +static void fm_repair(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = chkstr(a->proposed_repair_action); + else STRCP_TO(a->proposed_repair_action,s); +} + +static void fm_service_affect(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = tostr(a->service_affecting,bool_to_str); + else a->service_affecting = (((s == "t") || (s == "True"))? 1 :0); +} + +static void fm_suppression(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = tostr(a->suppression,bool_to_str); + else a->suppression = (((s == "t") || (s == "True"))? 1 :0); +} + +static void fm_inhibit_alarm(SFmAlarmDataT *a, std::string &s, bool is_get) { + if(is_get) s = tostr(a->inhibit_alarms,bool_to_str); + else a->inhibit_alarms = (((s == "t") || (s == "True"))? 1 :0); +} + +typedef void (*set_get_field_type)(SFmAlarmDataT *a, std::string &s, bool is_get); + +struct alarm_struct_update_t{ + EFmAlarmIndexMap id; + set_get_field_type func; +} fm_alarm_convert_func [] = { + { FM_ALM_IX_UUID, fm_set_uuid }, + { FM_ALM_IX_ALARM_ID, fm_tr_alarm_id }, + { FM_ALM_IX_ALARM_STATE, fm_alarm_state }, + { FM_ALM_IX_ENTITY_ID, fm_entity_id }, + { FM_ALM_IX_INSTANCE_ID, fm_instance_id }, + { FM_ALM_IX_TIMESTAMP, fm_timestamp }, + { FM_ALM_IX_SEVERITY, fm_alarm_severity }, + { FM_ALM_IX_REASON, fm_reason_text }, + { FM_ALM_IX_ALARM_TYPE, fm_alarm_type }, + { FM_ALM_IX_PROBABLE_CAUSE, fm_prop_cause }, + { FM_ALM_IX_REPAIR_ACTION, fm_repair }, + { FM_ALM_IX_SERVICE_AFFECT, fm_service_affect }, + { FM_ALM_IX_SUPPRESSION, fm_suppression }, + { FM_ALM_IX_INHIBIT_ALARM, fm_inhibit_alarm } +}; + + +static set_get_field_type find_func_set_get(EFmAlarmIndexMap id) { + size_t ix = 0; + size_t mx = sizeof (fm_alarm_convert_func)/sizeof(*fm_alarm_convert_func); + for ( ; ix < mx ; ++ix ) { + if (fm_alarm_convert_func[ix].id==id) + return fm_alarm_convert_func[ix].func; + } + return NULL; +} + +bool fm_alarm_set_field(EFmAlarmIndexMap field, SFmAlarmDataT *a, std::string &val) { + init_tables(); + set_get_field_type p = find_func_set_get(field); + if (p==NULL) return false; + p(a,val,false); + + return true; +} + +struct log_struct_update_t{ + EFmLogIndexMap id; + set_get_field_type func; +} fm_log_convert_func [] = { + { FM_LOG_IX_UUID, fm_set_uuid }, + { FM_LOG_IX_LOG_ID, fm_tr_alarm_id }, + { FM_LOG_IX_ENTITY_ID, fm_entity_id }, + { FM_LOG_IX_INSTANCE_ID, fm_instance_id }, + { FM_LOG_IX_TIMESTAMP, fm_timestamp }, + { FM_LOG_IX_SEVERITY, fm_alarm_severity }, + { FM_LOG_IX_REASON, fm_reason_text }, + { FM_LOG_IX_LOG_TYPE, fm_alarm_type }, + { FM_LOG_IX_PROBABLE_CAUSE, fm_prop_cause }, + { FM_LOG_IX_SERVICE_AFFECT, fm_service_affect } +}; + +static set_get_field_type fm_log_find_func_set_get(EFmLogIndexMap id) { + size_t ix = 0; + size_t mx = sizeof (fm_log_convert_func)/sizeof(*fm_log_convert_func); + for ( ; ix < mx ; ++ix ) { + if (fm_log_convert_func[ix].id==id) + return fm_log_convert_func[ix].func; + } + return NULL; +} +bool fm_log_set_field(EFmLogIndexMap field, SFmAlarmDataT *a, std::string &val) { + init_tables(); + set_get_field_type p = fm_log_find_func_set_get(field); + if (p==NULL) return false; + p(a,val,false); + + return true; +} + +struct event_log_struct_update_t{ + EFmEventLogIndexMap id; + set_get_field_type func; +} fm_event_log_convert_func [] = { + { FM_EVENT_LOG_IX_UUID, fm_set_uuid }, + { FM_EVENT_LOG_IX_EVENT_ID, fm_tr_alarm_id }, + { FM_EVENT_LOG_IX_STATE, fm_alarm_state }, + { FM_EVENT_LOG_IX_ENTITY_ID, fm_entity_id }, + { FM_EVENT_LOG_IX_INSTANCE_ID, fm_instance_id }, + { FM_EVENT_LOG_IX_TIMESTAMP, fm_timestamp }, + { FM_EVENT_LOG_IX_SEVERITY, fm_alarm_severity }, + { FM_EVENT_LOG_IX_REASON, fm_reason_text }, + { FM_EVENT_LOG_IX_EVENT_TYPE, fm_alarm_type }, + { FM_EVENT_LOG_IX_PROBABLE_CAUSE, fm_prop_cause }, + { FM_EVENT_LOG_IX_REPAIR_ACTION, fm_repair }, + { FM_EVENT_LOG_IX_SERVICE_AFFECT, fm_service_affect }, + { FM_EVENT_LOG_IX_SUPPRESSION, fm_suppression } +}; + +static set_get_field_type fm_event_log_find_func_set_get(EFmEventLogIndexMap id) { + size_t ix = 0; + size_t mx = sizeof (fm_event_log_convert_func)/sizeof(*fm_event_log_convert_func); + for ( ; ix < mx ; ++ix ) { + if (fm_event_log_convert_func[ix].id==id) + return fm_event_log_convert_func[ix].func; + } + return NULL; +} +bool fm_event_log_set_field(EFmEventLogIndexMap field, SFmAlarmDataT *a, std::string &val) { + init_tables(); + set_get_field_type p = fm_event_log_find_func_set_get(field); + if (p==NULL) return false; + p(a,val,false); + + return true; +} + + +bool fm_alarm_get_field(EFmAlarmIndexMap field, const SFmAlarmDataT *a, std::string &val) { + init_tables(); + set_get_field_type p = find_func_set_get(field); + if (p==NULL) return false; + p((SFmAlarmDataT*)a,val,true); + return true; +} + +static std::string fm_alarm_to_string(const SFmAlarmDataT *a) { + std::string s; + size_t ix = 0; + size_t mx = FM_ALM_IX_INHIBIT_ALARM ; + std::string field; + for ( ; ix <= mx ; ++ix ) { + fm_alarm_get_field(((EFmAlarmIndexMap)ix),a,field); + s+=field; + add_s(s); + } + return s; +} + +void fm_alarm_to_list(const SFmAlarmDataT *a, std::vector &list) { + size_t ix = 0; + size_t mx = FM_ALM_IX_INHIBIT_ALARM ; + std::string field; + for ( ; ix <= mx ; ++ix ) { + fm_alarm_get_field(((EFmAlarmIndexMap)ix),a,field); + list.push_back(field); + } +} + +void fm_formatted_str_to_vector(const std::string &s, std::vector &alarm) { + str_to_vector(s,alarm); +} + +/** + * public APIs + */ + +EFmErrorT fm_error_from_string(const std::string &str){ + return (EFmErrorT)toint(str,err_to_int); +} + +std::string fm_error_from_int(EFmErrorT id){ + return tostr((int)id,err_to_str); +} + +bool fm_alarm_filter_to_string(const AlarmFilter *filter, std::string &str) { + init_tables(); + + str+= chkstr(filter->alarm_id); + add_s(str); + str+= chkstr(filter->entity_instance_id); + add_s(str); + return true; +} + +bool fm_alarm_filter_from_string(const std::string &str, AlarmFilter *filter) { + strvect_t s; + str_to_vector(str,s); + if (s.size()<2) { + FM_ERROR_LOG("Alarm filter wrong format: %s",str.c_str()); + return false; + } + init_tables(); + + STRCP_TO(filter->alarm_id,s[0]); + STRCP_TO(filter->entity_instance_id,s[1]); + return true; +} + +bool fm_alarm_to_string(const SFmAlarmDataT *alarm, std::string &str) { + init_tables(); + str+= fm_alarm_to_string(alarm); + return str.size()>0; +} + +bool fm_alarm_from_string(const std::string &alstr,SFmAlarmDataT *a) { + strvect_t s; + str_to_vector(alstr, s); + + if (s.size()<(FM_ALM_IX_MAX)) { //includes adjustment for last entry + 1 (for starting at 0) + return false; + } + + init_tables(); + + size_t ix = 0; + size_t mx = s.size(); + for ( ; ix < mx ; ++ix ) { + fm_alarm_set_field((EFmAlarmIndexMap)ix,a,s[ix]); + } + + return true; +} + +void fm_uuid_create(fm_uuid_t &uuid){ + uuid_t uu; + + memset(uuid, 0, sizeof(uuid)); + uuid_generate(uu); + uuid_unparse_lower(uu, uuid); +} + +void fm_log_request(fm_buff_t &req, bool failed){ + SFmMsgHdrT *hdr = ptr_to_hdr(req); + std::string description; + + if (failed) { + description.assign("Failed to send FM"); + } else { + description.assign("Sending FM"); + } + switch(hdr->action) { + case EFmCreateFault: { + SFmAlarmDataT *data = (SFmAlarmDataT * )ptr_to_data(req); + FM_INFO_LOG("%s raise alarm request: alarm_id (%s), entity_id (%s)", + description.c_str(), data->alarm_id, data->entity_instance_id); + } + break; + case EFmDeleteFault: { + AlarmFilter *filter = (AlarmFilter * )ptr_to_data(req); + FM_INFO_LOG("%s clear alarm request: alarm_id (%s), entity_id (%s)", + description.c_str(), filter->alarm_id, filter->entity_instance_id); + } + break; + case EFmDeleteFaults: { + fm_ent_inst_t *entity_id = (fm_ent_inst_t*)ptr_to_data(req); + fm_ent_inst_t &eid = *entity_id; + FM_INFO_LOG("%s clear all request: entity_id (%s)", description.c_str(), eid); + } + break; + default: + FM_ERROR_LOG("Unexpected API action:%u\n", hdr->action); + break; + } +} + + +void fm_log_response(fm_buff_t &req, fm_buff_t &resp, bool failed){ + SFmMsgHdrT *hdr = ptr_to_hdr(req); + SFmMsgHdrT *resp_hdr = ptr_to_hdr(resp); + + switch(hdr->action) { + case EFmCreateFault: { + SFmAlarmDataT *data = (SFmAlarmDataT * )ptr_to_data(req); + if (failed) { + FM_WARNING_LOG("Failed to get response for FM raise alarm: alarm_id (%s), entity_id (%s)", + data->alarm_id, data->entity_instance_id); + } else { + FM_INFO_LOG("FM Response for raise alarm: (%d), alarm_id (%s), entity_id (%s)", + resp_hdr->msg_rc, data->alarm_id, data->entity_instance_id); + } + } + break; + case EFmDeleteFault: { + AlarmFilter *filter = (AlarmFilter * )ptr_to_data(req); + if (failed) { + FM_WARNING_LOG("Failed to get response for FM clear alarm: alarm_id (%s), entity_id (%s)", + filter->alarm_id, filter->entity_instance_id); + } else { + FM_INFO_LOG("FM Response for clear alarm: (%d), alarm_id (%s), entity_id (%s)", + resp_hdr->msg_rc, filter->alarm_id, filter->entity_instance_id); + } + } + break; + case EFmDeleteFaults: { + fm_ent_inst_t *entity_id = (fm_ent_inst_t*)ptr_to_data(req); + fm_ent_inst_t &eid = *entity_id; + if (failed) { + FM_WARNING_LOG("Failed to get response for FM clear all: entity_id (%s)", eid); + } else { + FM_INFO_LOG("FM Response for clear all: (%d), entity_id (%s)", + resp_hdr->msg_rc, eid); + } + } + break; + default: + FM_ERROR_LOG("Unexpected API action:%u\n", hdr->action); + break; + } +} + diff --git a/fm-common/sources/fmAlarmUtils.h b/fm-common/sources/fmAlarmUtils.h new file mode 100644 index 00000000..1bf5ebb8 --- /dev/null +++ b/fm-common/sources/fmAlarmUtils.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + + +#ifndef FMALARMUTILS_H_ +#define FMALARMUTILS_H_ + +#include "fmAPI.h" +#include "fmMsg.h" + +#include +#include + +enum EFmAlarmIndexMap { + FM_ALM_IX_UUID=0, + FM_ALM_IX_ALARM_ID, + FM_ALM_IX_ALARM_STATE, + FM_ALM_IX_ENTITY_ID, + FM_ALM_IX_INSTANCE_ID, + FM_ALM_IX_TIMESTAMP, + FM_ALM_IX_SEVERITY, + FM_ALM_IX_REASON, + FM_ALM_IX_ALARM_TYPE, + FM_ALM_IX_PROBABLE_CAUSE, + FM_ALM_IX_REPAIR_ACTION, + FM_ALM_IX_SERVICE_AFFECT, + FM_ALM_IX_SUPPRESSION, + FM_ALM_IX_INHIBIT_ALARM, + FM_ALM_IX_MAX +}; + +enum EFmLogIndexMap { + FM_LOG_IX_UUID=0, + FM_LOG_IX_LOG_ID, + FM_LOG_IX_ENTITY_ID, + FM_LOG_IX_INSTANCE_ID, + FM_LOG_IX_TIMESTAMP, + FM_LOG_IX_SEVERITY, + FM_LOG_IX_REASON, + FM_LOG_IX_LOG_TYPE, + FM_LOG_IX_PROBABLE_CAUSE, + FM_LOG_IX_SERVICE_AFFECT, + FM_LOG_IX_MAX +}; + +enum EFmEventLogIndexMap { + FM_EVENT_LOG_IX_UUID=0, + FM_EVENT_LOG_IX_EVENT_ID, + FM_EVENT_LOG_IX_STATE, + FM_EVENT_LOG_IX_ENTITY_ID, + FM_EVENT_LOG_IX_INSTANCE_ID, + FM_EVENT_LOG_IX_TIMESTAMP, + FM_EVENT_LOG_IX_SEVERITY, + FM_EVENT_LOG_IX_REASON, + FM_EVENT_LOG_IX_EVENT_TYPE, + FM_EVENT_LOG_IX_PROBABLE_CAUSE, + FM_EVENT_LOG_IX_REPAIR_ACTION, + FM_EVENT_LOG_IX_SERVICE_AFFECT, + FM_EVENT_LOG_IX_SUPPRESSION, + FM_EVENT_LOG_IX_MAX +}; + +bool fm_alarm_set_field(EFmAlarmIndexMap field, SFmAlarmDataT *a, std::string &val); +bool fm_alarm_get_field(EFmAlarmIndexMap field, const SFmAlarmDataT *a, std::string &val); +bool fm_log_set_field(EFmLogIndexMap field, SFmAlarmDataT *a, std::string &val); +bool fm_event_log_set_field(EFmEventLogIndexMap field, SFmAlarmDataT *a, std::string &val); + +void fm_formatted_str_to_vector(const std::string &s, std::vector &alarm); + +bool fm_alarm_to_string(const SFmAlarmDataT *alarm, std::string &str); +bool fm_alarm_from_string(const std::string &str,SFmAlarmDataT *alarm); + +/** + * This will create an alarm list from an alarm - will translate to string. + * The indexes of this API are based on EFmAlarmIndexMap + */ +void fm_alarm_to_list(const SFmAlarmDataT *a, std::vector &list); + +bool fm_alarm_filter_to_string(const AlarmFilter *alarm, std::string &str); +bool fm_alarm_filter_from_string(const std::string &str, AlarmFilter *alarm); + +/** + * Generate a FM UUID + */ +void fm_uuid_create(fm_uuid_t &uuid); + +/** + * General utilities to conver alarm fields to and from strings + */ +EFmErrorT fm_error_from_string(const std::string &str); +std::string fm_error_from_int(EFmErrorT id); + +void fm_log_request(fm_buff_t &req, bool failed=false); +void fm_log_response(fm_buff_t &req, fm_buff_t &resp, bool failed=false); + +#endif /* FMALARMUTILS_H_ */ diff --git a/fm-common/sources/fmDb.cpp b/fm-common/sources/fmDb.cpp new file mode 100644 index 00000000..b16c2d44 --- /dev/null +++ b/fm-common/sources/fmDb.cpp @@ -0,0 +1,199 @@ +// +// Copyright (c) 2016 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include +#include "fmLog.h" +#include "fmAPI.h" +#include "fmTime.h" +#include "fmAlarmUtils.h" +#include "fmDbUtils.h" +#include "fmDb.h" +#include "fmDbConstants.h" +#include "fmThread.h" + + +CFmDBSession::CFmDBSession() { + m_conn.uri = NULL; + m_conn.pgconn = NULL; + m_conn.status = DB_DISCONNECTED; +} + +CFmDBSession::~CFmDBSession() { + if (m_conn.pgconn != NULL){ + PQfinish(m_conn.pgconn); + } +} + +bool CFmDBSession::connect(const char *uri){ + const char *val = NULL; + PGconn *pgconn = NULL; + size_t retries = 30, count = 0, my_sleep = 2; //2 seconds + + while (count < retries){ + /* Make a connection to the database */ + pgconn = PQconnectdb(uri); + /* Check to see that the backend connection was successfully made */ + if ((pgconn == NULL) || (PQstatus(pgconn) != CONNECTION_OK)){ + FM_INFO_LOG("failed to connected to DB: (%s), retry (%d of %d) ", + uri, count+1, retries); + if (pgconn != NULL) { + FM_INFO_LOG("Postgress error message: (%s).", PQerrorMessage(pgconn)); + PQfinish(pgconn); + } + sleep(my_sleep); + count++; + }else { + break; + } + } + + if (count == retries) return false; + + m_conn.status = DB_CONNECTED; + m_conn.pgconn = pgconn; + m_conn.uri = uri; + + val = get_parameter_status("standard_conforming_strings"); + //FM_INFO_LOG("connect: server standard_conforming_strings parameter: %s", + // val ? val : "unavailable"); + m_conn.equote = (val && (0 == strcmp("off", val))); + //FM_INFO_LOG("connect: server requires E'' quotes: %s", m_conn.equote ? "YES" : "NO"); + + m_conn.server_version = PQserverVersion(m_conn.pgconn); + m_conn.protocol = PQprotocolVersion(m_conn.pgconn); + m_conn.encoding = get_parameter_status("client_encoding"); + + return true; +} + +bool CFmDBSession::check_conn(){ + if (PQstatus(m_conn.pgconn) != CONNECTION_OK) { + FM_ERROR_LOG("DB connection NOT OK\n"); + disconnect(); + return connect(m_conn.uri); + } + return true; +} + +void CFmDBSession::disconnect(){ + if (m_conn.pgconn != NULL){ + PQfinish(m_conn.pgconn); + } + if (m_conn.status == DB_CONNECTED){ + m_conn.status = DB_DISCONNECTED; + } +} + +const char * CFmDBSession::get_parameter_status(const char *param){ + return PQparameterStatus(m_conn.pgconn, param); +} + +bool CFmDBSession::query(const char *db_cmd,fm_db_result_t & result) { + PGresult *res; + int nfields, ntuples, i, j; + + if (check_conn() == false){ + FM_ERROR_LOG("Failed to reconnect: %s", PQerrorMessage(m_conn.pgconn)); + return false; + } + + res = PQexec(m_conn.pgconn, db_cmd); + if (PQresultStatus(res) != PGRES_TUPLES_OK){ + FM_ERROR_LOG("Status:(%s)\n", PQresStatus(PQresultStatus(res))); + FM_ERROR_LOG("Failed to execute (%s) (%s)", db_cmd, PQresultErrorMessage(res)); + PQclear(res); + return false; + } + + nfields = PQnfields(res); + ntuples = PQntuples(res); + FM_DEBUG_LOG("Execute cmd:(%s) OK, entries found: (%u)\n", db_cmd, ntuples); + + for (i = 0; i < ntuples; ++i){ + fm_db_single_result_t single_result; + + for (j =0; j < nfields; ++j){ + char * key = PQfname(res, j); + char * value = PQgetvalue(res, i, j); + single_result[key] = value; + } + result.push_back(single_result); + } + + PQclear(res); + return true; +} + +bool CFmDBSession::cmd(const char *db_cmd){ + PGresult *res; + bool rc = true; + + if (check_conn() == false){ + FM_ERROR_LOG("Failed to reconnect: %s", PQerrorMessage(m_conn.pgconn)); + return false; + } + + res = PQexec(m_conn.pgconn, db_cmd); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + FM_ERROR_LOG("Status:(%s)\n", PQresStatus(PQresultStatus(res))); + FM_ERROR_LOG("Failed to execute (%s) (%s)", db_cmd, PQresultErrorMessage(res)); + rc = false; + } + if (rc){ + int row = atoi(PQcmdTuples(res)); + FM_DEBUG_LOG("SQL command returned successful: %d rows affected.\n", row); + if (row < 1) rc = false; + } + + PQclear(res); + return rc; +} + +bool CFmDBSession::params_cmd(fm_db_util_sql_params & sql_params){ + PGresult *res, *last_res; + bool rc = true; + + if (check_conn() == false){ + FM_ERROR_LOG("Failed to reconnect: %s", PQerrorMessage(m_conn.pgconn)); + return false; + } + + res = PQexecParams(m_conn.pgconn, sql_params.db_cmd.c_str(), sql_params.n_params, + NULL,(const char* const*)&(sql_params.param_values[0]), + (const int*)&(sql_params.param_lengths[0]), (const int*)&(sql_params.param_format[0]), 1); + if (PQresultStatus(res) != PGRES_COMMAND_OK) { + FM_ERROR_LOG("Status:(%s)\n", PQresStatus(PQresultStatus(res))); + FM_ERROR_LOG("Failed to execute (%s) (%s)", sql_params.db_cmd.c_str(), + PQresultErrorMessage(res)); + rc = false; + } + if (rc){ + while ((last_res=PQgetResult(m_conn.pgconn)) != NULL){ + if (PQstatus(m_conn.pgconn) == CONNECTION_BAD){ + FM_INFO_LOG("POSTGRES DB connection is bad."); + PQclear(last_res); + break; + } + FM_INFO_LOG("Waiting for POSTGRES command to finish: (%d)", PQresultStatus(last_res)); + PQclear(last_res); + fmThreadSleep(10); + } + int row = atoi(PQcmdTuples(res)); + FM_DEBUG_LOG("SQL command returned successful: %d rows affected.", row); + if (row < 1) { + rc = false; + FM_ERROR_LOG("SQL command returned successful, but no row affected."); + } + } + PQclear(res); + return rc; + +} diff --git a/fm-common/sources/fmDb.h b/fm-common/sources/fmDb.h new file mode 100644 index 00000000..b95c1f8b --- /dev/null +++ b/fm-common/sources/fmDb.h @@ -0,0 +1,67 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMDB_H_ +#define FMDB_H_ + +#include "fmAPI.h" + +#include + +#include +#include +#include + +struct fm_db_util_sql_params { + int id; + int n_params; + std::string db_cmd; + std::vector param_values; + std::vector param_lengths; + std::vector param_format; + std::map scratch; +}; + +typedef std::map fm_db_single_result_t; +typedef std::vector fm_db_result_t; + +typedef struct{ + const char *uri; /* Connection URI */ + int status; /* status of the connection */ + int equote; /* use E''-style quotes for escaped strings */ + int protocol; /* protocol version */ + int server_version; /* server version */ + const char *encoding; /* client encoding */ + PGconn *pgconn; /* the postgresql connection */ +}SFmDBConn; + +class CFmDBSession { +protected: + SFmDBConn m_conn; + const char *get_parameter_status(const char *param); + +public: + CFmDBSession(); + ~CFmDBSession(); + + bool connect(const char *uri); + void disconnect(); + bool check_conn(); + bool reconnect(); + + bool query(const char *db_cmd,fm_db_result_t & result); + bool cmd(const char *db_cmd); + bool params_cmd(fm_db_util_sql_params & sql_params); + + PGconn* get_pgconn(){ + return m_conn.pgconn; + } + +}; + + + +#endif /* FMDB_H_ */ diff --git a/fm-common/sources/fmDbAPI.h b/fm-common/sources/fmDbAPI.h new file mode 100644 index 00000000..8031338c --- /dev/null +++ b/fm-common/sources/fmDbAPI.h @@ -0,0 +1,49 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMDBAPI_H_ +#define FMDBAPI_H_ + +#include +#include "fmAPI.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define FM_SNMP_TRAP_UTIL_SESSION_NULL NULL + +typedef void * TFmAlarmSessionT; + +typedef struct { + SFmAlarmDataT *alarm; + size_t num; +} SFmAlarmQueryT; + + +bool fm_snmp_util_create_session(TFmAlarmSessionT *handle, const char *db_conn); + +void fm_snmp_util_destroy_session(TFmAlarmSessionT handle); + +/* + * Used for applications running on the controller only. Pass in an struct + * and the API will allocate some alarms and return the number of alarms + * + * It is up to the caller to free the SFmAlamarQueryT->alarms entry when done + */ +bool fm_snmp_util_get_all_alarms(TFmAlarmSessionT handle, + SFmAlarmQueryT *query); + +bool fm_snmp_util_get_all_event_logs(TFmAlarmSessionT handle, + SFmAlarmQueryT *query); + +#ifdef __cplusplus +} +#endif + + + +#endif /* FMDBAPI_H_ */ diff --git a/fm-common/sources/fmDbAlarm.cpp b/fm-common/sources/fmDbAlarm.cpp new file mode 100644 index 00000000..f08612c9 --- /dev/null +++ b/fm-common/sources/fmDbAlarm.cpp @@ -0,0 +1,532 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +#include "fmLog.h" +#include "fmDbAlarm.h" +#include "fmAlarmUtils.h" +#include "fmDbConstants.h" +#include "fmDbUtils.h" + +typedef std::map itos_t; +typedef std::map stoi_t; + +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +static itos_t db_alarm_field_ix_to_str; +static stoi_t db_alarm_field_str_to_ix; + +static const char * field_map[] = { + FM_ALARM_COLUMN_CREATED_AT, //0 + FM_ALARM_COLUMN_UPDATED_AT, + FM_ALARM_COLUMN_DELETED_AT, + FM_ALARM_COLUMN_ID, + FM_ALARM_COLUMN_UUID, + FM_ALARM_COLUMN_ALARM_ID, + FM_ALARM_COLUMN_ALARM_STATE, + FM_ALARM_COLUMN_ENTITY_TYPE_ID, + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, + FM_ALARM_COLUMN_TIMESTAMP, + FM_ALARM_COLUMN_SEVERITY, + FM_ALARM_COLUMN_REASON_TEXT, + FM_ALARM_COLUMN_ALARM_TYPE, + FM_ALARM_COLUMN_PROBABLE_CAUSE, + FM_ALARM_COLUMN_PROPOSED_REPAIR_ACTION, + FM_ALARM_COLUMN_SERVICE_AFFECTING, + FM_ALARM_COLUMN_SUPPRESSION, + FM_ALARM_COLUMN_INHIBIT_ALARMS, + FM_ALARM_COLUMN_MASKED //18 +}; + + +void add_both_tables(const char *str, int id, itos_t &t1,stoi_t &t2 ) { + t1[id]=str; + t2[str]=id; +} + +static std::string tostr(int id, const itos_t &t ){ + itos_t::const_iterator it = t.find(id); + if (it!=t.end()) return it->second; + return "unknown"; +} +/* +static int toint(const std::string &s, const stoi_t &t) { + stoi_t::const_iterator it = t.find(s); + if (it!=t.end()) return it->second ; + return 0; +} +*/ +static void init_tables() { + pthread_mutex_lock(&mutex); + static bool has_inited=false; + + while (!has_inited) { + add_both_tables(FM_ALARM_COLUMN_UUID,FM_ALM_IX_UUID,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_ALARM_ID,FM_ALM_IX_ALARM_ID,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_ALARM_STATE,FM_ALM_IX_ALARM_STATE,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_ENTITY_TYPE_ID,FM_ALM_IX_ENTITY_ID,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_ENTITY_INSTANCE_ID,FM_ALM_IX_INSTANCE_ID,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_TIMESTAMP,FM_ALM_IX_TIMESTAMP,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_SEVERITY,FM_ALM_IX_SEVERITY,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + + add_both_tables(FM_ALARM_COLUMN_REASON_TEXT,FM_ALM_IX_REASON,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_ALARM_TYPE,FM_ALM_IX_ALARM_TYPE,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_PROBABLE_CAUSE,FM_ALM_IX_PROBABLE_CAUSE,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_PROPOSED_REPAIR_ACTION,FM_ALM_IX_REPAIR_ACTION,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_SERVICE_AFFECTING,FM_ALM_IX_SERVICE_AFFECT,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_SUPPRESSION,FM_ALM_IX_SUPPRESSION,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + add_both_tables(FM_ALARM_COLUMN_INHIBIT_ALARMS,FM_ALM_IX_INHIBIT_ALARM,db_alarm_field_ix_to_str,db_alarm_field_str_to_ix); + has_inited = true; + } + pthread_mutex_unlock(&mutex); +} + +void append(std::string &str, const std::string &what) { + str+=what; + str+="###"; +} + +bool CFmDbAlarm::import_data(data_type &m ) { + m_alarm_data = m; + return true; +} + +bool CFmDbAlarm::create_data(SFmAlarmDataT *alarm) { + init_tables(); + m_alarm_data.clear(); + size_t ix = FM_ALM_IX_UUID; + size_t mx = FM_ALM_IX_MAX; + std::string field; + for ( ; ix < mx ; ++ix ) { + std::string field_n = tostr(ix,db_alarm_field_ix_to_str); + fm_alarm_get_field((EFmAlarmIndexMap)ix,alarm,field); + m_alarm_data[field_n] = field; + } + return true; +} + +bool CFmDbAlarm::export_data(CFmDbAlarm::data_type &m) { + m = m_alarm_data; + return true; +} + +bool CFmDbAlarm::export_data(SFmAlarmDataT *alarm) { + init_tables(); + memset(alarm,0,sizeof(*alarm)); + + size_t ix = FM_ALM_IX_UUID; + size_t mx =FM_ALM_IX_MAX; + std::string field; + for ( ; ix < mx ; ++ix ) { + std::string field_n = tostr(ix,db_alarm_field_ix_to_str); + if (m_alarm_data.find(field_n)==m_alarm_data.end()) return false; + fm_alarm_set_field((EFmAlarmIndexMap)ix,alarm,m_alarm_data[field_n]); + } + return true; +} + +std::string CFmDbAlarm::find_field(const char *field) { + if (field==NULL) return ""; + if (m_alarm_data.find(field)==m_alarm_data.end()) return ""; + return m_alarm_data[field]; +} + +std::string CFmDbAlarm::to_formatted_db_string(const char ** list, size_t len) { + std::string details; + + if (list == NULL) { + list = &field_map[0]; + len = sizeof(field_map)/sizeof(*field_map); + } + + size_t ix = 0; + for ( ; ix < len ; ++ix ) { + FM_DB_UT_NAME_VAL(details, + list[ix], + m_alarm_data[list[ix]]); + if (ix < (len-1)) + details += "', "; + } + return details; +} + +void CFmDbAlarm::print() { + std::string str = to_formatted_db_string(); + FM_INFO_LOG("%s\n",str.c_str()); +} + +bool CFmDbAlarmOperation::create_alarm(CFmDBSession &sess,CFmDbAlarm &a) { + + CFmDbAlarm::data_type data; + if (!a.export_data(data)) return false; + + CFmDbAlarm::data_type::iterator it = + data.find(FM_ALARM_COLUMN_DELETED_AT); + if (it != data.end()){ + data.erase(it); + } + it = data.find(FM_ALARM_COLUMN_ID); + if (it != data.end()){ + data.erase(it); + } + + std::string query; + FM_DB_UT_NAME_VAL(query,FM_ALARM_COLUMN_ALARM_ID, + data[FM_ALARM_COLUMN_ALARM_ID]); + + query += " AND "; + FM_DB_UT_NAME_VAL(query,FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, + data[FM_ALARM_COLUMN_ENTITY_INSTANCE_ID]); + + std::string sql; + fm_db_util_build_sql_query((const char*)FM_ALARM_TABLE_NAME, query.c_str(), sql); + + fm_db_result_t result; + + if ((sess.query(sql.c_str(), result)) != true){ + return false; + } + + data[FM_ALARM_COLUMN_UUID] = a.find_field(FM_ALARM_COLUMN_UUID); + data[FM_ALARM_COLUMN_MASKED] = "False"; + + fm_db_util_sql_params sql_params; + + if (result.size() == 0){ + fm_db_util_build_sql_insert((const char*)FM_ALARM_TABLE_NAME, data, sql_params); + }else{ + fm_db_single_result_t alm = result[0]; + fm_db_util_build_sql_update((const char*)FM_ALARM_TABLE_NAME, + alm[FM_ALARM_COLUMN_ID],data, sql_params); + } + sql_params.n_params = data.size(); + FM_DEBUG_LOG("execute CMD (%s)\n", sql_params.db_cmd.c_str()); + return sess.params_cmd(sql_params); +} + +bool CFmDbAlarmOperation::delete_alarms(CFmDBSession &sess, const char *id) { + std::string sql; + + fm_db_util_build_sql_delete_all((const char*)FM_ALARM_TABLE_NAME, id, sql); + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + return sess.cmd(sql.c_str()); +} + +bool CFmDbAlarmOperation::delete_alarm(CFmDBSession &sess, AlarmFilter &af) { + std::string sql; + + fm_db_util_build_sql_delete((const char*)FM_ALARM_TABLE_NAME, &af, sql); + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + return sess.cmd(sql.c_str()); +} + + +bool CFmDbAlarmOperation::get_alarm(CFmDBSession &sess, AlarmFilter &af, fm_db_result_t & alarms) { + std::string sql; + char query[FM_MAX_SQL_STATEMENT_MAX]; + + if (strlen(af.entity_instance_id) == 0){ + snprintf(query, sizeof(query),"%s = '%s' AND %s = ' '", FM_ALARM_COLUMN_ALARM_ID, af.alarm_id, + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID); + } + else{ + snprintf(query, sizeof(query),"%s = '%s' AND %s = '%s'", FM_ALARM_COLUMN_ALARM_ID, af.alarm_id, + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, af.entity_instance_id); + } + fm_db_util_build_sql_query((const char*)FM_ALARM_TABLE_NAME, query, sql); + FM_DEBUG_LOG("get_alarm:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), alarms)) != true){ + return false; + } + return true; +} + +bool CFmDbAlarmOperation::get_alarms(CFmDBSession &sess,const char *id, fm_db_result_t & alarms) { + std::string sql; + + char query[FM_MAX_SQL_STATEMENT_MAX]; + fm_db_result_t res; + res.clear(); + + sql = FM_DB_SELECT_FROM_TABLE(FM_ALARM_TABLE_NAME); + sql += " "; + + sql += " INNER JOIN "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += " ON "; + sql += FM_ALARM_TABLE_NAME; + sql += "."; + sql += FM_ALARM_COLUMN_ALARM_ID; + sql += " = "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += "."; + sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID; + + sql += " WHERE "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += "."; + sql += FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS; + sql += " = '"; + sql += FM_EVENT_SUPPRESSION_UNSUPPRESSED; + sql += "'"; + + if (id != NULL){ + snprintf(query, sizeof(query),"%s like '%s%s'", FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, id,"%"); + if (NULL!=query) { + sql += " AND "; + sql += query; + } + } + + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), alarms)) != true) + return false; + + return true; +} + +bool CFmDbAlarmOperation::get_alarms_by_id(CFmDBSession &sess,const char *id, fm_db_result_t & alarms) { + + fm_alarm_id alm_id; + char query[FM_MAX_SQL_STATEMENT_MAX]; + std::string sql; + + memset(alm_id, 0 , sizeof(alm_id)); + strncpy(alm_id, id ,sizeof(alm_id)-1); + + snprintf(query, sizeof(query),"%s = '%s'", FM_ALARM_COLUMN_ALARM_ID, id); + + fm_db_util_build_sql_query((const char*)FM_ALARM_TABLE_NAME, query, sql); + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), alarms)) != true){ + return false; + } + + return true; +} + +bool CFmDbAlarmOperation::get_all_alarms(CFmDBSession &sess, SFmAlarmDataT **alarms, size_t *len ) { + fm_db_result_t res; + + *len = 0; + *alarms = NULL; + if (!get_alarms(sess, NULL, res)) + return false; + + std::string sname = fm_db_util_get_system_name(sess); + + unsigned int found_num_alarms = res.size(); + + if (found_num_alarms < 1) + return false; + + SFmAlarmDataT *p = + (SFmAlarmDataT*)malloc(found_num_alarms*sizeof(SFmAlarmDataT)); + + if (p==NULL) + return false; + + size_t ix = 0; + for ( ; ix < found_num_alarms; ++ix ){ + CFmDbAlarm dbAlm; + CFmDbAlarm::convert_to(res[ix],p+ix); + std::string eid = (p+ix)->entity_instance_id; + eid = sname + "." + eid; + strncpy((p+ix)->entity_instance_id, eid.c_str(), + sizeof((p+ix)->entity_instance_id)); + } + (*alarms) = p; + *len = found_num_alarms; + + return true; +} + +bool CFmDbAlarmOperation::get_history(CFmDBSession &sess,fm_db_result_t & alarms) { + std::string sql; + std::string separator = ", "; + std::string alias = " as "; + + sql = "SELECT * FROM "; + sql += FM_EVENT_LOG_TABLE_NAME; + + sql += " INNER JOIN "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += " ON "; + sql += FM_EVENT_LOG_TABLE_NAME; + sql += "."; + sql += FM_EVENT_LOG_COLUMN_EVENT_ID; + sql += " = "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += "."; + sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID; + + sql += " WHERE "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += "."; + sql += FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS; + sql += " = '"; + sql += FM_EVENT_SUPPRESSION_UNSUPPRESSED; + + sql += "' AND ("; + sql += FM_EVENT_LOG_COLUMN_STATE; + sql += " = 'set' OR "; + sql += FM_EVENT_LOG_COLUMN_STATE; + sql += " = 'clear' ) "; + + sql += std::string(FM_DB_ORDERBY_TIME()); + + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), alarms)) != true){ + return false; + } + return true; +} + +bool CFmDbAlarmOperation::mask_unmask_alarms(CFmDBSession &sess, + SFmAlarmDataT &a, bool mask){ + + std::string sql; + + char query[FM_MAX_SQL_STATEMENT_MAX]; + fm_db_result_t res; + res.clear(); + + snprintf(query, sizeof(query),"%s like '%s%s' and suppression=True", + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, a.entity_instance_id,"%"); + + + fm_db_util_build_sql_query((const char*)FM_ALARM_TABLE_NAME, query, sql); + + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), res)) != true){ + return false; + } + fm_db_result_t::iterator it = res.begin(); + fm_db_result_t::iterator end = res.end(); + for (; it != end; ++it){ + if (((*it)[FM_ALARM_COLUMN_ALARM_ID]==std::string(a.alarm_id)) && + ((*it)[FM_ALARM_COLUMN_ENTITY_INSTANCE_ID]==std::string(a.entity_instance_id))){ + FM_INFO_LOG("Skip the alarm that inhibits others (%s), (%s)\n", + a.alarm_id, a.entity_instance_id); + continue; + } + std::map data; + data.clear(); + fm_db_util_sql_params sql_params; + + fm_db_util_build_sql_update((const char*)FM_ALARM_TABLE_NAME, + (*it)[FM_ALARM_COLUMN_ID],data, sql_params, mask); + sql_params.n_params = data.size(); + FM_DEBUG_LOG("execute CMD (%s)\n", sql_params.db_cmd.c_str()); + sess.params_cmd(sql_params); + } + return true; +} + +bool CFmDbAlarmOperation::get_all_history_alarms(CFmDBSession &sess, SFmAlarmDataT **alarms, size_t *len ) { + fm_db_result_t res; + + *len = 0; + *alarms = NULL; + if (!get_history(sess,res)) return false; + + std::string sname = fm_db_util_get_system_name(sess); + + unsigned int found_num_alarms = res.size(); + + if (found_num_alarms < 1) return false; + + SFmAlarmDataT *p = + (SFmAlarmDataT*)malloc(found_num_alarms*sizeof(SFmAlarmDataT)); + + if (p==NULL){ + return false; + } + size_t ix = 0; + for ( ; ix < found_num_alarms; ++ix ){ + CFmDbAlarm dbAlm; + CFmDbAlarm::convert_to(res[ix],p+ix); + std::string eid = (p+ix)->entity_instance_id; + eid = sname + "." + eid; + strncpy((p+ix)->entity_instance_id, eid.c_str(), + sizeof((p+ix)->entity_instance_id)); + } + (*alarms) = p; + *len = found_num_alarms; + return true; +} + +bool CFmDbAlarmOperation::add_alarm_history(CFmDBSession &sess, + SFmAlarmDataT &a, bool set){ + + if (set){ + a.alarm_state = (a.alarm_state == FM_ALARM_STATE_CLEAR) ? + FM_ALARM_STATE_SET : a.alarm_state; + }else{ + a.alarm_state = FM_ALARM_STATE_CLEAR; + } + + CFmDbAlarm alm; + if (!alm.create_data(&a)) return false; + + CFmDbAlarm::data_type data; + if (!alm.export_data(data)) return false; + + CFmDbAlarm::data_type::iterator it = + data.find(FM_ALARM_COLUMN_DELETED_AT); + if (it != data.end()){ + data.erase(it); + } + + it = data.find(FM_ALARM_COLUMN_UPDATED_AT); + if (it != data.end()){ + data.erase(it); + } + + it = data.find(FM_ALARM_COLUMN_MASKED); + if (it != data.end()){ + data.erase(it); + } + + it = data.find(FM_ALARM_COLUMN_INHIBIT_ALARMS); + if (it != data.end()){ + data.erase(it); + } + + it = data.find(FM_ALARM_COLUMN_ID); + if (it != data.end()){ + data.erase(it); + } + + int id =0; + std::string sql; + + if (false == fm_db_util_get_next_log_id(sess, id)) { + return false; + } + if (0 != id) { + data[FM_ALARM_COLUMN_ID] = fm_db_util_int_to_string(id); + } + + // get the current time for clear event + if (!set){ + std::string time_str; + fm_db_util_make_timestamp_string(time_str); + data[FM_ALARM_COLUMN_TIMESTAMP] = time_str; + //set the same time in the alarm data that will be used for logging + fm_db_util_get_timestamp(time_str.c_str(), a.timestamp); + } + sql.clear(); + + fm_db_util_sql_params sql_params; + fm_db_util_event_log_build_sql_insert(data, sql_params); + FM_DEBUG_LOG("Add row (%s)\n", sql_params.db_cmd.c_str()); + return sess.params_cmd(sql_params); +} + diff --git a/fm-common/sources/fmDbAlarm.h b/fm-common/sources/fmDbAlarm.h new file mode 100644 index 00000000..9c6ee25b --- /dev/null +++ b/fm-common/sources/fmDbAlarm.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMDBALARM_H_ +#define FMDBALARM_H_ + +#include +#include +#include +#include + +#include "fmAPI.h" +#include "fmDbConstants.h" +#include "fmDb.h" + +class CFmDbAlarm { +public: + typedef std::map data_type; + + bool import_data(CFmDbAlarm::data_type &m); + bool create_data(SFmAlarmDataT *alarm); + bool export_data(SFmAlarmDataT *alarm); + bool export_data(CFmDbAlarm::data_type &m); + + + std::string find_field(const char *field); + + void set_field(const std::string &lhs, const std::string &rhs) { + m_alarm_data[lhs] = rhs; + } + + std::string to_formatted_db_string(const char ** list=NULL, size_t len=0); + void print(); + + static inline bool convert_to(CFmDbAlarm::data_type &m, SFmAlarmDataT *alarm ) { + CFmDbAlarm a; + if (!a.import_data(m)) return false; + return a.export_data(alarm); + } +protected: + + data_type m_alarm_data; +}; + + +class CFmDbAlarmOperation { + +public: + bool create_alarm(CFmDBSession &sess, CFmDbAlarm &a); + + bool delete_alarms(CFmDBSession &sess, const char *id); + bool delete_alarm(CFmDBSession &sess, AlarmFilter &af); + + bool delete_row(CFmDBSession &sess, const char* db_table); + + bool get_alarm(CFmDBSession &sess, AlarmFilter &af, fm_db_result_t & alarms); + bool get_alarms(CFmDBSession &sess, const char *id, fm_db_result_t & alarms) ; + bool get_history(CFmDBSession &sess, fm_db_result_t & alarms) ; + + bool get_all_alarms(CFmDBSession &sess, SFmAlarmDataT **alarms, size_t *len ); + + bool get_all_history_alarms(CFmDBSession &sess, SFmAlarmDataT **alarms, size_t *len ); + + bool get_alarms_by_id(CFmDBSession &sess, const char *id, fm_db_result_t & alarms); + + bool mask_unmask_alarms(CFmDBSession &sess, SFmAlarmDataT &a, bool mask = true); + + bool add_alarm_history(CFmDBSession &sess, SFmAlarmDataT &a, bool set); +}; + +#endif /* FMDBALARM_H_ */ diff --git a/fm-common/sources/fmDbConstants.h b/fm-common/sources/fmDbConstants.h new file mode 100644 index 00000000..18a865da --- /dev/null +++ b/fm-common/sources/fmDbConstants.h @@ -0,0 +1,99 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMDBCONSTANTS_H_ +#define FMDBCONSTANTS_H_ + +/* DB connection status */ +#define DB_DISCONNECTED 0 +#define DB_CONNECTED 1 + +#define FM_MAX_SQL_STATEMENT_MAX 4096 + +#define FM_DB_TABLE_COUNT_COLUMN "count" + +/* Alarm table name */ +#define FM_ALARM_TABLE_NAME "i_alarm" + +/* Event log table name */ +#define FM_EVENT_LOG_TABLE_NAME "i_event_log" + +/* Event suppression table name */ +#define FM_EVENT_SUPPRESSION_TABLE_NAME "event_suppression" + +/* Event suppression table sync script */ +#define FM_DB_SYNC_EVENT_SUPPRESSION "/usr/bin/fm_db_sync_event_suppression.py" + +/* Alarm Table Columns */ +#define FM_ALARM_COLUMN_CREATED_AT "created_at" +#define FM_ALARM_COLUMN_UPDATED_AT "updated_at" +#define FM_ALARM_COLUMN_DELETED_AT "deleted_at" +#define FM_ALARM_COLUMN_ID "id" +#define FM_ALARM_COLUMN_UUID "uuid" +#define FM_ALARM_COLUMN_ALARM_ID "alarm_id" +#define FM_ALARM_COLUMN_ALARM_STATE "alarm_state" +#define FM_ALARM_COLUMN_ENTITY_TYPE_ID "entity_type_id" +#define FM_ALARM_COLUMN_ENTITY_INSTANCE_ID "entity_instance_id" +#define FM_ALARM_COLUMN_TIMESTAMP "timestamp" +#define FM_ALARM_COLUMN_SEVERITY "severity" +#define FM_ALARM_COLUMN_REASON_TEXT "reason_text" +#define FM_ALARM_COLUMN_ALARM_TYPE "alarm_type" +#define FM_ALARM_COLUMN_PROBABLE_CAUSE "probable_cause" +#define FM_ALARM_COLUMN_PROPOSED_REPAIR_ACTION "proposed_repair_action" +#define FM_ALARM_COLUMN_SERVICE_AFFECTING "service_affecting" +#define FM_ALARM_COLUMN_SUPPRESSION "suppression" +#define FM_ALARM_COLUMN_INHIBIT_ALARMS "inhibit_alarms" +#define FM_ALARM_COLUMN_MASKED "masked" + +/* Event Log Table Columns */ +#define FM_EVENT_LOG_COLUMN_CREATED_AT "created_at" +#define FM_EVENT_LOG_COLUMN_UPDATED_AT "updated_at" +#define FM_EVENT_LOG_COLUMN_DELETED_AT "deleted_at" +#define FM_EVENT_LOG_COLUMN_ID "id" +#define FM_EVENT_LOG_COLUMN_UUID "uuid" +#define FM_EVENT_LOG_COLUMN_EVENT_ID "event_log_id" +#define FM_EVENT_LOG_COLUMN_STATE "state" +#define FM_EVENT_LOG_COLUMN_ENTITY_TYPE_ID "entity_type_id" +#define FM_EVENT_LOG_COLUMN_ENTITY_INSTANCE_ID "entity_instance_id" +#define FM_EVENT_LOG_COLUMN_TIMESTAMP "timestamp" +#define FM_EVENT_LOG_COLUMN_SEVERITY "severity" +#define FM_EVENT_LOG_COLUMN_REASON_TEXT "reason_text" +#define FM_EVENT_LOG_COLUMN_EVENT_TYPE "event_log_type" +#define FM_EVENT_LOG_COLUMN_PROBABLE_CAUSE "probable_cause" +#define FM_EVENT_LOG_COLUMN_PROPOSED_REPAIR_ACTION "proposed_repair_action" +#define FM_EVENT_LOG_COLUMN_SERVICE_AFFECTING "service_affecting" +#define FM_EVENT_LOG_COLUMN_SUPPRESSION "suppression" + +/* Event Suppression Table Columns */ +#define FM_EVENT_SUPPRESSION_COLUMN_CREATED_AT "created_at" +#define FM_EVENT_SUPPRESSION_COLUMN_UPDATED_AT "updated_at" +#define FM_EVENT_SUPPRESSION_COLUMN_DELETED_AT "deleted_at" +#define FM_EVENT_SUPPRESSION_COLUMN_ID "id" +#define FM_EVENT_SUPPRESSION_COLUMN_UUID "uuid" +#define FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID "alarm_id" +#define FM_EVENT_SUPPRESSION_COLUMN_DESCRIPTION "description" +#define FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS "suppression_status" + +#define FM_EVENT_SUPPRESSION_SUPPRESSED "suppressed" +#define FM_EVENT_SUPPRESSION_UNSUPPRESSED "unsuppressed" +#define FM_EVENT_SUPPRESSION_NONE "None" + +/* System table name */ +#define FM_SYSTEM_TABLE_NAME "i_system" + +#define FM_SYSTEM_NAME_COLUMN "name" +#define FM_SYSTEM_REGION_COLUMN "region_name" + +#define FM_ENTITY_ROOT_KEY "system=" +#define FM_ENTITY_REGION_KEY "region=" + +/* config keys */ +#define FM_SQL_CONNECTION "sql_connection" +#define FM_EVENT_LOG_MAX_SIZE "event_log_max_size" + +#define CLEAR_ALL_REASON_TEXT "System initiated hierarchical alarm clear" + +#endif /* FMDBCONSTANTS_H_ */ diff --git a/fm-common/sources/fmDbEventLog.cpp b/fm-common/sources/fmDbEventLog.cpp new file mode 100644 index 00000000..50e7f1ab --- /dev/null +++ b/fm-common/sources/fmDbEventLog.cpp @@ -0,0 +1,318 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include + +#include "fmLog.h" +#include "fmDbAlarm.h" +#include "fmDbEventLog.h" +#include "fmAlarmUtils.h" +#include "fmDbConstants.h" +#include "fmDbUtils.h" + +typedef std::map itos_t; +typedef std::map stoi_t; + +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +static itos_t db_event_log_field_ix_to_str; +static stoi_t db_event_log_field_str_to_ix; + +static const char * field_map[] = { + FM_EVENT_LOG_COLUMN_CREATED_AT, //0 + FM_EVENT_LOG_COLUMN_UPDATED_AT, + FM_EVENT_LOG_COLUMN_DELETED_AT, + FM_EVENT_LOG_COLUMN_ID, + FM_EVENT_LOG_COLUMN_UUID, + FM_EVENT_LOG_COLUMN_EVENT_ID, + FM_EVENT_LOG_COLUMN_STATE, + FM_EVENT_LOG_COLUMN_ENTITY_TYPE_ID, + FM_EVENT_LOG_COLUMN_ENTITY_INSTANCE_ID, + FM_EVENT_LOG_COLUMN_TIMESTAMP, + FM_EVENT_LOG_COLUMN_SEVERITY, + FM_EVENT_LOG_COLUMN_REASON_TEXT, + FM_EVENT_LOG_COLUMN_EVENT_TYPE, + FM_EVENT_LOG_COLUMN_PROBABLE_CAUSE, + FM_EVENT_LOG_COLUMN_PROPOSED_REPAIR_ACTION, + FM_EVENT_LOG_COLUMN_SERVICE_AFFECTING, + FM_EVENT_LOG_COLUMN_SUPPRESSION, +}; + +static const int alarm_to_event_log_index[] = { + FM_EVENT_LOG_IX_UUID, + FM_EVENT_LOG_IX_EVENT_ID, + FM_EVENT_LOG_IX_STATE, + FM_EVENT_LOG_IX_ENTITY_ID, + FM_EVENT_LOG_IX_INSTANCE_ID, + FM_EVENT_LOG_IX_TIMESTAMP, + FM_EVENT_LOG_IX_SEVERITY, + FM_EVENT_LOG_IX_REASON, + FM_EVENT_LOG_IX_EVENT_TYPE, + FM_EVENT_LOG_IX_PROBABLE_CAUSE, + FM_EVENT_LOG_IX_REPAIR_ACTION, + FM_EVENT_LOG_IX_SERVICE_AFFECT, + FM_EVENT_LOG_IX_SUPPRESSION, + -1, + FM_EVENT_LOG_IX_MAX +}; + +void CFmDbEventLog::add_both_tables(const char *str, int id, itos_t &t1,stoi_t &t2 ) { + t1[id]=str; + t2[str]=id; +} + +static std::string tostr(int id, const itos_t &t ){ + itos_t::const_iterator it = t.find(id); + if (it!=t.end()) return it->second; + return "unknown"; +} + +void CFmDbEventLog::init_tables() { + pthread_mutex_lock(&mutex); + static bool has_inited=false; + + while (!has_inited) { + add_both_tables(FM_EVENT_LOG_COLUMN_UUID,FM_EVENT_LOG_IX_UUID,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_EVENT_ID,FM_EVENT_LOG_IX_EVENT_ID,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_STATE,FM_EVENT_LOG_IX_STATE,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_ENTITY_TYPE_ID,FM_EVENT_LOG_IX_ENTITY_ID,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_ENTITY_INSTANCE_ID,FM_EVENT_LOG_IX_INSTANCE_ID,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_TIMESTAMP,FM_EVENT_LOG_IX_TIMESTAMP,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_SEVERITY,FM_EVENT_LOG_IX_SEVERITY,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_REASON_TEXT,FM_EVENT_LOG_IX_REASON,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_EVENT_TYPE,FM_EVENT_LOG_IX_EVENT_TYPE,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_PROBABLE_CAUSE,FM_EVENT_LOG_IX_PROBABLE_CAUSE,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_PROPOSED_REPAIR_ACTION, FM_EVENT_LOG_IX_REPAIR_ACTION, db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_SERVICE_AFFECTING,FM_EVENT_LOG_IX_SERVICE_AFFECT,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + add_both_tables(FM_EVENT_LOG_COLUMN_SUPPRESSION,FM_EVENT_LOG_IX_SUPPRESSION,db_event_log_field_ix_to_str,db_event_log_field_str_to_ix); + has_inited = true; + } + pthread_mutex_unlock(&mutex); +} + +void CFmDbEventLog::append(std::string &str, const std::string &what) { + str+=what; + str+="###"; +} + +bool CFmDbEventLog::import_data(data_type &m ) { + m_event_log_data = m; + return true; +} + +bool CFmDbEventLog::create_data(SFmAlarmDataT *alarm) { + init_tables(); + m_event_log_data.clear(); + size_t ix = FM_ALM_IX_UUID; + size_t mx = FM_ALM_IX_MAX; + std::string field; + int log_idx; + for ( ; ix < mx ; ++ix ) { + log_idx = alarm_to_event_log_index[ix]; + if (log_idx == -1) + continue; + std::string field_n = tostr(log_idx,db_event_log_field_ix_to_str); + if (field_n == "unknown") + continue; // ignore these fields + fm_alarm_get_field((EFmAlarmIndexMap)ix,alarm,field); + m_event_log_data[field_n] = field; + } + return true; +} + +bool CFmDbEventLog::export_data(CFmDbEventLog::data_type &m) { + m = m_event_log_data; + return true; +} + +bool CFmDbEventLog::export_data(SFmAlarmDataT *data) { + init_tables(); + memset(data,0,sizeof(*data)); + + size_t ix = FM_EVENT_LOG_IX_UUID; + size_t mx = FM_EVENT_LOG_IX_MAX; + std::string field; + for ( ; ix < mx ; ++ix ) { + std::string field_n = tostr(ix,db_event_log_field_ix_to_str); + if (m_event_log_data.find(field_n)==m_event_log_data.end()) return false; + fm_event_log_set_field((EFmEventLogIndexMap)ix,data,m_event_log_data[field_n]); + } + return true; +} + +std::string CFmDbEventLog::find_field(const char *field) { + if (field==NULL) return ""; + if (m_event_log_data.find(field)==m_event_log_data.end()) return ""; + return m_event_log_data[field]; +} + +std::string CFmDbEventLog::to_formatted_db_string(const char ** list, size_t len) { + std::string details; + + if (list == NULL) { + list = &field_map[0]; + len = sizeof(field_map)/sizeof(*field_map); + } + + size_t ix = 0; + for ( ; ix < len ; ++ix ) { + FM_DB_UT_NAME_VAL(details, + list[ix], + m_event_log_data[list[ix]]); + if (ix < (len-1)) + details += "', "; + } + return details; +} + +void CFmDbEventLog::print() { + std::string str = to_formatted_db_string(); + FM_INFO_LOG("%s\n",str.c_str()); +} + +bool CFmDbEventLogOperation::create_event_log(CFmDBSession &sess,CFmDbEventLog &a) { + + CFmDbEventLog::data_type data; + if (!a.export_data(data)) return false; + + CFmDbEventLog::data_type::iterator it = + data.find(FM_EVENT_LOG_COLUMN_DELETED_AT); + if (it != data.end()){ + data.erase(it); + } + + it = data.find(FM_EVENT_LOG_COLUMN_UPDATED_AT); + if (it != data.end()){ + data.erase(it); + } + + it = data.find(FM_EVENT_LOG_COLUMN_ID); + if (it != data.end()){ + data.erase(it); + } + + int id =0; + std::string sql; + + if ( false == fm_db_util_get_next_log_id(sess, id)) { + return false; + } + if (0 != id) { + data[FM_EVENT_LOG_COLUMN_ID] = fm_db_util_int_to_string(id); + } + + fm_db_util_sql_params sql_params; + fm_db_util_build_sql_insert((const char*)FM_EVENT_LOG_TABLE_NAME, data, sql_params); + sql_params.n_params = data.size(); + FM_DEBUG_LOG("Add row (%s)\n", sql_params.db_cmd.c_str()); + return sess.params_cmd(sql_params); +} + +bool CFmDbEventLogOperation::get_event_log(CFmDBSession &sess, AlarmFilter &af, fm_db_result_t & logs) { + std::string sql; + char query[FM_MAX_SQL_STATEMENT_MAX]; + + if (strlen(af.entity_instance_id) == 0){ + snprintf(query, sizeof(query),"%s = '%s' AND %s = ' '", FM_EVENT_LOG_COLUMN_EVENT_ID, af.alarm_id, + FM_EVENT_LOG_COLUMN_ENTITY_INSTANCE_ID); + } + else{ + snprintf(query, sizeof(query),"%s = '%s' AND %s = '%s'", FM_EVENT_LOG_COLUMN_EVENT_ID, af.alarm_id, + FM_EVENT_LOG_COLUMN_ENTITY_INSTANCE_ID, af.entity_instance_id); + } + fm_db_util_build_sql_query((const char*)FM_EVENT_LOG_TABLE_NAME, query, sql); + FM_DEBUG_LOG("get_log:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), logs)) != true){ + return false; + } + return true; +} + +bool CFmDbEventLogOperation::get_event_logs(CFmDBSession &sess, fm_db_result_t & logs) { + std::string sql; + + sql = FM_DB_SELECT_FROM_TABLE(FM_EVENT_LOG_TABLE_NAME); + + sql += " LEFT OUTER JOIN "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += " ON "; + sql += FM_EVENT_LOG_TABLE_NAME; + sql += "."; + sql += FM_EVENT_LOG_COLUMN_EVENT_ID; + sql += " = "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += "."; + sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID; + + sql += " WHERE "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += "."; + sql += FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS; + sql += " = '"; + sql += FM_EVENT_SUPPRESSION_UNSUPPRESSED; + + sql += "' OR "; + sql += FM_EVENT_LOG_COLUMN_STATE; + sql += " = 'log' "; + + // select statement built + + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), logs)) != true){ + return false; + } + return true; +} + +bool CFmDbEventLogOperation::get_event_logs_by_id(CFmDBSession &sess,const char *id, fm_db_result_t & logs) { + char query[FM_MAX_SQL_STATEMENT_MAX]; + std::string sql; + + snprintf(query, sizeof(query),"%s = '%s'", FM_EVENT_LOG_COLUMN_EVENT_ID, id); + + fm_db_util_build_sql_query((const char*)FM_EVENT_LOG_TABLE_NAME, query, sql); + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), logs)) != true){ + return false; + } + return true; +} + +bool CFmDbEventLogOperation::get_all_event_logs(CFmDBSession &sess, SFmAlarmDataT **logs, size_t *len ) { + fm_db_result_t res; + + *len = 0; + *logs = NULL; + + if (!get_event_logs(sess, res)) return false; + + std::string sname = fm_db_util_get_system_name(sess); + + unsigned int found_num_logs = res.size(); + + if (found_num_logs < 1) return false; + + SFmAlarmDataT *p = + (SFmAlarmDataT*)malloc(found_num_logs*sizeof(SFmAlarmDataT)); + + if (p==NULL){ + return false; + } + size_t ix = 0; + for ( ; ix < found_num_logs; ++ix ){ + CFmDbEventLog dbEventLog; + CFmDbEventLog::convert_to(res[ix],p+ix); + std::string eid = (p+ix)->entity_instance_id; + eid = sname + "." + eid; + strncpy((p+ix)->entity_instance_id, eid.c_str(), + sizeof((p+ix)->entity_instance_id)); + } + (*logs) = p; + *len = found_num_logs; + return true; +} diff --git a/fm-common/sources/fmDbEventLog.h b/fm-common/sources/fmDbEventLog.h new file mode 100644 index 00000000..15ae2a79 --- /dev/null +++ b/fm-common/sources/fmDbEventLog.h @@ -0,0 +1,69 @@ +// +// Copyright (c) 2016 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMDBEVENTLOG_H_ +#define FMDBEVENTLOG_H_ + +#include +#include +#include +#include + +#include "fmAPI.h" +#include "fmDbConstants.h" +#include "fmDb.h" + +typedef std::map itos_t; +typedef std::map stoi_t; + +class CFmDbEventLog { +public: + typedef std::map data_type; + + bool create_data(SFmAlarmDataT *alarm); + bool import_data(CFmDbEventLog::data_type &m); + bool export_data(SFmAlarmDataT *alarm); + bool export_data(CFmDbEventLog::data_type &m); + + void append(std::string &str, const std::string &what); + void add_both_tables(const char *str, int id, itos_t &t1,stoi_t &t2 ); + void init_tables(); + + std::string find_field(const char *field); + + void set_field(const std::string &lhs, const std::string &rhs) { + m_event_log_data[lhs] = rhs; + } + + std::string to_formatted_db_string(const char ** list=NULL, size_t len=0); + void print(); + + static inline bool convert_to(CFmDbEventLog::data_type &m, SFmAlarmDataT *alarm ) { + CFmDbEventLog a; + if (!a.import_data(m)) return false; + return a.export_data(alarm); + } +protected: + + data_type m_event_log_data; +}; + + +class CFmDbEventLogOperation { + +public: + bool create_event_log(CFmDBSession &sess, CFmDbEventLog &a); + + bool get_event_log(CFmDBSession &sess, AlarmFilter &af, fm_db_result_t & alarms); + bool get_event_logs(CFmDBSession &sess, fm_db_result_t & alarms) ; + + bool get_all_event_logs(CFmDBSession &sess, SFmAlarmDataT **alarms, size_t *len ); + bool get_event_logs_by_id(CFmDBSession &sess, const char *id, fm_db_result_t & alarms); + + +}; + +#endif /* FMDBEVENTLOG_H_ */ diff --git a/fm-common/sources/fmDbUtils.cpp b/fm-common/sources/fmDbUtils.cpp new file mode 100644 index 00000000..d05ccaa1 --- /dev/null +++ b/fm-common/sources/fmDbUtils.cpp @@ -0,0 +1,715 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "fmMutex.h" +#include "fmAPI.h" +#include "fmLog.h" +#include "fmFile.h" +#include "fmDb.h" +#include "fmDbUtils.h" +#include "fmDbAPI.h" +#include "fmDbConstants.h" +#include "fmAlarmUtils.h" + + +typedef std::map configParams; + +static const char *conf = NULL; + +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +CFmMutex & getConfMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +configParams &getConfigMap(){ + static configParams conf; + return conf; +} + +void FM_DB_UT_NAME_VAL( + std::string &result, + const std::string &lhs, const std::string &rhs) { + result+= lhs; + result+= " = '"; + result+=rhs; + result+="'"; +} + +void FM_DB_UT_NAME_PARAM( + std::string &result, + const std::string &lhs, const std::string &rhs) { + result+= lhs; + result+= "="; + result+=rhs; +} + +static inline void append_str(std::string &s, const std::string &app) { + if (s.size()!=0) s+= ", "; + s+=app; +} + +static inline std::string add_quote(const std::string &s) { + return std::string("'")+s+"'"; +} + +static int get_oldest_id(CFmDBSession &sess, const char* db_table){ + fm_db_result_t res; + int id = 0; + char sql[FM_MAX_SQL_STATEMENT_MAX]; + + memset(sql, 0, sizeof(sql)); + snprintf(sql, sizeof(sql), "SELECT %s FROM %s order by %s limit 1", + FM_ALARM_COLUMN_ID, db_table, + FM_ALARM_COLUMN_CREATED_AT); + + if (sess.query(sql, res)){ + if (res.size() > 0){ + std::map entry = res[0]; + id = fm_db_util_string_to_int(entry[FM_ALARM_COLUMN_ID]); + } + } + return id; +} + +static void get_config_parameters(){ + CfmFile f; + std::string delimiter = "="; + std::string line, key, value; + size_t pos = 0; + + if (conf == NULL){ + FM_ERROR_LOG("The config file is not set\n"); + exit(-1); + } + + if (!f.open(conf, CfmFile::READ, false)){ + FM_ERROR_LOG("Failed to open config file: %s\n", conf); + exit(-1); + } + + while (true){ + if (!f.read_line(line)) break; + + if (line.size() == 0) continue; + + if (line[0] == '#') continue; + + pos = line.find(delimiter); + key = line.substr(0, pos); + value = line.erase(0, pos + delimiter.length()); + getConfigMap()[key] = value; + if (key.compare("sql_connection") != 0){ + // Don't log sql_connection, as it has a password + FM_INFO_LOG("Config key (%s), value (%s)", + key.c_str(), value.c_str()); + } + } +} + +static inline CFmDBSession & FmDbSessionFromHandle(TFmAlarmSessionT *p){ + return *((CFmDBSession*)p); +} + +static void format_time_string(std::string &tstr, struct timespec *ts, + bool snmp){ + + char buff[200]; + + struct tm t; + int ret = 0; + + //tzset(); + memset(&t, 0, sizeof(t)); + memset(buff, 0, sizeof(buff)); + if (gmtime_r(&(ts->tv_sec), &t) == NULL) + return ; + + if (snmp){ + ret = strftime(buff, sizeof(buff), "%Y-%m-%d,%H:%M:%S.0,+0:0", &t); + }else{ + ret = strftime(buff,sizeof(buff), "%F %T", &t); + } + + if (ret == 0) return ; + + tstr+=buff; + + if (!snmp){ + //append the microseconds + snprintf(buff,sizeof(buff), ".%06ld", ts->tv_nsec/1000); + tstr+=buff; + } +} + +std::string fm_db_util_replace_single_quote(std::string const& original){ + std::string result; + std::string::const_iterator it = original.begin(); + for (; it != original.end(); ++it){ + if (*it == '\''){ + result.push_back('\''); + } + result.push_back(*it); + } + return result; +} + +std::string fm_db_util_int_to_string(int val){ + std::string result; + std::stringstream ss; + ss << val; + ss >> result; + return result; +} + +int fm_db_util_string_to_int(std::string val){ + int result; + std::stringstream ss; + ss << val; + ss >> result; + return result; +} + +void fm_db_util_make_timestamp_string(std::string &tstr, FMTimeT tm, + bool snmp){ + struct timespec ts; + if (tm != 0){ + ts.tv_sec = tm / 1000000; + ts.tv_nsec = (tm % 1000000) * 1000; + }else{ + clock_gettime(CLOCK_REALTIME, &ts); + } + tstr.clear(); + format_time_string(tstr,&ts, snmp); +} + +bool fm_db_util_get_timestamp(const char *str, FMTimeT &ft){ + struct timespec ts; + memset(&ts, 0, sizeof(ts)); + // only check if the year is present + if (strlen(str) < 10){ + //get the current time + clock_gettime(CLOCK_REALTIME, &ts); + }else{ + struct tm t; + memset(&t, 0, sizeof(t)); + strptime(str, "%F %T", &t); + ts.tv_sec = mktime(&t); + //now get the nanoseconds + char *tstr = strdup(str); + strsep(&tstr, "."); + if (tstr != NULL){ + ts.tv_nsec = atol(tstr)*1000; + } + } + ft = ts.tv_sec*1000000 + ts.tv_nsec/1000; + return true; +} + +bool fm_db_util_build_sql_query(const char* db_table, + const char* db_query, std::string &db_cmd){ + db_cmd = FM_DB_SELECT_FROM_TABLE(db_table); + + if (NULL!=db_query) { + db_cmd += " "; + db_cmd += FM_DB_WHERE(); + db_cmd += " "; + db_cmd += db_query; + } + return true; +} + +bool fm_db_util_build_sql_insert(const char* db_table, + std::map &map, + fm_db_util_sql_params ¶ms) { + + std::string keys; + std::string values; + std::string time_str; + + fm_db_util_make_timestamp_string(time_str); + map[FM_ALARM_COLUMN_CREATED_AT] = time_str; + + std::map::iterator at = + map.find(FM_ALARM_COLUMN_UPDATED_AT); + if (at != map.end()){ + map.erase(at); + } + + std::map::iterator it = map.begin(); + std::map::iterator end = map.end(); + + size_t i = 0; + std::string cmd_params; + char str[80]; + std::string param; + for ( ; it != end ; ++it ) { + param.clear(); + memset(str, 0, sizeof(str)); + append_str(keys,it->first); + if (it->first == FM_ALARM_COLUMN_ID){ + params.id = htonl(atoi(it->second.c_str())); + params.param_values.push_back((char*)¶ms.id); + params.param_lengths.push_back(sizeof(int)); + params.param_format.push_back(1); + sprintf(str,"$%lu::int,", ++i); + } else if ((it->first == FM_ALARM_COLUMN_CREATED_AT) || + (it->first == FM_ALARM_COLUMN_TIMESTAMP)){ + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str, "$%lu::timestamp,", ++i); + } else if ((it->first == FM_ALARM_COLUMN_SERVICE_AFFECTING) || + (it->first == FM_ALARM_COLUMN_SUPPRESSION) || + (it->first == FM_ALARM_COLUMN_INHIBIT_ALARMS) || + (it->first == FM_ALARM_COLUMN_MASKED)){ + params.scratch[it->first] = (it->second == "True") ? 1 : 0; + params.param_values.push_back((char *)&(params.scratch[it->first])); + params.param_lengths.push_back(sizeof(bool)); + params.param_format.push_back(1); + sprintf(str,"$%lu::boolean,", ++i); + } else { + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str,"$%lu::varchar,", ++i); + } + + param.assign(str); + cmd_params += param; + } + cmd_params.resize(cmd_params.size()-1); + params.db_cmd = "INSERT INTO "; + params.db_cmd += db_table; + params.db_cmd += " ( "; + params.db_cmd += keys; + params.db_cmd += ") VALUES ("; + params.db_cmd += cmd_params; + params.db_cmd += ");"; + + return true; +} + + +bool fm_db_util_event_log_build_sql_insert(std::map &map, + fm_db_util_sql_params ¶ms) { + + std::string keys; + std::string values; + std::string time_str; + + fm_db_util_make_timestamp_string(time_str); + map[FM_ALARM_COLUMN_CREATED_AT] = time_str; + + std::map::iterator at = + map.find(FM_ALARM_COLUMN_UPDATED_AT); + if (at != map.end()){ + map.erase(at); + } + + std::map::iterator it = map.begin(); + std::map::iterator end = map.end(); + + size_t i = 0; + std::string cmd_params; + char str[80]; + std::string param; + params.n_params = 0; + + for ( ; it != end ; ++it ) { + param.clear(); + memset(str, 0, sizeof(str)); + if (it->first == FM_ALARM_COLUMN_ID){ + append_str(keys,it->first); + params.id = htonl(atoi(it->second.c_str())); + params.param_values.push_back((char*)¶ms.id); + params.param_lengths.push_back(sizeof(int)); + params.param_format.push_back(1); + sprintf(str,"$%lu::int,", ++i); + } else if ((it->first == FM_ALARM_COLUMN_CREATED_AT) || + (it->first == FM_ALARM_COLUMN_TIMESTAMP)){ + append_str(keys,it->first); + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str, "$%lu::timestamp,", ++i); + } else if ((it->first == FM_ALARM_COLUMN_SERVICE_AFFECTING) || + (it->first == FM_ALARM_COLUMN_SUPPRESSION) || + (it->first == FM_ALARM_COLUMN_INHIBIT_ALARMS) || + (it->first == FM_ALARM_COLUMN_MASKED)){ + append_str(keys,it->first); + params.scratch[it->first] = (it->second == "True") ? 1 : 0; + params.param_values.push_back((char *)&(params.scratch[it->first])); + params.param_lengths.push_back(sizeof(bool)); + params.param_format.push_back(1); + sprintf(str,"$%lu::boolean,", ++i); + } else if ((it->first == FM_ALARM_COLUMN_ALARM_ID) || + (it->first == FM_EVENT_LOG_COLUMN_ID)){ + std::string event_log_id = FM_EVENT_LOG_COLUMN_EVENT_ID; + append_str(keys,event_log_id); + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str,"$%lu::varchar,", ++i); + } else if ((it->first == FM_ALARM_COLUMN_ALARM_TYPE) || + (it->first == FM_EVENT_LOG_COLUMN_EVENT_TYPE)){ + std::string event_log_type = FM_EVENT_LOG_COLUMN_EVENT_TYPE; + append_str(keys,event_log_type); + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str,"$%lu::varchar,", ++i); + }else if (it->first == FM_ALARM_COLUMN_ALARM_STATE) { + std::string event_state = FM_EVENT_LOG_COLUMN_STATE; + append_str(keys,event_state); + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str,"$%lu::varchar,", ++i); + } + else { + append_str(keys,it->first); + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str,"$%lu::varchar,", ++i); + } + + params.n_params++; + param.assign(str); + cmd_params += param; + } + + cmd_params.resize(cmd_params.size()-1); + params.db_cmd = "INSERT INTO "; + params.db_cmd += FM_EVENT_LOG_TABLE_NAME; + params.db_cmd += " ( "; + params.db_cmd += keys; + params.db_cmd += ") VALUES ("; + params.db_cmd += cmd_params; + params.db_cmd += ");"; + + return true; +} + + +bool fm_db_util_build_sql_update(const char* db_table, + const std::string & id, std::map &map, + fm_db_util_sql_params ¶ms, FMBoolTypeT masked){ + std::string time_str; + params.db_cmd = "UPDATE "; + params.db_cmd += db_table; + params.db_cmd += " SET "; + + fm_db_util_make_timestamp_string(time_str); + map[FM_ALARM_COLUMN_UPDATED_AT] = time_str; + map[FM_ALARM_COLUMN_MASKED] = masked ? "True" : "False"; + + std::map::iterator at = + map.find(FM_ALARM_COLUMN_CREATED_AT); + if (at != map.end()){ + map.erase(at); + } + + std::map::iterator it = map.begin(); + std::map::iterator end = map.end(); + + size_t i = 0; + char str[80]; + std::string param; + for ( ; it != end ; ++it ) { + param.clear(); + memset(str, 0, sizeof(str)); + if (it != map.begin()) + params.db_cmd.append(", "); + + if ((it->first == FM_ALARM_COLUMN_UPDATED_AT) || + (it->first == FM_ALARM_COLUMN_TIMESTAMP)){ + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str, "$%lu::timestamp", ++i); + } else if ((it->first == FM_ALARM_COLUMN_SERVICE_AFFECTING) || + (it->first == FM_ALARM_COLUMN_SUPPRESSION) || + (it->first == FM_ALARM_COLUMN_INHIBIT_ALARMS) || + (it->first == FM_ALARM_COLUMN_MASKED)){ + params.scratch[it->first] = (it->second == "True") ? 1 : 0; + params.param_values.push_back((char *)&(params.scratch[it->first])); + params.param_lengths.push_back(sizeof(bool)); + params.param_format.push_back(1); + sprintf(str,"$%lu::boolean", ++i); + } else { + params.param_values.push_back(it->second.c_str()); + params.param_lengths.push_back(strlen(it->second.c_str())); + params.param_format.push_back(0); + sprintf(str,"$%lu::varchar", ++i); + } + param.assign(str); + FM_DB_UT_NAME_PARAM(params.db_cmd, it->first, param); + } + + params.db_cmd += " WHERE "; + FM_DB_UT_NAME_VAL(params.db_cmd, FM_ALARM_COLUMN_ID, id); + + return true; +} + +bool fm_db_util_build_sql_delete(const char* db_table, AlarmFilter *db_data, + std::string &db_cmd){ + + if (db_data==NULL) return false; + + char sql[FM_MAX_SQL_STATEMENT_MAX]; + + if (strlen(db_data->entity_instance_id) == 0){ + snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s = '%s' AND %s = ' '", + db_table, FM_ALARM_COLUMN_ALARM_ID, db_data->alarm_id, + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID); + } + else{ + snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s = '%s' AND %s = '%s'", + db_table, FM_ALARM_COLUMN_ALARM_ID, db_data->alarm_id, + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, db_data->entity_instance_id); + } + db_cmd.assign(sql); + return true; +} + +bool fm_db_util_build_sql_delete_row(const char* db_table, int id, + std::string &db_cmd){ + + if (id == 0) return false; + + char sql[FM_MAX_SQL_STATEMENT_MAX]; + + snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s = %d", + db_table, FM_ALARM_COLUMN_ID, id); + db_cmd.assign(sql); + return true; +} + +bool fm_db_util_build_sql_delete_all(const char* db_table, const char *id, + std::string &db_cmd){ + + char sql[FM_MAX_SQL_STATEMENT_MAX]; + + snprintf(sql, sizeof(sql), "DElETE FROM %s WHERE %s like '%s%s'", db_table, + FM_ALARM_COLUMN_ENTITY_INSTANCE_ID, id,"%"); + db_cmd.assign(sql); + return true; +} + +void fm_db_util_set_conf_file(const char *fn){ + conf = fn; +} + +bool fm_db_util_get_config(std::string &key, std::string &val){ + + configParams::iterator it; + static int loaded = false; + CFmMutexGuard m(getConfMutex()); + + if (!loaded){ + get_config_parameters(); + loaded = true; + } + + it = getConfigMap().find(key); + if (it != getConfigMap().end()){ + val = it->second; + return true; + } + return false; +} + +int & fm_get_alarm_history_max_size(){ + static int max_size = 0; + + if (max_size == 0){ + std::string val; + std::string key = FM_EVENT_LOG_MAX_SIZE; + if (fm_db_util_get_config(key, val)){ + max_size = fm_db_util_string_to_int(val); + }else{ + FM_ERROR_LOG("Fail to get config value for (%s)\n", key.c_str()); + } + } + return max_size; +} + +int & fm_get_log_max_size(){ + static int max_size = 0; + + if (max_size == 0){ + std::string val; + std::string key = FM_EVENT_LOG_MAX_SIZE; + if (fm_db_util_get_config(key, val)){ + max_size = fm_db_util_string_to_int(val); + }else{ + FM_ERROR_LOG("Fail to get config value for (%s)\n", key.c_str()); + } + } + return max_size; +} + +std::string fm_db_util_get_system_name(CFmDBSession &sess){ + fm_db_result_t res; + std::string cmd; + std::string name = ""; + + fm_db_util_build_sql_query(FM_SYSTEM_TABLE_NAME, NULL, cmd); + if (sess.query(cmd.c_str(), res)){ + if (res.size() > 0){ + std::map entry = res[0]; + name = FM_ENTITY_ROOT_KEY + entry[FM_SYSTEM_NAME_COLUMN]; + } + } + return name; +} + +std::string fm_db_util_get_region_name(CFmDBSession &sess){ + fm_db_result_t res; + std::string cmd; + std::string name = ""; + + fm_db_util_build_sql_query(FM_SYSTEM_TABLE_NAME, NULL, cmd); + if (sess.query(cmd.c_str(), res)){ + if (res.size() > 0){ + std::map entry = res[0]; + name = FM_ENTITY_REGION_KEY + entry[FM_SYSTEM_REGION_COLUMN]; + } + } + return name; +} + +bool fm_db_util_get_row_counts(CFmDBSession &sess, + const char* db_table, int &counts){ + + fm_db_result_t res; + std::string cmd = + FM_DB_SELECT_ROW_COUNTS_FROM_TABLE(std::string(db_table)); + + res.clear(); + if (sess.query(cmd.c_str(), res)){ + if (res.size() > 0){ + std::map entry = res[0]; + counts = fm_db_util_string_to_int(entry[FM_DB_TABLE_COUNT_COLUMN]); + FM_DEBUG_LOG("Table (%s) row counts: (%llu)", + db_table, counts); + return true; + } + } + return false; +} + +bool fm_db_util_get_next_log_id(CFmDBSession &sess, int &id){ + + pthread_mutex_lock(&mutex); + static bool has_max_rows = false; + static int max = 0; + int active = 0; + + if (max == 0){ + max = fm_get_log_max_size(); + } + + if (!has_max_rows){ + fm_db_util_get_row_counts(sess, FM_EVENT_LOG_TABLE_NAME, active); + FM_INFO_LOG("Active row accounts:(%d), max:(%d)\n", active, max); + if (active >= max) { + has_max_rows = true; + } + } + + if (has_max_rows){ + std::string sql; + id = get_oldest_id(sess, FM_EVENT_LOG_TABLE_NAME); + fm_db_util_build_sql_delete_row(FM_EVENT_LOG_TABLE_NAME, id, sql); + FM_DEBUG_LOG("Delete row (%s)\n", sql.c_str()); + if (false == sess.cmd(sql.c_str())){ + FM_INFO_LOG("Fail to delete the old event log: (%d)", id); + pthread_mutex_unlock(&mutex); + return false; + } + } + FM_DEBUG_LOG("Return next log id: (%d)\n", id); + pthread_mutex_unlock(&mutex); + + return true; +} + +bool fm_db_util_create_session(CFmDBSession **sess){ + TFmAlarmSessionT handle; + const char *db_conn = NULL; + std::string val; + std::string key = FM_SQL_CONNECTION; + + if (fm_db_util_get_config(key, val) != true){ + FM_ERROR_LOG("Failed to get config for key: (%s)\n", key.c_str()); + return false; + } + + db_conn = val.c_str(); + if (fm_snmp_util_create_session(&handle, db_conn)){ + *sess = (CFmDBSession*)handle; + return true; + } + return false; +} + +bool fm_db_util_sync_event_suppression(void){ + + bool return_value = true; + const char *db_conn = NULL; + std::string val; + std::string key = FM_SQL_CONNECTION; + + if (fm_db_util_get_config(key, val) != true){ + FM_ERROR_LOG("Failed to get config for key: (%s)\n", key.c_str()); + return false; + } + + db_conn = val.c_str(); + + FILE* file; + int argc; + char * argv[2]; + + FM_INFO_LOG("Starting event suppression synchronization...\n"); + + argc = 2; + argv[0] = (char*)FM_DB_SYNC_EVENT_SUPPRESSION; + argv[1] = (char*)db_conn; + + Py_SetProgramName(argv[0]); + Py_Initialize(); + PySys_SetArgv(argc, argv); + file = fopen(FM_DB_SYNC_EVENT_SUPPRESSION,"r"); + PyRun_SimpleFile(file, FM_DB_SYNC_EVENT_SUPPRESSION); + fclose(file); + Py_Finalize(); + + FM_INFO_LOG("Completed event suppression synchronization.\n"); + + return return_value; +} + + diff --git a/fm-common/sources/fmDbUtils.h b/fm-common/sources/fmDbUtils.h new file mode 100644 index 00000000..5c6be631 --- /dev/null +++ b/fm-common/sources/fmDbUtils.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMDBUTILS_H_ +#define FMDBUTILS_H_ + +#include "fmAPI.h" +#include "fmDbAlarm.h" +#include "fmDbEventLog.h" +#include "fmDb.h" + +#include +#include +#include + +static inline const char *FM_DB_AND() { return "AND"; } +static inline const char *FM_DB_WHERE() { return "WHERE"; } +static inline const char *FM_DB_SELECT_FROM() { return "SELECT * FROM"; } +static inline const char *FM_DB_SELECT_COUNTS() { + return "SELECT COUNT(*) FROM"; +} + +static inline const char *FM_DB_ORDERBY_TIME() { return "order by timestamp desc"; } + +static inline std::string FM_DB_SELECT_FROM_TABLE(const std::string &table){ + return std::string(FM_DB_SELECT_FROM()) + " " +table; +} + +static inline std::string FM_DB_SELECT_ROW_COUNTS_FROM_TABLE( + const std::string &table){ + return std::string(FM_DB_SELECT_COUNTS()) + " " +table; +} + +void FM_DB_UT_NAME_VAL( std::string &result, + const std::string &lhs, const std::string &rhs); + +void FM_DB_UT_NAME_PARAM( std::string &result, + const std::string &lhs, const std::string &rhs); + +std::string fm_db_util_replace_single_quote(std::string const& original); + +void fm_db_util_make_timestamp_string(std::string &tstr, + FMTimeT tm=0, bool snmp=false); + +bool fm_db_util_get_timestamp(const char *str, FMTimeT &ft); + +bool fm_db_util_build_sql_query(const char* db_table, + const char* db_query, std::string &db_cmd); + +bool fm_db_util_build_sql_insert(const char* db_table, + std::map &map, + fm_db_util_sql_params &parms); + +bool fm_db_util_event_log_build_sql_insert(std::map &map, + fm_db_util_sql_params ¶ms); + +bool fm_db_util_build_sql_update(const char* db_table, + const std::string & id, std::map &map, + fm_db_util_sql_params &parms, FMBoolTypeT masked=0); + +bool fm_db_util_build_sql_delete(const char* db_table, + AlarmFilter *db_data, std::string &db_cmd); + +bool fm_db_util_build_sql_delete_row(const char* db_table, int id, + std::string &db_cmd); + +bool fm_db_util_build_sql_delete_all(const char* db_table, + const char *id, std::string &db_cmd); + +bool fm_db_util_get_row_counts(CFmDBSession &sess, const char* db_table, + int &counts); + +bool fm_db_util_create_session(CFmDBSession **sess); + +std::string fm_db_util_get_system_name(CFmDBSession &sess); + +std::string fm_db_util_get_region_name(CFmDBSession &sess); + +void fm_db_util_set_conf_file(const char *fn); + +bool fm_db_util_get_config(std::string &key, std::string &val); + +bool fm_db_util_get_next_log_id(CFmDBSession &sess, int &id); + +std::string fm_db_util_int_to_string(int val); + +int fm_db_util_string_to_int(std::string val); + +bool fm_db_util_sync_event_suppression(void); + +#endif /* FMDBUTILS_H_ */ diff --git a/fm-common/sources/fmEventSuppression.cpp b/fm-common/sources/fmEventSuppression.cpp new file mode 100644 index 00000000..b87370c0 --- /dev/null +++ b/fm-common/sources/fmEventSuppression.cpp @@ -0,0 +1,104 @@ +// +// Copyright (c) 2016 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include "fmDbConstants.h" +#include "fmLog.h" +#include "fmDbAlarm.h" +#include "fmEventSuppression.h" + +bool CFmEventSuppressionOperation::get_event_suppressed(CFmDBSession &sess, SFmAlarmDataT &data, bool &is_event_suppressed) { + + fm_db_result_t result; + + if (get_single_event_suppression(sess, data.alarm_id, result)) { + if (result.size() > 0){ + fm_db_single_result_t event_suppression = result[0]; + std::string db_suppression_status = event_suppression[FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS]; + + if (db_suppression_status.compare(FM_EVENT_SUPPRESSION_SUPPRESSED) == 0) { + is_event_suppressed = true; + } else { + is_event_suppressed = false; + } + } else + return false; + } else + return false; + + return true; +} + +bool CFmEventSuppressionOperation::get_single_event_suppression(CFmDBSession &sess, const char *alarm_id, fm_db_result_t & event_suppression) { + std::string sql; + std::string separator = ", "; + + sql = "SELECT "; + sql += FM_EVENT_SUPPRESSION_COLUMN_CREATED_AT + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_UPDATED_AT + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_DELETED_AT + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_ID + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_UUID + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_DESCRIPTION + separator; + sql += FM_EVENT_SUPPRESSION_COLUMN_SUPPRESSION_STATUS; + + sql += " FROM "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + + sql += " WHERE "; + sql += FM_EVENT_SUPPRESSION_COLUMN_ALARM_ID; + sql += " = '"; + sql += std::string(alarm_id); + sql += "'"; + + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + if ((sess.query(sql.c_str(), event_suppression)) != true){ + return false; + } + return true; +} + +bool CFmEventSuppressionOperation::set_table_notify_listen(CFmDBSession &sess){ + + std::string sql; + fm_db_result_t rule_name; + + // Verify if rule already in table: + sql = "SELECT rulename FROM pg_rules WHERE rulename='watch_event_supression'"; + + if ((sess.query(sql.c_str(), rule_name)) != true){ + return false; + } + + if (rule_name.size() == 0 ) { + sql.clear(); + sql = "CREATE RULE watch_event_supression AS ON UPDATE TO "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += " DO (NOTIFY "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + sql += ")"; + + if (sess.cmd(sql.c_str()) != true){ + return false; + } + + } + + sql.clear(); + sql = "LISTEN "; + sql += FM_EVENT_SUPPRESSION_TABLE_NAME; + + FM_DEBUG_LOG("CMD:(%s)\n", sql.c_str()); + sess.cmd(sql.c_str()); // TODO: sess.cmd() returns false since no row affected by LISTEN command +/* if (sess.cmd(sql.c_str()) != true){ + return false; + } */ + + return true; +} diff --git a/fm-common/sources/fmEventSuppression.h b/fm-common/sources/fmEventSuppression.h new file mode 100644 index 00000000..5a8297e8 --- /dev/null +++ b/fm-common/sources/fmEventSuppression.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2016 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + + +#ifndef FMEVENTSUPPRESSION_H_ +#define FMEVENTSUPPRESSION_H_ + + +/* +#include +#include +#include +#include + +#include "fmAPI.h" +#include "fmDbConstants.h" +*/ +#include "fmDb.h" + +class CFmEventSuppressionOperation { + +public: + + bool get_event_suppressed(CFmDBSession &sess, SFmAlarmDataT &data, bool &is_event_suppressed); + bool get_single_event_suppression(CFmDBSession &sess, const char *alarm_id, fm_db_result_t & event_suppression); + bool set_table_notify_listen(CFmDBSession &sess); +}; + + +#endif + + diff --git a/fm-common/sources/fmFile.cpp b/fm-common/sources/fmFile.cpp new file mode 100644 index 00000000..c1adb8ff --- /dev/null +++ b/fm-common/sources/fmFile.cpp @@ -0,0 +1,57 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include "fmFile.h" +#include "fmLog.h" + +#define FM_FILE_MODE_MAX 10 +#define FM_FILE_SIZE_MAX 2056 + +bool CfmFile::open(const char *path,eFileAccess a, bool binary) { + + char attr[FM_FILE_MODE_MAX]; + + switch(a) { + case READ: strcpy(attr,"r"); + break; + case READ_WRITE: strcpy(attr,"r+"); + break; + case WRITE: strcpy(attr,"w"); + break; + case APPEND: strcpy(attr,"a"); + break; + } + if (binary) { + strcat(attr,"b"); + } + + fp = fopen(path,attr); + + return fp!=NULL; +} + +int is_return_char(int c) { + return (((char)c)=='\n' || ((char)c)=='\r') ? 1 : 0; +} + + +bool CfmFile::read_line(std::string &s) { + char st[MAX_LINE_LEN]; + + bool b = fgets(st,sizeof(st)-1,fp)!=NULL; + if (b) { + s = st; + s.erase(std::find_if(s.begin(), s.end(), std::ptr_fun(is_return_char)),s.end()); + } else s = ""; + return b; +} + +void CfmFile::close(){ + fclose(fp); +} diff --git a/fm-common/sources/fmFile.h b/fm-common/sources/fmFile.h new file mode 100644 index 00000000..9ed5d352 --- /dev/null +++ b/fm-common/sources/fmFile.h @@ -0,0 +1,36 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef fmFILE_H_ +#define fmFILE_H_ + +#include +#include +#include + +class CfmFile { + enum {MAX_LINE_LEN = 4096 }; + FILE * fp; +public: + enum eFileAccess {READ, READ_WRITE, WRITE, APPEND}; + + CfmFile() : fp(NULL) {} + + virtual ~CfmFile() { if (fp!=NULL) fclose(fp); } + + bool valid() { return fp!=NULL; } + + bool open(const char *fn,eFileAccess a, bool binary=false); + + void close(); + + virtual bool read_line(std::string &line); + +}; + + + +#endif diff --git a/fm-common/sources/fmLog.cpp b/fm-common/sources/fmLog.cpp new file mode 100644 index 00000000..b867788e --- /dev/null +++ b/fm-common/sources/fmLog.cpp @@ -0,0 +1,169 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include "fmLog.h" +#include "fmDbAlarm.h" +#include "fmDbEventLog.h" + +#include +#include + +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +static char * escape_json(const char * s, char * buffer, const int bufLen); + +void fmLoggingInit() { + static bool has_inited=false; + if (!has_inited){ + openlog(NULL,LOG_CONS | LOG_NDELAY,LOG_LOCAL1); + setlogmask(LOG_UPTO (LOG_INFO)); + } + has_inited=true; +} + +void fmLogMsg(int level, const char *data,...){ + + va_list ap; + + va_start(ap, data); + vsyslog(level,data,ap); + va_end(ap); +} + +bool fmLogFileInit(){ + fmLoggingInit(); + return true; +} + +// formats event into json form for logging +static char * formattedEvent(CFmDbEventLog::data_type event_map, char * output, int outputSize) { + int bufLen = 1024; + char * buffer = (char *) malloc(bufLen); + + int outputLen = 0; + snprintf(output + outputLen, outputSize - outputLen, "{ \"%s\" : \"%s\", ", "event_log_id", escape_json(event_map["event_log_id"].c_str(), buffer, bufLen)); + + outputLen = strlen(output); + snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "reason_text", escape_json(event_map["reason_text"].c_str(), buffer, bufLen)); + + outputLen = strlen(output); + snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "entity_instance_id", escape_json(event_map["entity_instance_id"].c_str(), buffer, bufLen)); + + outputLen = strlen(output); + snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "severity", escape_json(event_map["severity"].c_str(), buffer, bufLen)); + + outputLen = strlen(output); + snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\", ", "state", escape_json(event_map["state"].c_str(), buffer, bufLen)); + + outputLen = strlen(output); + snprintf(output + outputLen, outputSize - outputLen, "\"%s\" : \"%s\" }", "timestamp", escape_json(event_map["timestamp"].c_str(), buffer, bufLen)); + + free(buffer); + return output; +} + +// logs event to syslog +void fmLogEVT(int level, CFmDbEventLog::data_type event_map) { + char * output = (char*) malloc(2048); + char * msg = formattedEvent(event_map, output, 2048); + fmLogMsg(level,msg); + free(output); +} + +void fmLogAddEventLog(SFmAlarmDataT * data, bool is_event_suppressed){ + pthread_mutex_lock(&mutex); + CFmDbEventLog event; + CFmDbEventLog::data_type event_map; + + event.create_data(data); + event.export_data(event_map); + + fmLogEVT(fmLogLevelInfo | LOG_LOCAL5, event_map); + + pthread_mutex_unlock(&mutex); +} + +// Converts a string (s) to be json safe. Special characters are escaped and written to buffer. +static char * escape_json(const char * s, char * buffer, const int bufLen) { + + int sLen = -1; + int bufLeft = bufLen; + int s_i = 0; + int buf_i = 0; + int ch; + char tmp_buf[16]; + char * escapedChrs = NULL; + int escapedChrsLen = -1; + + if (s==NULL || buffer==NULL || bufLen<1) { + return buffer; + } + + sLen = strlen(s); + buffer[0] = 0; + + if (s == 0) { + return buffer; + } + + while (s_i < sLen && bufLeft > 0) { + ch = s[s_i]; + switch (ch) { + case '\"': + escapedChrs = (char *) "\\\""; + break; + case '\\': + escapedChrs = (char *) "\\\\"; + break; + case '\b': + escapedChrs = (char *) "\\b"; + break; + case '\f': + escapedChrs = (char *) "\\f"; + break; + case '\n': + escapedChrs = (char *) "\\n"; + break; + case '\r': + escapedChrs = (char *) "\\r"; + break; + case '\t': + escapedChrs = (char *) "\\t"; + break; + default: + if (ch < 0) { + ch = 0xFFFD; /* replacement character */ + } + if (ch > 0xFFFF) { + /* beyond BMP (Basic Multilingual Plane); need a surrogate pair + * for reference, see: https://en.wikipedia.org/wiki/Plane_%28Unicode%29 + */ + snprintf(tmp_buf, sizeof(tmp_buf), "\\u%04X\\u%04X", + 0xD800 + ((ch - 0x10000) >> 10), + 0xDC00 + ((ch - 0x10000) & 0x3FF)); + } else if (ch < 0x20 || ch >= 0x7F) { + snprintf(tmp_buf, sizeof(tmp_buf), "\\u%04X", ch); + } else { + tmp_buf[0] = ch; + tmp_buf[1] = 0; + } + escapedChrs = tmp_buf; + } + escapedChrsLen = strlen(escapedChrs); + if (bufLeft <= escapedChrsLen) { + break; + } + strncpy(&buffer[buf_i], escapedChrs, bufLeft ); + bufLeft -= escapedChrsLen; + buf_i += escapedChrsLen; + s_i++; + } + + return buffer; +} diff --git a/fm-common/sources/fmLog.h b/fm-common/sources/fmLog.h new file mode 100644 index 00000000..d1f5ad12 --- /dev/null +++ b/fm-common/sources/fmLog.h @@ -0,0 +1,76 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMLOG_H_ +#define FMLOG_H_ + + +#include +#include +#include "fmAPI.h" + +extern "C" { +} + +enum { + fmLogLevelCritical=LOG_CRIT, + fmLogLevelError=LOG_ERR, + fmLogLevelWarning=LOG_WARNING, + fmLogLevelNotice=LOG_NOTICE, + fmLogLevelInfo = LOG_INFO, + fmLogLevelDebug=LOG_DEBUG, +}; + +#define FM_LOG_LINE_TO_STRING_impl(x) #x + +#define FM_LOG_LINE_TO_STRING(x) FM_LOG_LINE_TO_STRING_impl(x) + +#define PRINTF(data,...) printf(data,## __VA_ARGS__) + +#define FM_TRACE_LOG(data,...) \ + PRINTF(data,## __VA_ARGS__) + +#define FM_LOG_MSG(level,data,...) \ + fmLogMsg(level, __FILE__ "(" \ + FM_LOG_LINE_TO_STRING(__LINE__) "): " \ + data, ## __VA_ARGS__ ) + + +#define FM_INFO_LOG(data,...) \ + FM_LOG_MSG(fmLogLevelInfo,data,## __VA_ARGS__) + +#define FM_DEBUG_LOG(data,...) \ + FM_LOG_MSG(fmLogLevelDebug,data,## __VA_ARGS__) + +#define FM_NOTICE_LOG(data,...) \ + FM_LOG_MSG(fmLogLevelNotice,data,## __VA_ARGS__) + +#define FM_WARNING_LOG(data,...) \ + FM_LOG_MSG(fmLogLevelWarning,data,## __VA_ARGS__) + +#define FM_ERROR_LOG(data,...) \ + FM_LOG_MSG(fmLogLevelError,data,## __VA_ARGS__) + +#define FM_CRITICAL_LOG(data,...) \ + FM_LOG_MSG(fmLogLevelCritical,data,## __VA_ARGS__) + +#define FM_MAX_LOG_LENGTH 992 + + +void fmLoggingInit(); + +void fmLogMsg(int level, const char *data, ...); + +bool fmLogFileInit(); + +void fmLogAddEventLog(SFmAlarmDataT * data, bool is_event_suppressed); + +//void fmLogAddEventLog(SFmAlarmDataT * data); + + +#endif + + diff --git a/fm-common/sources/fmMsg.h b/fm-common/sources/fmMsg.h new file mode 100644 index 00000000..42e3413a --- /dev/null +++ b/fm-common/sources/fmMsg.h @@ -0,0 +1,69 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef _FM_MSG_H +#define _FM_MSG_H + +#include +#include "fmAPI.h" +#include + +#define FM_MSG_VAL_KEY (0x1a0ff11d) +#define FM_MSG_WAIT_FAIL (5) +#define FM_MSG_MAX_RET (2) +#define FM_MSG_INF_WAIT (0) + +typedef enum { + EFmMsgV1= 1, + EFmMaxVersion +}EFmMsgVersionT; + +typedef enum { + EFmMsgRx=0, + EFmMsgTx=1, + EFmMsgMax +}EFmMsgTypesT; + +typedef enum { + EFmCreateFault = 0, + EFmUpdateFault, + EFmDeleteFault, + EFmDeleteFaults, + EFmGetFault, + EFmGetFaults, + EFmReturnUUID, + EFmGetFaultsById, + EFmActMax +}EFmMsgActionsT; + + +typedef struct { + EFmMsgVersionT version; + EFmMsgActionsT action; + uint32_t msg_size; + uint32_t msg_rc; //filled in by server +} SFmMsgHdrT; + +typedef std::vector fm_buff_t; + + +EFmErrorT fm_msg_utils_prep_requet_msg(fm_buff_t &buff, + EFmMsgActionsT act, const void * data, uint32_t len) ; + +static inline void * ptr_to_data(fm_buff_t &buff) { + return &(buff[sizeof(SFmMsgHdrT)]); +} + +static inline SFmMsgHdrT * ptr_to_hdr(fm_buff_t &buff) { + return (SFmMsgHdrT *)&(buff[0]); +} + +static inline bool fm_valid_srv_msg(SFmMsgHdrT *msg, uint32_t exp_size) { + return (msg->msg_size==exp_size); +} + + +#endif /* _FM_MSG_H */ diff --git a/fm-common/sources/fmMsgServer.cpp b/fm-common/sources/fmMsgServer.cpp new file mode 100644 index 00000000..002dd730 --- /dev/null +++ b/fm-common/sources/fmMsgServer.cpp @@ -0,0 +1,735 @@ +// +// Copyright (c) 2017 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fmMsgServer.h" +#include "fmThread.h" +#include "fmSocket.h" +#include "fmAPI.h" +#include "fmMsg.h" +#include "fmAlarmUtils.h" +#include "fmLog.h" +#include "fmMutex.h" +#include "fmDbAlarm.h" +#include "fmSnmpConstants.h" +#include "fmSnmpUtils.h" +#include "fmDbUtils.h" +#include "fmDbEventLog.h" +#include "fmDbConstants.h" +#include "fmEventSuppression.h" + +#define FM_UUID_LENGTH 36 + +typedef struct{ + int fd; + fm_buff_t data; +}sFmGetReq; + +typedef struct{ + int type; + bool set; + SFmAlarmDataT data; +}sFmJobReq; + +typedef std::list fmGetList; +typedef std::list fmJobList; + +CFmMutex & getJobMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +CFmMutex & getListMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +CFmMutex & getSockMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +// trim from end +static inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), + std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + return s; +} + +fmJobList & getJobList(){ + static fmJobList lst; + return lst; +} + +fmGetList& getList(){ + static fmGetList lst; + return lst; +} + +static void enqueue_job(sFmJobReq &req){ + CFmMutexGuard m(getJobMutex()); + getJobList().push_back(req); +} + +static bool dequeue_job(sFmJobReq &req){ + if (getJobList().size() == 0){ + //FM_DEBUG_LOG("Job queue is empty\n"); + return false; + } + CFmMutexGuard m(getJobMutex()); + fmJobList::iterator it = getJobList().begin(); + req = (*it); + getJobList().pop_front(); + return true; +} + +static void enqueue_get(sFmGetReq &req){ + CFmMutexGuard m(getListMutex()); + getList().push_back(req); +} + +static bool dequeue_get(sFmGetReq &req){ + if (getList().size() == 0){ + //FM_DEBUG_LOG("Job queue is empty\n"); + return false; + } + CFmMutexGuard m(getListMutex()); + fmGetList::iterator it = getList().begin(); + req = (*it); + getList().pop_front(); + return true; +} + +void create_db_log(CFmDBSession &sess, sFmJobReq &req){ + SFmAlarmDataT alarm = req.data; + + if (alarm.alarm_state != FM_ALARM_STATE_MSG){ + FM_ERROR_LOG("Unexpected request :(%d) (%s) (%s)", alarm.alarm_state, + alarm.alarm_id, alarm.entity_instance_id); + return; + } + + fmLogAddEventLog(&alarm, false); + fm_snmp_util_gen_trap(sess, FM_ALARM_MESSAGE, alarm); +} + +void get_db_alarm(CFmDBSession &sess, sFmGetReq &req, void *context){ + + fm_buff_t buff = req.data; + SFmMsgHdrT *hdr = (SFmMsgHdrT *)&buff[0]; + void * data = &buff[sizeof(SFmMsgHdrT)]; + AlarmFilter *filter = (AlarmFilter *)data; + FmSocketServerProcessor *srv = (FmSocketServerProcessor *)context; + CFmDbAlarmOperation op; + fm_db_result_t res; + SFmAlarmDataT alarm; + + memset(&alarm, 0, sizeof(alarm)); + hdr->msg_rc = FM_ERR_OK; + res.clear(); + if ((op.get_alarm(sess, *filter, res)) != true){ + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + }else if (res.size() > 0){ + FM_INFO_LOG("Get alarm: (%s) (%s)\n", filter->alarm_id, + filter->entity_instance_id); + CFmDbAlarm::convert_to(res[0],&alarm); + }else{ + hdr->msg_rc = FM_ERR_ENTITY_NOT_FOUND; + } + + if (hdr->msg_rc == FM_ERR_OK) { + FM_DEBUG_LOG("Send resp: uuid (%s), alarm_id (%s)\n", + alarm.uuid, alarm.alarm_id); + srv->send_response(req.fd,hdr,&alarm,sizeof(alarm)); + }else{ + std::string err = fm_error_from_int((EFmErrorT)hdr->msg_rc); + FM_DEBUG_LOG("Get alarm (%s) (%s) failed,send resp:(%s)\n", + filter->alarm_id, filter->entity_instance_id, err.c_str()); + srv->send_response(req.fd,hdr,NULL,0); + } +} + +void get_db_alarms(CFmDBSession &sess, sFmGetReq &req, void *context){ + + fm_buff_t buff = req.data; + SFmMsgHdrT *hdr = (SFmMsgHdrT *)&buff[0]; + void * data = &buff[sizeof(SFmMsgHdrT)]; + fm_ent_inst_t *pid = (fm_ent_inst_t *)(data); + fm_ent_inst_t &id = *pid; + FmSocketServerProcessor *srv = (FmSocketServerProcessor *)context; + CFmDbAlarmOperation op; + fm_db_result_t res; + std::vector alarmv; + + FM_DEBUG_LOG("handle get_db_alarms:%s\n", id); + + hdr->msg_rc = FM_ERR_OK; + res.clear(); + if (op.get_alarms(sess, id, res) != true){ + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + }else if (res.size() > 0){ + int ix = 0; + int resp_len = res.size(); + SFmAlarmDataT alarm; + alarmv.clear(); + for ( ; ix < resp_len ; ++ix ) { + CFmDbAlarm::convert_to(res[ix],&alarm); + alarmv.push_back(alarm); + } + }else{ + FM_DEBUG_LOG("No alarms found for entity_instance_id (%s)\n", id); + hdr->msg_rc = FM_ERR_ENTITY_NOT_FOUND; + } + + if ((hdr->msg_rc==FM_ERR_OK) && (alarmv.size() > 0)){ + int found_num_alarms=alarmv.size(); + + int total_len =(found_num_alarms * sizeof(SFmAlarmDataT)) + sizeof(uint32_t); + + void * buffer = malloc(total_len); + if (buffer==NULL) { + hdr->msg_rc =FM_ERR_SERVER_NO_MEM; + srv->send_response(req.fd,hdr,NULL,0); + return; + } + uint32_t *alen = (uint32_t*) buffer; + *alen =found_num_alarms; + + SFmAlarmDataT * alarms = (SFmAlarmDataT*) ( ((char*)buffer)+sizeof(uint32_t)); + + memcpy(alarms,&(alarmv[0]),alarmv.size() * sizeof(SFmAlarmDataT)); + srv->send_response(req.fd,hdr,buffer,total_len); + free(buffer); + } else { + srv->send_response(req.fd,hdr,NULL,0); + } +} + +void get_db_alarms_by_id(CFmDBSession &sess, sFmGetReq &req, void *context){ + + fm_buff_t buff = req.data; + SFmMsgHdrT *hdr = (SFmMsgHdrT *)&buff[0]; + void * data = &buff[sizeof(SFmMsgHdrT)]; + fm_alarm_id *aid = (fm_alarm_id *)(data); + fm_alarm_id &id = *aid; + FmSocketServerProcessor *srv = (FmSocketServerProcessor *)context; + CFmDbAlarmOperation op; + fm_db_result_t res; + std::vector alarmv; + + FM_DEBUG_LOG("handle get_db_alarms_by_id:%s\n", id); + + hdr->msg_rc = FM_ERR_OK; + res.clear(); + if (op.get_alarms_by_id(sess, id, res) != true){ + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + }else if (res.size() > 0){ + int ix = 0; + int resp_len = res.size(); + CFmDbAlarm dbAlm; + SFmAlarmDataT alarm; + alarmv.clear(); + for ( ; ix < resp_len ; ++ix ) { + CFmDbAlarm::convert_to(res[ix],&alarm); + alarmv.push_back(alarm); + } + }else{ + FM_DEBUG_LOG("No alarms found for alarm_id (%s)\n", id); + hdr->msg_rc = FM_ERR_ENTITY_NOT_FOUND; + } + + if ((hdr->msg_rc==FM_ERR_OK) && (alarmv.size() > 0)){ + int found_num_alarms=alarmv.size(); + + int total_len =(found_num_alarms * sizeof(SFmAlarmDataT)) + sizeof(uint32_t); + + void * buffer = malloc(total_len); + if (buffer==NULL) { + hdr->msg_rc =FM_ERR_SERVER_NO_MEM; + srv->send_response(req.fd,hdr,NULL,0); + return; + } + uint32_t *alen = (uint32_t*) buffer; + *alen =found_num_alarms; + + SFmAlarmDataT * alarms = (SFmAlarmDataT*) ( ((char*)buffer)+sizeof(uint32_t)); + + memcpy(alarms,&(alarmv[0]),alarmv.size() * sizeof(SFmAlarmDataT)); + srv->send_response(req.fd,hdr,buffer,total_len); + free(buffer); + } else { + srv->send_response(req.fd,hdr,NULL,0); + } +} + +void fm_handle_job_request(CFmDBSession &sess, sFmJobReq &req){ + CFmDbAlarmOperation op; + CFmEventSuppressionOperation event_suppression_op; + + //check if it is a customer log request + if (req.type == FM_CUSTOMER_LOG) { + return create_db_log(sess,req); + } + + // check to see if there are any alarms need to be masked/unmasked + if (req.type != FM_ALARM_HIERARCHICAL_CLEAR){ + if (req.data.inhibit_alarms){ + FM_INFO_LOG("%s alarms: (%s)\n", req.set ? "Mask" : "Unmask", + req.data.entity_instance_id); + op.mask_unmask_alarms(sess, req.data, req.set); + } + } + if (!op.add_alarm_history(sess, req.data, req.set)){ + FM_ERROR_LOG("Failed to add historical alarm to DB (%s) (%s", + req.data.alarm_id, req.data.entity_instance_id); + } + + bool is_event_suppressed = false; + + if ((req.type != FM_ALARM_HIERARCHICAL_CLEAR) && + (!event_suppression_op.get_event_suppressed(sess, req.data, is_event_suppressed))) { + FM_ERROR_LOG("Failed to retrieve event suppression status in DB for (%s)", + req.data.alarm_id); + } else { + if (!is_event_suppressed) + fm_snmp_util_gen_trap(sess, req.type, req.data); + } + + fmLogAddEventLog(&req.data, is_event_suppressed); + +} + +void fm_handle_get_request(CFmDBSession &sess, sFmGetReq &req, + void *context){ + fm_buff_t buff = req.data; + SFmMsgHdrT *hdr = (SFmMsgHdrT *)&buff[0]; + switch(hdr->action) { + case EFmGetFault:get_db_alarm(sess,req,context); break; + case EFmGetFaults:get_db_alarms(sess,req,context); break; + case EFmGetFaultsById:get_db_alarms_by_id(sess,req,context); break; + default: + FM_ERROR_LOG("Unexpected job request, action:%u\n",hdr->action); + break; + } +} +inline void * prep_msg_buffer(std::vector &buff, int reserved_size, + SFmMsgHdrT *&hdr) { + buff.resize(sizeof(SFmMsgHdrT) + reserved_size); + hdr = (SFmMsgHdrT*)&(buff[0]); + hdr->msg_size = reserved_size; + hdr->version = EFmMsgV1; + hdr->msg_rc = 0; + return &(buff[sizeof(SFmMsgHdrT)]); +} + +#define is_request_valid(len,structdata) \ + if (len != sizeof(structdata)) { \ + hdr->msg_rc = FM_ERR_INVALID_REQ; \ + send_response(fd,hdr,NULL,0); \ + return; \ + } + + +void FmSocketServerProcessor::send_response(int fd, SFmMsgHdrT *hdr, void *data, size_t len) { + fm_buff_t resp; + CFmMutexGuard m(getSockMutex()); + if (fm_msg_utils_prep_requet_msg(resp,hdr->action,data,len)!=FM_ERR_OK) { + rm_socket(fd); + FM_INFO_LOG("Failed to prepare response, close fd:(%d)", fd); + ::close(fd); + return; + } + ptr_to_hdr(resp)->msg_rc = hdr->msg_rc; + if (!write_packet(fd,resp)){ + FM_INFO_LOG("Failed to send response, close fd:(%d)", fd); + rm_socket(fd); + ::close(fd); + return; + } +} + +void FmSocketServerProcessor::handle_create_fault(int fd, + SFmMsgHdrT *hdr, std::vector &rdata, CFmDBSession &sess) { + + is_request_valid(hdr->msg_size,SFmAlarmDataT); + void * data = &(rdata[sizeof(SFmMsgHdrT)]); + CFmDbAlarmOperation op; + CFmDbEventLogOperation log_op; + CFmDbEventLog dbLog; + CFmDbAlarm a; + sFmJobReq req; + + SFmAlarmDataT *alarm = (SFmAlarmDataT *)(data); + FM_DEBUG_LOG("Time stamp in the alarm message: (%lld)", alarm->timestamp); + if ((strlen(alarm->uuid)) != FM_UUID_LENGTH) { + fm_uuid_create(alarm->uuid); + } + hdr->msg_rc = FM_ERR_OK; + + req.data = *alarm; + req.set = true; + + FM_INFO_LOG("Raising Alarm/Log, (%s) (%s)", alarm->alarm_id, alarm->entity_instance_id); + //enqueue the customer log request after writing it the DB + if (alarm->alarm_state == FM_ALARM_STATE_MSG) { + alarm->alarm_state = FM_ALARM_STATE_LOG; + dbLog.create_data(alarm); + if (log_op.create_event_log(sess, dbLog)) { + FM_INFO_LOG("Log generated in DB: (%s) (%s) (%d)\n", + alarm->alarm_id, alarm->entity_instance_id, alarm->severity); + req.type = FM_CUSTOMER_LOG; + enqueue_job(req); + }else{ + FM_ERROR_LOG("Fail to create customer log: (%s) (%s)\n", + alarm->alarm_id, alarm->entity_instance_id); + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + } + FM_INFO_LOG("Send response for create log, uuid:(%s) (%u)\n", + alarm->uuid, hdr->msg_rc); + send_response(fd,hdr,alarm->uuid,sizeof(alarm->uuid)); + } else { + a.create_data(alarm); + //a.print(); + if (op.create_alarm(sess,a)){ + FM_INFO_LOG("Alarm created/updated: (%s) (%s) (%d) (%s)\n", + alarm->alarm_id, alarm->entity_instance_id, alarm->severity, alarm->uuid); + req.type = alarm->severity; + enqueue_job(req); + }else{ + FM_ERROR_LOG("Fail to created/updated alarm: (%s) (%s)\n", + alarm->alarm_id, alarm->entity_instance_id); + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + } + FM_INFO_LOG("Send response for create fault, uuid:(%s) (%u)\n", + alarm->uuid, hdr->msg_rc); + send_response(fd,hdr,alarm->uuid,sizeof(alarm->uuid)); + } +} + +void FmSocketServerProcessor::handle_delete_faults(int fd, + SFmMsgHdrT *hdr, std::vector &rdata, CFmDBSession &sess) { + + CFmDbAlarmOperation op; + sFmJobReq req; + is_request_valid(hdr->msg_size,fm_ent_inst_t); + void * data = &(rdata[sizeof(SFmMsgHdrT)]); + fm_ent_inst_t *pid = (fm_ent_inst_t *)(data); + fm_ent_inst_t &id = *pid; + + hdr->msg_rc = FM_ERR_OK; + if (op.delete_alarms(sess,id)){ + FM_DEBUG_LOG("Deleted alarms (%s)\n", id); + SFmAlarmDataT alarm; + memset(&alarm, 0, sizeof(alarm)); + //only cares about entity_instance_id in hierarchical alarm clear trap + strncpy(alarm.entity_instance_id, id, sizeof(alarm.entity_instance_id)-1); + strncpy(alarm.reason_text,CLEAR_ALL_REASON_TEXT, + sizeof(alarm.reason_text)-1); + fm_uuid_create(alarm.uuid); + req.type = FM_ALARM_HIERARCHICAL_CLEAR; + req.set = false; + req.data = alarm; + enqueue_job(req); + }else{ + FM_INFO_LOG("Fail to Delete alarms (%s)\n", id); + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + } + send_response(fd,hdr,NULL,0); +} + +void FmSocketServerProcessor::handle_delete_fault(int fd, + SFmMsgHdrT *hdr, std::vector &rdata, CFmDBSession &sess) { + + CFmDbAlarmOperation op; + sFmJobReq req; + CFmDbAlarm dbAlm; + SFmAlarmDataT alarm; + fm_db_result_t res; + + is_request_valid(hdr->msg_size,AlarmFilter); + void * data = &(rdata[sizeof(SFmMsgHdrT)]); + AlarmFilter *filter = (AlarmFilter *)(data); + hdr->msg_rc = FM_ERR_OK; + res.clear(); + if ((op.get_alarm(sess, *filter, res)) != true){ + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + }else{ + if (res.size() > 0){ + if(op.delete_alarm(sess, *filter)){ + FM_INFO_LOG("Deleted alarm: (%s) (%s)\n", + filter->alarm_id, filter->entity_instance_id); + CFmDbAlarm::convert_to(res[0],&alarm); + fm_uuid_create(alarm.uuid); + req.type = FM_ALARM_CLEAR; + req.set = false; + req.data = alarm; + enqueue_job(req); + }else{ + hdr->msg_rc = FM_ERR_DB_OPERATION_FAILURE; + } + }else{ + hdr->msg_rc = FM_ERR_ENTITY_NOT_FOUND; + FM_INFO_LOG("Deleted alarm failed: (%s) (%s) (%s)\n", + filter->alarm_id, filter->entity_instance_id, + fm_error_from_int((EFmErrorT)hdr->msg_rc).c_str()); + } + } + FM_INFO_LOG("Response to delete fault: %u\n", hdr->msg_rc); + send_response(fd,hdr,NULL,0); +} + +void FmSocketServerProcessor::handle_get_faults_by_id(int fd, + SFmMsgHdrT *hdr, std::vector &rdata) { + + is_request_valid(hdr->msg_size,fm_alarm_id); + sFmGetReq req; + req.fd = fd; + req.data = rdata; + enqueue_get(req); +} + +void FmSocketServerProcessor::handle_get_faults(int fd, + SFmMsgHdrT *hdr, std::vector &rdata) { + + is_request_valid(hdr->msg_size,fm_ent_inst_t); + sFmGetReq req; + req.fd = fd; + req.data = rdata; + enqueue_get(req); +} + +void FmSocketServerProcessor::handle_get_fault(int fd, + SFmMsgHdrT *hdr, std::vector &rdata) { + + is_request_valid(hdr->msg_size,AlarmFilter); + sFmGetReq req; + req.fd = fd; + req.data = rdata; + enqueue_get(req); +} + +void FmSocketServerProcessor::handle_socket_data(int fd, + std::vector &rdata, CFmDBSession &sess) { + + SFmMsgHdrT *hdr = (SFmMsgHdrT *)&(rdata[0]); + + FM_DEBUG_LOG("Processor: handler socket data, action:%u\n",hdr->action); + switch(hdr->action) { + case EFmCreateFault:handle_create_fault(fd,hdr,rdata, sess); break; + case EFmDeleteFault:handle_delete_fault(fd, hdr,rdata, sess); break; + case EFmDeleteFaults:handle_delete_faults(fd,hdr,rdata,sess); break; + case EFmGetFault:handle_get_fault(fd,hdr,rdata); break; + case EFmGetFaults:handle_get_faults(fd,hdr,rdata); break; + case EFmGetFaultsById:handle_get_faults_by_id(fd,hdr,rdata); break; + default: + FM_ERROR_LOG("Unexpected client request, action:%u\n",hdr->action); + break; + } +} + +extern "C" { +EFmErrorT fm_server_create(const char *fn) { + signal(SIGPIPE,SIG_IGN); + FmSocketServerProcessor srv; + size_t retries = 5, count = 0, my_sleep = 2000;//2 seconds + const std::string host = "controller"; + int rc = 0; + bool rt = false; + struct addrinfo hints; + struct addrinfo *result=NULL, *rp; + char addr[INET6_ADDRSTRLEN]; + memset(&hints,0,sizeof(hints)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_STREAM; /* Datagram socket */ + hints.ai_flags = 0; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + fmLoggingInit(); + + if (!fmLogFileInit()){ + exit(-1); + } + + fm_db_util_set_conf_file(fn); + + if (!fm_db_util_sync_event_suppression()){ + exit(-1); + } + + if (!fmCreateThread(fmJobHandlerThread,NULL)) { + exit(-1); + } + + if (!fmCreateThread(fmRegHandlerThread,&srv)) { + exit(-1); + } + + if (!fmCreateThread(fmEventSuppressionMonitorThread,NULL)) { + exit(-1); + } + + FM_INFO_LOG("Starting fmManager...\n"); + + while (true) { + rc = getaddrinfo(host.c_str(),NULL, &hints,&result); + if (rc == 0){ + for (rp = result; rp != NULL; rp = rp->ai_next) { + if (rp->ai_family==AF_INET||rp->ai_family==AF_INET6) { + if(rp->ai_family==AF_INET) { + inet_ntop(AF_INET, &(((sockaddr_in*)rp->ai_addr)->sin_addr), addr, sizeof(addr)); + } else if (rp->ai_family==AF_INET6) { + inet_ntop(AF_INET6, &(((sockaddr_in6*)rp->ai_addr)->sin6_addr), addr, sizeof(addr)); + } + rt = srv.server_sock(addr,8001,rp->ai_family); + if (rt == true) break; + if (count < retries){ + FM_INFO_LOG("Bind (%s) (%s) address failed, error: (%d) (%s)", + host.c_str(), addr, errno, strerror(errno)); + } + } + } + freeaddrinfo(result); + }else{ + FM_INFO_LOG("(%s) address lookup failed, error: (%d) (%s)", + host.c_str(),errno, strerror(errno)); + } + + if (rt ==true) break; + + if (count > retries){ + FM_ERROR_LOG("Failed to bind to controller IP, exit..."); + exit(-1); + } + + fmThreadSleep(my_sleep); + count++; + } + + if ( rt == false) + return (EFmErrorT)-1; + + srv.run(); + return FM_ERR_OK; +} + +void fmJobHandlerThread(void *context){ + + CFmDBSession *sess; + + if (fm_db_util_create_session(&sess) != true){ + FM_ERROR_LOG("Fail to create DB session, exit ...\n"); + exit (-1); + } + + while (true){ + sFmJobReq req; + while (dequeue_job(req)){ + fm_handle_job_request(*sess,req); + } + fmThreadSleep(200); + } +} + +void fmRegHandlerThread(void *context){ + + CFmDBSession *sess; + if (fm_db_util_create_session(&sess) != true){ + FM_ERROR_LOG("Fail to create DB session, exit ...\n"); + exit (-1); + } + while (true){ + sFmGetReq req; + while (dequeue_get(req)){ + fm_handle_get_request(*sess, req, context); + } + fmThreadSleep(100); + } +} + +bool fm_handle_event_suppress_changes(CFmDBSession &sess){ + + int sock_fd; + fd_set readset; + PGconn *pgconn = NULL; + PGnotify *notify; + + pgconn = sess.get_pgconn(); + sock_fd = PQsocket(pgconn); + + FD_ZERO(&readset); + FD_SET(sock_fd, &readset); + + // Wait for event_suppression update to occur + if (select(sock_fd + 1, &readset, NULL, NULL, NULL) < 0) + { + FM_ERROR_LOG("select() failed: %s\n", strerror(errno)); + + if (errno!=EINTR) + return false; + } + + // Now check for input. This will clear the queue + PQconsumeInput(pgconn); + while ((notify = PQnotifies(pgconn)) != NULL) + { + PQfreemem(notify); + } + + SFmAlarmDataT *alarm = NULL; + fm_snmp_util_gen_trap(sess, FM_WARM_START, *alarm); + + return true; +} + +void fmEventSuppressionMonitorThread(void *context){ + + CFmDBSession *sess; + CFmEventSuppressionOperation event_suppression_op; + + if (fm_db_util_create_session(&sess) != true){ + FM_ERROR_LOG("Fail to create DB session, exit ...\n"); + exit (-1); + } + + if (event_suppression_op.set_table_notify_listen(*sess) != true){ + FM_ERROR_LOG("Fail to set DB table notify and listen, exit ...\n"); + exit (-1); + } + + while (true){ + fm_handle_event_suppress_changes(*sess); + fmThreadSleep(30000); // 30 second wait allows some time to buffer in multiple notify events + // and send only 1 Warm Start trap as a result + } +} + +} + diff --git a/fm-common/sources/fmMsgServer.h b/fm-common/sources/fmMsgServer.h new file mode 100644 index 00000000..d93adc55 --- /dev/null +++ b/fm-common/sources/fmMsgServer.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMMSGSERVER_H_ +#define FMMSGSERVER_H_ + +#include +#include "fmSocket.h" +#include "fmMsg.h" +#include "fmDb.h" + +class FmSocketServerProcessor : public FmSocketServer { + +protected: + virtual void handle_socket_data(int fd,std::vector &data, + CFmDBSession &sess); + + virtual void handle_create_fault(int fd, SFmMsgHdrT *hdr, + std::vector &rdata, CFmDBSession &sess); + virtual void handle_delete_fault(int fd, SFmMsgHdrT *hdr, + std::vector &rdata, CFmDBSession &sess); + virtual void handle_delete_faults(int fd, SFmMsgHdrT *hdr, + std::vector &rdata,CFmDBSession &sess); + + virtual void handle_get_fault(int fd, SFmMsgHdrT *hdr, + std::vector &rdata); + virtual void handle_get_faults(int fd, SFmMsgHdrT *hdr, + std::vector &rdata); + virtual void handle_get_faults_by_id(int fd, SFmMsgHdrT *hdr, + std::vector &rdata); +public: + void send_response(int fd, SFmMsgHdrT *hdr, void *data, size_t len); +}; + +#endif /* FMMSGSERVER_H_ */ diff --git a/fm-common/sources/fmMutex.cpp b/fm-common/sources/fmMutex.cpp new file mode 100644 index 00000000..4b3aef9a --- /dev/null +++ b/fm-common/sources/fmMutex.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include "fmLog.h" +#include "fmMutex.h" + + +bool CFmMutex::lock() { + + //FM_DEBUG_LOG("lock %X",cntx); + return pthread_mutex_lock((pthread_mutex_t*)cntx)==0; + +} + +bool CFmMutex::unlock() { + + //FM_DEBUG_LOG("unlock %X",cntx); + return pthread_mutex_unlock((pthread_mutex_t*)cntx)==0; + +} + +CFmMutex::CFmMutex() { + + cntx = NULL; + + //use recursive Mutex to allow one thread to lock it multiple times + pthread_mutex_t tmutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + pthread_mutex_t * pMutex = new pthread_mutex_t; + if (pMutex!=NULL) { + *pMutex = tmutex; + cntx = pMutex; + } + +} + +CFmMutex::~CFmMutex() { + + pthread_mutex_destroy((pthread_mutex_t*)cntx); + delete ((pthread_mutex_t*)cntx); //safe if cntx is null + cntx = NULL; + +} + diff --git a/fm-common/sources/fmMutex.h b/fm-common/sources/fmMutex.h new file mode 100644 index 00000000..d31f4510 --- /dev/null +++ b/fm-common/sources/fmMutex.h @@ -0,0 +1,45 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FM_MUTEX_H_ +#define FM_MUTEX_H_ + + +class CFmMutex { + + void * cntx; + +public: + CFmMutex(); + ~CFmMutex(); + bool lock(); + bool unlock(); + +}; + +class CFmMutexGuard { + + CFmMutex & m; + bool rc; + +public: + CFmMutexGuard(CFmMutex & mu) : m(mu) { + rc = m.lock(); + } + + ~CFmMutexGuard() { + m.unlock(); + } + + bool getRc() { + return rc; + } +}; + + +#endif + + diff --git a/fm-common/sources/fmSnmpConstants.h b/fm-common/sources/fmSnmpConstants.h new file mode 100644 index 00000000..8cc3981a --- /dev/null +++ b/fm-common/sources/fmSnmpConstants.h @@ -0,0 +1,69 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include + +#define FM_ALARM_CLEAR 6 +#define FM_ALARM_HIERARCHICAL_CLEAR 7 +#define FM_ALARM_MESSAGE 8 + +#define FM_WARM_START 9 + +#define FM_CUSTOMER_LOG 10 + +/* Trap Destination table name */ +#define FM_TRAPDEST_TABLE_NAME "i_trap_destination" + +#define FM_TRAPDEST_IP_COLUMN "ip_address" + +#define FM_TRAPDEST_COMM_COLUMN "community" + +/* MIB Trap definitions */ +const std::string WRS_ALARM_MIB = "WRS-ALARM-MIB"; + +const std::string ALARM_CRITICAL = "wrsAlarmCritical"; +const std::string ALARM_MAJOR = "wrsAlarmMajor"; +const std::string ALARM_MINOR = "wrsAlarmMinor"; +const std::string ALARM_WARNING = "wrsAlarmWarning"; +const std::string ALARM_MSG = "wrsAlarmMessage"; +const std::string ALARM_CLEAR = "wrsAlarmClear"; +const std::string ALARM_HIERARCHICAL_CLEAR = "wrsAlarmHierarchicalClear"; + +const std::string ALARM_ID = "wrsAlarmActiveAlarmId"; +const std::string ALARM_INSTANCE_ID = "wrsAlarmActiveEntityInstanceId"; +const std::string ALARM_DATE_TIME = "wrsAlarmActiveDateAndTime"; +const std::string ALARM_SEVERITY = "wrsAlarmActiveAlarmSeverity"; +const std::string ALARM_REASON_TEXT = "wrsAlarmActiveReasonText"; +const std::string ALARM_EVENT_TYPE = "wrsAlarmActiveEventType"; +const std::string ALARM_CAUSE = "wrsAlarmActiveProbableCause"; +const std::string ALARM_REPAIR_ACTION = "wrsAlarmActiveProposedRepairAction"; +const std::string ALARM_SERVICE_AFFECTING = "wrsAlarmActiveServiceAffecting"; +const std::string ALARM_SUPPRESSION = "wrsAlarmActiveSuppressionAllowed"; + +const std::string CUSTOMER_LOG_ID = "wrsCustomerLogId"; +const std::string CUSTOMER_LOG_INSTANCE_ID = "wrsCustomerLogEntityInstanceId"; +const std::string CUSTOMER_LOG_DATE_TIME = "wrsCustomerLogDateAndTime"; +const std::string CUSTOMER_LOG_SEVERITY = "wrsCustomerLogSeverity"; +const std::string CUSTOMER_LOG_REASON_TEXT = "wrsCustomerLogReasonText"; +const std::string CUSTOMER_LOG_EVENT_TYPE = "wrsCustomerLogEventType"; +const std::string CUSTOMER_LOG_CAUSE = "wrsCustomerLogProbableCause"; +const std::string CUSTOMER_LOG_SERVICE_AFFECTING = "wrsCustomerLogServiceAffecting"; + +const std::string SNMPv2_MIB = "SNMPv2-MIB"; +const std::string WARM_START = "warmStart"; + +const std::string TRAP_CMD = "/usr/bin/snmptrap -v 2c"; +const std::string CLEAR_REASON_TEXT = "System initiated hierarchical alarm clear"; + +const std::string SEP = " "; +const std::string SCOPE = "::"; +const std::string STR_TYPE = " s "; +const std::string INT_TYPE = " i "; +const std::string OPTION_COMM = " -c "; + +const std::string DC_COMM_STR = "dcorchAlarmAggregator"; +const std::string CONF_PATH_ENV = "SNMPCONFPATH="; +const std::string CONF_DIR = "/etc/snmp"; diff --git a/fm-common/sources/fmSnmpUtils.cpp b/fm-common/sources/fmSnmpUtils.cpp new file mode 100644 index 00000000..0fd311f7 --- /dev/null +++ b/fm-common/sources/fmSnmpUtils.cpp @@ -0,0 +1,290 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include +#include +#include + +#include "fmDbAPI.h" +#include "fmFile.h" +#include "fmAPI.h" +#include "fmMsg.h" +#include "fmLog.h" +#include "fmDb.h" +#include "fmDbUtils.h" +#include "fmSnmpConstants.h" +#include "fmSnmpUtils.h" + +typedef std::map int_to_objtype; + +static int_to_objtype objtype_map; +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + + +static void add_to_table(int t, std::string objtype, int_to_objtype &tbl) { + tbl[t]=objtype; +} + +static void init_objtype_table() { + pthread_mutex_lock(&mutex); + static bool has_inited=false; + while (!has_inited){ + add_to_table(FM_ALARM_SEVERITY_CLEAR, ALARM_MSG, objtype_map); + add_to_table(FM_ALARM_SEVERITY_WARNING, ALARM_WARNING, objtype_map); + add_to_table(FM_ALARM_SEVERITY_MINOR, ALARM_MINOR, objtype_map); + add_to_table(FM_ALARM_SEVERITY_MAJOR, ALARM_MAJOR, objtype_map); + add_to_table(FM_ALARM_SEVERITY_CRITICAL, ALARM_CRITICAL, objtype_map); + add_to_table(FM_ALARM_CLEAR, ALARM_CLEAR, objtype_map); + add_to_table(FM_ALARM_HIERARCHICAL_CLEAR, ALARM_HIERARCHICAL_CLEAR, objtype_map); + add_to_table(FM_ALARM_MESSAGE, ALARM_MSG, objtype_map); + add_to_table(FM_WARM_START, WARM_START, objtype_map); + has_inited=true; + } + pthread_mutex_unlock(&mutex); +} + +static std::string add_time_val(std::string &str, + const std::string &objtype, FMTimeT time){ + std::string time_str; + fm_db_util_make_timestamp_string(time_str, time, true); + return str + objtype + STR_TYPE + time_str + SEP; +} + +static std::string add_str_val(std::string &str, + const std::string &objtype, const char *value){ + std::string val(value); + return str + objtype + STR_TYPE + '"' + val + '"' + SEP; +} + +static std::string add_int_val(std::string &str, + const std::string &objtype, int value){ + return str + objtype + INT_TYPE + fm_db_util_int_to_string(value) + SEP; +} + +static std::string get_trap_objtype(int type){ + init_objtype_table(); + return objtype_map[type]; +} +static bool get_trap_dest_list(CFmDBSession &sess,fm_db_result_t & res){ + std::string cmd; + + fm_db_util_build_sql_query(FM_TRAPDEST_TABLE_NAME, NULL, cmd); + return sess.query(cmd.c_str(), res); +} + +static std::string format_trap_cmd(CFmDBSession &sess, int type, SFmAlarmDataT &data, + std::string &ip, std::string &comm){ + std::string cmd; + std::string objtype; + std::string mib; + std::string s = "\"\" "; + std::string env; + + if (get_trap_objtype(type) == WARM_START) + mib = SNMPv2_MIB; + else + mib = WRS_ALARM_MIB; + + objtype = mib + SCOPE + get_trap_objtype(type); + + if (comm.compare(DC_COMM_STR) == 0){ + env = CONF_PATH_ENV + CONF_DIR + SEP; + } + else { + env = ""; + } + + cmd = env + TRAP_CMD + OPTION_COMM + comm + SEP + ip + SEP + s + objtype + SEP; + std::string operation_type =get_trap_objtype(type); + + if (operation_type == ALARM_CLEAR){ + cmd = add_str_val(cmd,ALARM_ID, data.alarm_id); + cmd = add_str_val(cmd, ALARM_INSTANCE_ID, data.entity_instance_id); + cmd = add_time_val(cmd, ALARM_DATE_TIME, data.timestamp); + cmd = add_str_val(cmd, ALARM_REASON_TEXT, data.reason_text); + } else if (operation_type == ALARM_HIERARCHICAL_CLEAR){ + cmd = add_str_val(cmd, ALARM_INSTANCE_ID, data.entity_instance_id); + cmd = add_time_val(cmd, ALARM_DATE_TIME, 0); + cmd = add_str_val(cmd, ALARM_REASON_TEXT, CLEAR_REASON_TEXT.c_str()); + } else if (operation_type == ALARM_MSG){ + cmd = add_str_val(cmd, CUSTOMER_LOG_ID, data.alarm_id); + cmd = add_str_val(cmd, CUSTOMER_LOG_INSTANCE_ID, data.entity_instance_id); + cmd = add_time_val(cmd, CUSTOMER_LOG_DATE_TIME, data.timestamp); + cmd = add_int_val(cmd, CUSTOMER_LOG_SEVERITY, data.severity); + cmd = add_str_val(cmd, CUSTOMER_LOG_REASON_TEXT, data.reason_text); + cmd = add_int_val(cmd, CUSTOMER_LOG_EVENT_TYPE, data.alarm_type); + cmd = add_int_val(cmd, CUSTOMER_LOG_CAUSE, data.probable_cause); + cmd = add_int_val(cmd, CUSTOMER_LOG_SERVICE_AFFECTING, data.service_affecting); + } else if (operation_type == WARM_START){ + // nothing to add to cmd + } else { + cmd = add_str_val(cmd, ALARM_ID, data.alarm_id); + cmd = add_str_val(cmd, ALARM_INSTANCE_ID, data.entity_instance_id); + cmd = add_time_val(cmd, ALARM_DATE_TIME, data.timestamp); + cmd = add_int_val(cmd, ALARM_SEVERITY, data.severity); + cmd = add_str_val(cmd, ALARM_REASON_TEXT, data.reason_text); + cmd = add_int_val(cmd, ALARM_EVENT_TYPE, data.alarm_type); + cmd = add_int_val(cmd, ALARM_CAUSE, data.probable_cause); + cmd = add_str_val(cmd, ALARM_REPAIR_ACTION, data.proposed_repair_action); + cmd = add_int_val(cmd, ALARM_SERVICE_AFFECTING, data.service_affecting); + cmd = add_int_val(cmd, ALARM_SUPPRESSION, data.suppression); + } + + return cmd; +} + +bool fm_snmp_util_gen_trap(CFmDBSession &sess, int type, SFmAlarmDataT &data) { + + bool rc = true; + fm_buff_t cmdbuff; + fm_db_result_t res; + std::string cmd, eid; + + if (!get_trap_dest_list(sess,res)) return false; + + if (&data != NULL) { + eid.assign(data.entity_instance_id); + std::string region_name = fm_db_util_get_region_name(sess); + std::string sys_name = fm_db_util_get_system_name(sess); + if (sys_name.length() != 0){ + eid = sys_name + "."+ eid; + } + if (region_name.length() != 0){ + eid = region_name + "."+ eid; + } + strncpy(data.entity_instance_id, eid.c_str(), + sizeof(data.entity_instance_id)-1); + } + + fm_db_result_t::iterator it = res.begin(); + fm_db_result_t::iterator end = res.end(); + + for (; it != end; ++it){ + memset(&(cmdbuff[0]), 0, cmdbuff.size()); + cmd.clear(); + std::string ip = (*it)[FM_TRAPDEST_IP_COLUMN]; + std::string comm = (*it)[FM_TRAPDEST_COMM_COLUMN]; + cmd = format_trap_cmd(sess,type, data, ip, comm); + + //FM_INFO_LOG("run cmd: %s\n", cmd.c_str()); + char *pline = &(cmdbuff[0]); + FILE *op = popen(cmd.c_str(),"r"); + if (op==NULL) { + FM_ERROR_LOG("popen() failed, errno: (%d) (%s)\n", + errno, strerror(errno)); + rc = false; + } + while (fgets(pline,cmdbuff.size(),op)!=NULL) { + FM_ERROR_LOG("Trap error message: (%s)\n", pline); + } + fclose(op); + } + return rc; +} + +static bool fm_snmp_get_db_connection(std::string &connection){ + CfmFile f; + const char *fn = "/etc/fm.conf"; + std::string sql_key = FM_SQL_CONNECTION; + std::string delimiter = "="; + std::string line, key, value; + size_t pos = 0; + + if (!f.open(fn, CfmFile::READ, false)){ + FM_ERROR_LOG("Failed to open config file: %s\n", fn); + exit (-1); + } + + while (true){ + if (!f.read_line(line)) break; + + if (line.size() == 0) continue; + + pos = line.find(delimiter); + key = line.substr(0, pos); + if (key == sql_key){ + value = line.erase(0, pos + delimiter.length()); + // Don't log sql_connection, as it has a password + //FM_DEBUG_LOG("Found it: (%s)\n", value.c_str()); + connection = value; + return true; + } + } + + return false;; +} + + +extern "C" { +bool fm_snmp_util_create_session(TFmAlarmSessionT *handle, const char* db_conn){ + + std::string key = FM_SQL_CONNECTION; + std::string conn; + CFmDBSession *sess = new CFmDBSession; + if (sess==NULL) return false;; + + if (db_conn == NULL){ + if (fm_snmp_get_db_connection(conn) != true){ + FM_ERROR_LOG("Fail to get db connection uri\n"); + delete sess; + return false; + } + db_conn = conn.c_str(); + } + + if (sess->connect(db_conn) != true){ + FM_ERROR_LOG("Fail to connect to (%s)\n", db_conn); + delete sess; + return false; + } + *handle = sess; + return true; +} + +void fm_snmp_util_destroy_session(TFmAlarmSessionT handle) { + CFmDBSession *sess = (CFmDBSession *)handle; + + if (sess != NULL){ + delete sess; + } +} + +bool fm_snmp_util_get_all_alarms(TFmAlarmSessionT handle, + SFmAlarmQueryT *query) { + + assert(handle!=NULL); + + CFmDbAlarmOperation op; + fm_db_result_t res; + + CFmDBSession &sess = *((CFmDBSession*)handle); + + if (!op.get_all_alarms(sess, &(query->alarm), &(query->num))) return false; + + return true; +} + +bool fm_snmp_util_get_all_event_logs(TFmAlarmSessionT handle, + SFmAlarmQueryT *query) { + + assert(handle!=NULL); + + CFmDbEventLogOperation op; + fm_db_result_t res; + + CFmDBSession &sess = *((CFmDBSession*)handle); + + if (!op.get_all_event_logs(sess, &(query->alarm), &(query->num))) return false; + + return true; +} + +} + diff --git a/fm-common/sources/fmSnmpUtils.h b/fm-common/sources/fmSnmpUtils.h new file mode 100644 index 00000000..e40573b5 --- /dev/null +++ b/fm-common/sources/fmSnmpUtils.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef __FM_SNMP_UTILS_H +#define __FM_SNMP_UTILS_H + +#include + +#include "fmAPI.h" +#include "fmDb.h" + +bool fm_snmp_util_gen_trap(CFmDBSession &sess, int type, SFmAlarmDataT &data); + +#endif diff --git a/fm-common/sources/fmSocket.cpp b/fm-common/sources/fmSocket.cpp new file mode 100644 index 00000000..e14e62d5 --- /dev/null +++ b/fm-common/sources/fmSocket.cpp @@ -0,0 +1,462 @@ +// +// Copyright (c) 2017 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fmSocket.h" +#include "fmThread.h" +#include "fmMutex.h" +#include "fmLog.h" +#include "fmDbUtils.h" + +CFmMutex & getConnectionMutex(){ + static CFmMutex *m = new CFmMutex; + return *m; +} + +void CFmSockAddr::set_type(socklen_t addr_len) { + if (addr_len==sizeof(address.ipv4)) { + type = AF_INET; + } else if (addr_len==sizeof(address.ipv6)) { + type = AF_INET6; + } else { + type = AF_UNIX; + } +} + + +CFmSocket::CFmSocket() { + m_fd = -1; +} + +CFmSocket::~CFmSocket() { + close(); +} + + +void CFmSocket::close() { + if (m_fd!=-1) { + //FM_INFO_LOG("close fd:(%d)", m_fd); + ::close(m_fd); + } + m_fd = -1; + +} + +bool CFmSocket::create_socket() { + int optval = 1; + socklen_t optlen = sizeof(optval); + + close(); + m_fd = ::socket(address_family,SOCK_STREAM,0); + if (m_fd == -1){ + FM_ERROR_LOG("Failed to create socket, error: (%d) (%s)", errno, strerror(errno)); + return false; + } + + /* Set the KEEPALIVE option active */ + if(setsockopt(m_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0) { + FM_ERROR_LOG("Failed to setsockopt, error: (%d) (%s)", errno, strerror(errno)); + close(); + return false; + } + //FM_DEBUG_LOG("SO_KEEPALIVE set on socket\n"); + + return true; +} + +bool CFmSocket::connect(const char *host, int port, int address_family) { + this->address_family = address_family; + if (!create_socket()) { + return false; + } + switch (address_family) { + //When address is IPv4 + case AF_INET: + { + struct sockaddr_in addr; + + if (inet_aton(host,&(addr.sin_addr))==0) { + FM_INFO_LOG("inet_aton() failed\n"); + return false; + } + addr.sin_port = htons(port); + addr.sin_family = AF_INET; + + fd_set wset; + FD_ZERO(&wset); + FD_SET(m_fd,&wset); + + return (::connect(m_fd,(const struct sockaddr *)&addr,sizeof(addr))==0); + } + //When address is IPv6 + case AF_INET6: + { + struct sockaddr_in6 addr; + + if (inet_pton(AF_INET6,host,&(addr.sin6_addr))<=0) { + FM_INFO_LOG("inet_aton() failed\n"); + return false; + } + addr.sin6_port = htons(port); + addr.sin6_family = AF_INET6; + + fd_set wset; + FD_ZERO(&wset); + FD_SET(m_fd,&wset); + + return (::connect(m_fd,(const struct sockaddr *)&addr,sizeof(addr))==0); + } + //Should never get here, needed for completeness + default: + { + return false; + } + } + +} + +bool CFmSocket::write(int fd, const void *data, long len) { + int offset = 0; + while (offset!=len) { + int rc = ::write(fd, ((char*)data)+offset,len-offset); + if (rc==0 || (rc==-1 && errno!=EINTR)) { + FM_ERROR_LOG("Socket Error: Failed to write to fd:(%d), len:(%d), rc:(%d), error:(%s)", + fd, len, rc, strerror(errno)); + return false; + } + if (rc==-1 && errno==EINTR) continue; + offset+=rc; + } + return true; +} + +bool CFmSocket::write_packet(int fd, const void *data, long plen) { + uint32_t len = htonl(plen); + bool rc = write(fd,&len,sizeof(len)); + if (!rc) return false; + return write(fd,data,plen); +} + +bool CFmSocket::write_packet(int fd, const std::vector &data) { + return write_packet(fd,&(data[0]),data.size()); +} + +bool CFmSocket::read_packet(int fd, std::vector &data) { + int32_t len = 0; + long tlen = sizeof(len); + int i = 10; + for ( ; i > 0 ; --i) { + if (!read(fd,&len,tlen)) { + return false; + } + break; + } + if (tlen!=sizeof(len)) + { + FM_ERROR_LOG("Socket Error: Length does not match the data size: (%ld), (%ld)", tlen, sizeof(len)); + return false; + } + len=ntohl(len); + data.resize(len); + tlen = len; + + if (!read(fd,&(data[0]),tlen)) return false; + return true; +} + +bool CFmSocket::read(int fd,void *data, long &len) { + int offset = 0; + while (offset!=len) { + int rc = ::read(fd, ((char*)data)+offset,len-offset); + if (rc==0 || (rc==-1 && errno!=EINTR)) { + // return code 0 means graceful close of TCP socket + if (rc !=0 ){ + FM_ERROR_LOG("Failed to read from fd:(%d), rc:(%d), error:(%s), len:(%d)", + fd, rc, strerror(errno), len); + } + len = offset; + return false; + } + if (rc==-1 && errno==EINTR) continue; + offset+=rc; + } + return true; +} + +bool CFmSocket::read_packet(std::vector &data) { + return read_packet(m_fd,data); +} +bool CFmSocket::read(void *data, long &len) { + return read(m_fd,data,len); +} + +int CFmSocket::select(int *rfd, int rlen, int *wfds, int wlen,int timeout, int timeoutusec, bool &timedout) { + fd_set rset,wset; + FD_ZERO(&rset); + wset=rset; + int max_fd = -1; + int ix = 0; + for ( ; ix < rlen ; ++ix ) { + if (max_fd < rfd[ix]) max_fd = rfd[ix]; + FD_SET(rfd[ix],&rset); + } + + ix = 0; + for ( ; ix < wlen ; ++ix ) { + if (max_fd < wfds[ix]) max_fd = wfds[ix]; + FD_SET(wfds[ix],&wset); + } + + struct timeval to; + to.tv_sec = timeout; + to.tv_usec = timeoutusec; + timedout=false; + int rc = 0; + while (true) { + rc = ::select(max_fd+1,&rset,&wset,NULL,&to); + if (rc==-1 && errno!=EINTR) { + break; + } + if (rc==-1) continue; + if (rc==0) timedout = true; + break; + } + if (rc>0) { + ix = 0; + for ( ; ix < rlen ; ++ix ) { + if (!FD_ISSET(rfd[ix],&rset)) { + rfd[ix]=-1; + } + } + + ix = 0; + for ( ; ix < wlen ; ++ix ) { + if (!FD_ISSET(wfds[ix],&wset)) { + wfds[ix] = -1; + } + } + } + return rc; +} + +int CFmSocket::select_read(int fd,int timeout, bool &timedout){ + return select(&fd,1,NULL,0,timeout,0,timedout); +} + +bool CFmSocket::recvfrom(void *data, long &len, CFmSockAddr &addr) { + socklen_t addr_len = sizeof(addr.address); + int l = ::recvfrom(m_fd,data,len,0,addr.get_sockaddr(),&addr_len); + if (l==-1) { len = errno; return false; } + len = l; + addr.set_type(addr_len); + return true; +} + +bool CFmSocket::write(const void *data, long len) { + return write(m_fd,data,len); +} + +void FmSocketServer::rm_socket(int sock) { + CFmMutexGuard m(getConnectionMutex()); + conn_map_t::iterator it = connections.find(sock); + if (it!=connections.end()) { + connections.erase(it); + } +} + +void FmSocketServer::handle_socket_data(int fd, std::vector &data, + CFmDBSession &sess) { + FM_INFO_LOG("Received data from sock:%d len %lu\n",fd,data.size()); +} + +bool FmSocketServer::good_socket(int sock) { + bool timedout=false; + int rc = select(&sock,1,NULL,0,0,0,timedout); + return (rc!=-1); +} + +void FmSocketServer::find_bad_fd() { + if (!good_socket(m_fd)) { + server_reset(); + } + std::vector lsock; + to_sock_array(lsock); + + int ix = 0; + int mx =lsock.size(); + for ( ; ix < mx ; ++ix) { + if (!good_socket(lsock[ix])) { + FM_INFO_LOG("Found bad fd, close it:(%d)", lsock[ix]); + ::close(lsock[ix]); + rm_socket(lsock[ix]); + } + } +} + +bool FmSocketServer::run() { + CFmDBSession *sess; + if (fm_db_util_create_session(&sess) != true){ + FM_ERROR_LOG("Fail to create DB session, exit ...\n"); + exit (-1); + } + while (true) { + std::vector lsock; + to_sock_array(lsock); + lsock.push_back(m_fd); + + bool timedout =false; + int rc = select(&(lsock[0]),lsock.size(),NULL,0,1,0,timedout); + if (timedout) continue; + if (rc==-1) { + find_bad_fd(); + continue; + } + //listening socket and close all current sockets.. + int ix = 0; + int mx = lsock.size(); + for ( ; ix < mx ; ++ix ) { + if (lsock[ix]==-1) continue; + if (lsock[ix]==m_fd) { + accept(); + continue; + } + std::vectorbuff; + buff.clear(); + bool rc = read_packet(lsock[ix],buff); + if (!rc) { + ::close(lsock[ix]); + rm_socket(lsock[ix]); + } else { + //FM_INFO_LOG("handle_socket_data\n"); + handle_socket_data(lsock[ix],buff, *sess); + } + + } + } + return false; +} + +FmSocketServer::~FmSocketServer() { + conn_map_t::iterator it = connections.begin(); + conn_map_t::iterator end = connections.end(); + for (; it != end ; ++it) { + ::close(it->first); + } + connections.clear(); +} +void FmSocketServer::to_sock_array(std::vector &socks) { + CFmMutexGuard m(getConnectionMutex()); + conn_map_t::iterator it = connections.begin(); + conn_map_t::iterator end = connections.end(); + for (; it != end ; ++it) { + socks.push_back(it->first); + } +} + +bool FmSocketServer::server_reset() { + if (!create_socket()) { + FM_INFO_LOG("Failed to create socket for port:(%d)\n", server_port); + return false; + } + switch (address_family) { + //When address is IPv4 + case AF_INET: + { + int optval = 1; + setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr(server_addr.c_str()); + addr.sin_port = htons(server_port); + + int ipAddr = addr.sin_addr.s_addr; + char str[INET_ADDRSTRLEN]; + memset(str,0, sizeof(str)); + inet_ntop( AF_INET, &ipAddr, str, INET_ADDRSTRLEN ); + + if (bind(m_fd,(const struct sockaddr *)&addr,sizeof(addr))!=0) { + return false; + } + FM_INFO_LOG("FM server socket binds the addr:(%s) port:(%d)\n",str, htons(server_port)); + + if (::listen(m_fd,10)==-1) { + FM_INFO_LOG("listen on fd:(%d) failed, errno: (%d) (%s)\n", + m_fd, errno, strerror(errno)); + } + return true; + } + //When address is IPv6 + case AF_INET6: + { + int optval = 1; + setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); + + struct sockaddr_in6 addr; + addr.sin6_family = AF_INET6; + inet_pton(AF_INET6,server_addr.c_str(),&(addr.sin6_addr)); + addr.sin6_port = htons(server_port); + + char str[INET6_ADDRSTRLEN]; + memset(str,0, sizeof(str)); + inet_ntop( AF_INET6, &addr.sin6_addr.s6_addr, str, INET6_ADDRSTRLEN ); + + if (bind(m_fd,(const struct sockaddr *)&addr,sizeof(addr))!=0) { + return false; + } + FM_INFO_LOG("FM server socket binds the addr:(%s) port:(%d)\n",str, htons(server_port)); + + if (::listen(m_fd,10)==-1) { + FM_INFO_LOG("listen on fd:(%d) failed, errno: (%d) (%s)\n", + m_fd, errno, strerror(errno)); + } + return true; + } + //Should never get here, needed for completeness + default: + { + return false; + } + } + +} + +bool FmSocketServer::server_sock(const char *bindaddr, int port, int address_family) { + this->address_family = address_family; + server_addr = bindaddr; + server_port = port; + return server_reset(); +} + +bool FmSocketServer::accept() { + client_conn con; + socklen_t alen = sizeof(con.addr); + + int fd = ::accept(m_fd,con.addr.get_sockaddr(),&alen); + if (fd==-1) { + FM_INFO_LOG("accept returns fd: (%d) errno: (%d) (%s)\n", + fd, errno, strerror(errno)); + return false; + } + con.sock = fd; + CFmMutexGuard m(getConnectionMutex()); + connections[fd] = con; + return true; +} + diff --git a/fm-common/sources/fmSocket.h b/fm-common/sources/fmSocket.h new file mode 100644 index 00000000..f960e548 --- /dev/null +++ b/fm-common/sources/fmSocket.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FMSOCKET_H_ +#define FMSOCKET_H_ + +#include "fmMutex.h" +#include "fmDb.h" + +#include +#include +#include + +#include +#include +#include +#include + +typedef struct CFmSockAddr_s { + int type; + union { + struct sockaddr_in ipv4; + struct sockaddr_in6 ipv6; + struct sockaddr_un un; + } address; + sockaddr * get_sockaddr() { + return (sockaddr*)(&address); + } + void set_type(socklen_t len); +} CFmSockAddr; + +class CFmSocket { +protected: + int m_fd; + int address_family; + + void close(); + bool create_socket(); +public: + CFmSocket(); + ~CFmSocket(); + + bool connect(const char *host, int port, int address_family); + + + static bool write(int fd, const void *data, long len); + static bool write_packet(int fd, const std::vector &data); + static bool write_packet(int fd, const void *data, long len); + + static bool read(int fd,void *data, long &len); + static bool read_packet(int fd, std::vector &data); + + // read length and then size of exact packet + bool read_packet(std::vector &data); + bool write_packet(const std::vector &data) { + return write_packet(m_fd,data); + } + bool write_packet(const void *data, long len) { + return write_packet(m_fd,data,len); + } + + bool read(void *data, long &len); + bool write(const void *data, long len); + + + int get_fd() { return m_fd; } + bool recvfrom(void *data, long &len, CFmSockAddr &addr ); + + static int select(int *rfd, int rlen, int *wfds, int wlen,int timeout,int timeoutusec, bool &timedout); + static int select_read(int fd,int timeout, bool &timedout); +}; + + +class FmSocketServer : public CFmSocket { +protected: + std::string server_addr; + int server_port; + + typedef struct { + CFmSockAddr addr; + int sock; + } client_conn; + + typedef std::map conn_map_t; + conn_map_t connections; + + void to_sock_array(std::vector &socks); + + bool accept(); + virtual void handle_socket_data(int fd,std::vector &data, + CFmDBSession &sess); + + void add_socket(int sock); + void rm_socket(int sock); + bool good_socket(int sock); + void find_bad_fd(); +public: + bool server_sock(const char *bindaddr, int port, int address_family); + bool server_reset(); + + bool run(); + + virtual ~FmSocketServer(); +}; + +#endif /* DMSOCKET_H_ */ diff --git a/fm-common/sources/fmThread.cpp b/fm-common/sources/fmThread.cpp new file mode 100644 index 00000000..6c4f7bd5 --- /dev/null +++ b/fm-common/sources/fmThread.cpp @@ -0,0 +1,97 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include +#include +#include +#include + +#include "fmThread.h" +#include "fmLog.h" + + +struct thread_struct { + FmThreadFunctionT fn; + void *cntx; +}; + +static void * ThreadProcL(void * lpParameter ) { + + thread_struct * p = (thread_struct *) lpParameter; + + p->fn(p->cntx); + delete p; + return 0; + +} +#define FM_MSEC_PER_SEC 1000 +#define FM_NSEC_PER_MILSEC 1000000 +static void our_sleep(unsigned int msec) { + + struct timespec req; + struct timespec left; + + memset(&left,0,sizeof(left)); + req.tv_sec = msec / FM_MSEC_PER_SEC; + req.tv_nsec = (msec % FM_MSEC_PER_SEC) * FM_NSEC_PER_MILSEC; + + while (nanosleep(&req,&left)==-1 && errno==EINTR) { + req = left; + } + +} + + +extern "C" { +bool fmCreateThread(FmThreadFunctionT fn, void *usrData) { + + int rt = 0; + pthread_t p_thread; + pthread_attr_t attr; + + //Initialize the thread attributes with the default values + rt =pthread_attr_init(&attr); + + if (rt != 0){ + FM_ERROR_LOG("Initialize the thread attributes failed:error=%d",rt); + return false; + } + + // could change the default values here + rt =pthread_attr_setstacksize(&attr, FM_THREAD_STACK_SIZE); + if (rt != 0){ + FM_ERROR_LOG("pthread_attr_setstacksize failed:error=%d",rt); + return false; + } + + thread_struct * p = new thread_struct; + if (p == NULL){ + FM_ERROR_LOG("Can't allocate the thread struct"); + return false; + + } + + p->fn = fn; + p->cntx = usrData; + rt= pthread_create(&p_thread,&attr,ThreadProcL,p); + + if (rt != 0){ + FM_ERROR_LOG("Failed to create the thread:error=%d",rt); + delete p; + return false; + } + + return true; + +} + +bool fmThreadSleep(unsigned int msec) { + our_sleep(msec); + return true; +} + +} diff --git a/fm-common/sources/fmThread.h b/fm-common/sources/fmThread.h new file mode 100644 index 00000000..60eae4bb --- /dev/null +++ b/fm-common/sources/fmThread.h @@ -0,0 +1,34 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FM_THREAD_H_ +#define FM_THREAD_H_ + +#include +//Set stack size of 2M (rather than 8M default). +#define FM_THREAD_STACK_SIZE (2 * 1024 * 1024) + +#ifdef __cplusplus +extern "C" { +#endif +typedef void (*FmThreadFunctionT) (void * context); +bool fmCreateThread(FmThreadFunctionT fn, void *cntx) ; +bool fmThreadSleep(unsigned int msec) ; +void fmJobHandlerThread(void *context); +void fmRegHandlerThread(void *context); +void fmEventSuppressionMonitorThread(void *context); + +#ifdef __cplusplus +} +#endif + +#endif + + + + + + diff --git a/fm-common/sources/fmTime.cpp b/fm-common/sources/fmTime.cpp new file mode 100644 index 00000000..f6a2a588 --- /dev/null +++ b/fm-common/sources/fmTime.cpp @@ -0,0 +1,48 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include "fmTime.h" +#include "fmLog.h" +#include +#include + +#define FM_USEC_PER_SEC 1000000 + + +static FMTimeT GetUptimeMicro() { + uint64_t thetm = 0; + struct timespec tv; + + if (clock_gettime(CLOCK_MONOTONIC_RAW,&tv)==0) { + thetm = tv.tv_nsec/1000; + thetm = ((uint64_t)tv.tv_sec) * FM_USEC_PER_SEC; + } else { + FM_ERROR_LOG("clock_gettime() failed: error: (%d), (%s)", errno, strerror(errno)); + } + return thetm; +} + +FMTimeT fmGetCurrentTime() { + + struct timeval tv; + + memset(&tv,0,sizeof(tv)); + if (gettimeofday(&tv, NULL) != 0){ + FM_ERROR_LOG("gettimeofday failed (errno:%d)",errno); + return 0; + } else { + return (((FMTimeT)tv.tv_sec) * FM_USEC_PER_SEC) + + ((FMTimeT)tv.tv_usec); + } +} + +FMTimeT fmGetCurrentHrt() { + return GetUptimeMicro(); +} + +FMTimeT CFmTimer::gethrtime(){ + return fmGetCurrentHrt(); +} diff --git a/fm-common/sources/fmTime.h b/fm-common/sources/fmTime.h new file mode 100644 index 00000000..1b7e4fb6 --- /dev/null +++ b/fm-common/sources/fmTime.h @@ -0,0 +1,81 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#ifndef FM_TIME_H_ +#define FM_TIME_H_ + + +#include +#include + +#include +#include +#include + + +#include "fmAPI.h" +#include "fmLog.h" + + +// time in microseconds +FMTimeT fmGetCurrentTime(); + +// time in microseconds +FMTimeT fmGetCurrentHrt(); + +/** + * Create a passive timer in microseconds + */ +class CFmTimer { + FMTimeT m_start; + FMTimeT m_offset; + + static bool isExpired(FMTimeT start, FMTimeT offset, + FMTimeT now) { + return (now-start) >= offset; + } + +public: + + static FMTimeT gethrtime(); + + unsigned long long getStartingTime() const { return m_start; } + + void reset() { + m_start = gethrtime(); + } + + void setExpired() { + m_start = gethrtime() - m_offset; + } + + void setExpiry(FMTimeT timeout) { + m_offset = timeout; + reset(); + } + + CFmTimer(FMTimeT timeout=0) { + setExpiry(timeout); + } + + bool isExpired() const { + return isExpired(m_start,m_offset,gethrtime()); + } + + FMTimeT remaining() const { + FMTimeT now = gethrtime(); + if (isExpired(m_start,m_offset,now)) { + return 0; + } + return m_offset - (now-m_start); + } + FMTimeT sec_to_micro(unsigned int t) { + return ((FMTimeT)(t)) * 10000000; + } +}; + +#endif + diff --git a/fm-common/sources/fm_cli.cpp b/fm-common/sources/fm_cli.cpp new file mode 100644 index 00000000..6156c5ce --- /dev/null +++ b/fm-common/sources/fm_cli.cpp @@ -0,0 +1,188 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include "fmAPI.h" +#include "fmAlarmUtils.h" +#include +#include +#include +#include +#include + +void error(const char *add="") { + printf("%s\n",add); + exit(-1); +} + +void ok(const char *s="") { + printf("Ok\n%s%s",s,strlen(s)!=0 ? "\n":""); + exit(0); +} + +void ok(fm_uuid_t *uuid) { + return ok(*uuid); +} + +void create_alarm(const char *al) { + SFmAlarmDataT alarm; + EFmErrorT rc; + + memset(&alarm,0,sizeof(alarm)); + + if (!fm_alarm_from_string(al,&alarm)) { + error("Invalid alarm string.."); + } + + //clear uuid and let it be set by fm-mgr + memset(alarm.uuid, 0, sizeof(*alarm.uuid)); + fm_uuid_t uuid; + if ((rc = fm_set_fault(&alarm,&uuid))!=FM_ERR_OK) { + std::string errstr = fm_error_from_int(rc); + error(errstr.c_str()); + } + ok(&uuid); +} + +void delete_alarms(const char *id) { + fm_ent_inst_t inst_id; + EFmErrorT rc; + + memset(inst_id, 0 , sizeof(inst_id)); + strncpy(inst_id, id ,sizeof(inst_id)-1); + + if ((rc = fm_clear_all(&inst_id))!=FM_ERR_OK) { + std::string errstr = fm_error_from_int(rc); + error(errstr.c_str()); + } + ok(); +} + +void delete_alarm(const char *f) { + AlarmFilter af; + EFmErrorT rc; + + memset(&af,0,sizeof(af)); + if (!fm_alarm_filter_from_string(f,&af)) { + error("Invalid alarm filter"); + } + if ((rc = fm_clear_fault(&af))!=FM_ERR_OK) { + std::string errstr = fm_error_from_int(rc); + error(errstr.c_str()); + } + ok(); +} + +void get_alarm(const char *f) { + AlarmFilter af; + EFmErrorT rc; + + memset(&af, 0, sizeof(af)); + if (!fm_alarm_filter_from_string(f,&af)) { + error("Invalid alarm filter"); + } + + SFmAlarmDataT ad; + memset(&ad, 0 , sizeof(ad)); + + if ((rc = fm_get_fault(&af,&ad))!=FM_ERR_OK) { + std::string errstr = fm_error_from_int(rc); + error(errstr.c_str()); + } + std::string s; + fm_alarm_to_string(&ad,s); + ok(s.c_str()); +} + +void get_alarms(const char *id) { + fm_ent_inst_t inst_id; + EFmErrorT rc; + + memset(inst_id, 0 , sizeof(inst_id)); + strncpy(inst_id, id ,sizeof(inst_id)-1); + + unsigned int max_alarms=500; + SFmAlarmDataT *p = (SFmAlarmDataT*)malloc(max_alarms*sizeof(SFmAlarmDataT)); + if (p==NULL) error("Not enough memory..."); + if ((rc=fm_get_faults(&inst_id,p,&max_alarms))!=FM_ERR_OK) { + free(p); + std::string errstr = fm_error_from_int(rc); + error(errstr.c_str()); + } + printf("Ok\n"); + + size_t ix = 0; + for ( ; ix < max_alarms; ++ix ) { + std::string a; + fm_alarm_to_string(p+ix,a); + printf("%s\n",a.c_str()); + } + free(p); + exit(0); +} + +void get_alarms_by_id(const char *id) { + fm_alarm_id alm_id; + EFmErrorT rc; + + memset(alm_id, 0 , sizeof(alm_id)); + strncpy(alm_id, id ,sizeof(alm_id)-1); + + unsigned int max_alarms=500; + SFmAlarmDataT *p = (SFmAlarmDataT*)malloc(max_alarms*sizeof(SFmAlarmDataT)); + if (p==NULL) error("Not enough memory..."); + if ((rc=fm_get_faults_by_id(&alm_id,p,&max_alarms))!=FM_ERR_OK) { + free(p); + std::string errstr = fm_error_from_int(rc); + error(errstr.c_str()); + } + printf("Ok\n"); + + size_t ix = 0; + for ( ; ix < max_alarms; ++ix ) { + std::string a; + fm_alarm_to_string(p+ix,a); + printf("%s\n",a.c_str()); + } + free(p); + exit(0); +} + +int main(int argc, char**argv) { + int c; + + if (argc < 3) { + error("Wrong arguments"); + } + while ( (c=getopt(argc,argv,"c:d:D:g:G:A:"))) { + switch(c) { + case 'c': + create_alarm(optarg); + break; + case 'd': + delete_alarm(optarg); + break; + case 'D': + delete_alarms(optarg); + break; + case 'g': + get_alarm(optarg); + break; + case 'G': + get_alarms(optarg); + break; + case 'A': + get_alarms_by_id(optarg); + break; + default: + error("Invalid option..."); + break; + } + } + + return 0; +} + + diff --git a/fm-common/sources/fm_db_sync_event_suppression.py b/fm-common/sources/fm_db_sync_event_suppression.py new file mode 100755 index 00000000..ee835bb7 --- /dev/null +++ b/fm-common/sources/fm_db_sync_event_suppression.py @@ -0,0 +1,195 @@ +#!/usr/bin/env python +# Copyright (c) 2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import sys +import os +import json +import datetime +import uuid as uuid_gen +import socket +from inspect import getframeinfo +from inspect import stack + +import yaml +import collections + +import sqlalchemy +from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy import Column, Boolean, Integer, String, DateTime + +FM_LOG_EVENT_LOG_FILE = "/var/log/platform.log" + +Base = declarative_base() + + +class EventSuppression(Base): + __tablename__ = 'event_suppression' + created_at = Column('created_at', DateTime) + id = Column('id', Integer, primary_key=True, nullable=False) + uuid = Column('uuid', String(36), unique=True) + alarm_id = Column('alarm_id', String(255), unique=True) + description = Column('description', String(255)) + suppression_status = Column('suppression_status', String(255)) + set_for_deletion = Column('set_for_deletion', Boolean) + mgmt_affecting = Column('mgmt_affecting', String(255)) + + +class ialarm(Base): + __tablename__ = 'i_alarm' + id = Column(Integer, primary_key=True, nullable=False) + alarm_id = Column('alarm_id', String(255), index=True) + + +class event_log(Base): + __tablename__ = 'i_event_log' + id = Column(Integer, primary_key=True, nullable=False) + event_log_id = Column('event_log_id', String(255), index=True) + state = Column(String(255)) + + +def prettyDict(dict): + output = json.dumps(dict,sort_keys=True, indent=4) + return output + + +def logInfo(msg): + try: + timestamp = str(datetime.datetime.now()) + host_name = socket.gethostname() + caller = getframeinfo(stack()[1][0]) + line_no = str(caller.lineno) + output = "\n" + timestamp + " " + host_name + " fmManager: info " \ + + current_file_name + "(" + line_no + "):" + " " + msg+"\n" + with open(FM_LOG_EVENT_LOG_FILE,"a") as logFile: + logFile.write(output) + except Exception as e: + print e + + +def get_events_yaml_filename(): + events_yaml_name = os.environ.get("EVENTS_YAML") + if events_yaml_name is not None and os.path.isfile(events_yaml_name): + return events_yaml_name + return "/etc/fm/events.yaml" + +# +# Main +# + +if len(sys.argv) < 2: + sys.exit("Postgres credentials required as argument.") + +postgresql_credentials = str(sys.argv[1]) + +# Set up logging: +current_file_name = __file__ +current_file_name = current_file_name[2:] # remove leading characters "./" + +# Set up sqlalchemy: +meta = sqlalchemy.MetaData() +engine = sqlalchemy.create_engine(postgresql_credentials) + +meta.bind = engine + +Session = sessionmaker(bind=engine) +session = Session() + +# Convert events.yaml to dict: +EVENT_TYPES_FILE = get_events_yaml_filename() + +if not os.path.isfile(EVENT_TYPES_FILE): + exit (-1) + +stream = file(EVENT_TYPES_FILE, 'r') +event_types = yaml.load(stream) + +for alarm_id in event_types: + if isinstance(alarm_id, float): + # force 3 digits after the decimal point, + # to include trailing zero's (ex.: 200.010) + formatted_alarm_id = "{:.3f}".format(alarm_id) + event_types[formatted_alarm_id] = event_types.pop(alarm_id) + +event_types = collections.OrderedDict(sorted(event_types.items())) + +yaml_event_list = [] +uneditable_descriptions = {'100.114', '200.007', '200.02', '200.021', '200.022', '800.002'} + +# Parse events.yaml dict, and add any new alarm to event_suppression table: +for event_type in event_types: + + if event_types.get(event_type).get('Type') == "Alarm": + event_created_at = datetime.datetime.now() + event_uuid = str(uuid_gen.uuid4()) + + string_event_type = str(event_type) + + yaml_event_list.append(string_event_type) + + if str(event_type) not in uneditable_descriptions: + event_description = (event_types.get(event_type) \ + .get('Description')) + else: + event_description = event_types.get(event_type).get('Description') + + event_description = str(event_description) + event_description = (event_description[:250] + ' ...') \ + if len(event_description) > 250 else event_description + + event_supp = session.query(EventSuppression) \ + .filter_by(alarm_id=string_event_type).first() + + event_mgmt_affecting = str(event_types.get(event_type).get( + 'Management_Affecting_Severity', 'warning')) + + if event_supp: + event_supp.description = event_description + event_supp.mgmt_affecting = event_mgmt_affecting + else: + event_supp = EventSuppression(created_at=event_created_at, + uuid=event_uuid, + alarm_id=string_event_type, + description=event_description, + suppression_status='unsuppressed', + set_for_deletion=False, + mgmt_affecting=event_mgmt_affecting) + session.add(event_supp) + logInfo("Created Event Type {} in event_suppression table.".format(string_event_type)) + + session.commit() + +event_supp = session.query(EventSuppression) +alarms = session.query(ialarm) +events = session.query(event_log).filter(event_log.state != 'log') + +alarm_ids_in_use = set() +for alarm in alarms: + alarm_ids_in_use.add(alarm.alarm_id) + +for event in events: + alarm_ids_in_use.add(event.event_log_id) + +for event_type in event_supp: + if event_type.alarm_id not in yaml_event_list: + if event_type.alarm_id not in alarm_ids_in_use: + event_supp = session.query(EventSuppression) \ + .filter_by(alarm_id=event_type.alarm_id).first() + session.delete(event_supp) + logInfo("Deleted Event Type {} from event_suppression table.".format(event_type.alarm_id)) + else: + event_supp.suppression_status='unsuppressed' + event_supp.set_for_deletion = True + logInfo("Event Type {} no longer in events.yaml, but still used by alarm in database.".format(event_type.alarm_id)) + logInfo("Event Type {} marked as set for deletion in event_suppression table.".format(event_type.alarm_id)) + + session.commit() + +session.close() + + + + diff --git a/fm-doc/LICENSE b/fm-doc/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/fm-doc/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fm-doc/centos/build_srpm.data b/fm-doc/centos/build_srpm.data new file mode 100644 index 00000000..cce66760 --- /dev/null +++ b/fm-doc/centos/build_srpm.data @@ -0,0 +1,2 @@ +SRC_DIR="fm_doc" +TIS_PATCH_VER=16 diff --git a/fm-doc/centos/fm-doc.spec b/fm-doc/centos/fm-doc.spec new file mode 100644 index 00000000..271446b8 --- /dev/null +++ b/fm-doc/centos/fm-doc.spec @@ -0,0 +1,45 @@ +Summary: CGTS Platform Fault Management Documentation Package +Name: fm-doc +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +BuildRequires: fm-api-doc +BuildRequires: fm-common-doc +BuildRequires: python-yaml + +Source0: %{name}-%{version}.tar.gz + +%define cgcs_doc_deploy_dir /opt/deploy/cgcs_doc + +%description +A yaml file description of the CGTS Alarms and Customer Logs generated by +the Titanium Cloud System. Also included and used at build time is a simple syntax +checker to ensure no duplicate IDs are used, and generally the correct +field values are documented. + +%prep +%setup + +%install +CGCS_DOC_DEPLOY=$RPM_BUILD_ROOT/%{cgcs_doc_deploy_dir} +install -d $CGCS_DOC_DEPLOY +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/fm/ +install -m 744 events.yaml $RPM_BUILD_ROOT/%{_sysconfdir}/fm/ +install -m 644 events.yaml $CGCS_DOC_DEPLOY +install -m 755 checkEventYaml $CGCS_DOC_DEPLOY +install -m 644 parseEventYaml.py $CGCS_DOC_DEPLOY +install -m 644 check_missing_alarms.py $CGCS_DOC_DEPLOY +pushd $CGCS_DOC_DEPLOY +cp %{cgcs_doc_deploy_dir}/constants.py %{cgcs_doc_deploy_dir}/fmAlarm.h . +./checkEventYaml +rm constants.py* fmAlarm.h* +popd + +%files +%license LICENSE +%defattr(-,root,root,-) +%{cgcs_doc_deploy_dir}/* +%{_sysconfdir}/fm/events.yaml diff --git a/fm-doc/fm_doc/LICENSE b/fm-doc/fm_doc/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/fm-doc/fm_doc/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fm-doc/fm_doc/checkEventYaml b/fm-doc/fm_doc/checkEventYaml new file mode 100755 index 00000000..0ba09f63 --- /dev/null +++ b/fm-doc/fm_doc/checkEventYaml @@ -0,0 +1,33 @@ +#!/bin/bash -e + +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +USAGE="usage: ${0##*/} [ ]" + +FMEVENTDOC_YAMLFILE="events.yaml" + +if [ "$#" -gt 0 ] +then + FMEVENTDOC_YAMLFILE=$1 +fi + +echo "File: " ${FMEVENTDOC_YAMLFILE} +echo "Checking for duplicate records ..." +DUP_LINES=$(cat ${FMEVENTDOC_YAMLFILE} | egrep "^[0-9]" | cut --characters=1-7 | sort | uniq -d | wc -l) + +if [ ${DUP_LINES} -gt 0 ]; then + echo "ERROR Duplicate records defined:" + cat ${FMEVENTDOC_YAMLFILE} | egrep "^[0-9]" | cut --characters=1-7 | sort | uniq -d + echo + echo "Done" + exit 1 +fi + +python parseEventYaml.py ${FMEVENTDOC_YAMLFILE} +python check_missing_alarms.py ${FMEVENTDOC_YAMLFILE} +exit $? + diff --git a/fm-doc/fm_doc/check_missing_alarms.py b/fm-doc/fm_doc/check_missing_alarms.py new file mode 100644 index 00000000..672e8820 --- /dev/null +++ b/fm-doc/fm_doc/check_missing_alarms.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# Copyright (c) 2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import sys +import os + +import yaml +import collections + +import constants as fm_constants + +FM_ALARM_H="fmAlarm.h" + +def get_events_alarm_list(events): + for alarm_id in events: + if isinstance(alarm_id, float): + formatted_alarm_id = "{:.3f}".format(alarm_id) # force 3 digits after the point, to include trailing zero's (ex.: 200.010) + events[formatted_alarm_id] = events.pop(alarm_id) + + events = collections.OrderedDict(sorted(events.items())) + + events_alarm_list = [] + + for alarm_id in events: + if events.get(alarm_id).get('Type') == "Alarm": + events_alarm_list.append(str(alarm_id)) + + return events_alarm_list + +def get_constants_alarms(): + fm_constants_raw_dict = fm_constants.__dict__ + + fm_constants_alarms_dict = {k:v for k,v in fm_constants_raw_dict.iteritems() if 'FM_ALARM_ID' in k} + del fm_constants_alarms_dict['FM_ALARM_ID_INDEX'] # this is not an alarm + + fm_constants_alarms = [] + for alarm_constant_name in fm_constants_alarms_dict: + alarm_constant_full_name = 'fm_constants.' + alarm_constant_name + fm_constants_alarms.append(eval(alarm_constant_full_name)) + + return fm_constants_alarms + + +def get_fm_alarms(): + + fm_alarm_group_lines = [] + fm_alarm_groups = {} + fm_alarms = [] + + with open(FM_ALARM_H) as f: + fm_alarms_file = f.readlines() + + fm_alarm_group_lines = filter(lambda k: 'define ALARM_GROUP_' in k, fm_alarms_file) + + for line in fm_alarm_group_lines: + group_name = line.split()[1] + group_value = line.split()[2] + group_value = group_value[1:-1] # remove quotes + fm_alarm_groups[group_name] = group_value + + fm_alarm_lines = filter(lambda k: 'FM_ALARM_ID' in k, fm_alarms_file) + + for line in fm_alarm_lines: + alarm_name = line.split()[1] + group_name = line.split()[2] + group_name = group_name[1:] + alarm_right_digits_value = line.split()[3] + alarm_right_digits_value = alarm_right_digits_value[1:-2] + alarm_left_digits_value = fm_alarm_groups[group_name] + alarm_value = alarm_left_digits_value + alarm_right_digits_value + fm_alarms.append(alarm_value) + + return fm_alarms + +# +# Main +# + +if len(sys.argv) == 1: + print "Missing file argument.\n" + exit(1) + +if not os.path.isfile(sys.argv[1]): + print "File \'%s\' does not exist.\n" % (sys.argv[1]) + exit(1) + +exitValue = 0 + +with open(sys.argv[1], 'r') as stream: + try: + events = yaml.load(stream) + events_alarm_list = get_events_alarm_list(events) + + except yaml.YAMLError as exc: + print(exc) + +constants_alarms = get_constants_alarms() +for alarm_id in constants_alarms: + if alarm_id not in events_alarm_list: + print "\n ERROR: constants.py alarm \'%s\' must be defined in file events.yaml.\n" % (alarm_id) + exitValue = 1 + +fm_alarms = get_fm_alarms() +for alarm_id in fm_alarms: + if alarm_id not in events_alarm_list: + print "\n ERROR: fmAlarm.h alarm \'%s\' must be defined in file events.yaml.\n" % (alarm_id) + exitValue = 1 + +exit (exitValue) + diff --git a/fm-doc/fm_doc/events.yaml b/fm-doc/fm_doc/events.yaml new file mode 100755 index 00000000..170b586f --- /dev/null +++ b/fm-doc/fm_doc/events.yaml @@ -0,0 +1,3098 @@ +--- + +# +# Copyright (c) 2013-2018 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################ +# +# ALARM & CUSTOMER LOG DOCUMENTATION +# +############################################################################ + +############################################################################ +# +# Record Format ... for documentation +# +# 100.001: +# Type: < Alarm | Log > +# Description: < yaml string > +# OR +# [ < yaml string >, // list of yaml strings +# < yaml string > ] +# OR +# critical: < yaml string > // i.e. dictionary of yaml strings indexed by severity +# major: < yaml string > +# minor: < yaml string > +# warning: < yaml string > +# Entity_Instance_ID: < yaml string ... e.g. host=.interface= > +# OR +# [ < yaml string >, // list of yaml strings +# < yaml string > ] +# Severity: < critical | major | minor | warning > +# OR +# [ critical, major ] // list of severity values +# Proposed_Repair_Action: < yaml string > // NOTE ALARM ONLY FIELD +# OR +# critical: < yaml string > // i.e. dictionary of yaml strings indexed by severity +# major: < yaml string > +# minor: < yaml string > +# warning: < yaml string > +# Maintenance_Action: < yaml string > // NOTE ALARM ONLY FIELD +# OR +# critical: < yaml string > // i.e. dictionary of yaml strings indexed by severity +# major: < yaml string > +# minor: < yaml string > +# warning: < yaml string > +# Inhibit_Alarms: < True | False > // NOTE ALARM ONLY FIELD +# Alarm_Type: < operational-violation | ... > +# Probable_Cause: < timing-problem | ... > +# OR +# [ < timing-problem | ... >, // list of probable-causes +# < timing-problem | ... > ] +# Service_Affecting: < True | False > +# Suppression: < True | False > // NOTE ALARM ONLY FIELD +# Management_Affecting_Severity: < none | critical | major | minor | warning > +# // lowest alarm level of this type that will block forced upgrades & orchestration actions +# +# +# Other Notes: +# - use general record format above +# - the only dictionaries allowed are ones indexed by severity +# - if there are multiple lists in a record, +# then they should all have the same # of items and corresponding list items represent instance of alarm +# - if you can't describe the alarm/log based on the above rules, +# then you can use a multi-line string format +# - DELETING alarms from events.yaml: alarms should only be deleted when going to a new Titanium Cloud release +# - if all possible alarm severities are mgmt affecting, the convention is to +# use 'warning' as the Management_Affecting_Severity, even if warning is not a possible severity for that alarm +# +# Testing: +# - Testing of events.yaml can be done by running regular make command +# and specifying fm-doc: +# nice -n 20 ionice -c Idle make -C build fm-doc.rebuild +# - When building, events.yaml will be parsed for correct format, and also +# to ensure that Alarm IDs defined in constants.py and fmAlarm.h are +# listed in events.yaml +# +############################################################################ + + +#--------------------------------------------------------------------------- +# RMON +#--------------------------------------------------------------------------- + + +100.101: + Type: Alarm + Description: |- + Platform CPU threshold exceeded; threshold x%, actual y% . + CRITICAL @ 95% + MAJOR @ 90% + MINOR @ 80% + Entity_Instance_ID: host= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: major + +100.102: + Type: Alarm + Description: |- + VSwitch CPU threshold exceeded; threshold x%, actual y% . + CRITICAL @ 95% + MAJOR @ 90% + MINOR @ 80% + Entity_Instance_ID: host= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: none + +100.103: + Type: Alarm + Description: |- + Memory threshold exceeded; threshold x%, actual y% . + CRITICAL @ 90% + MAJOR @ 80% + MINOR @ 70% + Entity_Instance_ID: host= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support; may require additional memory on Host." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: none + +100.104: # NOTE This should really be split into two different Alarms. + Type: Alarm + Description: |- + host=.filesystem= + File System threshold exceeded; threshold x%, actual y% . + CRITICAL @ 90% + MAJOR @ 80% + MINOR @ 70% + OR + host=.volumegroup= + Monitor and if condition persists, consider adding additional physical volumes to the volume group. + Entity_Instance_ID: |- + host=.filesystem= + OR + host=.volumegroup= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: critical + +#-------- +# 100.105: Retired (with R2 release): previously monitored /etc/nova/instances +# NFS mount from controller to computes +#-------- + +100.106: + Type: Alarm + Description: "'OAM' Port failed." + Entity_Instance_ID: host=.port= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +100.107: + Type: Alarm + Description: |- + 'OAM' Interface degraded. + OR + 'OAM' Interface failed. + Entity_Instance_ID: host=.interface= + Severity: [ critical, major ] + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +100.108: + Type: Alarm + Description: "'MGMT' Port failed." + Entity_Instance_ID: host=.port= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +100.109: + Type: Alarm + Description: |- + 'MGMT' Interface degraded. + OR + 'MGMT' Interface failed. + Entity_Instance_ID: host=.interface= + Severity: [ critical, major ] + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +100.110: + Type: Alarm + Description: "'INFRA' Port failed." + Entity_Instance_ID: host=.port= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +100.111: + Type: Alarm + Description: |- + 'INFRA' Interface degraded. + OR + 'INFRA' Interface failed. + Entity_Instance_ID: host=.interface= + Severity: [ critical, major ] + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +100.112: + Type: Alarm + Description: "'DATA-VRS' Port down." + Entity_Instance_ID: host=.port= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: none + +100.113: + Type: Alarm + Description: |- + 'DATA-VRS' Interface degraded. + OR + 'DATA-VRS' Interface down. + Entity_Instance_ID: host=.interface= + Severity: [ critical, major ] + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: none + +100.114: + Type: Alarm + Description: + major: "NTP configuration does not contain any valid or reachable NTP servers." + minor: "NTP address is not a valid or a reachable NTP server." + Entity_Instance_ID: + major: host=.ntp + minor: host=.ntp= + Severity: [ major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: none + Inhibit_Alarms: + Alarm_Type: communication + Probable_Cause: unknown + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + +100.115: + Type: Alarm + Description: "VSwitch Memory Usage, processor threshold exceeded; threshold x%, actual y% ." + Entity_Instance_ID: host=.processor= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: none + +100.116: + Type: Alarm + Description: "Cinder LVM Thinpool Usage threshold exceeded; threshold x%, actual y% ." + Entity_Instance_ID: host= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: none + +100.117: + Type: Alarm + Description: "Nova LVM Thinpool Usage threshold exceeded; threshold x%, actual y% ." + Entity_Instance_ID: host= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + critical: degrade + major: degrade + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: major + +100.118: + Type: Alarm + Description: Controller cannot establish connection with remote logging server. + Entity_Instance_ID: host= + Severity: minor + Proposed_Repair_Action: "Ensure Remote Log Server IP is reachable from Controller through OAM interface; otherwise contact next level of support." + Maintenance_Action: none + Inhibit_Alarms: False + Alarm_Type: communication + Probable_Cause: communication-subsystem-failure + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + +#--------------------------------------------------------------------------- +# MAINTENANCE +#--------------------------------------------------------------------------- + + +200.001: + Type: Alarm + Description: was administratively locked to take it out-of-service. + Entity_Instance_ID: host= + Severity: warning + Proposed_Repair_Action: Administratively unlock Host to bring it back in-service. + Maintenance_Action: none + Inhibit_Alarms: True + Alarm_Type: operational-violation + Probable_Cause: out-of-service + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + +200.004: + Type: Alarm + Description: |- + experienced a service-affecting failure. + Host is being auto recovered by Reboot. + Entity_Instance_ID: host= + Severity: critical + Proposed_Repair_Action: If auto-recovery is consistently unable to recover host to the unlocked-enabled state contact next level of support or lock and replace failing host. + Maintenance_Action: auto recover + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: application-subsystem-failure + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +200.011: + Type: Alarm + Description: experienced a configuration failure during initialization. Host is being re-configured by Reboot. + Entity_Instance_ID: host= + Severity: critical + Proposed_Repair_Action: If auto-recovery is consistently unable to recover host to the unlocked-enabled state contact next level of support or lock and replace failing host. + Maintenance_Action: auto-recover + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: configuration-or-customization-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +200.010: + Type: Alarm + Description: access to board management module has failed. + Entity_Instance_ID: host= + Severity: warning + Proposed_Repair_Action: Check Host's board management configuration and connectivity. + Maintenance_Action: auto recover + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: communication-subsystem-failure + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + +200.012: + Type: Alarm + Description: controller function has in-service failure while compute services remain healthy. + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: Lock and then Unlock host to recover. Avoid using 'Force Lock' action as that will impact compute services running on this host. If lock action fails then contact next level of support to investigate and recover. + Maintenance_Action: "degrade - requires manual action" + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: communication-subsystem-failure + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +200.013: + Type: Alarm + Description: compute service of the only available controller is not poperational. Auto-recovery is disabled. Deggrading host instead. + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: Enable second controller and Switch Activity (Swact) over to it as soon as possible. Then Lock and Unlock host to recover its local compute service. + Maintenance_Action: "degrade - requires manual action" + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: communication-subsystem-failure + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +200.005: + Type: Alarm + Description: |- + Degrade: + is experiencing an intermittent 'Management Network' communication failures that have exceeded its lower alarming threshold. + + Failure: + is experiencing a persistent critical 'Management Network' communication failure." + Entity_Instance_ID: host= + Severity: [ critical, major ] + Proposed_Repair_Action: "Check 'Management Network' connectivity and support for multicast messaging. If problem consistently occurs after that and Host is reset, then contact next level of support or lock and replace failing host." + Maintenance_Action: auto recover + Inhibit_Alarms: False + Alarm_Type: communication + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +200.009: + Type: Alarm + Description: |- + Degrade: + is experiencing an intermittent 'Infrastructure Network' communication failures that have exceeded its lower alarming threshold. + + Failure: + is experiencing a persistent critical 'Infrastructure Network' communication failure." + Entity_Instance_ID: host= + Severity: [ critical, major ] + Proposed_Repair_Action: "Check 'Infrastructure Network' connectivity and support for multicast messaging. If problem consistently occurs after that and Host is reset, then contact next level of support or lock and replace failing host." + Maintenance_Action: auto recover + Inhibit_Alarms: False + Alarm_Type: communication + Probable_Cause: unknown + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + + +200.006: + Type: Alarm + Description: |- + Main Process Monitor Daemon Failure (major): + 'Process Monitor' (pmond) process is not running or functioning properly. The system is trying to recover this process. + + Monitored Process Failure (critical/major/minor): + Critical: critical '' process has failed and could not be auto-recovered gracefully. + Auto-recovery progression by host reboot is required and in progress. + Major: is degraded due to the failure of its '' process. Auto recovery of this major process is in progress. + Minor: '' process has failed. Auto recovery of this minor process is in progress. + OR + '' process has failed. Manual recovery is required. + Entity_Instance_ID: host=.process= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: |- + If this alarm does not automatically clear after some time and continues to be asserted after Host is locked and unlocked then contact next level of support for root cause analysis and recovery. + + If problem consistently occurs after Host is locked and unlocked then contact next level of support for root cause analysis and recovery." + Maintenance_Action: + critical: auto-recover + major: degrade + minor: + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: + critical: True + major: True + minor: False + Suppression: True + Management_Affecting_Severity: warning + + +# 200.006: // NOTE using duplicate ID of a completely analogous Alarm for this +# Type: Log +# Description: |- +# Main Process Monitor Daemon Failure (major) +# 'Process Monitor' (pmond) process is not running or functioning properly. +# The system is trying to recover this process. +# +# Monitored Process Failure (critical/major/minor) +# critical: critical '' process has failed and could not be auto-recovered gracefully. +# Auto-recovery progression by host reboot is required and in progress. +# major: is degraded due to the failure of its '' process. Auto recovery of this major process is in progress. +# minor: '' process has failed. Auto recovery of this minor process is in progress. +# OR +# '' process has failed. Manual recovery is required. +# Entity_Instance_ID: host=.process= +# Severity: minor +# Alarm_Type: other +# Probable_Cause: unspecified-reason +# Service_Affecting: True + + +200.007: + Type: Alarm + Description: + critical: "Host is degraded due to a 'critical' out-of-tolerance reading from the '' sensor" + major: "Host is degraded due to a 'major' out-of-tolerance reading from the '' sensor" + minor: "Host is reporting a 'minor' out-of-tolerance reading from the '' sensor" + Entity_Instance_ID: host=.sensor= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: "If problem consistently occurs after Host is power cycled and or reset, contact next level of support or lock and replace failing host." + Maintenance_Action: + critical: degrade + major: degrade + minor: auto-recover (polling) + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: + critical: True + major: False + minor: False + Suppression: True + Management_Affecting_Severity: none + +200.014: + Type: Alarm + Description: "The Hardware Monitor was unable to load, configure and monitor one or more hardware sensors." + Entity_Instance_ID: host= + Severity: minor + Proposed_Repair_Action: Check Board Management Controller provisioning. Try reprovisioning the BMC. If problem persists try power cycling the host and then the entire server including the BMC power. If problem persists then contact next level of support. + Maintenance_Action: None + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: False + Suppression: True + Management_Affecting_Severity: none + +200.015: + Type: Alarm + Description: Unable to read one or more sensor groups from this host's board management controller + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: Check board management connectivity and try rebooting the board management controller. If problem persists contact next level of support or lock and replace failing host. + Maintenance_Action: None + Inhibit_Alarms: False + Alarm_Type: operational-violation + Probable_Cause: unknown + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + + +200.020: + Type: Log + Description: [ " has been 'discovered' on the network", + " has been 'added' to the system", + " has 'entered' multi-node failure avoidance", + " has 'exited' multi-node failure avoidance" ] + Entity_Instance_ID: [ host=.event=discovered, + host=.event=add, + host=.event=mnfa_enter, + host=.event=mnfa_exit ] + Severity: warning + Alarm_Type: other + Probable_Cause: unspecified-reason + Service_Affecting: True + + +200.021: + Type: Log + Description: [ " board management controller has been 'provisioned'", + " board management controller has been 're-provisioned'", + " board management controller has been 'de-provisioned'", + " manual 'unlock' request", + " manual 'reboot' request", + " manual 'reset' request", + " manual 'power-off' request", + " manual 'power-on' request", + " manual 'reinstall' request", + " manual 'force-lock' request", + " manual 'delete' request", + " manual 'controller switchover' request" ] + Entity_Instance_ID: [ host=.command=provision, + host=.command=reprovision, + host=.command=deprovision, + host=.command=unlock, + host=.command=reboot, + host=.command=reset, + host=.command=power-off, + host=.command=power-on, + host=.command=reinstall, + host=.command=force-lock, + host=.command=delete, + host=.command=swact ] + Severity: warning + Alarm_Type: other + Probable_Cause: unspecified-reason + Service_Affecting: False + + +200.022: + Type: Log + Description: [ " is now 'disabled'", + " is now 'enabled'", + " is now 'online'", + " is now 'offline'", + " is 'disabled-failed' to the system", + " reinstall failed", + " reinstall completed successfully"] + Entity_Instance_ID: [ host=.state=disabled, + host=.state=enabled, + host=.status=online, + host=.status=offline, + host=.status=failed, + host=.status=reinstall-failed, + host=.status=reinstall-complete ] + Severity: warning + Alarm_Type: other + Probable_Cause: unspecified-reason + Service_Affecting: True + + +#--------------------------------------------------------------------------- +# BACKUP AND RESTORE +#--------------------------------------------------------------------------- + +210.001: + Type: Alarm + Description: System Backup in progress. + Entity_Instance_ID: host=controller + Severity: minor + Proposed_Repair_Action: No action required. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + + +#--------------------------------------------------------------------------- +# SYSTEM CONFIGURATION +#--------------------------------------------------------------------------- + +250.001: + Type: Alarm + Description: Configuration is out-of-date. + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: Administratively lock and unlock to update config. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + +250.002: + Type: Alarm + Description: Ceph cache tiering configuration is out-of-date. + Entity_Instance_ID: cluster= + Severity: major + Proposed_Repair_Action: Apply Ceph service parameter settings. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + + +#--------------------------------------------------------------------------- +# VM Compute Services +#--------------------------------------------------------------------------- +270.001: + Type: Alarm + Description: "Host compute services failure[, reason = ]" + Entity_Instance_ID: host=.services=compute + Severity: critical + Proposed_Repair_Action: Wait for host services recovery to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +270.101: + Type: Log + Description: "Host compute services failure[, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +270.102: + Type: Log + Description: Host compute services enabled + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +270.103: + Type: Log + Description: Host compute services disabled + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + + +275.001: + Type: Log + Description: Host hypervisor is now - + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + + +#--------------------------------------------------------------------------- +# DISTRIBUTED CLOUD +#--------------------------------------------------------------------------- + +280.001: + Type: Alarm + Description: is offline + Entity_Instance_ID: subcloud= + Severity: critical + Proposed_Repair_Action: Wait for subcloud to become online; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: communication + Probable_Cause: loss-of-signal + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + +280.002: + Type: Alarm + Description: sync_status is out-of-sync + Entity_Instance_ID: [subcloud=.resource=] + Severity: major + Proposed_Repair_Action: If problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: other + Probable_Cause: application-subsystem-failure + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + + +#--------------------------------------------------------------------------- +# NETWORK +#--------------------------------------------------------------------------- + +300.001: + Type: Alarm + Description: "'Data' Port failed." + Entity_Instance_ID: host=.port= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.002: + Type: Alarm + Description: |- + 'Data' Interface degraded. + OR + 'Data' Interface failed. + Entity_Instance_ID: host=.interface= + Severity: [ critical, major ] + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.003: + Type: Alarm + Description: Networking Agent not responding. + Entity_Instance_ID: host=.agent= + Severity: major + Proposed_Repair_Action: "If condition persists, attempt to clear issue by administratively locking and unlocking the Host." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.004: + Type: Alarm + Description: No enabled compute host with connectivity to provider network. + Entity_Instance_ID: service=networking.providernet= + Severity: major + Proposed_Repair_Action: Enable compute hosts with required provider network connectivity. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.005: + Type: Alarm + Description: |- + Communication failure detected over provider network x% for ranges y% on host z%. + OR + Communication failure detected over provider network x% on host z%. + Entity_Instance_ID: host=.service=networking.providernet= + Severity: major + Proposed_Repair_Action: Check neighbour switch port VLAN assignments. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.010: + Type: Alarm + Description: |- + ML2 Driver Agent non-reachable + OR + ML2 Driver Agent reachable but non-responsive + OR + ML2 Driver Agent authentication failure + OR + ML2 Driver Agent is unable to sync Neutron database + Entity_Instance_ID: host=.ml2driver= + Severity: major + Proposed_Repair_Action: "Monitor and if condition persists, contact next level of support." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + + +300.012: + Type: Alarm + Description: "Openflow Controller connection failed." + Entity_Instance_ID: host=.openflow-controller= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.013: + Type: Alarm + Description: |- + No active Openflow controller connections found for this network. + OR + One or more Openflow controller connections in disconnected state for this network. + Entity_Instance_ID: host=.openflow-network= + Severity: [ critical, major ] + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.014: + Type: Alarm + Description: "OVSDB Manager connection failed." + Entity_Instance_ID: host=.sdn-controller= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + + +300.015: + Type: Alarm + Description: "No active OVSDB connections found." + Entity_Instance_ID: host= + Severity: critical + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + +300.016: + Type: Alarm + Description: "Dynamic routing agent x% lost connectivity to peer y%." + Entity_Instance_ID: host=,agent=,bgp-peer= + Severity: major + Proposed_Repair_Action: If condition persists, fix connectivity to peer. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: loss-of-signal + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + + +#--------------------------------------------------------------------------- +# HIGH AVAILABILITY +#--------------------------------------------------------------------------- + +400.001: + Type: Alarm + Description: |- + Service group failure; . + OR + Service group degraded; . + OR + Service group warning; . + Entity_Instance_ID: service_domain=.service_group=.host= + Severity: [ critical, major, minor ] + Proposed_Repair_Action: Contact next level of support. + Maintenance_Action: + Inhibit_Alarms: False + Alarm_Type: processing-error + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + + +400.002: + Type: Alarm + Description: |- + Service group loss of redundancy; expected standby member but only standby member available. + OR + Service group loss of redundancy; expected standby member but only standby member available. + OR + Service group loss of redundancy; expected active member but no active members available. + OR + Service group loss of redundancy; expected active member but only active member available. + Entity_Instance_ID: service_domain=.service_group= + Severity: major + Proposed_Repair_Action: "Bring a controller node back in to service, otherwise contact next level of support." + Maintenance_Action: + Inhibit_Alarms: False + Alarm_Type: processing-error + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + + +400.003: + Type: Alarm + Description: |- + License key is not installed; a valid license key is required for operation. + OR + License key has expired or is invalid; a valid license key is required for operation. + OR + Evaluation license key will expire on ; there are days remaining in this evaluation. + OR + Evaluation license key will expire on ; there is only 1 day remaining in this evaluation. + Entity_Instance_ID: host= + Severity: critical + Proposed_Repair_Action: Contact next level of support to obtain a new license key. + Maintenance_Action: + Inhibit_Alarms: False + Alarm_Type: processing-error + Probable_Cause: key-expired + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: critical + + +# 400.004: // NOTE Removed +# Type: Alarm +# Description: Service group software modification detected; . +# Entity_Instance_ID: host= +# Severity: major +# Proposed_Repair_Action: Contact next level of support. +# Maintenance_Action: +# Inhibit_Alarms: False +# Alarm_Type: processing-error +# Probable_Cause: software-program-error +# Service_Affecting: True +# Suppression: False + + +400.005: + Type: Alarm + Description: |- + Communication failure detected with peer over port . + OR + Communication failure detected with peer over port within the last 30 seconds. + Entity_Instance_ID: host=.network= + Severity: major + Proposed_Repair_Action: Check cabling and far-end port configuration and status on adjacent equipment. + Maintenance_Action: + Inhibit_Alarms: False + Alarm_Type: communication + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + + +#--------------------------------------------------------------------------- +# SM +#--------------------------------------------------------------------------- + +401.001: + Type: Log + Description: Service group state change from to on host + Entity_Instance_ID: service_domain=.service_group=.host= + Severity: critical + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + +401.002: + Type: Log + Description: |- + Service group loss of redundancy; expected standby member but no standby members available + or + Service group loss of redundancy; expected standby member but only standby member(s) available + or + Service group has no active members available; expected active member(s) + or + Service group loss of redundancy; expected active member(s) but only active member(s) available + Entity_Instance_ID: service_domain=.service_group= + Severity: critical + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + +401.003: + Type: Log + Description: |- + License key has expired or is invalid + or + Evaluation license key will expire on + or + License key is valid + Entity_Instance_ID: host= + Severity: critical + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + +401.005: + Type: Log + Description: |- + Communication failure detected with peer over port on host + or + Communication failure detected with peer over port on host within the last seconds + or + Communication established with peer over port on host + Entity_Instance_ID: host=.network= + Severity: critical + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + +401.007: + Type: Log + Description: Swact or swact-force + Entity_Instance_ID: host= + Severity: critical + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + + +#--------------------------------------------------------------------------- +# SECURITY +#--------------------------------------------------------------------------- + +500.100: + Type: Alarm + Description: TPM initialization failed on host. + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: reinstall HTTPS certificate; if problem persists contact next level of support. + Maintenance_Action: degrade + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: procedural-error + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: none + +500.101: + Type: Alarm + Description: Developer patch certificate enabled. + Entity_Instance_ID: host=controller + Severity: critical + Proposed_Repair_Action: Reinstall system to disable developer certificate and remove untrusted patches. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + +500.500: + Type: Log + Description: "Host has IMA Appraisal failure for service when executing , reason = ]" + Entity_Instance_ID: host=.service= + Severity: major + Alarm_Type: integrity-violation + Probable_Cause: information-modification-detected + Service_Affecting: False + + + +#--------------------------------------------------------------------------- +# VM +#--------------------------------------------------------------------------- + +700.001: + Type: Alarm + Description: |- + Instance owned by has failed on host + Instance owned by has failed to schedule + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: The system will attempt recovery; no repair action required + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: software-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.002: + Type: Alarm + Description: Instance owned by is paused on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Unpause the instance + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: procedural-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.003: + Type: Alarm + Description: Instance owned by is suspended on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Resume the instance + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: procedural-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.004: + Type: Alarm + Description: Instance owned by is stopped on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Start the instance + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: procedural-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.005: + Type: Alarm + Description: Instance owned by is rebooting on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Wait for reboot to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.006: + Type: Alarm + Description: Instance owned by is rebuilding on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Wait for rebuild to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.007: + Type: Alarm + Description: Instance owned by is evacuating from host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Wait for evacuate to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.008: + Type: Alarm + Description: Instance owned by is live migrating from host + Entity_Instance_ID: tenant=.instance= + Severity: warning + Proposed_Repair_Action: Wait for live migration to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.009: + Type: Alarm + Description: Instance owned by is cold migrating from host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Wait for cold migration to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.010: + Type: Alarm + Description: Instance owned by has been cold-migrated to host waiting for confirmation + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Confirm or revert cold-migrate of instance + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.011: + Type: Alarm + Description: Instance owned by is reverting cold migrate to host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: "Wait for cold migration revert to complete; if problem persists contact next level of support" + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: other + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.012: + Type: Alarm + Description: Instance owned by is resizing on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: Wait for resize to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.013: + Type: Alarm + Description: Instance owned by has been resized on host waiting for confirmation + Entity_Instance_ID: itenant=.instance= + Severity: critical + Proposed_Repair_Action: Confirm or revert resize of instance + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.014: + Type: Alarm + Description: Instance owned by is reverting resize on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Proposed_Repair_Action: "Wait for resize revert to complete; if problem persists contact next level of support" + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: other + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.015: + Type: Alarm + Description: Guest Heartbeat not established for instance owned by on host + Entity_Instance_ID: tenant=.instance= + Severity: major + Proposed_Repair_Action: "Verify that the instance is running the Guest-Client daemon, or disable Guest Heartbeat for the instance if no longer needed, otherwise contact next level of support" + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: communication + Probable_Cause: procedural-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.016: + Type: Alarm + Description: Multi-Node Recovery Mode + Entity_Instance_ID: subsystem=vim + Severity: minor + Proposed_Repair_Action: "Wait for the system to exit out of this mode" + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +700.017: + Type: Alarm + Description: Server group policy was not satisfied + Entity_Instance_ID: server-group + Severity: minor + Proposed_Repair_Action: "Migrate instances in an attempt to satisfy the policy; if problem persists contact next level of support" + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: processing-error + Probable_Cause: procedural-error + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: none + + +700.101: + Type: Log + Description: Instance is enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.102: + Type: Log + Description: Instance owned by has failed[, reason = ] + Instance owned by has failed to schedule[, reason = ] + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.103: + Type: Log + Description: Create issued |by the system> against owned by + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.104: + Type: Log + Description: Creating instance owned by + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.105: + Type: Log + Description: "Create rejected for instance [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.106: + Type: Log + Description: "Create cancelled for instance [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.107: + Type: Log + Description: "Create failed for instance [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.108: + Type: Log + Description: Inance owned by has been created + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.109: + Type: Log + Description: "Delete issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.110: + Type: Log + Description: Deleting instance owned by + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.111: + Type: Log + Description: "Delete rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.112: + Type: Log + Description: "Delete cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.113: + Type: Log + Description: "Delete failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.114: + Type: Log + Description: Deleted instance owned by + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.115: + Type: Log + Description: "Pause issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.116: + Type: Log + Description: Pause inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.117: + Type: Log + Description: "Pause rejected for instance enabled on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.118: + Type: Log + Description: "Pause cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.119: + Type: Log + Description: "Pause failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.120: + Type: Log + Description: Pause complete for instance now paused on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.121: + Type: Log + Description: "Unpause issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.122: + Type: Log + Description: Unpause inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.123: + Type: Log + Description: "Unpause rejected for instance paused on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.124: + Type: Log + Description: "Unpause cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.125: + Type: Log + Description: "Unpause failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.126: + Type: Log + Description: Unpause complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.127: + Type: Log + Description: "Suspend issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.128: + Type: Log + Description: Suspend inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.129: + Type: Log + Description: "Suspend rejected for instance enabled on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.130: + Type: Log + Description: "Suspend cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.131: + Type: Log + Description: "Suspend failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.132: + Type: Log + Description: Suspend complete for instance now suspended on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.133: + Type: Log + Description: "Resume issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.134: + Type: Log + Description: Resume inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.135: + Type: Log + Description: "Resume rejected for instance suspended on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.136: + Type: Log + Description: "Resume cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.137: + Type: Log + Description: "Resume failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.138: + Type: Log + Description: Resume complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.139: + Type: Log + Description: "Start issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.140: + Type: Log + Description: Start inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.141: + Type: Log + Description: "Start rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.142: + Type: Log + Description: "Start cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.143: + Type: Log + Description: "Start failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.144: + Type: Log + Description: Start complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.145: + Type: Log + Description: "Stop issued |by the system|by the instance> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.146: + Type: Log + Description: Stop inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.147: + Type: Log + Description: "Stop rejected for instance enabled on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.148: + Type: Log + Description: "Stop cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.149: + Type: Log + Description: "Stop failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.150: + Type: Log + Description: Stop complete for instance now disabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.151: + Type: Log + Description: "Live-Migrate issued |by the system> against instance owned by from host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.152: + Type: Log + Description: Live-Migrate inprogress for instance from host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.153: + Type: Log + Description: "Live-Migrate rejected for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.154: + Type: Log + Description: "Live-Migrate cancelled for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.155: + Type: Log + Description: "Live-Migrate failed for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.156: + Type: Log + Description: Live-Migrate complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.157: + Type: Log + Description: "Cold-Migrate issued |by the system> against instance owned by from host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.158: + Type: Log + Description: Cold-Migrate inprogress for instance from host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.159: + Type: Log + Description: "Cold-Migrate rejected for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.160: + Type: Log + Description: "Cold-Migrate cancelled for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.161: + Type: Log + Description: "Cold-Migrate failed for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.162: + Type: Log + Description: Cold-Migrate complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.163: + Type: Log + Description: "Cold-Migrate-Confirm issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.164: + Type: Log + Description: Cold-Migrate-Confirm inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.165: + Type: Log + Description: "Cold-Migrate-Confirm rejected for instance now enabled on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.166: + Type: Log + Description: "Cold-Migrate-Confirm cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.167: + Type: Log + Description: "Cold-Migrate-Confirm failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.168: + Type: Log + Description: Cold-Migrate-Confirm complete for instance enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.169: + Type: Log + Description: "Cold-Migrate-Revert issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.170: + Type: Log + Description: Cold-Migrate-Revert inprogress for instance from host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.171: + Type: Log + Description: "Cold-Migrate-Revert rejected for instance now on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.172: + Type: Log + Description: "Cold-Migrate-Revert cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.173: + Type: Log + Description: "Cold-Migrate-Revert failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.174: + Type: Log + Description: Cold-Migrate-Revert complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.175: + Type: Log + Description: "Evacuate issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.176: + Type: Log + Description: Evacuating instance owned by from host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.177: + Type: Log + Description: "Evacuate rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.178: + Type: Log + Description: "Evacuate cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.179: + Type: Log + Description: "Evacuate failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.180: + Type: Log + Description: Evacuate complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.181: + Type: Log + Description: "Reboot <(soft-reboot)|(hard-reboot)> issued |by the system|by the instance> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.182: + Type: Log + Description: Reboot inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.183: + Type: Log + Description: "Reboot rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.184: + Type: Log + Description: "Reboot cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.185: + Type: Log + Description: "Reboot failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.186: + Type: Log + Description: Reboot complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.187: + Type: Log + Description: "Rebuild issued |by the system> against instance using image on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.188: + Type: Log + Description: Rebuild inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.189: + Type: Log + Description: "Rebuild rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.190: + Type: Log + Description: "Rebuild cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.191: + Type: Log + Description: "Rebuild failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.192: + Type: Log + Description: Rebuild complete for instance now enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.193: + Type: Log + Description: "Resize issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.194: + Type: Log + Description: Resize inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.195: + Type: Log + Description: "Resize rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.196: + Type: Log + Description: "Resize cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.197: + Type: Log + Description: "Resize failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.198: + Type: Log + Description: Resize complete for instance enabled on host waiting for confirmation + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.199: + Type: Log + Description: "Resize-Confirm issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.200: + Type: Log + Description: Resize-Confirm inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.201: + Type: Log + Description: "Resize-Confirm rejected for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.202: + Type: Log + Description: "Resize-Confirm cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.203: + Type: Log + Description: "Resize-Confirm failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.204: + Type: Log + Description: Resize-Confirm complete for instance enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.205: + Type: Log + Description: "Resize-Revert issued |by the system> against instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.206: + Type: Log + Description: Resize-Revert inprogress for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.207: + Type: Log + Description: "Resize-Revert rejected for instance owned by on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.208: + Type: Log + Description: "Resize-Revert cancelled for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.209: + Type: Log + Description: "Resize-Revert failed for instance on host [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.210: + Type: Log + Description: Resize-Revert complete for instance enabled on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.211: + Type: Log + Description: Guest Heartbeat established for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: major + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.212: + Type: Log + Description: Guest Heartbeat disconnected for instance on host + Entity_Instance_ID: tenant=.instance= + Severity: major + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.213: + Type: Log + Description: "Guest Heartbeat failed for instance [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.214: + Type: Log + Description: Instance has been renamed to owned by on host + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.215: + Type: Log + Description: "Guest Health Check failed for instance [, reason = ]" + Entity_Instance_ID: tenant=.instance= + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +700.216: + Type: Log + Description: "Entered Multi-Node Recovery Mode" + Entity_Instance_ID: subsystem=vim + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + + +700.217: + Type: Log + Description: "Exited Multi-Node Recovery Mode" + Entity_Instance_ID: subsystem=vim + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + + +#--------------------------------------------------------------------------- +# STORAGE +#--------------------------------------------------------------------------- + +800.001: + Type: Alarm + Description: |- + Storage Alarm Condition: + 1 mons down, quorum 1,2 controller-1,storage-0 + Entity_Instance_ID: cluster= + Severity: [ critical, major ] + Proposed_Repair_Action: "If problem persists, contact next level of support." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: equipment-malfunction + Service_Affecting: + critical: True + major: False + Suppression: False + Management_Affecting_Severity: warning + +800.010: + Type: Alarm + Description: |- + Potential data loss. No available OSDs in storage replication group. + Entity_Instance_ID: cluster=.peergroup= + Severity: [ critical ] + Proposed_Repair_Action: "Ensure storage hosts from replication group are unlocked and available. + Check if OSDs of each storage host are up and running. + If problem persists contact next level of support." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: equipment-malfunction + Service_Affecting: + critical: True + Suppression: False + Management_Affecting_Severity: warning + +800.011: + Type: Alarm + Description: |- + Loss of replication in peergroup. + Entity_Instance_ID: cluster=.peergroup= + Severity: [ major ] + Proposed_Repair_Action: "Ensure storage hosts from replication group are unlocked and available. + Check if OSDs of each storage host are up and running. + If problem persists contact next level of support." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: equipment-malfunction + Service_Affecting: + major: True + Suppression: False + Management_Affecting_Severity: warning + +800.002: + Type: Alarm + Description: [ "Image storage media is full: There is not enough disk space on the image storage media.", + "Instance snapshot failed: There is not enough disk space on the image storage media.", + "Supplied () and generated from uploaded image () did not match. Setting image status to 'killed'.", + "Error in store configuration. Adding images to store is disabled.", + "Forbidden upload attempt: ", + "Insufficient permissions on image storage media: ", + "Denying attempt to upload image larger than bytes.", + "Denying attempt to upload image because it exceeds the quota: ", + "Received HTTP error while uploading image ", + "Client disconnected before sending all data to backend", + "Failed to upload image " ] + Entity_Instance_ID: [ "image=, instance=", + "tenant=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=", + "image=, instance=" ] + Alarm_Type: [ physical-violation, + physical-violation, + integrity-violation, + integrity-violation, + security-service-or-mechanism-violation, + security-service-or-mechanism-violation, + security-service-or-mechanism-violation, + security-service-or-mechanism-violation, + communication, + communication, + operational-violation ] + Severity: warning + Proposed_Repair_Action: + Maintenance_Action: + Inhibit_Alarms: + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + + +800.003: + Type: Alarm + Description: |- + Storage Alarm Condition: + Quota/Space mismatch for the tier. The sum of Ceph pool quotas does not match the tier size. + Entity_Instance_ID: cluster=.tier= + Severity: minor + Proposed_Repair_Action: "Update ceph storage pool quotas to use all available tier space." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: configuration-out-of-date + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + + +800.100: + Type: Alarm + Description: |- + Storage Alarm Condition: + Cinder I/O Congestion is above normal range and is building + Entity_Instance_ID: cinder_io_monitor + Severity: major + Proposed_Repair_Action: "Reduce the I/O load on the Cinder LVM backend. Use + Cinder QoS mechanisms on high usage volumes." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: qos + Probable_Cause: congestion + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: none + +800.101: + Type: Alarm + Description: |- + Storage Alarm Condition: + Cinder I/O Congestion is high and impacting guest performance + Entity_Instance_ID: cinder_io_monitor + Severity: critical + Proposed_Repair_Action: "Reduce the I/O load on the Cinder LVM backend. + Cinder actions may fail until congestion is reduced. + Use Cinder QoS mechanisms on high usage volumes." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: qos + Probable_Cause: congestion + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + +800.102: + Type: Alarm + Description: |- + Storage Alarm Condition: + PV configuration on . Reason: . + Entity_Instance_ID: pv= + Severity: [ critical, major ] + Proposed_Repair_Action: "Remove failed PV and associated Storage Device then recreate them." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: configuration-or-customization-error + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: major + +800.103: + Type: Alarm + Description: |- + Storage Alarm Condition: + [ Metadata usage for LVM thin pool / exceeded threshold and automatic extension failed, + Metadata usage for LVM thin pool / exceeded threshold ]; threshold x%, actual y%. + Entity_Instance_ID: .lvmthinpool=/ + Severity: critical + Proposed_Repair_Action: "Increase Storage Space Allotment for Cinder on the 'lvm' backend. + Consult the System Administration Manual for more details. + If problem persists, contact next level of support." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: threshold-crossed + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: major + +800.104: + Type: Alarm + Description: |- + Storage Alarm Condition: + configuration failed to apply on host: . + Entity_Instance_ID: storage_backend= + Severity: critical + Proposed_Repair_Action: "Update backend setting to reapply configuration. + Consult the System Administration Manual for more details. + If problem persists, contact next level of support." + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: configuration-or-customization-error + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: major + + + +#--------------------------------------------------------------------------- +# SOFTWARE +#--------------------------------------------------------------------------- + +900.001: + Type: Alarm + Description: Patching operation in progress. + Entity_Instance_ID: host=controller + Severity: minor + Proposed_Repair_Action: Complete reboots of affected hosts. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: environmental + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + +900.002: + Type: Alarm + Description: Obsolete patch in system. + Entity_Instance_ID: host=controller + Severity: warning + Proposed_Repair_Action: Remove and delete obsolete patches. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: environmental + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + +900.003: + Type: Alarm + Description: Patch host install failure. + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: Undo patching operation. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: environmental + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + +900.004: + Type: Alarm + Description: Host version mismatch. + Entity_Instance_ID: host= + Severity: major + Proposed_Repair_Action: Reinstall host to update applied load. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: False + Management_Affecting_Severity: warning + +900.005: + Type: Alarm + Description: System Upgrade in progress. + Entity_Instance_ID: host=controller + Severity: minor + Proposed_Repair_Action: No action required. + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: operational-violation + Probable_Cause: unspecified-reason + Service_Affecting: False + Suppression: False + Management_Affecting_Severity: warning + +900.101: + Type: Alarm + Description: Software patch auto-apply inprogress + Entity_Instance_ID: orchestration=sw-patch + Severity: major + Proposed_Repair_Action: Wait for software patch auto-apply to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +900.102: + Type: Alarm + Description: Software patch auto-apply aborting + Entity_Instance_ID: orchestration=sw-patch + Severity: major + Proposed_Repair_Action: Wait for software patch auto-apply abort to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +900.103: + Type: Alarm + Description: Software patch auto-apply failed + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Proposed_Repair_Action: Attempt to apply software patches manually; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +900.111: + Type: Log + Description: Software patch auto-apply start + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.112: + Type: Log + Description: Software patch auto-apply inprogress + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.113: + Type: Log + Description: Software patch auto-apply rejected + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.114: + Type: Log + Description: Software patch auto-apply cancelled + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.115: + Type: Log + Description: Software patch auto-apply failed + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.116: + Type: Log + Description: Software patch auto-apply completed + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.117: + Type: Log + Description: Software patch auto-apply abort + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.118: + Type: Log + Description: Software patch auto-apply aborting + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.119: + Type: Log + Description: Software patch auto-apply abort rejected + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.120: + Type: Log + Description: Software patch auto-apply abort failed + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.121: + Type: Log + Description: Software patch auto-apply aborted + Entity_Instance_ID: orchestration=sw-patch + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.201: + Type: Alarm + Description: Software upgrade auto-apply inprogress + Entity_Instance_ID: orchestration=sw-upgrade + Severity: major + Proposed_Repair_Action: Wait for software upgrade auto-apply to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +900.202: + Type: Alarm + Description: Software upgrade auto-apply aborting + Entity_Instance_ID: orchestration=sw-upgrade + Severity: major + Proposed_Repair_Action: Wait for software upgrade auto-apply abort to complete; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +900.203: + Type: Alarm + Description: Software upgrade auto-apply failed + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Proposed_Repair_Action: Attempt to apply software upgrade manually; if problem persists contact next level of support + Maintenance_Action: + Inhibit_Alarms: + Alarm_Type: equipment + Probable_Cause: underlying-resource-unavailable + Service_Affecting: True + Suppression: True + Management_Affecting_Severity: warning + +900.211: + Type: Log + Description: Software upgrade auto-apply start + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.212: + Type: Log + Description: Software upgrade auto-apply inprogress + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.213: + Type: Log + Description: Software upgrade auto-apply rejected + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.214: + Type: Log + Description: Software upgrade auto-apply cancelled + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.215: + Type: Log + Description: Software upgrade auto-apply failed + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.216: + Type: Log + Description: Software upgrade auto-apply completed + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.217: + Type: Log + Description: Software upgrade auto-apply abort + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.218: + Type: Log + Description: Software upgrade auto-apply aborting + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.219: + Type: Log + Description: Software upgrade auto-apply abort rejected + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.220: + Type: Log + Description: Software upgrade auto-apply abort failed + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False + +900.221: + Type: Log + Description: Software upgrade auto-apply aborted + Entity_Instance_ID: orchestration=sw-upgrade + Severity: critical + Alarm_Type: equipment + Probable_Cause: unspecified-reason + Service_Affecting: False +... diff --git a/fm-doc/fm_doc/parseEventYaml.py b/fm-doc/fm_doc/parseEventYaml.py new file mode 100755 index 00000000..4575919e --- /dev/null +++ b/fm-doc/fm_doc/parseEventYaml.py @@ -0,0 +1,196 @@ +# +# Copyright (c) 2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +import sys +import os + +import yaml +import constants + +# Record Format (for full description see events.yaml) +# +# 100.001: +# Type: Alarm +# Description: "Degrade: is experiencing an intermittent 'Management Network' communication failure." +# Entity_Instance_ID: host= +# Severity: critical +# Proposed_Repair_Action: "Check Host's board management configuration and connectivity." +# Maintenance_Action: auto recover +# Inhibit_Alarms: True +# Alarm_Type: operational-violation +# Probable_Cause: timing-problem +# Service_Affecting: False +# Suppression: True +# Management_Affecting_Severity: warning +# + +type_FieldName = 'Type' +type_FieldValue_Alarm = 'Alarm' +type_FieldValues = [ type_FieldValue_Alarm, 'Log' ] + +description_FieldName = 'Description' +description_FieldValues = [] # arbitrary string + +entityInstanceId_FieldName = 'Entity_Instance_ID' +entityInstanceId_FieldValues = [] # arbitrary string + +severity_FieldName = 'Severity' +severity_FieldValues = constants.ALARM_SEVERITY + +proposedRepairAction_FieldName = 'Proposed_Repair_Action' +proposedRepairAction_FieldValues = [] # arbitrary string + +maintenanceAction_FieldName = 'Maintenance_Action' +maintenanceAction_FieldValues = [] # arbitrary string + +inhibitAlarms_FieldName = 'Inhibit_Alarms' +inhibitAlarms_FieldValues = [ True, False ] + +alarmType_FieldName = 'Alarm_Type' +alarmType_FieldValues = constants.ALARM_TYPE + +probableCause_FieldName = 'Probable_Cause' +probableCause_FieldValues = constants.ALARM_PROBABLE_CAUSE + +serviceAffecting_FieldName = 'Service_Affecting' +serviceAffecting_FieldValues = [ True, False ] + +suppression_FieldName = 'Suppression' +suppression_FieldValues = [ True, False ] + +managementAffectingSeverity_FieldName = 'Management_Affecting_Severity' +managementAffectingSeverity_FieldValues = constants.ALARM_SEVERITY.append('none') + + +alarmFields = { +type_FieldName : type_FieldValues, +description_FieldName : description_FieldValues, +entityInstanceId_FieldName : entityInstanceId_FieldValues, +severity_FieldName : severity_FieldValues, +proposedRepairAction_FieldName : proposedRepairAction_FieldValues, +maintenanceAction_FieldName : maintenanceAction_FieldValues, +inhibitAlarms_FieldName : inhibitAlarms_FieldValues, +alarmType_FieldName : alarmType_FieldValues, +probableCause_FieldName : probableCause_FieldValues, +serviceAffecting_FieldName : serviceAffecting_FieldValues, +suppression_FieldName : suppression_FieldValues, +managementAffectingSeverity_FieldName : managementAffectingSeverity_FieldValues +} + +logFields = { +type_FieldName : type_FieldValues, +description_FieldName : description_FieldValues, +entityInstanceId_FieldName : entityInstanceId_FieldValues, +severity_FieldName : severity_FieldValues, +alarmType_FieldName : alarmType_FieldValues, +probableCause_FieldName : probableCause_FieldValues, +serviceAffecting_FieldName : serviceAffecting_FieldValues +} + + + + +def checkField( fieldKey, fieldValues, key, event ): + if not event.has_key(fieldKey): + print "\n ERROR: %s missing \'%s\' field." % (key, fieldKey) + return False + # print "START: %s :END" % event[fieldKey] + + if type(event[fieldKey]) is str: + if not fieldValues: + return True + if event[fieldKey] in fieldValues: + return True + else: + print "\n ERROR: \'%s\' is not a valid \'%s\' field value." % (event[fieldKey], fieldKey) + print " Valid values are:", fieldValues + return False + + if type(event[fieldKey]) is list: + if not fieldValues: + return True + for listvalue in event[fieldKey]: + if not listvalue in fieldValues: + print "\n ERROR: \'%s\' is not a valid \'%s\' field value." % (listvalue, fieldKey) + print " Valid values are:", fieldValues + return False + + if type(event[fieldKey]) is dict: + for dictKey, dictValue in event[fieldKey].iteritems(): + if not dictKey in severity_FieldValues: + print "\n ERROR: \'%s\' is not a valid \'%s\' index value." % (dictKey, fieldKey) + print " Valid index values are:", severity_FieldValues + return False + if fieldValues: + if not dictValue in fieldValues: + print "\n ERROR: \'%s\' is not a valid \'%s\' field value." % (dictValue, fieldKey) + print " Valid values are:", fieldValues + return False + return True + + +def checkTypeField( key, event ): + if not event.has_key(type_FieldName): + print "\n ERROR: %s missing \'%s\' field." % (key, type_FieldName) + return False + if event[type_FieldName] in type_FieldValues: + return True + print "\n ERROR: \'%s\' is not a valid \'%s\' field value." % (event[type_FieldName], type_FieldName) + return False + + + +def checkFields( key, event ): + isOk = True + if not checkTypeField(key, event) : + return False + isAlarm = (event[type_FieldName] == type_FieldValue_Alarm) + eventFields = alarmFields if isAlarm else logFields + + for fieldKey, fieldValues in eventFields.iteritems(): + if not checkField(fieldKey, fieldValues, key, event) : + isOk = False + + for itemKey, itemValue in event.iteritems(): + if not eventFields.has_key(itemKey): + print "\n ERROR: \'%s\' is not a valid \'%s\' field." % (itemKey, ("Alarm" if isAlarm else "Log") ) + isOk = False + + return isOk + + +# +# Main +# + +if len(sys.argv) == 1: + print "Missing file argument.\n" + exit(1) + +if not os.path.isfile(sys.argv[1]): + print "File \'%s\' does not exist.\n" % (sys.argv[1]) + exit(1) + +with open(sys.argv[1], 'r') as stream: + try: + events = yaml.load(stream) + exitValue = 0 + + for key in events: + print "%6.3f: checking ... " % key, + if not checkFields( key, events[key] ): + print + exitValue = 1 + else: + print 'OK.' + + print 'Done.' + + except yaml.YAMLError as exc: + print(exc) + +exit (exitValue) + diff --git a/fm-mgr/PKG-INFO b/fm-mgr/PKG-INFO new file mode 100644 index 00000000..cd68fd88 --- /dev/null +++ b/fm-mgr/PKG-INFO @@ -0,0 +1,2 @@ +Name: fm-mgr +Version: 1.0 diff --git a/fm-mgr/centos/build_srpm.data b/fm-mgr/centos/build_srpm.data new file mode 100644 index 00000000..63c17a90 --- /dev/null +++ b/fm-mgr/centos/build_srpm.data @@ -0,0 +1,2 @@ +SRC_DIR="sources" +TIS_PATCH_VER=5 diff --git a/fm-mgr/centos/fm-mgr.spec b/fm-mgr/centos/fm-mgr.spec new file mode 100644 index 00000000..34171e38 --- /dev/null +++ b/fm-mgr/centos/fm-mgr.spec @@ -0,0 +1,50 @@ +%define local_dir /usr/local +%define local_bindir %{local_dir}/bin + +Summary: CGTS Platform Fault Manager Package +Name: fm-mgr +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +Source0: %{name}-%{version}.tar.gz +BuildRequires: fm-common-dev +BuildRequires: systemd-devel +BuildRequires: libuuid-devel + +%description +CGTS platform Fault Manager that serves the client +application fault management requests and raise/clear/update +alarms in the active alarm database. + +%prep +%setup + +%build +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +make MAJOR=$MAJOR MINOR=$MINOR %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +make DEST_DIR=$RPM_BUILD_ROOT BIN_DIR=%{local_bindir} LIB_DIR=%{_libdir} INC_DIR=%{_includedir} MAJOR=$MAJOR MINOR=$MINOR install_non_bb + +%clean +rm -rf $RPM_BUILD_ROOT + + +%files +%defattr(-,root,root,-) +%doc LICENSE +%{local_bindir}/fmManager +%config(noreplace) %{_sysconfdir}/fm.conf +%_sysconfdir/init.d/fminit +%{_unitdir}/fminit.service +%config(noreplace) %{_sysconfdir}/logrotate.d/fm.logrotate + diff --git a/fm-mgr/sources/LICENSE b/fm-mgr/sources/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/fm-mgr/sources/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/fm-mgr/sources/Makefile b/fm-mgr/sources/Makefile new file mode 100755 index 00000000..dd96719a --- /dev/null +++ b/fm-mgr/sources/Makefile @@ -0,0 +1,30 @@ +SRCS = fm_main.cpp +OBJS = fm_main.o + +OBJS = $(SRCS:.cpp=.o) +INCLUDES = -I. +CCFLAGS = -g -O2 -Wall -Werror + +build: fmManager + +.cpp.o: + $(CXX) $(INCLUDES) $(CCFLAGS) $(EXTRACCFLAGS) -c $< -o $@ + +fmManager: $(OBJS) + $(CXX) -o $@ $(OBJS) $(LDFLAGS) -lfmcommon -lrt -lpthread -luuid + +clean: + @rm -f $(OBJS) + +install_non_bb: + mkdir -p $(DEST_DIR)/usr/lib/systemd/system + install -m 755 -d $(DEST_DIR)/etc + install -m 755 -d $(DEST_DIR)/etc/init.d + install -m 755 -d $(DEST_DIR)/etc/logrotate.d + install -m 755 -d $(DEST_DIR)/usr/local + install -m 755 -d $(DEST_DIR)/usr/local/bin + install -m 644 fm.conf $(DEST_DIR)/etc/fm.conf + install -m 755 fminit $(DEST_DIR)/etc/init.d/fminit + install -m 755 fmManager $(DEST_DIR)/usr/local/bin/fmManager + install -m 644 fm.logrotate $(DEST_DIR)/etc/logrotate.d/fm.logrotate + install -m 644 fminit.service $(DEST_DIR)/usr/lib/systemd/system/fminit.service diff --git a/fm-mgr/sources/fm.conf b/fm-mgr/sources/fm.conf new file mode 100644 index 00000000..4161aae6 --- /dev/null +++ b/fm-mgr/sources/fm.conf @@ -0,0 +1,8 @@ +################################################### +# +# fm.conf +# +# The configuration file for the fmManager process. +# +################################################### +event_log_max_size=4000 diff --git a/fm-mgr/sources/fm.logrotate b/fm-mgr/sources/fm.logrotate new file mode 100644 index 00000000..de83c185 --- /dev/null +++ b/fm-mgr/sources/fm.logrotate @@ -0,0 +1,35 @@ +# +# Copyright (c) 2014 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# +nodateext + +/var/log/fm-event.log +{ + nodateext + size 200M + start 1 + missingok + rotate 20 + compress + sharedscripts + postrotate + systemctl reload syslog-ng > /dev/null 2>&1 || true + endscript +} + +/var/log/fm-manager.log +{ + nodateext + size 10M + start 1 + rotate 20 + missingok + notifempty + compress + sharedscripts + postrotate + systemctl reload syslog-ng > /dev/null 2>&1 || true + endscript +} diff --git a/fm-mgr/sources/fm_main.cpp b/fm-mgr/sources/fm_main.cpp new file mode 100644 index 00000000..760a5395 --- /dev/null +++ b/fm-mgr/sources/fm_main.cpp @@ -0,0 +1,59 @@ +// +// Copyright (c) 2014 Wind River Systems, Inc. +// +// SPDX-License-Identifier: Apache-2.0 +// + +#include +#include + +#include + +#include +#include +#include +#include + +void sig_handler(int signo) { + int result = 0; + if (signo == SIGHUP){ + result = setlogmask(LOG_UPTO (LOG_DEBUG)); + if (result == LOG_UPTO (LOG_DEBUG)){ + result = setlogmask(LOG_UPTO (LOG_INFO)); + syslog(LOG_INFO, "Received SIGHUP, set log level from %d to LOG_INFO", result); + }else{ + syslog(LOG_INFO, "Received SIGHUP, set log level from %d to LOG_DEBUG", result); + } + } +} + +int main(int argc, char *argv[]) { + int c; + const char *fn = NULL; + + if (argc < 3) { + syslog(LOG_ERR, "Wrong arguments\n"); + exit(-1); + } + + while ((c=getopt(argc,argv,"c:")) != -1) { + switch(c) { + case 'c': + fn = optarg; + break; + default: + syslog(LOG_ERR, "Invalid option...\n"); + exit(-1); + } + } + + /* ignore SIGPIPE */ + signal(SIGPIPE, SIG_IGN); + + if (signal(SIGHUP, sig_handler) == SIG_ERR){ + syslog(LOG_INFO, "Can't catch SIGHUP\n"); + } + + fm_server_create(fn); + exit(0); +} diff --git a/fm-mgr/sources/fminit b/fm-mgr/sources/fminit new file mode 100755 index 00000000..37b87c91 --- /dev/null +++ b/fm-mgr/sources/fminit @@ -0,0 +1,111 @@ +#! /bin/sh +# +# Copyright (c) 2013-2014 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# chkconfig: 2345 95 95 +# +### BEGIN INIT INFO +# Provides: fminit +# Default-Start: 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: Fault Manager +### END INIT INFO + +. /etc/init.d/functions + +FMMGR_NAME="fmManager" +FMMGR="/usr/local/bin/${FMMGR_NAME}" +PIDFILE=/var/run/${FMMGR_NAME}.pid +CONFIGFILE=/etc/fm.conf + + +# Linux Standard Base (LSB) Error Codes +RETVAL=0 +GENERIC_ERROR=1 +INVALID_ARGS=2 +NOT_RUNNING=3 +NOT_INSTALLED=5 + +if [ ! -e "$FMMGR" ] ; then + logger "$FMMGR is missing" + exit ${NOT_INSTALLED} +fi + + +PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin +export PATH + +case "$1" in + start) + # The FMMGR runs on controller only + echo -n "Starting ${FMMGR_NAME}: " + if [ -n "`pidof ${FMMGR_NAME}`" ] ; then + echo -n "is already running " + RETVAL=0 + else + start-stop-daemon --start -b --make-pidfile --pidfile $PIDFILE --chuid fm -x ${FMMGR} -- -c ${CONFIGFILE} + RETVAL=$? + fi + if [ ${RETVAL} -eq 0 ] ; then + pid=`pidof ${FMMGR_NAME}` + echo "OK" + logger "${FMMGR} (${pid})" + else + echo "FAIL" + RETVAL=${GENERIC_ERROR} + fi + + + ;; + stop) + status ${FMMGR_NAME} >/dev/null + if [ $? -ne 0 ]; then + echo "$FMMGR_NAME is not running" + RETVAL=0 + else + echo -n "Stopping ${FMMGR_NAME}: " + killproc ${FMMGR_NAME} + if [ -n "`pidof ${FMMGR_NAME}`" ] ; then + logger "Going to SIGKILL ${FMMGR_NAME}" + killproc -KILL ${FMMGR_NAME} + fi + /bin/rm -rf $PIDFILE + status ${FMMGR_NAME} >/dev/null + if [ $? -ne 0 ]; then + echo "Stopped" + RETVAL=0 + else + echo "Failed" + RETVAL=${GENERIC_ERROR} + fi + fi + ;; + restart) + $0 stop + sleep 1 + $0 start + ;; + + status) + status ${FMMGR_NAME} >/dev/null + RETVAL=$? + if [ ! ${RETVAL} -eq 0 ] ; then + RETVAL=${NOT_RUNNING} + fi + + ;; + + condrestart) + $0 restart + ;; + + *) + echo "usage: $0 { start | stop | status | restart | condrestart | status }" + ;; +esac + +exit $RETVAL diff --git a/fm-mgr/sources/fminit.service b/fm-mgr/sources/fminit.service new file mode 100644 index 00000000..7d7cc96a --- /dev/null +++ b/fm-mgr/sources/fminit.service @@ -0,0 +1,17 @@ +[Unit] +Description=Titanium Cloud Fault Management Initialization +After=network.target syslog.target + +[Service] +Type=forking +Restart=no +KillMode=process +RemainAfterExit=yes +ExecStart=/etc/rc.d/init.d/fminit start +ExecStop=/etc/rc.d/init.d/fminit stop +ExecReload=/etc/rc.d/init.d/fminit reload +PIDFile=/var/run/fmManager.pid + +[Install] +WantedBy=multi-user.target + diff --git a/mwa-cleo.map b/mwa-cleo.map new file mode 100644 index 00000000..e5c6c438 --- /dev/null +++ b/mwa-cleo.map @@ -0,0 +1,6 @@ +cgcs/middleware/fault/recipes-common/fm-api|fm-api +cgcs/middleware/fault/recipes-common/fm-common|fm-common +cgcs/middleware/fault/recipes-common/fm-doc|fm-doc +cgcs/middleware/fault/recipes-control/fm-mgr|fm-mgr +cgcs/middleware/fault/recipes-control/snmp-audittrail|snmp-audittrail +cgcs/middleware/fault/recipes-control/snmp-ext|snmp-ext diff --git a/snmp-audittrail/centos/build_srpm.data b/snmp-audittrail/centos/build_srpm.data new file mode 100644 index 00000000..5c86664a --- /dev/null +++ b/snmp-audittrail/centos/build_srpm.data @@ -0,0 +1,2 @@ +SRC_DIR="sources" +TIS_PATCH_VER=4 diff --git a/snmp-audittrail/centos/snmp-audittrail.spec b/snmp-audittrail/centos/snmp-audittrail.spec new file mode 100644 index 00000000..9d01095b --- /dev/null +++ b/snmp-audittrail/centos/snmp-audittrail.spec @@ -0,0 +1,56 @@ +Summary: Titanium Cloud Platform SNMP Audit Trail +Name: snmp-audittrail +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +Source0: %{name}-%{version}.tar.gz +BuildRequires: net-snmp-devel +BuildRequires: fm-common-dev +BuildRequires: uuid-devel +BuildRequires: uuid +Requires: net-snmp +Requires: uuid + +%description +Titanium Cloud platform SNMP Audit Trail provides audit trail support for incoming +SNMP requests. + +%package -n snmp-audittrail-devel +Summary: Titanium Cloud Platform SNMP Audit Trail Package - Development files +Group: devel +Requires: snmp-audittrail = %{version}-%{release} + +%description -n snmp-audittrail-devel +Titanium Cloud platform SNMP Audit Trail provides audit trail support for incoming +SNMP requests. This package contains symbolic links, header files, and related +items necessary for software development. + +%prep +%setup + +%build +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +PATCHVER=` echo %{release} | awk -F r '{print $2}' | awk -F . '{print $1}'` +make MAJOR=$MAJOR MINOR=$MINOR PATCH=$PATCHVER %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +PATCHVER=` echo %{release} | awk -F r '{print $2}' | awk -F . '{print $1}'` +make DEST_DIR=$RPM_BUILD_ROOT LIB_DIR=%{_libdir} MAJOR=$MAJOR MINOR=$MINOR PATCH=$PATCHVER install_non_bb + +%files +%defattr(-,root,root,-) +%doc LICENSE +%{_libdir}/*.so.* + +%files -n snmp-audittrail-devel +%defattr(-,root,root,-) +%{_libdir}/*.so diff --git a/snmp-audittrail/sources/LICENSE b/snmp-audittrail/sources/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/snmp-audittrail/sources/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/snmp-audittrail/sources/Makefile b/snmp-audittrail/sources/Makefile new file mode 100644 index 00000000..7803c59d --- /dev/null +++ b/snmp-audittrail/sources/Makefile @@ -0,0 +1,25 @@ +SRCS = snmpAuditPlugin.c + +OBJS = $(SRCS:.c=.o) +LDLIBS = -lfmcommon -lnetsnmp -lnetsnmpagent -luuid +INCLUDES += -I./ +CCFLAGS = -fPIC -g -O2 -Wall -Werror +LIBCGTSAGENT_SO := libsnmpAuditPlugin.so +build: lib + +.c.o: + $(CXX) $(CCFLAGS) $(INCLUDES) -c $< -o $@ + +lib: $(OBJS) + $(CXX) $(OBJS) $(LDLIBS) -o $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) -shared + ln -sf $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(LIBCGTSAGENT_SO).$(MAJOR) + ln -sf $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(LIBCGTSAGENT_SO) + +clean: + @rm -f $(OBJ) *.o *.so.* + +install_non_bb: + install -m 755 -d $(DEST_DIR)$(LIB_DIR) + install -m 755 $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(DEST_DIR)$(LIB_DIR) + ln -s $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(DEST_DIR)$(LIB_DIR)/$(LIBCGTSAGENT_SO).$(MAJOR) + ln -s $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(DEST_DIR)$(LIB_DIR)/$(LIBCGTSAGENT_SO) diff --git a/snmp-audittrail/sources/snmpAuditPlugin.c b/snmp-audittrail/sources/snmpAuditPlugin.c new file mode 100644 index 00000000..46d5fd9d --- /dev/null +++ b/snmp-audittrail/sources/snmpAuditPlugin.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_BUF_STR (256) + +#define AUDIT_TAG "snmp-auditor" + +/* Used to keep track of the first handler call for a transaction */ +typedef struct s_audit_req_t { + long transid; + long reqid; +} audit_req_t; + +typedef struct s_enum_to_string_t { + const int enumval; + const char *str; +} enum_to_string_t; + + +/* Logs IP session information, in the format: "remote IP:port ==> local IP:port" */ +static inline char* fmtaddr(const char *prefix, int af, + void *remote_addr, unsigned short remote_port, + char*buf, size_t buflen) +{ + char remote_addr_str[LOG_BUF_STR+1]; + + if (NULL == inet_ntop(af, remote_addr, remote_addr_str, sizeof(remote_addr_str))) { + strncpy(remote_addr_str, "UNKNOWN", LOG_BUF_STR+1); + } + remote_addr_str[LOG_BUF_STR] = 0; + + snprintf(buf, buflen, "transport:%s remote:%s", prefix, remote_addr_str); + return buf; +} + + +#ifdef NETSNMP_ENABLE_IPV6 +static char* ipv6_fmtaddr(const char *prefix, netsnmp_addr_pair *addr_pair, char*buf, size_t buflen) +{ + return fmtaddr(prefix, AF_INET6, + (void *)&addr_pair->remote_addr.sin6.sin6_addr, addr_pair->remote_addr.sin6.sin6_port, + buf, buflen); +} +#endif + + +static char* ipv4_fmtaddr(const char *prefix, netsnmp_addr_pair *addr_pair, char*buf, size_t buflen) +{ + return fmtaddr(prefix, AF_INET, + (void *)&addr_pair->remote_addr.sin.sin_addr, addr_pair->remote_addr.sin.sin_port, + buf, buflen); +} + + +/* Logs IP session information */ +static char* log_session_addresses(const oid* tDomain, netsnmp_addr_pair *addr_pair, char*buf, size_t buflen) +{ + if (tDomain == netsnmpUDPDomain) { + return ipv4_fmtaddr("udp", addr_pair, buf, buflen); + } + + if (tDomain == netsnmp_snmpTCPDomain) { + return ipv4_fmtaddr("tcp", addr_pair, buf, buflen); + } + +#ifdef NETSNMP_ENABLE_IPV6 + if (tDomain == netsnmp_UDPIPv6Domain) { + return ipv6_fmtaddr("udpv6", addr_pair, buf, buflen); + } + + if (tDomain == netsnmp_TCPIPv6Domain) { + return ipv6_fmtaddr("tcpv6", addr_pair, buf, buflen); + } +#endif + strncpy(buf, "IP FMT ERROR", buflen); + buf[buflen-1] = 0; + return buf; +} + + +/* SNMP OID formatting (a wrapper around the 'standard' function */ +static inline char* fmtoid(const oid * theoid, size_t len, int* no_overflow) +{ + u_char *buf = NULL; + size_t buf_len = 0; + size_t out_len = 0; + + *no_overflow = sprint_realloc_objid(&buf, &buf_len, &out_len, 1, theoid, len); + if (NULL == buf) { + *no_overflow = 0; + } + + return (char*)buf; +} + + +/* SNMP var bind formatting (a convenience function) - formats the OID (variable name) + This function is always called with var != NULL */ +static inline char* fmtmsg_var(netsnmp_variable_list * var, int* no_overflow) +{ + return fmtoid(var->name, var->name_length, no_overflow); +} + +static const char* get_version(long version) +{ + switch (version) { + case 0: return "v1"; + case 1: return "v2c"; + case 2: return "v3"; + } + return "error"; +} + + +static const char *get_str_from_enum(int enumval, const enum_to_string_t* table, const char* defval) +{ + const enum_to_string_t* ptr = table; + + for ( ; ptr->str != NULL; ++ptr) { + if (ptr->enumval == enumval) { + return ptr->str; + } + } + if (NULL == defval) { + return "unknown"; + } + return defval; +} + + +static const char *get_auth_error(int errorcode) +{ + static enum_to_string_t errorcodes_str[] = { + { VACM_SUCCESS, "Success", }, + { VACM_NOSECNAME, "InvalidCommunityName" }, + { VACM_NOGROUP, "NoGroup" }, + { VACM_NOACCESS, "NoAccess" }, + { VACM_NOVIEW, "NoViewAccess" }, + { VACM_NOTINVIEW, "NotInView" }, + { VACM_NOSUCHCONTEXT, "NoSuchContext" }, + { VACM_SUBTREE_UNKNOWN,"SubtreeUnknown" }, + {0, NULL} + }; + return get_str_from_enum(errorcode, errorcodes_str, "unknown err"); +} + +static const char *get_result_error(int errorcode) +{ + static enum_to_string_t errorcodes_str[] = { + { 0, "pass" }, + { SNMP_NOSUCHOBJECT, "NoSuchObject" }, + { SNMP_NOSUCHINSTANCE, "NoSuchInstance" }, + { SNMP_ENDOFMIBVIEW, "EndOfMIBView" }, + {0, NULL} + }; + return get_str_from_enum(errorcode, errorcodes_str, "pass"); +} + + +/* Logs all var-binds in PDU (only variable names, aka OID's) */ +static void log_var_list(netsnmp_pdu *pdu) +{ + netsnmp_variable_list * var; + + for (var = pdu->variables; var != NULL; var = var->next_variable) { + int no_overflow_var = 0; + char* var_str = fmtmsg_var(var, &no_overflow_var); + + snmp_log(LOG_INFO, AUDIT_TAG" reqid:%ld oid:%s%s\n", + pdu->reqid, + (var_str != NULL) ? var_str : "INVALID", + (no_overflow_var) ? "" : " [TRUNCATED]"); + free(var_str); + } +} + +/* Logs the 'header' of a PDU/request (IP addresses, reqid, msg type, version) */ +static void log_pdu_header(netsnmp_pdu *pdu, const char *status) +{ + char buf[LOG_BUF_STR]; + netsnmp_addr_pair *addr_pair = (netsnmp_addr_pair *)pdu->transport_data; + + snmp_log(LOG_INFO, AUDIT_TAG" %s reqid:%ld msg-type:%s version:%s%s\n", + log_session_addresses(pdu->tDomain, addr_pair, buf, sizeof(buf)), + pdu->reqid, snmp_pdu_type(pdu->command), get_version(pdu->version), status); +} + +/* Logs the results of a request, namely results obtained from actual processing handlers */ +static void log_results(long reqid, netsnmp_request_info *requests) +{ + netsnmp_request_info *req; + + for (req = requests; req != NULL; req = req->next) { + netsnmp_variable_list *var = req->requestvb; + + if (NULL == var) { + continue; + } + if (var->type != ASN_NULL) { /* NULL means no result, so skip */ + int no_overflow_var = 0; + char* var_str = fmtmsg_var(var, &no_overflow_var); + + /* Print only first variable: this is the request that we get a result for */ + snmp_log(LOG_INFO, AUDIT_TAG" reqid:%ld oid:%s%s status:%s\n", reqid, + (var_str != NULL) ? var_str : "INVALID", + (no_overflow_var) ? "" : " [TRUNCATED]", get_result_error(var->type)); + free(var_str); + } + } +} + + +static void log_invalid_oid_trees(netsnmp_pdu *pdu) +{ + char buf[LOG_BUF_STR]; + netsnmp_variable_list *var; + netsnmp_addr_pair *addr_pair = (netsnmp_addr_pair *)pdu->transport_data; + int first_time = 1; + + for (var = pdu->variables; var != NULL; var = var->next_variable) { + netsnmp_subtree *tp = netsnmp_subtree_find(var->name, var->name_length, + NULL, pdu->contextName); + if (tp != NULL) { + int prefix_len = netsnmp_oid_find_prefix(tp->start_a, + tp->start_len, + tp->end_a, tp->end_len); + while (prefix_len < 1) { + tp = tp->next; + if (NULL == tp) { + break; + } + prefix_len = netsnmp_oid_find_prefix(tp->start_a, + tp->start_len, + tp->end_a, tp->end_len); + } + DEBUGMSGTL(("helper:snmpAudit", "var=%p tp=%p prefix_len=%d\n", var, tp, prefix_len )); + } + else { + DEBUGMSGTL(("helper:snmpAudit", "tp NOT found var=%p\n", var)); + } + if (NULL == tp) { + int no_overflow_var = 0; + char* var_str = fmtmsg_var(var, &no_overflow_var); + + if (first_time) { + first_time = 0; + snmp_log(LOG_INFO, AUDIT_TAG" %s reqid:%ld msg-type:%s version:%s\n", + log_session_addresses(pdu->tDomain, addr_pair, buf, sizeof(buf)), pdu->reqid, + snmp_pdu_type(pdu->command), + get_version(pdu->version)); + log_var_list(pdu); + } + + snmp_log(LOG_INFO, AUDIT_TAG" reqid:%ld oid:%s%s status:%s\n", + pdu->reqid, + (var_str != NULL) ? var_str : "INVALID", + (no_overflow_var) ? "" : " [TRUNCATED]", + get_result_error(SNMP_ENDOFMIBVIEW)); + free(var_str); + } + } +} + +/* + * Register with 'SNMPD_CALLBACK_ACM_CHECK_INITIAL == minorId' + * This function is used to log authorization errors and invalid OID's errors, + * for GET BULK and GET NEXT requests + */ +static int audit_callback_acm_check_initial(int majorID, int minorID, void *serverarg, + void *clientarg) +{ + struct view_parameters *view_parms = + (struct view_parameters *) serverarg; + netsnmp_pdu *pdu = view_parms->pdu; + + DEBUGMSGTL(("helper:snmpAudit", "%s msg-type: %s errcode=%d minorID=%d\n", + __FUNCTION__, snmp_pdu_type(pdu->command), view_parms->errorcode, minorID)); + + if (view_parms->errorcode != VACM_SUCCESS) { + /* Log Authentication errors */ + char buf[LOG_BUF_STR]; + netsnmp_addr_pair *addr_pair = (netsnmp_addr_pair *)pdu->transport_data; + + snmp_log(LOG_INFO, AUDIT_TAG" %s reqid:%ld msg-type:%s version:%s status:%s\n", + log_session_addresses(pdu->tDomain, addr_pair, buf, sizeof(buf)), pdu->reqid, + snmp_pdu_type(pdu->command), get_version(pdu->version), + get_auth_error(view_parms->errorcode)); + log_var_list(pdu); + return 0; + } + + if (SNMP_MSG_GETBULK == pdu->command || + SNMP_MSG_GETNEXT == pdu->command) { + /* Log possible invalid OID subtrees for GETNEXT and GETBULK request + * (e.g. "1.10" - outside the normal ISO MIB subtree) + */ + log_invalid_oid_trees(pdu); + } + return 0; +} + +/* + * Register with 'SNMPD_CALLBACK_ACM_CHECK == minorId' + * This function is used to log SET requests (which are normally rejected) + */ +static int audit_callback_acm_check(int majorID, int minorID, void *serverarg, + void *clientarg) +{ + struct view_parameters *view_parms = + (struct view_parameters *) serverarg; + netsnmp_pdu *pdu = view_parms->pdu; + + DEBUGMSGTL(("helper:snmpAudit", "%s msg-type: %s errcode=%d minorID=%d\n", + __FUNCTION__, snmp_pdu_type(pdu->command), view_parms->errorcode, minorID)); + if (SNMP_MSG_SET == pdu->command) { + char status_buf[LOG_BUF_STR]; + snprintf(status_buf, LOG_BUF_STR, + " status:%s", get_auth_error(view_parms->errorcode)); + log_pdu_header(pdu, status_buf); + log_var_list(pdu); + } + return 0; +} + + +/* Main log handler function: logs 'normal' requests: + * everything except SET operations, authentication errors and GETBULK/GETNEXT for invalid OIDs */ +static int audit_log_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + static audit_req_t req = { + .transid = 0, + .reqid = 0 + }; + netsnmp_pdu *orig_pdu = reqinfo->asp->orig_pdu; + int ret; + + /* Note. Assumes single-threaded processing. */ + if ((req.transid != orig_pdu->transid) && + (req.reqid != orig_pdu->reqid)) { + + /* New transaction */ + req.transid = orig_pdu->transid; + req.reqid = orig_pdu->reqid; + + /* Logs session information (e.g. IP addresses, version...) */ + log_pdu_header(orig_pdu, ""); + /* Logs the variables names in the request */ + log_var_list(orig_pdu); + } + /* Calls the next handlers, to obtain processing results */ + ret = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests); + /* Logs the variables names in the results + * resulted from the calls to 'netsnmp_call_next_handler' above + * which invokes all other handlers in the chain. + */ + log_results(orig_pdu->reqid, requests); + return ret; +} + + + +/* + * Initialization routine, automatically called by the agent + * (to get called, the function name must match init_FILENAME()) + */ +extern "C" void init_snmpAuditPlugin(void) { + + netsnmp_mib_handler *audit_handler = NULL; + + snmp_log(LOG_INFO, "init_snmpAuditPlugin\n"); + audit_handler = netsnmp_create_handler("snmpAudit", + audit_log_handler); + if (audit_handler != NULL) { + netsnmp_register_handler_by_name("snmpAudit", audit_handler); + } + + netsnmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK, + audit_callback_acm_check, + NULL, NETSNMP_CALLBACK_LOWEST_PRIORITY ); + netsnmp_register_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK_INITIAL, + audit_callback_acm_check_initial, + NULL, NETSNMP_CALLBACK_LOWEST_PRIORITY); +} + +extern "C" void deinit_snmpAuditPlugin(void) +{ + snmp_log(LOG_INFO, "deinit_snmpAuditPlugin\n"); + snmp_unregister_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK, + audit_callback_acm_check, NULL, 1); + snmp_unregister_callback(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK_INITIAL, + audit_callback_acm_check_initial, NULL, 1); +} diff --git a/snmp-ext/centos/build_srpm.data b/snmp-ext/centos/build_srpm.data new file mode 100644 index 00000000..706c821c --- /dev/null +++ b/snmp-ext/centos/build_srpm.data @@ -0,0 +1,3 @@ +SRC_DIR="sources" +COPY_LIST="mibs/*" +TIS_PATCH_VER=1 diff --git a/snmp-ext/centos/snmp-ext.spec b/snmp-ext/centos/snmp-ext.spec new file mode 100644 index 00000000..2c8e859b --- /dev/null +++ b/snmp-ext/centos/snmp-ext.spec @@ -0,0 +1,82 @@ +Summary: CGTS Platform SNMP extension Package +Name: snmp-ext +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown +Source0: %{name}-%{version}.tar.gz +BuildRequires: fm-common-dev +BuildRequires: net-snmp-devel +BuildRequires: libuuid-devel +Requires: fm-common +Requires: net-snmp + +Source1: wrsAlarmMib.mib.txt +Source2: wrsEnterpriseReg.mib.txt + +%define mib_ver 2.0 +%define cgcs_sdk_deploy_dir /opt/deploy/cgcs_sdk + +%description +Titanium Cloud platform SNMP extension provides Wind River enterprise MIBs support +and it serves as SNMP based alarm surveillance module for Network Manager +System. + +%package -n snmp-ext-devel +Summary: Titanium Cloud Platform SNMP extension Package - Development files +Group: devel +Requires: snmp-ext = %{version}-%{release} + +%description -n snmp-ext-devel +Titanium Cloud platform SNMP extension provides Wind River enterprise MIBs support +and it serves as SNMP based alarm surveillance module for Network Manager +System. This package contains symbolic links, header files, and related +items necessary for software development. + +%package -n %{name}-cgts-sdk +Summary: Titanium Cloud Platform SNMP extension Package - SDK +Group: devel + +%description -n %{name}-cgts-sdk + +%prep +%setup + +%build +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +PATCHVER=` echo %{release} | awk -F r '{print $2}' | awk -F . '{print $1}'` +make MAJOR=$MAJOR MINOR=$MINOR PATCH=$PATCHVER %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` + +PATCHVER=` echo %{release} | awk -F r '{print $2}' | awk -F . '{print $1}'` +make DEST_DIR=$RPM_BUILD_ROOT LIB_DIR=%{_libdir} MAJOR=$MAJOR MINOR=$MINOR PATCH=$PATCHVER install_non_bb + +MIBDIR=wrs-snmp-mib-${MAJOR}.%{mib_ver} +mkdir -p $RPM_BUILD_ROOT%{_datadir}/snmp/mibs +install -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_datadir}/snmp/mibs +install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_datadir}/snmp/mibs +tar -zc --transform=s/^mibs/${MIBDIR}/ -f wrs-snmp-mib-${MAJOR}.%{mib_ver}.tgz -C $RPM_BUILD_ROOT%{_datadir}/snmp mibs +mkdir -p $RPM_BUILD_ROOT%{cgcs_sdk_deploy_dir} +install -m 644 wrs-snmp-mib-${MAJOR}.%{mib_ver}.tgz $RPM_BUILD_ROOT%{cgcs_sdk_deploy_dir} + +%files +%defattr(-,root,root,-) +%doc LICENSE +%{_libdir}/*.so.* +%{_datadir}/snmp/mibs/* + +%files -n snmp-ext-devel +%defattr(-,root,root,-) +%{_libdir}/*.so + +%files -n %{name}-cgts-sdk +%{cgcs_sdk_deploy_dir}/wrs-snmp-mib-*.%{mib_ver}.tgz diff --git a/snmp-ext/mibs/wrsAlarmMib.mib.txt b/snmp-ext/mibs/wrsAlarmMib.mib.txt new file mode 100644 index 00000000..7c5fb7fe --- /dev/null +++ b/snmp-ext/mibs/wrsAlarmMib.mib.txt @@ -0,0 +1,818 @@ +WRS-ALARM-MIB + +DEFINITIONS ::= BEGIN + + IMPORTS + wrsAlarms, WrsUUID, WrsBoolean FROM WRS-ENTERPRISE-REG-MIB + + NOTIFICATION-GROUP, OBJECT-GROUP, MODULE-COMPLIANCE + FROM SNMPv2-CONF + + DateAndTime, DisplayString, TEXTUAL-CONVENTION + FROM SNMPv2-TC + + MODULE-IDENTITY, OBJECT-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, Unsigned32 + FROM SNMPv2-SMI; + + + wrsAlarmMIB MODULE-IDENTITY + LAST-UPDATED "201703310000Z" + ORGANIZATION "Wind River Systems, Inc." + CONTACT-INFO "Wind River Systems, Inc. + 500 Wind River Way + Alameda, CA 94501, USA + Contact : Wind River Systems Support + E-mail: support@windriver.com + Phone : 510.748.4100" + DESCRIPTION "This module contains objects of the + Titanium Cloud Alarm MIB, + including notifications." + + -- Revision history + REVISION "201703310000Z" + DESCRIPTION "Titanium Cloud Release 4 version, with new Event table and removal of deprecated customer and alarm history tables." + ::= { wrsAlarms 1 } + + wrsAlarmObjects OBJECT IDENTIFIER ::= { wrsAlarmMIB 1 } + wrsAlarmConformance OBJECT IDENTIFIER ::= { wrsAlarmMIB 2 } + wrsAlarmCompliances OBJECT IDENTIFIER ::= { wrsAlarmConformance 1 } + wrsAlarmGroups OBJECT IDENTIFIER ::= { wrsAlarmConformance 2 } + + + -- Textual Conventions + + WrsAlarmSeverity ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "The severity of the alarm." + SYNTAX INTEGER + { + not-applicable (0), + warning (1), + minor (2), + major (3), + critical (4) + } + + WrsAlarmState ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "The state of the alarm." + SYNTAX INTEGER + { + clear (0), + set (1), + log (3) + } + + WrsAlarmId ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "An ID identifying the particular Alarm condition. + Typically used as an index for looking up Alarm details + in a System's Alarm Document. + + This will be a structured ID, in order to allow grouping of + Alarms into general categories and allow specific Alarms to + be independently added and numbered within the group. + + e.g. . + where = 000 - 999 + = 000 - 999 + + NOTE: the { alarm-id, entity-instance-id } uniquely identifies an ACTIVE Alarm. + e.g. + - an alarm is cleared based on the matching { alarm-id, entity-instance-id }, + - consecutive sets of an alarm with matching { alarm-id, entity-instance-id } + updates the fields of the single ACTIVE Alarm. + E.g. updates severity for example. " + SYNTAX OCTET STRING (SIZE (0..7)) + + WrsAlarmEntityInstanceId ::= TEXTUAL-CONVENTION + DISPLAY-HINT "255a" + STATUS current + DESCRIPTION "This is a textual description of the resource under alarm. + + A '.' separated list of sub-entity-type=instance-value pairs, + representing the containment structure of the overall entity + instance. + + Can be larger than 256 bytes. + + Note that this containment structure will be used for + processing hierarchical clears. + + e.g + system=ironpass1-4 + system=ironpass1-4 . host=compute-0 + system=ironpass1-4 . host=compute-0 . port=eth0 + system=ironpass1-4 . host=compute-0 . disk=/dev/sda + + system=ironpass1-4 . instance=vyatta_rtr_0 + system=ironpass1-4 . stack=vyatta_scaling_rtrs + + NOTE: the { alarm-id, entity-instance-id } uniquely identifies an ACTIVE Alarm. + e.g. + - an alarm is cleared based on the matching { alarm-id, entity-instance-id }, + - consecutive sets of an alarm with matching { alarm-id, entity-instance-id } + updates the fields of the single ACTIVE Alarm. + E.g. updates severity for example." + SYNTAX OCTET STRING + + WrsAlarmText ::= TEXTUAL-CONVENTION + DISPLAY-HINT "255a" + STATUS current + DESCRIPTION "Variable length string to encapsulate alarm or message + information from the entity raising the trap. + Can be larger than 256 bytes." + SYNTAX OCTET STRING + + WrsAlarmProbableCause ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "ITU-T probable cause values. Duplicate values defined in + X.733 are appended with X733 to ensure syntactic uniqueness. + Probable cause value 0 is reserved for special purposes. + + The Internet Assigned Number Authority (IANA) is responsible + for the assignment of the enumerations in this TC. + IANAItuProbableCause value of 0 is reserved for special + purposes and MUST NOT be assigned. + + Values of IANAItuProbableCause in the range 1 to 1023 are + reserved for causes that correspond to ITU-T probable cause. + + All other requests for new causes will be handled on a + first-come, first served basis and will be assigned + enumeration values starting with 1025. + + Request should come in the form of well-formed + SMI [RFC2578] for enumeration names that are unique and + sufficiently descriptive. + + While some effort will be taken to ensure that new probable + causes do not conceptually duplicate existing probable + causes it is acknowledged that the existence of conceptual + duplicates in the starting probable cause list is an known + industry reality. + + To aid IANA in the administration of probable cause names + and values, the OPS Area Director will appoint one or more + experts to help review requests. + + See http://www.iana.org" + REFERENCE + "ITU Recommendation M.3100, 'Generic Network Information + Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm + Reporting Function', 1992 + ITU Recommendation X.736, 'Information Technology - Open + Systems Interconnection - System Management: Security + Alarm Reporting Function', 1992" + SYNTAX INTEGER + { + not-applicable (0), + -- The following probable causes were defined in M.3100 + adaptor-error (1), + application-subsystem-failure (2), + bandwidth-reduced (3), + call-establishment-error (4), + communication-protocol-error (5), + communication-subsystem-failure (6), + configuration-or-customization-error (7), + congestion (8), + corrupt-data (9), + cpu-cycles-limit-exceeded (10), + dataset-or-modem-error (11), + degraded-signal (12), + dte-dce-interface-error (13), + enclosure-door-open (14), + equipment-malfunction (15), + excessive-vibration (16), + file-error (17), + fire-detected (18), + flood-detected (19), + framing-error (20), + heating-ventilation-cooling-system-problem (21), + humidity-unacceptable (22), + io-device-error (23), + input-device-error (24), + lan-error (25), + leak-detected (26), + local-node-transmission-error (27), + loss-of-frame (28), + loss-of-signal (29), + material-supply-exhausted (30), + multiplexer-problem (31), + out-of-memory (32), + output-device-error (33), + performance-degraded (34), + power-problem (35), + processor-problem (36), + pump-failure (37), + queue-size-exceeded (38), + receive-failure (39), + receiver-failure (40), + remote-node-transmission-error (41), + resource-at-or-nearing-capacity (42), + response-time-excessive (43), + retransmission-rate-excessive (44), + software-error (45), + software-program-abnormally-terminated (46), + software-program-error (47), + storage-capacity-problem (48), + temperature-unacceptable (49), + threshold-crossed (50), + timing-problem (51), + toxic-leak-detected (52), + transmit-failure (53), + transmitter-failure (54), + underlying-resource-unavailable (55), + version-mismatch (56), + duplicate-information (57), + information-missing (58), + information-modification-detected (59), + information-out-of-sequence (60), + unexpected-information (61), + denial-of-service (62), + out-of-service (63), + procedural-error (64), + unspecified-reason (65), + cable-tamper (66), + intrusion-detection (67), + authentication-failure (68), + breach-of-confidentiality (69), + non-repudiation-failure (70), + unauthorized-access-attempt (71), + delayed-information (72), + key-expired (73), + out-of-hours-activity (74) + } + + WrsAlarmEventType ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION + "The ITU event Type values. + + The Internet Assigned Number Authority (IANA) is + responsible for the assignment of the enumerations + in this TC. + + Request should come in the form of well-formed + SMI [RFC2578] for enumeration names that are unique + and sufficiently descriptive. + + See http://www.iana.org " + REFERENCE + "ITU Recommendation X.736, 'Information Technology - Open + Systems Interconnection - System Management: Security + Alarm Reporting Function', 1992" + SYNTAX INTEGER + { + other (0), + communicationsAlarm (1), + qualityOfServiceAlarm (2), + processingErrorAlarm (3), + equipmentAlarm (4), + environmentalAlarm (5), + integrityViolation (6), + operationalViolation (7), + physicalViolation (8), + securityServiceOrMechanismViolation (9), + timeDomainViolation (10) + } + + + -- Wind River Systems Active Alarm Table + + wrsAlarmActiveTable OBJECT-TYPE + SYNTAX SEQUENCE OF WrsAlarmActiveEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "This table contains information about active alarms." + ::= { wrsAlarmObjects 1 } + + wrsAlarmActiveEntry OBJECT-TYPE + SYNTAX WrsAlarmActiveEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "An active alarm entry" + INDEX { wrsAlarmActiveIndex } + ::= { wrsAlarmActiveTable 1 } + + WrsAlarmActiveEntry ::= SEQUENCE { + wrsAlarmActiveIndex Unsigned32, + wrsAlarmActiveUuid DisplayString, + wrsAlarmActiveAlarmId WrsAlarmId, + wrsAlarmActiveEntityInstanceId WrsAlarmEntityInstanceId, + wrsAlarmActiveDateAndTime DateAndTime, + wrsAlarmActiveAlarmSeverity WrsAlarmSeverity, + wrsAlarmActiveReasonText WrsAlarmText, + wrsAlarmActiveEventType WrsAlarmEventType, + wrsAlarmActiveProbableCause WrsAlarmProbableCause, + wrsAlarmActiveProposedRepairAction WrsAlarmText, + wrsAlarmActiveServiceAffecting WrsBoolean, + wrsAlarmActiveSuppressionAllowed WrsBoolean + } + + wrsAlarmActiveIndex OBJECT-TYPE + SYNTAX Unsigned32 (1..4294967295) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "The index of the Active Alarm in the Active Alarm Table." + ::= { wrsAlarmActiveEntry 1 } + + wrsAlarmActiveUuid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "An ID identifying the active alarm instance in the Active Alarm Table." + ::= { wrsAlarmActiveEntry 2 } + + wrsAlarmActiveAlarmId OBJECT-TYPE + SYNTAX WrsAlarmId + MAX-ACCESS read-only + STATUS current + DESCRIPTION "An ID identifying the particular Alarm condition. + Typically used as an index for looking up Alarm details + in a System's Alarm Document. + + This will be a structured ID, in order to allow grouping of + Alarms into general categories and allow specific Alarms to + be independently added and numbered within the group. + + e.g. . + where = 000 - 999 + = 000 - 999 + + NOTE: the { alarm-id, entity-instance-id } uniquely identifies an ACTIVE Alarm. + e.g. + - an alarm is cleared based on the matching { alarm-id, entity-instance-id }, + - consecutive sets of an alarm with matching { alarm-id, entity-instance-id } + updates the fields of the single ACTIVE Alarm. + E.g. updates severity for example. " + ::= { wrsAlarmActiveEntry 3 } + + wrsAlarmActiveEntityInstanceId OBJECT-TYPE + SYNTAX WrsAlarmEntityInstanceId + MAX-ACCESS read-only + STATUS current + DESCRIPTION "This is a textual description of the resource under alarm. + + A '.' separated list of sub-entity-type=instance-value pairs, + representing the containment structure of the overall entity + instance. + + Note that this containment structure will be used for + processing hierarchical clears. + + e.g + system=ironpass1-4 + system=ironpass1-4 . host=compute-0 + system=ironpass1-4 . host=compute-0 . port=eth0 + system=ironpass1-4 . host=compute-0 . disk=/dev/sda + + system=ironpass1-4 . instance=vyatta_rtr_0 + system=ironpass1-4 . stack=vyatta_scaling_rtrs + + NOTE: the { alarm-id, entity-instance-id } uniquely identifies an ACTIVE Alarm. + e.g. + - an alarm is cleared based on the matching { alarm-id, entity-instance-id }, + - consecutive sets of an alarm with matching { alarm-id, entity-instance-id } + updates the fields of the single ACTIVE Alarm. + E.g. updates severity for example." + ::= { wrsAlarmActiveEntry 4 } + + wrsAlarmActiveDateAndTime OBJECT-TYPE + SYNTAX DateAndTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Provided in this table as a convenience. It is a copy of the Date and Time of the alarm." + ::= { wrsAlarmActiveEntry 5} + + wrsAlarmActiveAlarmSeverity OBJECT-TYPE + SYNTAX WrsAlarmSeverity + MAX-ACCESS read-only + STATUS current + DESCRIPTION "The severity of the alarm." + ::= { wrsAlarmActiveEntry 6} + + wrsAlarmActiveReasonText OBJECT-TYPE + SYNTAX WrsAlarmText + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Represents the per active alarm instance additional text field." + REFERENCE "ITU Recommendation M.3100, 'Generic Network Information Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm Reporting Function', 1992" + ::= { wrsAlarmActiveEntry 7} + + wrsAlarmActiveEventType OBJECT-TYPE + SYNTAX WrsAlarmEventType + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Represents the per active alarm instance event type values." + REFERENCE "ITU Recommendation M.3100, 'Generic Network Information Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm Reporting Function', 1992 + ITU Recommendation X.736, 'Information Technology - Open + Systems Interconnection - System Management: Security + Alarm Reporting Function', 1992" + ::= { wrsAlarmActiveEntry 8 } + + wrsAlarmActiveProbableCause OBJECT-TYPE + SYNTAX WrsAlarmProbableCause + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Per active alarm instance ITU probable cause values." + REFERENCE "ITU Recommendation M.3100, 'Generic Network Information Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm Reporting Function', 1992 + ITU Recommendation X.736, 'Information Technology - Open + Systems Interconnection - System Management: Security + Alarm Reporting Function', 1992" + ::= { wrsAlarmActiveEntry 9 } + + wrsAlarmActiveProposedRepairAction OBJECT-TYPE + SYNTAX WrsAlarmText + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Represents more of the per active alarm instance additional text field." + ::= { wrsAlarmActiveEntry 10} + + wrsAlarmActiveServiceAffecting OBJECT-TYPE + SYNTAX WrsBoolean + MAX-ACCESS read-only + STATUS current + DESCRIPTION "This attribute indicates whether the alarm is service affecting or not." + ::= { wrsAlarmActiveEntry 11 } + + wrsAlarmActiveSuppressionAllowed OBJECT-TYPE + SYNTAX WrsBoolean + MAX-ACCESS read-only + STATUS current + DESCRIPTION "This attribute indicates whether the alarm can be manually suppressed or not." + ::= { wrsAlarmActiveEntry 12 } + + + -- Wind River Event Table + + wrsEventTable OBJECT-TYPE + SYNTAX SEQUENCE OF WrsEventEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "This table contains information about events." + ::= { wrsAlarmObjects 4 } + + wrsEventEntry OBJECT-TYPE + SYNTAX WrsEventEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "An event entry" + INDEX { wrsEventIndex } + ::= { wrsEventTable 1 } + + WrsEventEntry ::= SEQUENCE { + wrsEventIndex Unsigned32, + wrsEventUuid DisplayString, + wrsEventEventId WrsAlarmId, + wrsEventState WrsAlarmState, + wrsEventEntityInstanceId WrsAlarmEntityInstanceId, + wrsEventDateAndTime DateAndTime, + wrsEventSeverity WrsAlarmSeverity, + wrsEventReasonText WrsAlarmText, + wrsEventEventType WrsAlarmEventType, + wrsEventProbableCause WrsAlarmProbableCause, + wrsEventProposedRepairAction WrsAlarmText, + wrsEventServiceAffecting WrsBoolean, + wrsEventSuppressionAllowed WrsBoolean + } + + wrsEventIndex OBJECT-TYPE + SYNTAX Unsigned32 (1..4294967295) + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION "The index of the event in the Event Table." + ::= { wrsEventEntry 1 } + + wrsEventUuid OBJECT-TYPE + SYNTAX DisplayString + MAX-ACCESS read-only + STATUS current + DESCRIPTION "An ID identifying the event instance in the Event Table." + ::= { wrsEventEntry 2 } + + wrsEventEventId OBJECT-TYPE + SYNTAX WrsAlarmId + MAX-ACCESS read-only + STATUS current + DESCRIPTION "An ID identifying the particular Event condition. + Typically used as an index for looking up Event details + in a System's Event Document. + + This will be a structured ID, in order to allow grouping of + Events into general categories and allow specific Event to + be independently added and numbered within the group. + + e.g. . + where = 000 - 999 + = 000 - 999 " + ::= { wrsEventEntry 3 } + + wrsEventState OBJECT-TYPE + SYNTAX WrsAlarmState + MAX-ACCESS read-only + STATUS current + DESCRIPTION "The state of the event. + + For Customer log events, this field is set to LOG. The attributes that are applicable for a LOG state are: + State, EventId, EntityInstanceId, DateAndTime, Severity, ReasonText, EventType, ProbableCause, ServiceAffecting + + " + ::= { wrsEventEntry 4 } + + wrsEventEntityInstanceId OBJECT-TYPE + SYNTAX WrsAlarmEntityInstanceId + MAX-ACCESS read-only + STATUS current + DESCRIPTION "This is a textual description of the resource under event. + + A '.' separated list of sub-entity-type=instance-value pairs, + representing the containment structure of the overall entity + instance. + + e.g + system=ironpass1-4 + system=ironpass1-4 . host=compute-0 + system=ironpass1-4 . host=compute-0 . port=eth0 + system=ironpass1-4 . host=compute-0 . disk=/dev/sda + + system=ironpass1-4 . instance=vyatta_rtr_0 + system=ironpass1-4 . stack=vyatta_scaling_rtrs" + ::= { wrsEventEntry 5 } + + wrsEventDateAndTime OBJECT-TYPE + SYNTAX DateAndTime + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Provided in this table as a convenience. It is the event last update Date and Time ." + ::= { wrsEventEntry 6 } + + wrsEventSeverity OBJECT-TYPE + SYNTAX WrsAlarmSeverity + MAX-ACCESS read-only + STATUS current + DESCRIPTION "The severity of the Event." + ::= { wrsEventEntry 7 } + + wrsEventReasonText OBJECT-TYPE + SYNTAX WrsAlarmText + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Represents the per Event instance additional text field." + REFERENCE "ITU Recommendation M.3100, 'Generic Network Information Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm Reporting Function', 1992" + ::= { wrsEventEntry 8 } + + wrsEventEventType OBJECT-TYPE + SYNTAX WrsAlarmEventType + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Represents the per Event instance event type values." + REFERENCE "ITU Recommendation M.3100, 'Generic Network Information Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm Reporting Function', 1992 + ITU Recommendation X.736, 'Information Technology - Open + Systems Interconnection - System Management: Security + Alarm Reporting Function', 1992" + ::= { wrsEventEntry 9 } + + wrsEventProbableCause OBJECT-TYPE + SYNTAX WrsAlarmProbableCause + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Per Event instance ITU probable cause values." + REFERENCE "ITU Recommendation M.3100, 'Generic Network Information Model', 1995 + ITU Recommendation X.733, 'Information Technology - Open + Systems Interconnection - System Management: Alarm Reporting Function', 1992 + ITU Recommendation X.736, 'Information Technology - Open + Systems Interconnection - System Management: Security + Alarm Reporting Function', 1992" + ::= { wrsEventEntry 10 } + + wrsEventProposedRepairAction OBJECT-TYPE + SYNTAX WrsAlarmText + MAX-ACCESS read-only + STATUS current + DESCRIPTION "Represents more of the per historical alarm instance additional text field. + Applies to alarms only." + ::= { wrsEventEntry 11} + + wrsEventServiceAffecting OBJECT-TYPE + SYNTAX WrsBoolean + MAX-ACCESS read-only + STATUS current + DESCRIPTION "This attribute indicates whether the Event is service affecting or not." + ::= { wrsEventEntry 12 } + + wrsEventSuppressionAllowed OBJECT-TYPE + SYNTAX WrsBoolean + MAX-ACCESS read-only + STATUS current + DESCRIPTION "This attribute indicates whether the alarm can be manually suppressed or not. + Applies to alarms only." + ::= { wrsEventEntry 13 } + + + -- All notification OIDs would be prefixed with a zero OID to facilitate snmp v1<->v2 conversion + + wrsTrapPrefix OBJECT-IDENTITY + STATUS current + DESCRIPTION "This OID represents the prefix branch for all WIND RIVER ITU Alarm Trap. + The last but one sub identifier in the OID of any Notification must have the value + zero to facilitate v2<-->v1 conversion." + ::= {wrsAlarmObjects 0 } + + +-- Generic Severity-based Traps / Alarms + + wrsAlarmCritical NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveAlarmSeverity, + wrsAlarmActiveReasonText, + wrsAlarmActiveEventType, + wrsAlarmActiveProbableCause, + wrsAlarmActiveProposedRepairAction, + wrsAlarmActiveServiceAffecting, + wrsAlarmActiveSuppressionAllowed + } + STATUS current + DESCRIPTION "This notification indicates that an alarm of 'Critical' severity + has been raised on the system. + The varbinds include details of the alarm." + ::= { wrsTrapPrefix 1 } + + + wrsAlarmMajor NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveAlarmSeverity, + wrsAlarmActiveReasonText, + wrsAlarmActiveEventType, + wrsAlarmActiveProbableCause, + wrsAlarmActiveProposedRepairAction, + wrsAlarmActiveServiceAffecting, + wrsAlarmActiveSuppressionAllowed + } + STATUS current + DESCRIPTION "This notification indicates that an alarm of 'Major' severity + has been raised on the system. + The varbinds include details of the alarm." + ::= { wrsTrapPrefix 2 } + + + wrsAlarmMinor NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveAlarmSeverity, + wrsAlarmActiveReasonText, + wrsAlarmActiveEventType, + wrsAlarmActiveProbableCause, + wrsAlarmActiveProposedRepairAction, + wrsAlarmActiveServiceAffecting, + wrsAlarmActiveSuppressionAllowed + } + STATUS current + DESCRIPTION "This notification indicates that an alarm of 'Minor' severity + has been raised on the system. + The varbinds include details of the alarm." + ::= { wrsTrapPrefix 3 } + + + wrsAlarmWarning NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveAlarmSeverity, + wrsAlarmActiveReasonText, + wrsAlarmActiveEventType, + wrsAlarmActiveProbableCause, + wrsAlarmActiveProposedRepairAction, + wrsAlarmActiveServiceAffecting, + wrsAlarmActiveSuppressionAllowed + } + STATUS current + DESCRIPTION "This notification indicates that an alarm of 'Warning' severity + has been raised on the system. + The varbinds include details of the alarm." + ::= { wrsTrapPrefix 4 } + + + wrsAlarmMessage NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveAlarmSeverity, + wrsAlarmActiveReasonText, + wrsAlarmActiveEventType, + wrsAlarmActiveProbableCause, + wrsAlarmActiveProposedRepairAction, + wrsAlarmActiveServiceAffecting, + wrsAlarmActiveSuppressionAllowed + } + STATUS current + DESCRIPTION "This notification indicates that a stateless message alarm + event has occurred on the system. + The varbinds include details of the alarm. + Note that these events are stored in the Customer Log Table." + ::= { wrsTrapPrefix 5 } + + + wrsAlarmClear NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveReasonText + } + STATUS current + DESCRIPTION "This notification indicates that a previously + reported alarm have been cleared. + The previously reported alarm is identified by the + { AlarmId, EntityInstanceId } tuple." + ::= { wrsTrapPrefix 9 } + + wrsAlarmHierarchicalClear NOTIFICATION-TYPE + OBJECTS { + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveReasonText + } + STATUS current + DESCRIPTION "This notification indicates that one or more previously + reported alarms have been cleared. + The previously reported alarms are identified by the + EntityInstanceId attribute. + ALL alarms against EntityInstanceId and all of its children + have been cleared." + ::= { wrsTrapPrefix 99 } + + + +-- Notification group definitions + + wrsAlarmNotificationsGroup NOTIFICATION-GROUP + NOTIFICATIONS { + wrsAlarmClear, + wrsAlarmHierarchicalClear, + wrsAlarmMessage, + wrsAlarmWarning, + wrsAlarmMinor, + wrsAlarmMajor, + wrsAlarmCritical + } + STATUS current + DESCRIPTION "Wind River alarm notification group." + ::= { wrsAlarmGroups 1} + + wrsAlarmGroup OBJECT-GROUP + OBJECTS { + wrsAlarmActiveUuid, + wrsAlarmActiveAlarmId, + wrsAlarmActiveEntityInstanceId, + wrsAlarmActiveDateAndTime, + wrsAlarmActiveAlarmSeverity, + wrsAlarmActiveReasonText, + wrsAlarmActiveEventType, + wrsAlarmActiveProbableCause, + wrsAlarmActiveProposedRepairAction, + wrsAlarmActiveServiceAffecting, + wrsAlarmActiveSuppressionAllowed + } + STATUS current + DESCRIPTION "Wind River alarm group." + ::= { wrsAlarmGroups 2} + + + +-- Compliance + + wrsAlarmCompliance MODULE-COMPLIANCE + STATUS current + DESCRIPTION "The compliance statement for entities which implement + the Wind River Alarm MIB." + MODULE -- this module + MANDATORY-GROUPS { wrsAlarmGroup + } + ::= { wrsAlarmCompliances 1} + + +END diff --git a/snmp-ext/mibs/wrsEnterpriseReg.mib.txt b/snmp-ext/mibs/wrsEnterpriseReg.mib.txt new file mode 100644 index 00000000..f009cac1 --- /dev/null +++ b/snmp-ext/mibs/wrsEnterpriseReg.mib.txt @@ -0,0 +1,132 @@ +------------------------------------------------------------------------------ +-- +-- File : wrsEnterpriseReg.mib +-- Description : Wind River Enterprise Registration Hierarchy MIB +-- Version : 1.2.0 +-- Date : June 2, 2017 +-- OBSOLETES : wrsMasterMib.mib v0.6 (August 29, 2000) +-- +-- Copyright (c) 2014-2017 Wind River Systems, Inc. All Rights Reserved. +-- +-- This module defines the Wind River Systems (WRS) registration hierarchy, +-- +-- The Wind River Systems registration tree is administered with the following +-- hierarchy: +-- iso(1).org(3).dod(6).internet(1).private(4).enterprise(1) +-- .wrs(731) +-- .wrs(731).wrsCommon(1) +-- .wrs(731).wrsCommon(1).wrs(1-...) ... cont'd in wrsCommon.mib +-- .wrs(731).wrs(2-...) ... cont'd in wrs.mib +-- +-- Reproduction of this document is authorized on condition that this +-- copyright notice is included. This Wind River Enterprise Registration MIB +-- embodies proprietary intellectual property of Wind River Systems (WRS). +-- WRS retains all title and ownership in the specification, including any +-- revisions. +-- +-- It is the intent of WRS to encourage the widespread use of this +-- specification in connection with the management of Wind River products. +-- WRS grants vendors, end-users, and other interested parties a +-- non-exclusive license to use this specification in connection with the +-- management of Wind River products. +-- +-- This specification is supplied "AS IS", and WRS makes no warranty, +-- either express or implied, as to the use, operations, condition, +-- or performance of this specification. +-- +------------------------------------------------------------------------------ + +WRS-ENTERPRISE-REG-MIB DEFINITIONS ::= BEGIN + +IMPORTS + TEXTUAL-CONVENTION FROM SNMPv2-TC + MODULE-IDENTITY, enterprises FROM SNMPv2-SMI; + + wrs MODULE-IDENTITY + LAST-UPDATED "201407100000Z" -- July 10, 2014 + ORGANIZATION "Wind River Systems, Inc." + CONTACT-INFO "Wind River Systems, Inc. + 500 Wind River Way + Alameda, CA 94501, USA + Contact: Wind River Systems Support + E-mail : support@windriver.com + Phone : 510.748.4100" + DESCRIPTION "This module defines the Wind River Systems, Inc. Registration hierarchy." + + -- Revision history + REVISION "201407100000Z" -- July 10, 2014 + DESCRIPTION "Initial Version of MIB." + + ::= { enterprises 731 } + +-- WRS Common Enterprise MIB Modules + wrsCommon OBJECT IDENTIFIER ::= { wrs 1 } + wrsAlarms OBJECT IDENTIFIER ::= { wrsCommon 1 } -- Common WRS Enterprise Alarm MIB + +-- WRS Products +-- tms1_0 OBJECT IDENTIFIER ::= { wrs 1 } Obsolete + tms OBJECT IDENTIFIER ::= { wrs 2 } + wrsTs OBJECT IDENTIFIER ::= { wrs 3 } -- WRS Titanium Cloud specific Enterprise MIBs + + + + + + +--------------------------------------------------------------------------- +-- TMS OID Definitions +-- + +-- TMS Major MIB Categories + idb OBJECT IDENTIFIER ::= { tms 1 } -- IDB MIBs + tmsGeneric OBJECT IDENTIFIER ::= { tms 2 } -- TMS Generic MIBs + oemSwapi OBJECT IDENTIFIER ::= { tms 3 } -- OEM swAPI MIBs + oemProd OBJECT IDENTIFIER ::= { tms 4 } -- OEM Product MIBs + +-- TMS IDB Internal Module MIBs + rmonMib OBJECT IDENTIFIER ::= { idb 1 } +-- garpMib OBJECT IDENTIFIER ::= { idb 2 } SMIv2 +-- stpMib OBJECT IDENTIFIER ::= { idb 3 } SMIv2 + +-- TMS Generic MIBs +-- tmsCommonMib OBJECT IDENTIFIER ::= { tmsGeneric 1 } SMIv2 +-- tmsL3Mib OBJECT IDENTIFIER ::= { tmsGeneric 2 } SMIv2 + +-- OEM swAPI MIBs +-- pmSwapi OBJECT IDENTIFIER ::= { oemSwapi 1 } SMIv2 +-- bcmSwapi OBJECT IDENTIFIER ::= { oemSwapi 2 } SMIv2 +-- pcSwapi OBJECT IDENTIFIER ::= { oemSwapi 3 } SMIv2 + +-- OEM Product MIBs +-- pm3575 OBJECT IDENTIFIER ::= { oemProd 1 } SMIv2 +-- bcm5600 OBJECT IDENTIFIER ::= { oemProd 2 } SMIv2 +-- pcSwitch OBJECT IDENTIFIER ::= { oemProd 3 } SMIv2 + + + +--------------------------------------------------------------------------- +-- General Textual Conventions +-- + +WrsUUID ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "Universally Unique IDentifier; + format is typically XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX , + where X is a hex-digit." + SYNTAX OCTET STRING (SIZE (0..36)) + +WrsBoolean ::= TEXTUAL-CONVENTION + STATUS current + DESCRIPTION "Boolean type." + SYNTAX INTEGER + { + false (0), + true (1) + } + + +-- +-- END of WRS-ENTERPRISE-REG-MIB +-- + +END diff --git a/snmp-ext/sources/LICENSE b/snmp-ext/sources/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/snmp-ext/sources/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/snmp-ext/sources/Makefile b/snmp-ext/sources/Makefile new file mode 100644 index 00000000..fe2a328e --- /dev/null +++ b/snmp-ext/sources/Makefile @@ -0,0 +1,25 @@ +SRCS = cgtsActiveAlarms.c cgtsAgentPlugin.c cgtsEventLogs.c + +OBJS = $(SRCS:.c=.o) +LDLIBS = -lfmcommon -lnetsnmp -lnetsnmpagent -luuid +INCLUDES += -I./ +CCFLAGS = -fPIC -g -O2 -Wall -Werror +LIBCGTSAGENT_SO := libcgtsAgentPlugin.so +build: lib + +.c.o: + $(CXX) $(CCFLAGS) $(INCLUDES) -c $< -o $@ + +lib: $(OBJS) + $(CXX) $(OBJS) $(LDLIBS) -o $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) -shared + ln -sf $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(LIBCGTSAGENT_SO).$(MAJOR) + ln -sf $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(LIBCGTSAGENT_SO) + +clean: + @rm -f $(OBJ) *.o *.so.* + +install_non_bb: + install -m 755 -d $(DEST_DIR)$(LIB_DIR) + install -m 755 $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(DEST_DIR)$(LIB_DIR) + ln -s $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(DEST_DIR)$(LIB_DIR)/$(LIBCGTSAGENT_SO).$(MAJOR) + ln -s $(LIBCGTSAGENT_SO).$(MAJOR).$(MINOR).$(PATCH) $(DEST_DIR)$(LIB_DIR)/$(LIBCGTSAGENT_SO) diff --git a/snmp-ext/sources/cgtsActiveAlarms.c b/snmp-ext/sources/cgtsActiveAlarms.c new file mode 100644 index 00000000..e1abc688 --- /dev/null +++ b/snmp-ext/sources/cgtsActiveAlarms.c @@ -0,0 +1,266 @@ +/* +* Copyright (c) 2013-2014 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cgtsAgentPlugin.h" + + +netsnmp_feature_require(date_n_time) + +#define MINLOADFREQ 1 /* min reload frequency in seconds */ + +static long Active_Alarm_Count = 0; +static struct activealarm *alarm_list; +static struct activealarm *alarmaddr, savealarm, *savealarmaddr; +static int saveIndex = 0; +static char saveUuid[36]; +static long LastLoad = 0; /* ET in secs at last table load */ +extern long long_return; + + +int Active_Alarm_Get_Count(void); + +static void +Alarm_Scan_Init() +{ + struct timeval et; /* elapsed time */ + struct activealarm **activealarm_ptr; + SFmAlarmQueryT aquery; + size_t i = 0; + + saveIndex = 0; + netsnmp_get_monotonic_clock(&et); + if ( et.tv_sec < LastLoad + MINLOADFREQ ) { + DEBUGMSG(("cgtsAgentPlugin", "Skip reload" )); + alarmaddr = alarm_list; + return; + } + LastLoad = et.tv_sec; + + /* + * free old list: + */ + while (alarm_list) { + struct activealarm *old = alarm_list; + alarm_list = alarm_list->next; + free(old); + } + alarmaddr = 0; + activealarm_ptr = &alarm_list; + + /* + * query active alarm list from DB + */ + if (fm_snmp_util_get_all_alarms(getAlarmSession(), &aquery) != true){ + DEBUGMSG(("cgtsAgentPlugin", "get_all_alarms from db failed\n")); + return; + } + DEBUGMSG(("cgtsAgentPlugin", "get_all_alarms returns %lu alarms\n", aquery.num)); + for (i = 0; i < aquery.num; ++i){ + struct activealarm *almnew; + /*populate alarm_list*/ + almnew = (struct activealarm *) calloc(1, sizeof(struct activealarm)); + if (almnew == NULL) + break; /* alloc error */ + *activealarm_ptr = almnew; + activealarm_ptr = &almnew->next; + memset(&almnew->alarmdata, 0 , sizeof(almnew->alarmdata)); + memcpy(&almnew->alarmdata, aquery.alarm + i, sizeof(almnew->alarmdata)); + } + alarmaddr = alarm_list; + free(aquery.alarm); +} + +static int +Alarm_Scan_NextAlarm(int *Index, + char *Name, + struct activealarm *Aalm) +{ + struct activealarm alm; + while (alarmaddr) { + alm = *alarmaddr; + strlcpy(saveUuid, alm.alarmdata.uuid, sizeof(saveUuid)); + if (Index) + *Index = ++saveIndex; + if (Aalm) + *Aalm = alm; + if (Name) + strcpy(Name, saveUuid); + + savealarm = alm; + savealarmaddr = alarmaddr; + alarmaddr = alm.next; + return 1; + } + return 0; +} + +static int +Alarm_Scan_By_Index(int Index, + char *Name, + struct activealarm *Aalm) +{ + int i; + + DEBUGMSGTL(("cgtsAgentPlugin","Alarm_Scan_By_Index")); + Alarm_Scan_Init(); + while (Alarm_Scan_NextAlarm(&i, Name, Aalm)) { + if (i == Index) + break; + } + if (i != Index) + return (-1); /* Error, doesn't exist */ + return (0); /* DONE */ +} + +static int +header_alarmEntry(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, + WriteMethod ** write_method) +{ +#define ALM_ENTRY_NAME_LENGTH 14 + oid newname[MAX_OID_LEN]; + register int index; + int result, count; + + DEBUGMSGTL(("cgtsAgentPlugin", "header_alarmEntry: ")); + DEBUGMSGOID(("cgtsAgentPlugin", name, *length)); + DEBUGMSG(("cgtsAgentPlugin", "exact %d\n", exact)); + + memcpy((char *) newname, (char *) vp->name, + (int) vp->namelen * sizeof(oid)); + /* + * find "next" alarm + */ + count = Active_Alarm_Get_Count(); + DEBUGMSG(("cgtsAgentPlugin", "count %d\n", count)); + for (index = 1; index <= count; index++) { + newname[ALM_ENTRY_NAME_LENGTH] = (oid) index; + result = + snmp_oid_compare(name, *length, newname, + (int) vp->namelen + 1); + if ((exact && (result == 0)) || (!exact && (result < 0))) + break; + } + if (index > count) { + DEBUGMSGTL(("cgtsAgentPlugin", "... index out of range\n")); + return MATCH_FAILED; + } + + memcpy((char *) name, (char *) newname, + ((int) vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ + + DEBUGMSGTL(("cgtsAgentPlugin", "... get ALM data ")); + DEBUGMSGOID(("cgtsAgentPlugin", name, *length)); + DEBUGMSG(("cgtsAgentPlugin", "\n")); + + DEBUGMSG(("cgtsAgentPlugin","Return index: %d\n", index)); + return index; +} + + +int +Active_Alarm_Get_Count(void) +{ + static time_t scan_time = 0; + time_t time_now = time(NULL); + + if (!Active_Alarm_Count || (time_now > scan_time + 60)) { + scan_time = time_now; + Alarm_Scan_Init(); + Active_Alarm_Count = 0; + while (Alarm_Scan_NextAlarm(NULL, NULL, NULL) != 0) { + Active_Alarm_Count++; + } + } + return (Active_Alarm_Count); +} + +u_char * +var_alarms(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, + WriteMethod ** write_method) +{ + static struct activealarm alrm; + static char Name[36]; + char *cp; + int index = 0; + + DEBUGMSGTL(("cgtsAgentPlugin", "var_alarms")); + index = header_alarmEntry(vp, name, length, exact, var_len, write_method); + if (index == MATCH_FAILED) + return NULL; + + Alarm_Scan_By_Index(index, Name, &alrm); + + switch (vp->magic) { + case ALARM_INDEX: + long_return = index; + return (u_char *) & long_return; + case ALARM_UUID: + cp = Name; + *var_len = strlen(cp); + return (u_char *) cp; + case ALARM_ID: + cp = alrm.alarmdata.alarm_id; + *var_len = strlen(cp); + return (u_char *) cp; + case ALARM_INSTANCE_ID: + cp = alrm.alarmdata.entity_instance_id; + *var_len = strlen(cp); + return (u_char *) cp; + case ALARM_TIME:{ + time_t when = alrm.alarmdata.timestamp/SECOND_PER_MICROSECOND; + cp = (char *) date_n_time(&when, var_len ); + return (u_char *) cp; + } + case ALARM_SEVERITY: + long_return = alrm.alarmdata.severity; + return (u_char *) & long_return; + case ALARM_REASONTEXT: + cp = alrm.alarmdata.reason_text; + *var_len = strlen(cp); + return (u_char *) cp; + case ALARM_EVENTTYPE: + long_return = alrm.alarmdata.alarm_type; + return (u_char *) & long_return; + case ALARM_PROBABLECAUSE: + long_return = alrm.alarmdata.probable_cause; + return (u_char *) & long_return; + case ALARM_REPAIRACTION: + cp = alrm.alarmdata.proposed_repair_action; + *var_len = strlen(cp); + return (u_char *) cp; + case ALARM_SERVICEAFFECTING: + long_return = alrm.alarmdata.service_affecting; + return (u_char *) & long_return; + case ALARM_SUPPRESSION: + long_return = alrm.alarmdata.suppression; + return (u_char *) & long_return; + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_alarms\n", + vp->magic)); + } + return NULL; +} + diff --git a/snmp-ext/sources/cgtsAgentPlugin.c b/snmp-ext/sources/cgtsAgentPlugin.c new file mode 100644 index 00000000..b19ef773 --- /dev/null +++ b/snmp-ext/sources/cgtsAgentPlugin.c @@ -0,0 +1,164 @@ +/* +* Copyright (c) 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cgtsAgentPlugin.h" + + +#define CGTS_ALM_TABLE_NAME "wrsAlarmActiveTable" +#define CGTS_EVENT_TABLE_NAME "wrsEventTable" + +#define _UNREGISTER_MIB(var, miboid) \ + do{ \ + size_t varsize = sizeof(struct variable2); \ + struct variable2 *vp; \ + oid myoid[MAX_OID_LEN]; \ + size_t length; \ + int i, result; \ + int numvars = sizeof(var)/varsize; \ + int miboidlen = sizeof(miboid)/sizeof(oid); \ + for (i=0; i < numvars; i++) { \ + vp = (struct variable2 *)((char *)var + varsize * i); \ + memcpy(myoid, miboid, miboidlen * sizeof(oid)); \ + memcpy(myoid+miboidlen, vp->name, vp->namelen * sizeof(oid)); \ + length = miboidlen + vp->namelen; \ + result = unregister_mib(myoid, length); \ + DEBUGMSGOID(("cgtsAgentPlugin", myoid, length)); \ + if (result != MIB_UNREGISTERED_OK) { \ + snmp_log(LOG_ERR, "%s: Unregistering failed:%d\n", \ + __FUNCTION__, result); \ + } else { \ + DEBUGMSGTL(("cgtsAgentPlugin", "Unregistering succeeded\n")); \ + } \ + } \ + }while(0); + + +static TFmAlarmSessionT alm_handle; + +/* + * * the OID we want to register our integer at. This should be the + * * OID node for the entire table. In our case this is the + * * wrsAlarmActiveTable oid definition + */ +oid cgtsAlarmTable_oid[] = + { 1, 3, 6, 1, 4, 1, 731, 1, 1, 1, 1, 1}; + +oid cgtsEventLogTable_oid[] = + { 1, 3, 6, 1, 4, 1, 731, 1, 1, 1, 1, 4}; + + +struct variable2 alarm_variables[] = { + {ALARM_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 1}}, + {ALARM_UUID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 2}}, + {ALARM_ID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 3}}, + {ALARM_INSTANCE_ID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 4}}, + {ALARM_TIME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 5}}, + {ALARM_SEVERITY, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 6}}, + {ALARM_REASONTEXT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 7}}, + {ALARM_EVENTTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 8}}, + {ALARM_PROBABLECAUSE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 9}}, + {ALARM_REPAIRACTION , ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 10}}, + {ALARM_SERVICEAFFECTING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 11}}, + {ALARM_SUPPRESSION, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_alarms, 2, {1, 12}}, +}; + +struct variable2 event_log_variables[] = { + {EVENT_INDEX, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 1}}, + {EVENT_UUID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 2}}, + {EVENT_EVENT_ID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 3}}, + {EVENT_STATE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 4}}, + {EVENT_INSTANCE_ID, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 5}}, + {EVENT_TIME, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 6}}, + {EVENT_SEVERITY, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 7}}, + {EVENT_REASONTEXT, ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 8}}, + {EVENT_EVENTTYPE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 9}}, + {EVENT_PROBABLECAUSE, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 10}}, + {EVENT_REPAIRACTION , ASN_OCTET_STR, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 11}}, + {EVENT_SERVICEAFFECTING, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 12}}, + {EVENT_SUPPRESSION, ASN_INTEGER, NETSNMP_OLDAPI_RONLY, + var_events, 2, {1, 13}}, +}; + + +TFmAlarmSessionT getAlarmSession() +{ + return alm_handle; +} + +/* + * our initialization routine, automatically called by the agent + * (to get called, the function name must match init_FILENAME()) + */ +void +init_cgtsAgentPlugin(void) +{ + snmp_log(LOG_INFO,"init_cgtsAgentPlugin start"); + snmp_log(LOG_INFO,"MIB registration: %s",CGTS_ALM_TABLE_NAME); + REGISTER_MIB(CGTS_ALM_TABLE_NAME, alarm_variables, + variable2, cgtsAlarmTable_oid); + + snmp_log(LOG_INFO,"MIB registration: %s",CGTS_EVENT_TABLE_NAME); + REGISTER_MIB(CGTS_EVENT_TABLE_NAME, event_log_variables, + variable2, cgtsEventLogTable_oid); + + snmp_log(LOG_INFO,"get alarm database handler"); + if (fm_snmp_util_create_session(&alm_handle, NULL) != true){ + snmp_log(LOG_ERR,"failed to get alarm database handler"); + exit(-1); + } + /* + * a debugging statement. Run the agent with -DcgtsAgentPlugin to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("cgtsAgentPlugin", "Done initializing.\n")); +} + +void +deinit_cgtsAgentPlugin(void) +{ + snmp_log(LOG_INFO,"deinit_cgtsAgentPlugin start"); + _UNREGISTER_MIB(alarm_variables, cgtsAlarmTable_oid); + _UNREGISTER_MIB(event_log_variables, cgtsEventLogTable_oid); + fm_snmp_util_destroy_session(alm_handle); +} + + + diff --git a/snmp-ext/sources/cgtsAgentPlugin.h b/snmp-ext/sources/cgtsAgentPlugin.h new file mode 100644 index 00000000..df82e1fd --- /dev/null +++ b/snmp-ext/sources/cgtsAgentPlugin.h @@ -0,0 +1,69 @@ +/* +* Copyright (c) 2013-2014 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* +*/ + +#ifndef CGTSAGENTPLUGIN_H +#define CGTSAGENTPLUGIN_H + +#include +#include +#include + +extern FindVarMethod var_alarms; + +extern FindVarMethod var_events; + +/* Active alarm Table */ +#define ALARM_INDEX 1 +#define ALARM_UUID 2 +#define ALARM_ID 3 +#define ALARM_INSTANCE_ID 4 +#define ALARM_TIME 5 +#define ALARM_SEVERITY 6 +#define ALARM_REASONTEXT 7 +#define ALARM_EVENTTYPE 8 +#define ALARM_PROBABLECAUSE 9 +#define ALARM_REPAIRACTION 10 +#define ALARM_SERVICEAFFECTING 11 +#define ALARM_SUPPRESSION 12 + +/* Event Log Table */ +#define EVENT_INDEX 1 +#define EVENT_UUID 2 +#define EVENT_EVENT_ID 3 +#define EVENT_STATE 4 +#define EVENT_INSTANCE_ID 5 +#define EVENT_TIME 6 +#define EVENT_SEVERITY 7 +#define EVENT_REASONTEXT 8 +#define EVENT_EVENTTYPE 9 +#define EVENT_PROBABLECAUSE 10 +#define EVENT_REPAIRACTION 11 +#define EVENT_SERVICEAFFECTING 12 +#define EVENT_SUPPRESSION 13 + + +#define SECOND_PER_MICROSECOND 1000000 + +struct activealarm { + SFmAlarmDataT alarmdata; + struct activealarm *next; +}; + +/* + * function declarations + */ +#ifdef __cplusplus +extern "C" { +#endif +void init_cgtsAgentPlugin(void); +void deinit_cgtsAgentPlugin(void); +TFmAlarmSessionT getAlarmSession(); +#ifdef __cplusplus +} +#endif + +#endif /* CGTSAGENTPLUGIN_H */ diff --git a/snmp-ext/sources/cgtsEventLogs.c b/snmp-ext/sources/cgtsEventLogs.c new file mode 100644 index 00000000..848261fa --- /dev/null +++ b/snmp-ext/sources/cgtsEventLogs.c @@ -0,0 +1,268 @@ +/* +* Copyright (c) 2013-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "cgtsAgentPlugin.h" + + +netsnmp_feature_require(date_n_time) + +#define MINLOADFREQ 2 /* min reload frequency in seconds */ + +static long Event_Log_Count = 0; +static struct activealarm *alarm_list; +static struct activealarm *alarmaddr, savealarm, *savealarmaddr; +static int saveIndex = 0; +static char saveUuid[36]; +static long LastLoad = 0; /* ET in secs at last table load */ +extern long long_return; + + +int Event_Log_Get_Count(void); + +static void +Event_Log_Scan_Init() +{ + struct timeval et; /* elapsed time */ + struct activealarm **activealarm_ptr; + SFmAlarmQueryT aquery; + size_t i = 0; + + saveIndex = 0; + netsnmp_get_monotonic_clock(&et); + if ( et.tv_sec < LastLoad + MINLOADFREQ ) { + DEBUGMSG(("cgtsAgentPlugin", "Skip reload" )); + alarmaddr = alarm_list; + return; + } + LastLoad = et.tv_sec; + + /* + * free old list: + */ + while (alarm_list) { + struct activealarm *old = alarm_list; + alarm_list = alarm_list->next; + free(old); + } + alarmaddr = 0; + activealarm_ptr = &alarm_list; + + /* + * query event log list from DB + */ + if (fm_snmp_util_get_all_event_logs(getAlarmSession(), &aquery) != true){ + DEBUGMSG(("cgtsAgentPlugin", "get_all_event_logs from db failed\n")); + return; + } + DEBUGMSG(("cgtsAgentPlugin", "get_all_event_logs returns %lu logs\n", aquery.num)); + for (i = 0; i < aquery.num; ++i){ + struct activealarm *almnew; + /*populate alarm_list*/ + almnew = (struct activealarm *) calloc(1, sizeof(struct activealarm)); + if (almnew == NULL) + break; /* alloc error */ + *activealarm_ptr = almnew; + activealarm_ptr = &almnew->next; + memset(&almnew->alarmdata, 0 , sizeof(almnew->alarmdata)); + memcpy(&almnew->alarmdata, aquery.alarm + i, sizeof(almnew->alarmdata)); + } + alarmaddr = alarm_list; + free(aquery.alarm); +} + +static int +Event_Log_Scan_NextLog(int *Index, + char *Name, + struct activealarm *Aalm) +{ + struct activealarm alm; + while (alarmaddr) { + alm = *alarmaddr; + strlcpy(saveUuid, alm.alarmdata.uuid, sizeof(saveUuid)); + if (Index) + *Index = ++saveIndex; + if (Aalm) + *Aalm = alm; + if (Name) + strcpy(Name, saveUuid); + + savealarm = alm; + savealarmaddr = alarmaddr; + alarmaddr = alm.next; + return 1; + } + return 0; +} + +static int +Event_Log_Scan_By_Index(int Index, + char *Name, + struct activealarm *Aalm) +{ + int i; + + DEBUGMSGTL(("cgtsAgentPlugin","Event_Log_Scan_By_Index")); + Event_Log_Scan_Init(); + while (Event_Log_Scan_NextLog(&i, Name, Aalm)) { + if (i == Index) + break; + } + if (i != Index) + return (-1); /* Error, doesn't exist */ + return (0); /* DONE */ +} + +static int +header_eventLogEntry(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, + WriteMethod ** write_method) +{ +#define ALM_ENTRY_NAME_LENGTH 14 + oid newname[MAX_OID_LEN]; + register int index; + int result, count; + + DEBUGMSGTL(("cgtsAgentPlugin", "header_eventLogEntry: ")); + DEBUGMSGOID(("cgtsAgentPlugin", name, *length)); + DEBUGMSG(("cgtsAgentPlugin", "exact %d\n", exact)); + + memcpy((char *) newname, (char *) vp->name, + (int) vp->namelen * sizeof(oid)); + /* + * find "next" log + */ + count = Event_Log_Get_Count(); + DEBUGMSG(("cgtsAgentPlugin", "count %d\n", count)); + for (index = 1; index <= count; index++) { + newname[ALM_ENTRY_NAME_LENGTH] = (oid) index; + result = + snmp_oid_compare(name, *length, newname, + (int) vp->namelen + 1); + if ((exact && (result == 0)) || (!exact && (result < 0))) + break; + } + if (index > count) { + DEBUGMSGTL(("cgtsAgentPlugin", "... index out of range\n")); + return MATCH_FAILED; + } + + memcpy((char *) name, (char *) newname, + ((int) vp->namelen + 1) * sizeof(oid)); + *length = vp->namelen + 1; + *write_method = 0; + *var_len = sizeof(long); /* default to 'long' results */ + + DEBUGMSGTL(("cgtsAgentPlugin", "... get ALM data ")); + DEBUGMSGOID(("cgtsAgentPlugin", name, *length)); + DEBUGMSG(("cgtsAgentPlugin", "\n")); + + DEBUGMSG(("cgtsAgentPlugin","Return index: %d\n", index)); + return index; +} + +int +Event_Log_Get_Count(void) +{ + static time_t scan_time = 0; + time_t time_now = time(NULL); + + if (!Event_Log_Count || (time_now > scan_time + 60)) { + scan_time = time_now; + Event_Log_Scan_Init(); + Event_Log_Count = 0; + while (Event_Log_Scan_NextLog(NULL, NULL, NULL) != 0) { + Event_Log_Count++; + } + } + return (Event_Log_Count); +} + +u_char * +var_events(struct variable *vp, + oid * name, + size_t * length, + int exact, size_t * var_len, + WriteMethod ** write_method) +{ + static struct activealarm alrm; + static char Name[36]; + char *cp; + int index = 0; + + DEBUGMSGTL(("cgtsAgentPlugin", "var_events")); + index = header_eventLogEntry(vp, name, length, exact, var_len, write_method); + if (index == MATCH_FAILED) + return NULL; + + Event_Log_Scan_By_Index(index, Name, &alrm); + + switch (vp->magic) { + case EVENT_INDEX: + long_return = index; + return (u_char *) & long_return; + case EVENT_UUID: + cp = Name; + *var_len = strlen(cp); + return (u_char *) cp; + case EVENT_EVENT_ID: + cp = alrm.alarmdata.alarm_id; + *var_len = strlen(cp); + return (u_char *) cp; + case EVENT_STATE: + long_return = alrm.alarmdata.alarm_state; + return (u_char *) & long_return; + case EVENT_INSTANCE_ID: + cp = alrm.alarmdata.entity_instance_id; + *var_len = strlen(cp); + return (u_char *) cp; + case EVENT_TIME:{ + time_t when = alrm.alarmdata.timestamp/SECOND_PER_MICROSECOND; + cp = (char *) date_n_time(&when, var_len ); + return (u_char *) cp; + } + case EVENT_SEVERITY: + long_return = alrm.alarmdata.severity; + return (u_char *) & long_return; + case EVENT_REASONTEXT: + cp = alrm.alarmdata.reason_text; + *var_len = strlen(cp); + return (u_char *) cp; + case EVENT_EVENTTYPE: + long_return = alrm.alarmdata.alarm_type; + return (u_char *) & long_return; + case EVENT_PROBABLECAUSE: + long_return = alrm.alarmdata.probable_cause; + return (u_char *) & long_return; + case EVENT_REPAIRACTION: + cp = alrm.alarmdata.proposed_repair_action; + *var_len = strlen(cp); + return (u_char *) cp; + case EVENT_SERVICEAFFECTING: + long_return = alrm.alarmdata.service_affecting; + return (u_char *) & long_return; + case EVENT_SUPPRESSION: + long_return = alrm.alarmdata.suppression; + return (u_char *) & long_return; + default: + DEBUGMSGTL(("snmpd", "unknown sub-id %d in var_events\n", + vp->magic)); + } + return NULL; +} +