diff --git a/doc/LICENSE b/doc/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..87316c7a9ac51a931b7abf65868f9af703fc1c33 --- /dev/null +++ b/doc/LICENSE @@ -0,0 +1,427 @@ +Attribution-ShareAlike 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-ShareAlike 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-ShareAlike 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. BY-SA Compatible License means a license listed at + creativecommons.org/compatiblelicenses, approved by Creative + Commons as essentially the equivalent of this Public License. + + d. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + e. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + f. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + g. License Elements means the license attributes listed in the name + of a Creative Commons Public License. The License Elements of this + Public License are Attribution and ShareAlike. + + h. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + i. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + j. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + k. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + l. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + m. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. Additional offer from the Licensor -- Adapted Material. + Every recipient of Adapted Material from You + automatically receives an offer from the Licensor to + exercise the Licensed Rights in the Adapted Material + under the conditions of the Adapter's License You apply. + + c. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + b. ShareAlike. + + In addition to the conditions in Section 3(a), if You Share + Adapted Material You produce, the following conditions also apply. + + 1. The Adapter's License You apply must be a Creative Commons + license with the same License Elements, this version or + later, or a BY-SA Compatible License. + + 2. You must include the text of, or the URI or hyperlink to, the + Adapter's License You apply. You may satisfy this condition + in any reasonable manner based on the medium, means, and + context in which You Share Adapted Material. + + 3. You may not offer or impose any additional or different terms + or conditions on, or apply any Effective Technological + Measures to, Adapted Material that restrict exercise of the + rights granted under the Adapter's License You apply. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material, + + including for purposes of Section 3(b); and + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git a/doc/UserGuide b/doc/UserGuide new file mode 100644 index 0000000000000000000000000000000000000000..877f05152f4fa05fae63ec31370f5149f22d90dc --- /dev/null +++ b/doc/UserGuide @@ -0,0 +1,33 @@ +# sysSentry 介绍 +sysSentry是一款故障巡检框架,为用户提供在后台进行故障巡检的能力;sysSentry通过提前发现系统中的软硬件故障并及时通知系统运维人员处理的方式,达到减少故障演变为现网事故、提升系统可靠性的目标。 + +## 一、安装sysSentry +```bash +yum install -y sysSentry xalarm libxalarm +``` + +## 二、快速使用指南 + +1、启动巡检框架 +```bash +systemctl start sysSentry +systemctl start xalarmd + +### 执行成功后可通过status命令查看状态为running +systemctl status sysSentry +systemctl status xalarmd +``` + +2、使用sentryctl命令管理框架 +```bash +### 启动指定巡检任务 +sentryctl start +### 终止指定巡检任务 +sentryctl stop +### 列出所有已加载的巡检任务及当前状态 +sentryctl list +### 查询指定巡检任务状态 +sentryctl status +### 重载指定任务配置 +sentryctl reload +``` \ No newline at end of file diff --git a/sysSentry-1.0.2/License/LICENSE b/sysSentry-1.0.2/License/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9e32cdef1625daed25cf365c865f01050877cff3 --- /dev/null +++ b/sysSentry-1.0.2/License/LICENSE @@ -0,0 +1,127 @@ + 木兰宽松许可证, 第2版 + + 木兰宽松许可证, 第2版 + 2020年1月 http://license.coscl.org.cn/MulanPSL2 + + + 您对“软件”的复制、使用、修改及分发受木兰宽松许可证,第2版(“本许可证”)的如下条款的约束: + + 0. 定义 + + “软件”是指由“贡献”构成的许可在“本许可证”下的程序和相关文档的集合。 + + “贡献”是指由任一“贡献者”许可在“本许可证”下的受版权法保护的作品。 + + “贡献者”是指将受版权法保护的作品许可在“本许可证”下的自然人或“法人实体”。 + + “法人实体”是指提交贡献的机构及其“关联实体”。 + + “关联实体”是指,对“本许可证”下的行为方而言,控制、受控制或与其共同受控制的机构,此处的控制是指有受控方或共同受控方至少50%直接或间接的投票权、资金或其他有价证券。 + + 1. 授予版权许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的版权许可,您可以复制、使用、修改、分发其“贡献”,不论修改与否。 + + 2. 授予专利许可 + + 每个“贡献者”根据“本许可证”授予您永久性的、全球性的、免费的、非独占的、不可撤销的(根据本条规定撤销除外)专利许可,供您制造、委托制造、使用、许诺销售、销售、进口其“贡献”或以其他方式转移其“贡献”。前述专利许可仅限于“贡献者”现在或将来拥有或控制的其“贡献”本身或其“贡献”与许可“贡献”时的“软件”结合而将必然会侵犯的专利权利要求,不包括对“贡献”的修改或包含“贡献”的其他结合。如果您或您的“关联实体”直接或间接地,就“软件”或其中的“贡献”对任何人发起专利侵权诉讼(包括反诉或交叉诉讼)或其他专利维权行动,指控其侵犯专利权,则“本许可证”授予您对“软件”的专利许可自您提起诉讼或发起维权行动之日终止。 + + 3. 无商标许可 + + “本许可证”不提供对“贡献者”的商品名称、商标、服务标志或产品名称的商标许可,但您为满足第4条规定的声明义务而必须使用除外。 + + 4. 分发限制 + + 您可以在任何媒介中将“软件”以源程序形式或可执行形式重新分发,不论修改与否,但您必须向接收者提供“本许可证”的副本,并保留“软件”中的版权、商标、专利及免责声明。 + + 5. 免责声明与责任限制 + + “软件”及其中的“贡献”在提供时不带任何明示或默示的担保。在任何情况下,“贡献者”或版权所有者不对任何人因使用“软件”或其中的“贡献”而引发的任何直接或间接损失承担责任,不论因何种原因导致或者基于何种法律理论,即使其曾被建议有此种损失的可能性。 + + 6. 语言 + “本许可证”以中英文双语表述,中英文版本具有同等法律效力。如果中英文版本存在任何冲突不一致,以中文版为准。 + + 条款结束 + + 如何将木兰宽松许可证,第2版,应用到您的软件 + + 如果您希望将木兰宽松许可证,第2版,应用到您的新软件,为了方便接收者查阅,建议您完成如下三步: + + 1, 请您补充如下声明中的空白,包括软件名、软件的首次发表年份以及您作为版权人的名字; + + 2, 请您在软件包的一级目录下创建以“LICENSE”为名的文件,将整个许可证文本放入该文件中; + + 3, 请将如下声明文本放入每个源文件的头部注释中。 + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. + + + Mulan Permissive Software License,Version 2 + + Mulan Permissive Software License,Version 2 (Mulan PSL v2) + January 2020 http://license.coscl.org.cn/MulanPSL2 + + Your reproduction, use, modification and distribution of the Software shall be subject to Mulan PSL v2 (this License) with the following terms and conditions: + + 0. Definition + + Software means the program and related documents which are licensed under this License and comprise all Contribution(s). + + Contribution means the copyrightable work licensed by a particular Contributor under this License. + + Contributor means the Individual or Legal Entity who licenses its copyrightable work under this License. + + Legal Entity means the entity making a Contribution and all its Affiliates. + + Affiliates means entities that control, are controlled by, or are under common control with the acting entity under this License, ‘control’ means direct or indirect ownership of at least fifty percent (50%) of the voting power, capital or other securities of controlled or commonly controlled entity. + + 1. Grant of Copyright License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable copyright license to reproduce, use, modify, or distribute its Contribution, with modification or not. + + 2. Grant of Patent License + + Subject to the terms and conditions of this License, each Contributor hereby grants to you a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (except for revocation under this Section) patent license to make, have made, use, offer for sale, sell, import or otherwise transfer its Contribution, where such patent license is only limited to the patent claims owned or controlled by such Contributor now or in future which will be necessarily infringed by its Contribution alone, or by combination of the Contribution with the Software to which the Contribution was contributed. The patent license shall not apply to any modification of the Contribution, and any other combination which includes the Contribution. If you or your Affiliates directly or indirectly institute patent litigation (including a cross claim or counterclaim in a litigation) or other patent enforcement activities against any individual or entity by alleging that the Software or any Contribution in it infringes patents, then any patent license granted to you under this License for the Software shall terminate as of the date such litigation or activity is filed or taken. + + 3. No Trademark License + + No trademark license is granted to use the trade names, trademarks, service marks, or product names of Contributor, except as required to fulfill notice requirements in Section 4. + + 4. Distribution Restriction + + You may distribute the Software in any medium with or without modification, whether in source or executable forms, provided that you provide recipients with a copy of this License and retain copyright, patent, trademark and disclaimer statements in the Software. + + 5. Disclaimer of Warranty and Limitation of Liability + + THE SOFTWARE AND CONTRIBUTION IN IT ARE PROVIDED WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED. IN NO EVENT SHALL ANY CONTRIBUTOR OR COPYRIGHT HOLDER BE LIABLE TO YOU FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO ANY DIRECT, OR INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM YOUR USE OR INABILITY TO USE THE SOFTWARE OR THE CONTRIBUTION IN IT, NO MATTER HOW IT’S CAUSED OR BASED ON WHICH LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + + 6. Language + + THIS LICENSE IS WRITTEN IN BOTH CHINESE AND ENGLISH, AND THE CHINESE VERSION AND ENGLISH VERSION SHALL HAVE THE SAME LEGAL EFFECT. IN THE CASE OF DIVERGENCE BETWEEN THE CHINESE AND ENGLISH VERSIONS, THE CHINESE VERSION SHALL PREVAIL. + + END OF THE TERMS AND CONDITIONS + + How to Apply the Mulan Permissive Software License,Version 2 (Mulan PSL v2) to Your Software + + To apply the Mulan PSL v2 to your work, for easy identification by recipients, you are suggested to complete following three steps: + + i Fill in the blanks in following statement, including insert your software name, the year of the first publication of your software, and your name identified as the copyright owner; + + ii Create a file named “LICENSE” which contains the whole context of this License in the first directory of your software package; + + iii Attach the statement to the appropriate annotated syntax at the beginning of each source file. + + + Copyright (c) [Year] [name of copyright holder] + [Software Name] is licensed under Mulan PSL v2. + You can use this software according to the terms and conditions of the Mulan PSL v2. + You may obtain a copy of Mulan PSL v2 at: + http://license.coscl.org.cn/MulanPSL2 + THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + See the Mulan PSL v2 for more details. diff --git a/sysSentry-1.0.2/README b/sysSentry-1.0.2/README new file mode 100644 index 0000000000000000000000000000000000000000..877f05152f4fa05fae63ec31370f5149f22d90dc --- /dev/null +++ b/sysSentry-1.0.2/README @@ -0,0 +1,33 @@ +# sysSentry 介绍 +sysSentry是一款故障巡检框架,为用户提供在后台进行故障巡检的能力;sysSentry通过提前发现系统中的软硬件故障并及时通知系统运维人员处理的方式,达到减少故障演变为现网事故、提升系统可靠性的目标。 + +## 一、安装sysSentry +```bash +yum install -y sysSentry xalarm libxalarm +``` + +## 二、快速使用指南 + +1、启动巡检框架 +```bash +systemctl start sysSentry +systemctl start xalarmd + +### 执行成功后可通过status命令查看状态为running +systemctl status sysSentry +systemctl status xalarmd +``` + +2、使用sentryctl命令管理框架 +```bash +### 启动指定巡检任务 +sentryctl start +### 终止指定巡检任务 +sentryctl stop +### 列出所有已加载的巡检任务及当前状态 +sentryctl list +### 查询指定巡检任务状态 +sentryctl status +### 重载指定任务配置 +sentryctl reload +``` \ No newline at end of file diff --git a/sysSentry-1.0.2/RELEASE-NOTES.md b/sysSentry-1.0.2/RELEASE-NOTES.md new file mode 100644 index 0000000000000000000000000000000000000000..6aa5f4a49cd99240738bf053ae0f63a5096da126 --- /dev/null +++ b/sysSentry-1.0.2/RELEASE-NOTES.md @@ -0,0 +1,3 @@ +## 1.0.0 + +1. Initial version diff --git a/sysSentry-1.0.2/build/build.sh b/sysSentry-1.0.2/build/build.sh new file mode 100644 index 0000000000000000000000000000000000000000..17af8a0dd91a711e2610a0b7889383236d708121 --- /dev/null +++ b/sysSentry-1.0.2/build/build.sh @@ -0,0 +1,70 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +PRJ_DIR=$(dirname $(readlink -f "$0")) +SRC_DIR=${PRJ_DIR}/../src/libso + +function print_help() +{ + echo "Usage: $0 OPERATOR OPTIONS" + echo "OPERATOR: " + echo " -i build and install" + echo " -b build" + echo " -c clean" + +} + +function clean() +{ + cd ${SRC_DIR} + rm -rf ./build +} + +function build() +{ + echo "start compile" + cd ${SRC_DIR} + cmake . -DXD_INSTALL_BINDIR=$1 -B build + cd build + make +} + +function install() +{ + cd ${SRC_DIR} + cmake . -DXD_INSTALL_BINDIR=$1 -B build + cd build + make install +} + +[ "$1" == "-c" ] && { + clean + exit 0 +} + +[ "$1" == "-b" ] && { + INTALL_DIR=$2 + [ -z $2 ] && { + INTALL_DIR=/usr/lib64 + mkdir -p ${INTALL_DIR} + } + + build ${INTALL_DIR} + exit 0 +} + +[ "$1" == "-i" ] && { + INTALL_DIR=$2 + [ -z $2 ] && { + INTALL_DIR=/usr/lib64 + mkdir -p ${INTALL_DIR} + } + install ${INTALL_DIR} + exit 0 +} + +if [ -z $1 ] || [ $1 == "-h" ] + then + print_help + exit 0 +fi diff --git a/sysSentry-1.0.2/config/inspect.conf b/sysSentry-1.0.2/config/inspect.conf new file mode 100644 index 0000000000000000000000000000000000000000..071cca1169a15c7ff6cc807e6a1013d684520ad8 --- /dev/null +++ b/sysSentry-1.0.2/config/inspect.conf @@ -0,0 +1,2 @@ +[inspect] +Interval=3 \ No newline at end of file diff --git a/sysSentry-1.0.2/config/logrotate b/sysSentry-1.0.2/config/logrotate new file mode 100644 index 0000000000000000000000000000000000000000..f54e7b3c44c50602a659d6b6107bcc3cb2fd4a8e --- /dev/null +++ b/sysSentry-1.0.2/config/logrotate @@ -0,0 +1,8 @@ +/var/log/sysSentry/*.log { + nocompress + missingok + notifempty + copytruncate + rotate 2 + size +4096k +} diff --git a/sysSentry-1.0.2/config/xalarm.conf b/sysSentry-1.0.2/config/xalarm.conf new file mode 100644 index 0000000000000000000000000000000000000000..14c6d3902afbb2623f0fde8639a5f8ff7e8d5792 --- /dev/null +++ b/sysSentry-1.0.2/config/xalarm.conf @@ -0,0 +1,2 @@ +[filter] +id_mask = 1001-1128 diff --git a/sysSentry-1.0.2/selftest/libs/expect.sh b/sysSentry-1.0.2/selftest/libs/expect.sh new file mode 100644 index 0000000000000000000000000000000000000000..9fc097dfbcac63d5c31fbfc98e004621d4640eac --- /dev/null +++ b/sysSentry-1.0.2/selftest/libs/expect.sh @@ -0,0 +1,94 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/log.sh" + +ets_expects_failed=0 +unexp_cmd="((++ets_expects_failed))" + +function get_file_line() { + echo "$(basename "${BASH_SOURCE[2]}")": ${BASH_LINENO[1]} +} + +function get_expects_failed_num() { + echo "${ets_expects_failed}" +} + +function clean_expects_failed_num() { + ets_expects_failed=0 +} + +function add_failure() { + local msg=${1:-} + + ((++ets_expects_failed)) + log_error "add_failure(msg=${msg}) - $(get_file_line)" + return 1 +} + +function expect_eq() { + local actual=${1:-1} + local expect=${2:-0} + local msg=${3:-} + if [ "${actual}" -eq "${expect}" ]; then + return 0 + else + ((++ets_expects_failed)) + echo "expect_eq(${actual}, ${expect}, msg=${msg}) - $(get_file_line)" + return 1 + fi +} + +function expect_ne() { + local actual=${1:-1} + local expect=${2:-1} + local msg=${3:-} + + if [ "${actual}" -ne "${expect}" ]; then + return 0 + else + ((++ets_expects_failed)) + log_error "expect_ne(${actual}, ${expect}, msg=${msg}) - $(get_file_line)" + return 1 + fi +} + +function expect_gt() { + local actual=${1:-0} + local expect=${2:-1} + local msg=${3:-} + + if [ "${actual}" -gt "${expect}" ]; then + return 0 + else + ((++ets_expects_failed)) + log_error "expect_gt(${actual}, ${expect}, msg=${msg}) - $(get_file_line)" + return 1 + fi +} + +function expect_true() { + local cmd=$1 + local msg=$2 + + if eval "${cmd}" &> /dev/null; then + return 0 + else + ((++ets_expects_failed)) + log_error "expect_true(${cmd}, msg=${msg}) - $(get_file_line)" + return 1 + fi +} + +function expect_false() { + local cmd=$1 + local msg=$2 + + if eval "${cmd}" &> /dev/null; then + ((++ets_expects_failed)) + log_error "expect_false(${cmd}, msg=${msg}) - $(get_file_line)" + return 1 + else + return 0 + fi +} \ No newline at end of file diff --git a/sysSentry-1.0.2/selftest/libs/lib.sh b/sysSentry-1.0.2/selftest/libs/lib.sh new file mode 100644 index 0000000000000000000000000000000000000000..edf7e8143e38484fc75acaf91c121d6786078b49 --- /dev/null +++ b/sysSentry-1.0.2/selftest/libs/lib.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +OLD_PATH=$(pwd) + +function run_testcase() { + local testcasename=$1 + trap post_test EXIT INT TERM + pre_test + do_test + + if [ "$(get_expects_failed_num)" != "0" ]; then + echo "$testcasename check failed!!" + exit 1 + else + echo "$testcasename check successful!!" + exit 0 + fi +} + diff --git a/sysSentry-1.0.2/selftest/libs/log.sh b/sysSentry-1.0.2/selftest/libs/log.sh new file mode 100644 index 0000000000000000000000000000000000000000..9a5c55137f1f467edf5b0d6e6ad4824e347a8574 --- /dev/null +++ b/sysSentry-1.0.2/selftest/libs/log.sh @@ -0,0 +1,20 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +# 新命名风格断言 +function log_info() { + echo "[$(date +"%F %T")] [ INFO ] $*" +} + +function log_warn() { + echo -e "\033[33m[$(date +"%F %T")] [WARNING] $* \033[0m" +} + +function log_error() { + echo -e "\033[31m[$(date +"%F %T")] [ ERROR ] $* \033[0m" +} + +function log_debug() { + [ "$command_debug" == "yes" ] && echo "[$(date +"%F %T")] [ DEBUG ] $*" + echo -n "" +} \ No newline at end of file diff --git a/sysSentry-1.0.2/selftest/libs/shopt.sh b/sysSentry-1.0.2/selftest/libs/shopt.sh new file mode 100644 index 0000000000000000000000000000000000000000..806439819b139d6e17255dff5478759b7890ad4f --- /dev/null +++ b/sysSentry-1.0.2/selftest/libs/shopt.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + + +ets_shopt="" + +function shopt_set() { + local new_opt=$1 + + if [ -z "$ets_shopt" ]; then + ets_shopt="$-" + fi + + set "$new_opt" +} + +function shopt_recover() { + set +$- + set -${ets_shopt} + unset ets_shopt +} diff --git a/sysSentry-1.0.2/selftest/libs/wait.sh b/sysSentry-1.0.2/selftest/libs/wait.sh new file mode 100644 index 0000000000000000000000000000000000000000..33dd643eb01602ddd26947d48821941b3a3394e0 --- /dev/null +++ b/sysSentry-1.0.2/selftest/libs/wait.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +function wait_cmd_condition() { + local cmd=$1 + local condition=$2 + local expect=$3 + local interval=$4 + local count=$5 + local debug=${6:-0} + local i=0 + local ret=0 + + shopt_set +e + for ((i = 0; i < $count; i++)); do + if [ "$debug" -eq 0 ]; then + eval "$cmd" &> /dev/null + else + eval "$cmd" + fi + ret=$? + + local tmp_condition="[ $ret $condition $expect ]" + if eval "$tmp_condition"; then + return 0 + else + sleep "$interval" + ret=1 + fi + done + shopt_recover + return $ret +} + +function wait_cmd_ok() { + local cmd=$1 + local interval=$2 + local count=$3 + local debug=${4:-0} + + wait_cmd_condition "$cmd" "=" "0" "$interval" "$count" "$debug" + return $? +} + +function wait_cmd_nok() { + local cmd=$1 + local interval=$2 + local count=$3 + local debug=${4:-0} + + wait_cmd_condition "$cmd" "!=" "0" "$interval" "$count" "$debug" + return $? +} \ No newline at end of file diff --git a/sysSentry-1.0.2/selftest/mod/test_config.mod b/sysSentry-1.0.2/selftest/mod/test_config.mod new file mode 100644 index 0000000000000000000000000000000000000000..bdef47560b3405c00b75ae9cd2fc1c0b3fac4f1e --- /dev/null +++ b/sysSentry-1.0.2/selftest/mod/test_config.mod @@ -0,0 +1,7 @@ +[common] +enabled=yes +task_start=test_task +task_stop=pkill test_task +type=oneshot +interval=60 +heartbeat_interval=3600 \ No newline at end of file diff --git a/sysSentry-1.0.2/selftest/mod/test_task.c b/sysSentry-1.0.2/selftest/mod/test_task.c new file mode 100644 index 0000000000000000000000000000000000000000..9549f1915cfe7fe6b25ced6c9e478c7d814520b2 --- /dev/null +++ b/sysSentry-1.0.2/selftest/mod/test_task.c @@ -0,0 +1,21 @@ + +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: test program + * Author: zhuo feng + * Create: 2023-11-11 + */ + +#include +#include + +#define SLEEP_TIME 10 + +int main(void) +{ + printf("-----test begin-----\n"); + sleep(SLEEP_TIME); + printf("-----test end -----\n"); + + return 0; +} \ No newline at end of file diff --git a/sysSentry-1.0.2/selftest/test.sh b/sysSentry-1.0.2/selftest/test.sh new file mode 100644 index 0000000000000000000000000000000000000000..9e69e0163924fdcfe6a5dd2a92aede71cfec5f3c --- /dev/null +++ b/sysSentry-1.0.2/selftest/test.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source ./libs/expect.sh +export SYS_PATH=$(pwd) +tmp_log="result.log" +testcase_success=0 +testcase_fail=0 + +success_cases=() +fail_cases=() + +for file in $(find test/ -name test_\*\.sh) +do + echo "=== run test $file start ===" + sh $file > ${tmp_log} 2>&1 + + if [ $? -eq 0 ]; then + ((++testcase_success)) + success_cases+=("$file") + else + ((++testcase_fail)) + fail_cases+=("$file") + echo "test $file failed!" + cat ${tmp_log} + fi + echo "=== run test $file end ===" +done + +echo "----------Success cases:----------" +for file_name in "${success_cases[@]}"; do + echo "$file_name" +done + +echo "----------Fail cases:----------" +for file_name in "${fail_cases[@]}"; do + echo "$file_name" +done + +rm -rf ${tmp_log} + +echo "============ TOTAL RESULT ============" +echo "[result] success:$testcase_success failed:$testcase_fail" diff --git a/sysSentry-1.0.2/selftest/test/common.sh b/sysSentry-1.0.2/selftest/test/common.sh new file mode 100644 index 0000000000000000000000000000000000000000..ce058b380265aba387dab0de9c68ee8818275596 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/common.sh @@ -0,0 +1,87 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +function common_pre_test() { + + kill -9 `ps aux|grep syssentry|grep -v grep|awk '{print $2}'` + kill -9 `ps aux|grep test_task|grep -v grep|awk '{print $2}'` + + task_start="$1" + task_stop="$2" + type="$3" + interval="$4" + heartbeat_interval="$5" + test_task_name="$6" + + update_test_config "$task_start" "$task_stop" "$type" $interval $heartbeat_interval + + gcc mod/test_task.c -o test_task + cp test_task /usr/bin + cp mod/test_config.mod /etc/sysSentry/tasks/"$test_task_name".mod + + syssentry & + sleep 1 +} + +function update_test_config() { + config_file="mod/test_config.mod" + task_start="$1" + task_stop="$2" + type="$3" + interval="$4" + heartbeat_interval="$5" + + if [ -f "$config_file" ]; then + sed -i "s/^task_start=.*/task_start=$task_start/" "$config_file" + sed -i "s/^task_stop=.*/task_stop=$task_stop/" "$config_file" + sed -i "s/^type=.*/type=$type/" "$config_file" + sed -i "s/^interval=.*/interval=$interval/" "$config_file" + sed -i "s/^heartbeat_interval=.*/heartbeat_interval=$heartbeat_interval/" "$config_file" + echo "test_config.mod file has been updated." + else + echo "test_config.mod file not found." + fi +} + +function add_test_config() { + task_start="$1" + task_stop="$2" + type="$3" + interval="$4" + heartbeat_interval="$5" + config_file="/etc/sysSentry/tasks/$6" + + touch "$config_file" + + if [ -f "$config_file" ]; then + echo "[common]" > "$config_file" + echo "enabled=yes" >> "$config_file" + echo "task_start=$task_start">> "$config_file" + echo "task_stop=$task_stop">> "$config_file" + echo "type=$type">> "$config_file" + echo "interval=$interval">> "$config_file" + echo "heartbeat_interval=$heartbeat_interval">> "$config_file" + echo "test_config.mod file has been added." + else + echo "test_config.mod file not added." + fi + + gcc mod/test_task.c -o test_task + cp test_task /usr/bin + + syssentry & + sleep 1 +} + +function look_pid() { + task_task="$1" + pid=$(ps -ef | grep '$task_task' | grep -v grep | awk '{print $2}') + if [ -z "$pid"] + then + echo "task_task is not existed" + return 0 + else + echo "task_task is existed" + return 1 + fi +} \ No newline at end of file diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_end_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_end_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..0b1e61eaabde7ccbadb0809391bc048320f8fe9b --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_end_exception.sh @@ -0,0 +1,49 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 异常的task_stop命令,在运行时是否报错 + +function pre_test() { + common_pre_test "test_task" "aaa" "oneshot" 60 3600 "test_end_exception" +} + +function do_test() { + sentryctl status test_end_exception 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sentryctl start test_end_exception + expect_eq $? 0 + + sentryctl status test_end_exception 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + start_line=$(expr $(wc -l < /var/log/sysSentry/sysSentry.log) + 1) + sentryctl stop test_end_exception + expect_eq $? 0 + end_line=$(wc -l < /var/log/sysSentry/sysSentry.log) + + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/sysSentry.log > ${tmp_log} + expect_true "grep -E '(stop Popen failed)' ${tmp_log}" || cat ${tmp_log} + + sentryctl status test_end_exception 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task + rm -rf /usr/bin/test_task /etc/sysSentry/tasks/test_end_exception.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..f1d21e1f2709e979c5f0275f07de15eb7e2321e6 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_exception.sh @@ -0,0 +1,83 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +#未启动守护进程时,sentryctl执行是否正确处理异常 +#sentryctl 一个命令字后带多个变参 +#sentryctl 多个命令字同时使用 +#sentryctl 使用错误的变参 +#sentryctl 使用非法的命令字 +#配置文件重载(修改任务类型) + +function pre_test() { + kill -9 `ps aux|grep syssentry|grep -v grep|awk '{print $2}'` + kill -9 `ps aux|grep test_task|grep -v grep|awk '{print $2}'` + + update_test_config "test_task" "pkill test_task" "oneshot" 60 3600 + gcc mod/test_task.c -o test_task + cp test_task /usr/bin + cp mod/test_config.mod /etc/sysSentry/tasks/test_sentryctl_exception.mod +} + +function do_test() { + + sentryctl status test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: client_send_and_recv failed)' ${tmp_log}" + + sentryctl start test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: client_send_and_recv failed)' ${tmp_log}" + + sentryctl stop test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: client_send_and_recv failed)' ${tmp_log}" + + sentryctl reload test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: client_send_and_recv failed)' ${tmp_log}" + + sentryctl list 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: client_send_and_recv failed)' ${tmp_log}" + + syssentry & + pid1=$(ps -ef | grep syssentry | grep -v grep | awk '{print $2}') + + syssentry & + pid2=$(ps -ef | grep syssentry | grep -v grep | awk '{print $2}') + + expect_eq $pid1 $pid2 + + sentryctl start stop test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: error: unrecognized arguments)' ${tmp_log}" + + sentryctl start test_sentryctl_exception aaa 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: error: unrecognized arguments)' ${tmp_log}" + + sentryctl aaa test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: error: argument cmd_type: invalid choice:)' ${tmp_log}" + + update_test_config "test_task" "pkill test_task" "period" 60 3600 + cp mod/test_config.mod /etc/sysSentry/tasks/test_sentryctl_exception.mod + + sentryctl reload test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(type of mod is different from old type, reload failed)' ${tmp_log}" + + sentryctl aaa test_sentryctl_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(sentryctl: error: argument cmd_type: invalid choice:)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task + rm -rf /usr/bin/test_task /etc/sysSentry/tasks/test_sentryctl_exception.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_heartbeat_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_heartbeat_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..91d54327a3ae4a8e20e2433639c3354ad27fc488 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_heartbeat_exception.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" +start_line=0 + +# 测试异常的心跳间隔的巡检任务 + +function pre_test() { + start_line=$(expr $(wc -l < /var/log/sysSentry/sysSentry.log) + 1) + common_pre_test "test_task" "pkill test_task" "oneshot" 60 -1 "test_heartbeat_exception" +} + +function do_test() { + #systemctl start sysSentry + #expect_eq $? 0 + + end_line=$(wc -l < /var/log/sysSentry/sysSentry.log) + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/sysSentry.log > ${tmp_log} + expect_true "grep -E '(heartbeat interval -1 is invalid)' ${tmp_log}" || cat ${tmp_log} + + sentryctl status test_heartbeat_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sleep 1 + + sentryctl start test_heartbeat_exception + expect_eq $? 0 + + sentryctl status test_heartbeat_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sleep 12 + + sentryctl status test_heartbeat_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task + rm -rf /usr/bin/test_task /etc/sysSentry/tasks/test_heartbeat_exception.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_interval_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_interval_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..3cd83c124be61f6a4381d2a43ad3417111a2ba89 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_interval_exception.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" +start_line=0 + +# 测试异常的时间间隔的巡检任务 + +function pre_test() { + start_line=$(expr $(wc -l < /var/log/sysSentry/sysSentry.log) + 1) + common_pre_test "test_task" "pkill test_task" "period" -1 3600 "test_interval_exception" +} + +function do_test() { + #systemctl start sysSentry + #expect_eq $? 0 + + end_line=$(wc -l < /var/log/sysSentry/sysSentry.log) + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/sysSentry.log > ${tmp_log} + expect_true "grep -E '(period delay is invalid)' ${tmp_log}" || cat ${tmp_log} + + sleep 1 + + sentryctl status test_interval_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sleep 3 + + sentryctl status test_interval_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sentryctl stop test_interval_exception + expect_eq $? 0 + + sleep 1 + + sentryctl status test_interval_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task + rm -rf /usr/bin/test_task /etc/sysSentry/tasks/test_interval_exception.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_modname_long_length_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_modname_long_length_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..837b6fb2b35dee7939b62b5a678ba138eb9fc325 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_modname_long_length_exception.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 测试子任务名过长的测试用例 + +# length:256 +str="a" +result1="" +for i in {1..256}; do + result+="$str" +done + +function pre_test() { + syssentry & + sleep 1 +} + +function do_test() { + + sentryctl status $result 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: cannot find task by name)' ${tmp_log}" + + + result2="" + for i in {1..251}; do + result2+="$str" + done + add_test_config "test_task" "pkill test_task" "oneshot" 60 3600 "$result2.mod" + + sentryctl reload $result2 + expect_eq $? 0 + + sentryctl status $result2 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + cat /etc/sysSentry/tasks/"$result2.mod" + rm -rf ${tmp_log} test_task /usr/bin/test_task /etc/sysSentry/tasks/"$result2.mod" +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_modname_valid.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_modname_valid.sh new file mode 100644 index 0000000000000000000000000000000000000000..b2a4c65d41984485012ab3b056182153e3d9e344 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_modname_valid.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 测试子任务名有效性测试用例 +result1="this is a1122+#modname" + +function pre_test() { + common_pre_test "test_task" "pkill test_task" "oneshot" 60 3600 "$result1" +} + +function do_test() { + + sentryctl list 2>&1 | tee ${tmp_log} + expect_false "grep -E '($result1)' ${tmp_log}" + + result2="this_is_a1122_modname" + common_pre_test "test_task" "pkill test_task" "oneshot" 60 3600 "$result2" + + sentryctl list 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '($result2)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} + rm -rf test_task /usr/bin/test_task /etc/sysSentry/tasks/"$result1".mod + rm -rf /etc/sysSentry/tasks/"$result2".mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_normal.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_normal.sh new file mode 100644 index 0000000000000000000000000000000000000000..b2eafcc32a34382f0cd3efce35a7834df9cc9989 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_normal.sh @@ -0,0 +1,51 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 正常流程执行 + +function pre_test() { + common_pre_test "test_task" "pkill test_task" "oneshot" 60 3600 "test_normal" +} + +function do_test() { + sentryctl status test_normal 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sentryctl list 2>&1 | tee ${tmp_log} + expect_true "grep -E '(['test_normal', 'EXITED'])' ${tmp_log}" + + sentryctl start test_normal + expect_eq $? 0 + + sentryctl start test_normal 2>&1 | tee ${tmp_log} + expect_true "grep -E '(task is running, please wait)' ${tmp_log}" + + sentryctl stop test_normal + expect_eq $? 0 + + look_pid "test_task" + if [ $? -eq 0 ] + then + sentryctl status test_normal 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + fi +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} + rm -rf test_task /usr/bin/test_task /etc/sysSentry/tasks/test_normal.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_reload.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_reload.sh new file mode 100644 index 0000000000000000000000000000000000000000..bc33809a5e1977932c961a90607a90884dbdc1ef --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_reload.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 查看更新配置文件是否生效 + +function pre_test() { + common_pre_test "test_task" "pkill test_task" "period" 60 3600 "test_sentryctl_reload" +} + +function do_test() { + + sentryctl status test_sentryctl_reload 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: WAITING | RUNNING)' ${tmp_log}" + + sentryctl start test_sentryctl_reload + expect_eq $? 0 + + update_test_config "test_task" "pkill test_task" "period" 60 5 + cp mod/test_config.mod /etc/sysSentry/tasks/test_sentryctl_reload.mod + + sentryctl reload test_sentryctl_reload + expect_eq $? 0 + + sentryctl stop test_sentryctl_reload + expect_eq $? 0 + + sentryctl start test_sentryctl_reload + expect_eq $? 0 + + sentryctl status test_sentryctl_reload 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sleep 7 + pid=$(ps aux | grep test_task | grep -v grep | awk '{print $2}') + if [ -z "$pid" ]; then + sentryctl status test_sentryctl_reload 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: FAILED)' ${tmp_log}" + fi + + update_test_config "test_task" "pkill test_task" "period" 20 3600 + cp mod/test_config.mod /etc/sysSentry/tasks/test_sentryctl_reload.mod + + sentryctl reload test_sentryctl_reload + expect_eq $? 0 + + sentryctl stop test_sentryctl_reload + expect_eq $? 0 + + sentryctl start test_sentryctl_reload + expect_eq $? 0 + + sentryctl status test_sentryctl_reload 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sleep 13 + + sentryctl status test_sentryctl_reload 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: WAITING)' ${tmp_log}" + + sleep 9 + + sentryctl status test_sentryctl_reload 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task /usr/bin/test_task /etc/sysSentry/tasks/test_sentryctl_reload.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_start_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_start_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..0b12f5f6bbba81f781e3d30f140a8a0aa55dcfc1 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_start_exception.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 异常的task_start命令,在运行时是否报错 + +function pre_test() { + common_pre_test "aaaa" "pkill test_task" "oneshot" 60 3600 "test_start_exception" +} + +function do_test() { + sentryctl status test_start_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sleep 1 + + sentryctl start test_start_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(start command is invalid, popen failed)' ${tmp_log}" + + sentryctl status test_start_exception 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: FAILED)' ${tmp_log}" +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task + rm -rf /usr/bin/test_task /etc/sysSentry/tasks/test_start_exception.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_type_exception.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_type_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..35e624b04075556915279ce6cf43c78413a2f1e8 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_type_exception.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" +start_line=0 + +# 测试异常的巡检类型的任务 + +function pre_test() { + start_line=$(expr $(wc -l < /var/log/sysSentry/sysSentry.log) + 1) + common_pre_test "test_task" "pkill test_task" "aaa" 60 3600 "test_type_exception" +} + +function do_test() { + end_line=$(wc -l < /var/log/sysSentry/sysSentry.log) + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/sysSentry.log > ${tmp_log} + expect_true "grep -E '(test_type_exception load failed)' ${tmp_log}" || cat ${tmp_log} + + sentryctl status test_type_exception 2>&1 | tee ${tmp_log} + expect_true "grep -E '(status: cannot find task by name)' ${tmp_log}" + + sentryctl start test_type_exception 2>&1 | tee ${tmp_log} + expect_true "grep -E '(task not exist)' ${tmp_log}" + + sentryctl stop test_type_exception 2>&1 | tee ${tmp_log} + expect_true "grep -E '(task not exist)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task /usr/bin/test_task /etc/sysSentry/tasks/test_type_exception.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_type_oneshot.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_type_oneshot.sh new file mode 100644 index 0000000000000000000000000000000000000000..74c113cb1d400c314952e4c56e72506214498cc9 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_type_oneshot.sh @@ -0,0 +1,72 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 测试oneshot巡检类型的各种任务状态 + +function pre_test() { + common_pre_test "test_task" "pkill test_task" "oneshot" 60 36000 "test_type_oneshot" +} + +function do_test() { + #systemctl start sysSentry + #expect_eq $? 0 + + sentryctl status test_type_oneshot 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sentryctl start test_type_oneshot + expect_eq $? 0 + + sentryctl status test_type_oneshot 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sentryctl stop test_type_oneshot + expect_eq $? 0 + + sleep 1 + + sentryctl status test_type_oneshot 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sentryctl start test_type_oneshot + expect_eq $? 0 + + if pgrep -x "test_task" >/dev/null; then + pkill -x "test_task" + sleep 1 + sentryctl status test_type_oneshot 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: FAILED)' ${tmp_log}" + + sentryctl start test_type_oneshot + expect_eq $? 0 + + sleep 1 + + sentryctl status test_type_oneshot 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + fi + + sleep 12 + + sentryctl status test_type_oneshot 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task /usr/bin/test_task /etc/sysSentry/tasks/test_type_oneshot.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_sentryctl_type_period.sh b/sysSentry-1.0.2/selftest/test/test_sentryctl_type_period.sh new file mode 100644 index 0000000000000000000000000000000000000000..635fc8e965d035086cd8f3682ba622c3f954e603 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_sentryctl_type_period.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "test/common.sh" +set +e + +tmp_log="tmp_log" + +# 测试period巡检类型的各种任务状态 + +function pre_test() { + common_pre_test "test_task" "pkill test_task" "period" 60 3600 "test_type_period" +} + +function do_test() { + #systemctl start sysSentry + #expect_eq $? 0 + + sentryctl status test_type_period 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: WAITING | RUNNING)' ${tmp_log}" + + sentryctl start test_type_period + expect_eq $? 0 + + sentryctl status test_type_period 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: RUNNING)' ${tmp_log}" + + sentryctl stop test_type_period + expect_eq $? 0 + + sleep 1 + + sentryctl status test_type_period 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: EXITED)' ${tmp_log}" + + sentryctl start test_type_period + expect_eq $? 0 + + sleep 12 + + # wating状态 + sentryctl status test_type_period 2>&1 | tee ${tmp_log} | cat + expect_true "grep -E '(status: WAITING)' ${tmp_log}" + + sentryctl start test_type_period + expect_eq $? 0 + + if pgrep -x "test_task" >/dev/null; then + pkill -x "test_task" + sleep 2 + sentryctl status test_type_period | grep -w "status: FAILED" + expect_eq $? 0 + + sentryctl stop test_type_period + expect_eq $? 0 + + sentryctl status test_type_period | grep -w "status: EXITED" + expect_eq $? 0 + fi + +} + +function post_test() { + while [[ -n "`ps aux|grep -w syssentry|grep -v grep`" ]]; do + kill -9 `pgrep -w syssentry` + kill -9 `pgrep -w test_task` + sleep 1 + done + rm -rf ${tmp_log} test_task /usr/bin/test_task /etc/sysSentry/tasks/test_type_period.mod +} +set -x +run_testcase diff --git a/sysSentry-1.0.2/selftest/test/test_xalarm_read_config_exception.sh b/sysSentry-1.0.2/selftest/test/test_xalarm_read_config_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..d31d53b53c61e06a95fd8324cbe637bf66c811e3 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_xalarm_read_config_exception.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "libs/wait.sh" +source "libs/shopt.sh" +set +e + +#测试读取配置文件异常的场景 + +function pre_test() { + cp /etc/sysSentry/xalarm.conf /etc/sysSentry/xalarm.conf.bak + rm -f ./tmp_log + systemctl stop xalarmd.service +} + +function do_test() { + + # 异常的alarm id + start_line=$(expr $(wc -l < /var/log/sysSentry/xalarm.log) + 1) + echo -e "[filter]\nid_mask = 999,9999,aaa,test-and-run,7869-2431" > /etc/sysSentry/xalarm.conf + systemctl start xalarmd.service + end_line=$(wc -l < /var/log/sysSentry/xalarm.log) + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/xalarm.log >> ./tmp_log + wait_cmd_ok "grep \"invalid alarm id 999, ignored\" ./tmp_log" 1 3 + expect_eq $? 0 "xalarm config: alarm id less than 1001" + + wait_cmd_ok "grep \"invalid alarm id 9999, ignored\" ./tmp_log" 1 3 + expect_eq $? 0 "xalarm config: alarm id more than 9999" + + wait_cmd_ok "grep \"invalid alarm id aaa, ignored\" ./tmp_log" 1 3 + expect_eq $? 0 "xalarm config: alarm id is not number" + + wait_cmd_ok "grep \"invalid alarm id test-and-run, ignored\" ./tmp_log" 1 3 + expect_eq $? 0 "xalarm config: alarm id is not number interval" + + wait_cmd_ok "grep \"invalid alarm id 7869-2431, ignored\" ./tmp_log" 1 3 + expect_eq $? 0 "xalarm config: alarm id is not a valid number interval" + + rm -f /etc/sysSentry/xalarm.conf + start_line=$(expr $(wc -l < /var/log/sysSentry/xalarm.log) + 1) + echo -e "[no_filter]\nid_mask = 123" > /etc/sysSentry/xalarm.conf + systemctl restart xalarmd.service + end_line=$(wc -l < /var/log/sysSentry/xalarm.log) + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/xalarm.log >> ./tmp_log + wait_cmd_ok "grep \"no filter conf\" ./tmp_log" 1 3 + expect_eq $? 0 "no filter conf" + + rm -f /etc/sysSentry/xalarm.conf + start_line=$(expr $(wc -l < /var/log/sysSentry/xalarm.log) + 1) + echo -e "[filter]\nid_mask_number = 123" > /etc/sysSentry/xalarm.conf + systemctl restart xalarmd.service + end_line=$(wc -l < /var/log/sysSentry/xalarm.log) + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/xalarm.log >> ./tmp_log + wait_cmd_ok "grep \"no id_mask conf\" ./tmp_log" 1 3 + expect_eq $? 0 "no id_mask conf" + +} + +function post_test() { + cat ./tmp_log + rm -f /etc/sysSentry/xalarm.conf ./tmp_log + cp /etc/sysSentry/xalarm.conf.bak /etc/sysSentry/xalarm.conf + systemctl stop xalarmd.service +} + +run_testcase + diff --git a/sysSentry-1.0.2/selftest/test/test_xalarm_register_and_unregister_exception.sh b/sysSentry-1.0.2/selftest/test/test_xalarm_register_and_unregister_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..6d41fe75d3b69730df3d061e42b7330358286d0d --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_xalarm_register_and_unregister_exception.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "libs/wait.sh" +source "libs/shopt.sh" +set +e + +#测试unregister的场景,其他用户解注册已有clientId和没出现的clientId,重复注册 + +function pre_test() { + rm -rf ./checklog xalarm/unreg_demo xalarm/send_demo xalarm/reg_demo + gcc xalarm/reg_demo.c -o xalarm/reg_demo -lxalarm + gcc xalarm/unreg_demo.c -o xalarm/unreg_demo -lxalarm + systemctl start xalarmd.service +} + +function do_test() { + ./xalarm/reg_demo 2 >> checklog 2>&1 & + wait_cmd_ok "grep \"xalarm_Register: alarm has registered\" ./checklog" 1 3 + expect_eq $? 0 "register twice" + + ./xalarm/reg_demo >> checklog 2>&1 & + ./xalarm/unreg_demo 0 >> checklog 2>&1 & + wait_cmd_ok "grep \"unregister xalarm, client id is 0.xalarm_UnRegister: alarm has not registered\" ./checklog" 1 3 + expect_eq $? 0 "unregister available client id of xalarm" + + ./xalarm/unreg_demo 100 >> checklog 2>&1 & + wait_cmd_ok "grep \"unregister xalarm, client id is 100.xalarm_UnRegister: alarm has not registered\" ./checklog" 1 3 + expect_eq $? 0 "unregister unavailable client id of xalarm" + +} + +function post_test() { + kill -9 $(pgrep -w unreg_demo) + cat ./checklog + rm -rf ./checklog xalarm/unreg_demo xalarm/reg_demo + systemctl stop xalarmd.service +} + +run_testcase + + + diff --git a/sysSentry-1.0.2/selftest/test/test_xalarm_restart_exception.sh b/sysSentry-1.0.2/selftest/test/test_xalarm_restart_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..cc244356a9f28835fbcc3e67616a3f8064f038b0 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_xalarm_restart_exception.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "libs/wait.sh" +source "libs/shopt.sh" +set +e + +#验证启动多次xalarmd的场景 + +function pre_test() { + rm -f ./tmp_log + systemctl stop xalarmd +} + +function do_test() { + # 验证多次启动的场景 + start_line=$(expr $(wc -l < /var/log/sysSentry/xalarm.log) + 1) + /usr/bin/xalarmd + /usr/bin/xalarmd + end_line=$(wc -l < /var/log/sysSentry/xalarm.log) + + process_num=$(ps -ef | grep xalarmd | grep -v grep | wc -l) + echo "xalarm process num is $process_num" >> ./tmp_log + expect_eq $process_num 1 "check xalarmd can launch multiple times" + + sed -n "${start_line}, ${end_line}p" /var/log/sysSentry/xalarm.log >> ./tmp_log + wait_cmd_ok "grep \"get pid file lock failed\" ./tmp_log" 1 3 + expect_eq $? 0 "check xalarmd get pid file lock fail log" + + cat ./tmp_log +} + +function post_test() { + rm -f ./tmp_log + kill $(pgrep -w xalarmd) +} + +run_testcase + + + diff --git a/sysSentry-1.0.2/selftest/test/test_xalarm_send_message.sh b/sysSentry-1.0.2/selftest/test/test_xalarm_send_message.sh new file mode 100644 index 0000000000000000000000000000000000000000..4c8c687dcde4c6bbd0daa30bc9f688a350d95f11 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_xalarm_send_message.sh @@ -0,0 +1,90 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "libs/wait.sh" +source "libs/shopt.sh" +set +e + +#测试发送消息的场景,参数合法性校验以及关闭xalarmd之后的场景 + +function pre_test() { + rm -rf ./checklog ./tmp_log xalarm/send_demo xalarm/reg_demo + gcc xalarm/send_demo.c -o xalarm/send_demo -lxalarm + gcc xalarm/reg_demo.c -o xalarm/reg_demo -lxalarm + systemctl start xalarmd.service +} + +function do_test() { + ./xalarm/reg_demo >> checklog 2>&1 & + wait_cmd_ok "grep \"register success\" ./checklog" 1 3 + expect_eq $? 0 "xalarm register success" + + # 发送用户注册的alarm id消息 + ./xalarm/send_demo 1001 1 2 "cpu usage high warning" >> checklog 2>&1 & + wait_cmd_ok "grep \"id:1001\" ./checklog" 1 3 + expect_eq $? 0 "alarm id check" + + wait_cmd_ok "grep \"level:1\" ./checklog" 1 3 + expect_eq $? 0 "alarm level check" + + wait_cmd_ok "grep \"type:2\" ./checklog" 1 3 + expect_eq $? 0 "alarm type check" + + wait_cmd_ok "grep \"cpu usage high warning\" ./checklog" 1 3 + expect_eq $? 0 "alarm message check" + + # 发送用户未注册的alarm id消息 + start_line=$(wc -l < ./checklog) + ./xalarm/send_demo 1007 1 2 "cpu usage high warning" >> checklog 2>&1 & + end_line=$(wc -l < ./checklog) + expect_eq $end_line $start_line "send unregistered alarm id to xalarm" + + # 验证不合法参数 + start_line=$(expr $(wc -l < ./checklog) + 1) + ./xalarm/send_demo 9000 2 1 "cpu usage high" >> checklog 2>&1 & + end_line=$(wc -l < ./checklog) + sed -n "${start_line}, ${end_line}p" ./checklog > ./tmp_log + wait_cmd_ok "grep \"xalarm_Report: alarm info invalid\" ./tmp_log" 1 3 + expect_eq $? 0 "alarm id check" + + start_line=$(expr $(wc -l < ./checklog) + 1) + ./xalarm/send_demo 1002 7 -1 "cpu usage high" >> checklog 2>&1 & + end_line=$(wc -l < ./checklog) + sed -n "${start_line}, ${end_line}p" ./checklog > ./tmp_log + wait_cmd_ok "grep \"xalarm_Report: alarm info invalid\" ./tmp_log" 1 3 + expect_eq $? 0 "alarm type check" + + start_line=$(expr $(wc -l < ./checklog) + 1) + ./xalarm/send_demo 1002 2 -1 "cpu usage high" >> checklog 2>&1 & + end_line=$(wc -l < ./checklog) + sed -n "${start_line}, ${end_line}p" ./checklog > ./tmp_log + wait_cmd_ok "grep \"xalarm_Report: alarm info invalid\" ./tmp_log" 1 3 + expect_eq $? 0 "alarm level check" + + # 验证解注册 + sleep 10 + ./xalarm/send_demo 1001 1 2 "cpu usage high warning" >> checklog 2>&1 & + wait_cmd_ok "grep \"unregister xalarm success\" ./checklog" 1 3 + expect_eq $? 0 "check unregister xalarm" + + # 停止xalarmd服务后发消息 + systemctl stop xalarmd.service + + ./xalarm/send_demo 1001 1 2 "cpu usage high warning" >> checklog 2>&1 & + wait_cmd_ok "grep \"xalarm_Report: sendto failed errno: 2\" ./checklog" 1 3 + expect_eq $? 0 "xalarm send message while stop xalarmd service" +} + +function post_test() { + kill -9 $(pgrep -w reg_demo) + cat ./checklog + rm -rf ./checklog ./tmp_log xalarm/send_demo xalarm/reg_demo + systemctl stop xalarmd.service +} + +run_testcase + + + diff --git a/sysSentry-1.0.2/selftest/test/test_xalarm_upgrade_exception.sh b/sysSentry-1.0.2/selftest/test/test_xalarm_upgrade_exception.sh new file mode 100644 index 0000000000000000000000000000000000000000..045df3bad66e53e1082a47354c752edea03c1d56 --- /dev/null +++ b/sysSentry-1.0.2/selftest/test/test_xalarm_upgrade_exception.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +source "libs/expect.sh" +source "libs/lib.sh" +source "libs/wait.sh" +source "libs/shopt.sh" +set +e + +#测试upgrade场景:更新生效的场景、错误的clientId、错误的alarm id + +function pre_test() { + rm -rf ./checklog xalarm/upgrade_demo xalarm/send_demo + gcc xalarm/upgrade_demo.c -o xalarm/upgrade_demo -lxalarm + gcc xalarm/send_demo.c -o xalarm/send_demo -lxalarm + systemctl start xalarmd.service +} + +function do_test() { + ./xalarm/upgrade_demo 4 0 1001 1002 1003 1004 >> checklog 2>&1 & + ./xalarm/send_demo 1004 1 2 "cpu usage high warning" + wait_cmd_ok "grep \"id:1004\" ./checklog" 1 3 + expect_eq $? 0 "check upgrade take effect" + + kill -9 $(pgrep -w upgrade_demo) + rm -rf checklog + + ./xalarm/upgrade_demo 4 0 1001 1002 1003 4004 >> checklog 2>&1 & + wait_cmd_ok "grep \"xalarm_Upgrade: invalid args\" ./checklog" 1 3 + expect_eq $? 0 "upgrade with invalid alarm id" + + rm -rf checklog + + ./xalarm/upgrade_demo 4 999 1001 1002 1003 1004 >> checklog 2>&1 & + wait_cmd_ok "grep \"xalarm_Upgrade: invalid args\" ./checklog" 1 3 + expect_eq $? 0 "upgrade with invalid client id" + +} + +function post_test() { + kill -9 $(pgrep -w upgrade_demo) + cat ./checklog + rm -rf ./checklog xalarm/upgrade_demo xalarm/send_demo + systemctl stop xalarmd.service +} + +run_testcase + + + diff --git a/sysSentry-1.0.2/selftest/xalarm/CMakeLists.txt b/sysSentry-1.0.2/selftest/xalarm/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..9f03cc9c25c204e07a615281b7b593e80e206770 --- /dev/null +++ b/sysSentry-1.0.2/selftest/xalarm/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +cmake_minimum_required(VERSION 3.12.1) +project(xd_alarm_demo) + +SET(CMAKE_VERBOSE_MAKEFILE OFF) + +add_executable(reg_alarm_demo reg_demo.c) +add_executable(send_alarm_demo send_demo.c) +add_executable(unreg_alarm_demo unreg_demo.c) +add_executable(upgrade_alarm_demo upgrade_demo.c) +target_link_libraries(reg_alarm_demo xalarm) +target_link_libraries(send_alarm_demo xalarm) +target_link_libraries(unreg_alarm_demo xalarm) +target_link_libraries(upgrade_alarm_demo xalarm) diff --git a/sysSentry-1.0.2/selftest/xalarm/reg_demo.c b/sysSentry-1.0.2/selftest/xalarm/reg_demo.c new file mode 100644 index 0000000000000000000000000000000000000000..2f9824a95d5860fdfe015a474a00ba185a4a7b80 --- /dev/null +++ b/sysSentry-1.0.2/selftest/xalarm/reg_demo.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: register alarm + */ +#include +#include +#include +#include + + +#define SLEEP_TIME 10 +#define ALARM_ID_1 1001 +#define ALARM_ID_2 1002 +#define ALARM_ID_3 1003 +#define ID_LIST_LENGTH 3 +#define ID_INDEX_0 0 +#define ID_INDEX_1 1 +#define ID_INDEX_2 2 +#define REGISTER_TIMES 1 +#define ARG_NUM 2 +#define REGISTER_TIMES_INDEX 1 + +void RefreshOutput(void) +{ + int ret = fflush(stdout); + if (ret != 0) { + printf("failed to fflush\n"); + } +} + +void callback(struct alarm_info *param) +{ + int alarmid, alarmlevel, alarmtype; + long long alarmtime; + char *pucParas; + + alarmid = xalarm_getid(param); + alarmlevel = xalarm_getlevel(param); + alarmtype = xalarm_gettype(param); + alarmtime = xalarm_gettime(param); + pucParas = xalarm_getdesc(param); + + printf("[alarmid:%d] [alarmlevel:%d] [alarmtype:%d] [alarmtime:%lld ms] [msg:%s]\n", + alarmid, alarmlevel, alarmtype, alarmtime, pucParas); + + RefreshOutput(); +} + +int main(int argc, char **argv) +{ + int clientId; + int registerTimes = REGISTER_TIMES; + int ret; + struct alarm_subscription_info id_filter; + + printf("demo start\n"); + + id_filter.id_list[ID_INDEX_0] = ALARM_ID_1; + id_filter.id_list[ID_INDEX_1] = ALARM_ID_2; + id_filter.id_list[ID_INDEX_2] = ALARM_ID_3; + id_filter.len = ID_LIST_LENGTH; + + if (argc == ARG_NUM) { + registerTimes = atoi(argv[REGISTER_TIMES_INDEX]); + } + for (int i = 0;i < registerTimes; ++i) { + clientId = xalarm_Register(callback, id_filter); + } + if (clientId < 0) { + printf("demo register failed\n"); + return -1; + } else { + printf("xalarm register success, client id is %d\n", clientId); + } + printf("demo waiting alarm\n"); + RefreshOutput(); + sleep(SLEEP_TIME); + + xalarm_UnRegister(clientId); + printf("unregister xalarm success\n"); + RefreshOutput(); + return 0; +} + diff --git a/sysSentry-1.0.2/selftest/xalarm/send_demo.c b/sysSentry-1.0.2/selftest/xalarm/send_demo.c new file mode 100644 index 0000000000000000000000000000000000000000..65dc3bbe8586c93ce0d03056cd1d71e12914c7c5 --- /dev/null +++ b/sysSentry-1.0.2/selftest/xalarm/send_demo.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: send alarm + */ +#include +#include +#include +#include + + +#define ALARMID 1002 +#define LEVEL 2 +#define TYPE 1 +#define ARG_NUM 5 +#define ALARM_ID_ARG_INDEX 1 +#define ALARM_LEVEL_ARG_INDEX 2 +#define ALARM_TYPE_ARG_INDEX 3 +#define ALARM_MSG_ARG_INDEX 4 + +int main(int argc, char **argv) +{ + int alarmId = ALARMID; + int level = LEVEL; + int type = TYPE; + unsigned char *msg = "test messages\0"; + + if (argc == ARG_NUM) { + alarmId = atoi(argv[ALARM_ID_ARG_INDEX]); + level = atoi(argv[ALARM_LEVEL_ARG_INDEX]); + type = atoi(argv[ALARM_TYPE_ARG_INDEX]); + msg = argv[ALARM_MSG_ARG_INDEX]; + } + + xalarm_Report(alarmId, level, type, msg); + + return 0; +} diff --git a/sysSentry-1.0.2/selftest/xalarm/unreg_demo.c b/sysSentry-1.0.2/selftest/xalarm/unreg_demo.c new file mode 100644 index 0000000000000000000000000000000000000000..90638f3924790beedaa22fef3b0235b5fa99f147 --- /dev/null +++ b/sysSentry-1.0.2/selftest/xalarm/unreg_demo.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: unreg alarm + */ +#include +#include +#include +#include + +#define DEFAULT_CLIENT_ID 0 +#define ARG_NUM 2 +#define CLIENT_ID_ARG_INDEX 1 + +int main(int argc, char **argv) +{ + unsigned char msg[ALARM_INFO_MAX_PARAS_LEN] = "test messages"; + + int clientId = DEFAULT_CLIENT_ID; + + if (argc == ARG_NUM) { + clientId = atoi(argv[CLIENT_ID_ARG_INDEX]); + } + + printf("unregister xalarm, client id is %d.", clientId); + xalarm_UnRegister(clientId); + int ret = fflush(stdout); + if (ret != 0) { + return -1; + } + return 0; +} diff --git a/sysSentry-1.0.2/selftest/xalarm/upgrade_demo.c b/sysSentry-1.0.2/selftest/xalarm/upgrade_demo.c new file mode 100644 index 0000000000000000000000000000000000000000..b2551fb2f56d2eeec366723221bf4ab61dbd0d75 --- /dev/null +++ b/sysSentry-1.0.2/selftest/xalarm/upgrade_demo.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: upgrade alarm + */ +#include +#include +#include +#include + +#define SLEEP_TIME 10 +#define ID_FILTER_LEN_ARG_INDEX 1 +#define CLIENT_ID_ARG_INDEX 2 +#define MIN_ARG_NUMS 3 +#define ID_FILTER_BEGIN_INDEX 3 +#define ID_INDEX_0 0 +#define ALARM_ID_1 1001 +#define ID_LIST_LENGTH 1 + +void RefreshOutput(void) +{ + int ret = fflush(stdout); + if (ret != 0) { + printf("failed to fflush\n"); + } +} + +void Hook(struct alarm_info *param) +{ + int alarmId, alarmLevel, alarmType; + long long alarmTime; + char *pucParas; + + alarmId = xalarm_getid(param); + alarmLevel = xalarm_getlevel(param); + alarmType = xalarm_gettype(param); + alarmTime = xalarm_gettime(param); + pucParas = xalarm_getdesc(param); + + printf("alarmid:%d alarmlevel:%d alarmtype:%d alarmtime:%lld ms msg:%s\n", + alarmId, alarmLevel, alarmType, alarmTime, pucParas); + + RefreshOutput(); +} + +int main(int argc, char **argv) +{ + struct alarm_subscription_info id_filter; + int clientId; + + id_filter.id_list[ID_INDEX_0] = ALARM_ID_1; + id_filter.len = ID_LIST_LENGTH; + clientId = xalarm_Register(Hook, id_filter); + if (clientId < 0) { + printf("demo register failed\n"); + return -1; + } + + // 参数:[filename, id_filter_len, client_id, filter_1, filter_2, ...] + if (argc <= MIN_ARG_NUMS) { + id_filter.len = 0; + clientId = 0; + } else { + id_filter.len = atoi(argv[ID_FILTER_LEN_ARG_INDEX]); + clientId = atoi(argv[CLIENT_ID_ARG_INDEX]); + } + + for (int i = ID_FILTER_BEGIN_INDEX; i < argc; ++i) { + id_filter.id_list[i - ID_FILTER_BEGIN_INDEX] = atoi(argv[i]); + } + + printf("upgrade client id as %d", clientId); + xalarm_Upgrade(id_filter, clientId); + + RefreshOutput(); + sleep(SLEEP_TIME); + xalarm_UnRegister(clientId); + return 0; +} diff --git a/sysSentry-1.0.2/service/sysSentry.service b/sysSentry-1.0.2/service/sysSentry.service new file mode 100644 index 0000000000000000000000000000000000000000..4d85a6c2af31ac4f14b86259bc9e4525491a5cc1 --- /dev/null +++ b/sysSentry-1.0.2/service/sysSentry.service @@ -0,0 +1,12 @@ +[Unit] +Description=EulerOS System Inspection Frame + +[Service] +ExecStart=/usr/bin/syssentry +ExecStop=/bin/kill $MAINPID +KillMode=process +Restart=on-failure +RestartSec=10s + +[Install] +WantedBy=multi-user.target diff --git a/sysSentry-1.0.2/service/xalarmd.service b/sysSentry-1.0.2/service/xalarmd.service new file mode 100644 index 0000000000000000000000000000000000000000..0665b39a03f2d7c56669ed6ab9dc2f0f8136ef5a --- /dev/null +++ b/sysSentry-1.0.2/service/xalarmd.service @@ -0,0 +1,9 @@ +[Unit] +Description = xalarm daemon for alarm messages forwarding + +[Service] +ExecStart =/usr/bin/python3 /usr/bin/xalarmd +Type = forking + +[Install] +WantedBy = multi-user.target diff --git a/sysSentry-1.0.2/src/libso/CMakeLists.txt b/sysSentry-1.0.2/src/libso/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3ca3f7f3f4c7cc30dd5a19c74bb78b6ab4a11760 --- /dev/null +++ b/sysSentry-1.0.2/src/libso/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +# Description: cmake file for libxalarm + +cmake_minimum_required(VERSION 3.12.1) +project(libxalarm) + +SET(CMAKE_VERBOSE_MAKEFILE OFF) + +add_subdirectory(xalarm) diff --git a/sysSentry-1.0.2/src/libso/xalarm/CMakeLists.txt b/sysSentry-1.0.2/src/libso/xalarm/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8abfb87dfd22ae55cac4a3bf718f6f7f3075a872 --- /dev/null +++ b/sysSentry-1.0.2/src/libso/xalarm/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. +# Description: cmake file for libxalarm +add_library(xalarm SHARED register_xalarm.c) +target_link_libraries(xalarm PRIVATE pthread securec) +set_target_properties(xalarm PROPERTIES LINK_FLAGS "-Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wtrampolines") +set_target_properties(xalarm PROPERTIES CMAKE_C_FLAGS "-shared -fPIC -fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2 -Wall -Werror -g") + +install(TARGETS xalarm LIBRARY DESTINATION ${XD_INSTALL_BINDIR}) \ No newline at end of file diff --git a/sysSentry-1.0.2/src/libso/xalarm/register_xalarm.c b/sysSentry-1.0.2/src/libso/xalarm/register_xalarm.c new file mode 100644 index 0000000000000000000000000000000000000000..31714fa1448faf3ff92f8ba0ee6115925c80c485 --- /dev/null +++ b/sysSentry-1.0.2/src/libso/xalarm/register_xalarm.c @@ -0,0 +1,412 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: inspection message alarm program + * Author: Lan Sheng + * Create: 2023-10-23 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "register_xalarm.h" + +#define DIR_XALARM "/var/run/xalarm" +#define PATH_REG_ALARM "/var/run/xalarm/alarm" +#define PATH_REPORT_ALARM "/var/run/xalarm/report" +#define ALARM_DIR_PERMISSION 0750 +#define ALARM_SOCKET_PERMISSION 0700 +#define TIME_UNIT_MILLISECONDS 1000 + +#define MAX_PARAS_LEN 511 +#define MIN_ALARM_ID 1001 +#define MAX_ALARM_ID (MIN_ALARM_ID + MAX_NUM_OF_ALARM_ID - 1) + +#define ALARM_ENABLED 1 +#define RECV_DELAY_MSEC 100 + +struct alarm_register_info { + char alarm_enable_bitmap[MAX_NUM_OF_ALARM_ID]; + int register_fd; + pthread_t register_tid; + bool is_registered; + alarm_callback_func callback; + int thread_should_stop; +}; + +struct alarm_register_info g_register_info = {{0}, -1, ULONG_MAX, false, NULL, 1}; + +static bool id_is_registered(unsigned short alarm_id) +{ + if (alarm_id < MIN_ALARM_ID || alarm_id > MAX_ALARM_ID) { + return false; + } + + return g_register_info.alarm_enable_bitmap[alarm_id - MIN_ALARM_ID] == ALARM_ENABLED; +} + +static void put_alarm_info(struct alarm_info *info) +{ + if ((g_register_info.callback != NULL) && (info != NULL) && (id_is_registered(info->usAlarmId))) { + g_register_info.callback(info); + } +} + +static int create_unix_socket(const char *path) +{ + struct sockaddr_un alarm_addr; + int fd = -1; + int ret = 0; + int flags; + + if (path == NULL || path[0] == '\0') { + printf("create_unix_socket path is null"); + return -1; + } + + fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + printf("socket failed:%s\n", strerror(errno)); + return -1; + } + flags = fcntl(fd, F_GETFL, 0); + ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK); + if (ret == -1) { + printf("%s: fcntl setfl failed\n", __func__); + goto release_socket; + } + + if (access(PATH_REG_ALARM, F_OK) == 0) { + ret = unlink(PATH_REG_ALARM); + if (ret != 0) { + printf("unlink register socket file failed\n"); + goto release_socket; + } + } + + if (access(DIR_XALARM, F_OK) == -1) { + if (mkdir(DIR_XALARM, ALARM_DIR_PERMISSION) == -1) { + printf("mkdir %s failed\n", DIR_XALARM); + goto release_socket; + } + } + + ret = memset_s(&alarm_addr, sizeof(alarm_addr), 0, sizeof(alarm_addr)); + if (ret != 0) { + printf("create_unix_socket: memset_s alarm_addr failed, ret: %d\n", ret); + goto remove_dir; + } + alarm_addr.sun_family = AF_UNIX; + ret = strncpy_s(alarm_addr.sun_path, sizeof(alarm_addr.sun_path), path, sizeof(alarm_addr.sun_path) - 1); + if (ret != 0) { + printf("create_unix_socket: strncpy_s alarm_addr.sun_path failed, ret: %d\n", ret); + goto remove_dir; + } + if (bind(fd, (struct sockaddr *)&alarm_addr, sizeof(alarm_addr.sun_family) + strlen(alarm_addr.sun_path)) < 0) { + printf("bind socket failed:%s\n", strerror(errno)); + goto remove_dir; + } + if (chmod(path, ALARM_SOCKET_PERMISSION) < 0) { + printf("chmod %s failed: %s\n", path, strerror(errno)); + goto unlink_sockfile; + } + + return fd; + +unlink_sockfile: + ret = unlink(PATH_REG_ALARM); + if (ret != 0) { + printf("unlink register socket file failed\n"); + } +remove_dir: + ret = rmdir(DIR_XALARM); + if (ret != 0) { + printf("rmdir %s failed: %s\n", path, strerror(errno)); + } +release_socket: + (void)close(fd); + + return -1; +} + +static void *alarm_recv(void *arg) +{ + int recvlen = 0; + struct alarm_info info; + int ret = 0; + + /* prctl does not return false if arg2 is right when arg1 is PR_SET_NAME */ + ret = prctl(PR_SET_NAME, "register-recv"); + if (ret != 0) { + printf("alarm_recv: prctl set thread name failed\n"); + return NULL; + } + while (!g_register_info.thread_should_stop) { + recvlen = recv(g_register_info.register_fd, &info, sizeof(struct alarm_info), 0); + if (recvlen == (int)sizeof(struct alarm_info)) { + put_alarm_info(&info); + } else if (recvlen < 0) { + if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) { + usleep(RECV_DELAY_MSEC * TIME_UNIT_MILLISECONDS); + continue; + } + printf("recv error len:%d errno:%d\n", recvlen, errno); + } + } + return NULL; +} + +static pthread_t create_thread(void) +{ + int ret; + pthread_t t_id = ULONG_MAX; + + ret = pthread_create(&t_id, NULL, alarm_recv, NULL); + if (ret < 0) { + printf("create_thread: pthread_create error ret:%d\n", ret); + t_id = ULONG_MAX; + } + return t_id; +} + +static void set_alarm_id(struct alarm_subscription_info id_filter) +{ + int i; + + memset_s(g_register_info.alarm_enable_bitmap, MAX_NUM_OF_ALARM_ID * sizeof(char), + 0, MAX_NUM_OF_ALARM_ID * sizeof(char)); + for (i = 0; i < id_filter.len; i++) { + g_register_info.alarm_enable_bitmap[id_filter.id_list[i] - MIN_ALARM_ID] = ALARM_ENABLED; + } +} + +static bool alarm_subscription_verify(struct alarm_subscription_info id_filter) +{ + int i; + + if (id_filter.len > MAX_NUM_OF_ALARM_ID) { + return false; + } + + for (i = 0; i < id_filter.len; i++) { + if (id_filter.id_list[i] < MIN_ALARM_ID || id_filter.id_list[i] > MAX_ALARM_ID) { + return false; + } + } + return true; +} + +bool xalarm_Upgrade(struct alarm_subscription_info id_filter, int client_id) +{ + if (!g_register_info.is_registered) { + printf("%s: alarm has not registered, cannot upgrade\n", __func__); + return false; + } + + if (!alarm_subscription_verify(id_filter) || client_id != 0) { + printf("%s: invalid args\n", __func__); + return false; + } + set_alarm_id(id_filter); + + return true; +} + +int xalarm_Register(alarm_callback_func callback, struct alarm_subscription_info id_filter) +{ + if (g_register_info.is_registered || (g_register_info.register_fd != -1) || + (g_register_info.register_tid != ULONG_MAX)) { + printf("%s: alarm has registered\n", __func__); + return -1; + } + + if (!alarm_subscription_verify(id_filter) || callback == NULL) { + printf("%s: param is invalid\n", __func__); + return -1; + } + + g_register_info.register_fd = create_unix_socket(PATH_REG_ALARM); + if (g_register_info.register_fd == -1) { + printf("%s: create_unix_socket failed\n", __func__); + return -1; + } + + g_register_info.thread_should_stop = 0; + g_register_info.register_tid = create_thread(); + if (g_register_info.register_tid == ULONG_MAX) { + printf("%s: create_thread failed\n", __func__); + (void)close(g_register_info.register_fd); + g_register_info.register_fd = -1; + g_register_info.thread_should_stop = 1; + return -1; + } + + set_alarm_id(id_filter); + g_register_info.callback = callback; + g_register_info.is_registered = true; + return 0; +} + +void xalarm_UnRegister(int client_id) +{ + int ret; + + if (!g_register_info.is_registered) { + printf("%s: alarm has not registered\n", __func__); + return; + } + + if (client_id != 0) { + printf("%s: invalid client\n", __func__); + return; + } + + if (g_register_info.register_tid != ULONG_MAX) { + g_register_info.thread_should_stop = 1; + pthread_join(g_register_info.register_tid, NULL); + g_register_info.register_tid = ULONG_MAX; + } + + if (g_register_info.register_fd != -1) { + (void)close(g_register_info.register_fd); + g_register_info.register_fd = -1; + ret = unlink(PATH_REG_ALARM); + if (ret != 0) { + printf("%s: unlink register socket file failed\n", __func__); + } + } + + memset_s(g_register_info.alarm_enable_bitmap, MAX_NUM_OF_ALARM_ID * sizeof(char), + 0, MAX_NUM_OF_ALARM_ID * sizeof(char)); + g_register_info.callback = NULL; + g_register_info.is_registered = false; +} + +/* return 0 if invalid id\level\type */ +unsigned short xalarm_getid(const struct alarm_info *palarm) +{ + return palarm == NULL ? 0 : palarm->usAlarmId; +} + +unsigned char xalarm_getlevel(const struct alarm_info *palarm) +{ + return palarm == NULL ? 0 : palarm->ucAlarmLevel; +} + +unsigned char xalarm_gettype(const struct alarm_info *palarm) +{ + return palarm == NULL ? 0 : palarm->ucAlarmType; +} + +long long xalarm_gettime(const struct alarm_info *palarm) +{ + return palarm == NULL ? 0 : ((long long)(palarm->AlarmTime.tv_sec) * TIME_UNIT_MILLISECONDS + + (long long)(palarm->AlarmTime.tv_usec) / TIME_UNIT_MILLISECONDS); +} + +char *xalarm_getdesc(const struct alarm_info *palarm) +{ + return palarm == NULL ? NULL : (char *)palarm->pucParas; +} + +static int init_report_addr(struct sockaddr_un *alarm_addr) +{ + int ret; + + if (alarm_addr == NULL) { + fprintf(stderr, "%s: alarm_addr is null\n", __func__); + return -1; + } + + ret = memset_s(alarm_addr, sizeof(struct sockaddr_un), 0, sizeof(struct sockaddr_un)); + if (ret != 0) { + fprintf(stderr, "%s: memset_s alarm_addr failed, ret: %d\n", __func__, ret); + return -1; + } + alarm_addr->sun_family = AF_UNIX; + ret = strncpy_s(alarm_addr->sun_path, sizeof(alarm_addr->sun_path), PATH_REPORT_ALARM, + sizeof(alarm_addr->sun_path) - 1); + if (ret != 0) { + fprintf(stderr, "%s: strncpy_s alarm_addr->sun_path failed, ret: %d\n", __func__, ret); + return -1; + } + + return 0; +} + +int xalarm_Report(unsigned short usAlarmId, unsigned char ucAlarmLevel, + unsigned char ucAlarmType, char *pucParas) +{ + int ret, fd; + struct alarm_info info; + struct sockaddr_un alarm_addr; + + if ((usAlarmId < MIN_ALARM_ID || usAlarmId > MAX_ALARM_ID) || + (ucAlarmLevel < ALARM_LEVEL_FATAL || ucAlarmLevel > ALARM_LEVEL_DEBUG) || + (ucAlarmType < ALARM_TYPE_OCCUR || ucAlarmType > ALARM_TYPE_RECOVER)) { + fprintf(stderr, "%s: alarm info invalid\n", __func__); + return -1; + } + + ret = memset_s(&info, sizeof(struct alarm_info), 0, sizeof(struct alarm_info)); + if (ret != 0) { + fprintf(stderr, "%s: memset_s info failed, ret: %d\n", __func__, ret); + return -1; + } + info.usAlarmId = usAlarmId; + info.ucAlarmLevel = ucAlarmLevel; + info.ucAlarmType = ucAlarmType; + gettimeofday(&info.AlarmTime, NULL); + if (pucParas != NULL) { + ret = strncpy_s((char *)info.pucParas, MAX_PARAS_LEN, (char *)pucParas, MAX_PARAS_LEN - 1); + if (ret != 0) { + fprintf(stderr, "%s: strncpy_s info.pucParas failed, ret: %d\n", __func__, ret); + return -1; + } + } + + fd = socket(AF_UNIX, SOCK_DGRAM, 0); + if (fd < 0) { + fprintf(stderr, "%s socket create error: %s\n", __func__, strerror(errno)); + return -1; + } + + ret = init_report_addr(&alarm_addr); + if (ret == -1) { + close(fd); + return -1; + } + + while (true) { + ret = sendto(fd, &info, sizeof(struct alarm_info), 0, (struct sockaddr *)&alarm_addr, + sizeof(alarm_addr.sun_family) + strlen(alarm_addr.sun_path)); + if (ret < 0) { + if (errno == EINTR) { + /* interrupted by signal, ignore */ + continue; + } else { + fprintf(stderr, "%s: sendto failed errno: %d\n", __func__, errno); + } + } else if (ret == 0) { + fprintf(stderr, "%s: sendto failed, ret is 0\n", __func__); + } else { + if (ret != (int)sizeof(struct alarm_info)) { + fprintf(stderr, "%s sendto failed, ret:%d, len:%u\n", __func__, ret, sizeof(struct alarm_info)); + } + } + break; + } + close(fd); + + return (ret > 0) ? 0 : -1; +} diff --git a/sysSentry-1.0.2/src/libso/xalarm/register_xalarm.h b/sysSentry-1.0.2/src/libso/xalarm/register_xalarm.h new file mode 100644 index 0000000000000000000000000000000000000000..8e911a309439227e7c1d85df7f121f5bd83e38fe --- /dev/null +++ b/sysSentry-1.0.2/src/libso/xalarm/register_xalarm.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2023-2024. All rights reserved. + * Description: inspection message alarm program + * Author: Lan Sheng + * Create: 2023-10-23 + */ + +#ifndef __REGISTER_XALARM_H +#define __REGISTER_XALARM_H + +#include +#include + +#define ALARM_INFO_MAX_PARAS_LEN 512 +#define MAX_STRERROR_SIZE 1024 +#define MAX_ALARM_TYEPS 1024 +#define MIN_ALARM_ID 1001 +#define BYTE_TO_BITS 8 + +#define MEMORY_ALARM_ID 1001 + +#define ALARM_LEVEL_FATAL 1 +#define ALARM_LEVEL_ERROR 2 +#define ALARM_LEVEL_WARNING 3 +#define ALARM_LEVEL_INFO 4 +#define ALARM_LEVEL_DEBUG 5 + +#define ALARM_TYPE_OCCUR 1 +#define ALARM_TYPE_RECOVER 2 + +#define MAX_NUM_OF_ALARM_ID 128 + +/* + * usAlarmId:unsigned short,告警id,某一类故障一个id,id定义避免重复。 + * ucAlarmLevel: 告警级别,从FATAL到DEBUG + * ucAlarmType:unsigned char,告警类别,表示告警产生或告警恢复(对用户呈现需要用户操作的故障恢复) + * AlarmTime:struct timeval,告警生成时间戳 + * pucParas:unsigned char*,告警描述信息 + */ +/* socket 通信格式 */ +struct alarm_info { + unsigned short usAlarmId; + unsigned char ucAlarmLevel; + unsigned char ucAlarmType; + struct timeval AlarmTime; + char pucParas[ALARM_INFO_MAX_PARAS_LEN]; +}; + +/* + * hook回调函数处理 + * Notes : 下述函数不支持多线程,不是信号安全函数 + */ +typedef void (*alarm_callback_func)(struct alarm_info *palarm); + +struct alarm_subscription_info { + int id_list[MAX_NUM_OF_ALARM_ID]; + unsigned int len; +}; + +int xalarm_Register(alarm_callback_func callback, struct alarm_subscription_info id_filter); +void xalarm_UnRegister(int client_id); +bool xalarm_Upgrade(struct alarm_subscription_info id_filter, int client_id); + +unsigned short xalarm_getid(const struct alarm_info *palarm); +unsigned char xalarm_gettype(const struct alarm_info *palarm); +unsigned char xalarm_getlevel(const struct alarm_info *palarm); +long long xalarm_gettime(const struct alarm_info *palarm); +char *xalarm_getdesc(const struct alarm_info *palarm); + +int xalarm_Report(unsigned short usAlarmId, + unsigned char ucAlarmLevel, + unsigned char ucAlarmType, + char *pucParas); + +#endif diff --git a/sysSentry-1.0.2/src/python/sentry b/sysSentry-1.0.2/src/python/sentry new file mode 100644 index 0000000000000000000000000000000000000000..07f806c06e37654e86721d66bf099c77cdcc7de2 --- /dev/null +++ b/sysSentry-1.0.2/src/python/sentry @@ -0,0 +1,6 @@ +#!/bin/bash +# Copyright (c), 2023-2024, Huawei Tech. Co., Ltd. + +SCRIPT_DIR=$(cd "$(dirname "$0")";pwd) +export PYTHONPATH=$PYTHONPATH:$SCRIPT_DIR +/usr/bin/python3 -m syssentry $@ diff --git a/sysSentry-1.0.2/src/python/setup.py b/sysSentry-1.0.2/src/python/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..2c086a74b49b15db6520729a3dd2becdfbb30665 --- /dev/null +++ b/sysSentry-1.0.2/src/python/setup.py @@ -0,0 +1,36 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +project setup. +""" +from setuptools import setup, find_packages + + +setup( + name="syssentry", + version="1.0.1", + description="System inspection framework tool set", + packages=find_packages(), + include_package_data=True, + classifiers=[ + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: 3.9', + ], + entry_points={ + 'console_scripts': [ + 'syssentry=syssentry.syssentry:main', + 'xalarmd=xalarm.xalarm_daemon:alarm_process_create' + ] + }, +) diff --git a/sysSentry-1.0.2/src/python/syssentry/__init__.py b/sysSentry-1.0.2/src/python/syssentry/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/sysSentry-1.0.2/src/python/syssentry/__main__.py b/sysSentry-1.0.2/src/python/syssentry/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..662da31a34ec38baf5166496f8d8d53d43dee211 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/__main__.py @@ -0,0 +1,17 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +main +""" +from syssentry import syssentry + +syssentry.main() diff --git a/sysSentry-1.0.2/src/python/syssentry/callbacks.py b/sysSentry-1.0.2/src/python/syssentry/callbacks.py new file mode 100644 index 0000000000000000000000000000000000000000..a13c5272ad2e25ba854583312ee9ebccb5039d04 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/callbacks.py @@ -0,0 +1,91 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +callback methods. +""" +import json +import logging + + +from .task_map import TasksMap, ONESHOT_TYPE, PERIOD_TYPE +from .mod_status import EXITED_STATUS, RUNNING_STATUS, WAITING_STATUS, set_runtime_status + + +def task_get_status(mod_name): + """get status by mod name""" + task = TasksMap.get_task_by_name(mod_name) + if not task: + return "failed", "cannot find task by name" + if not task.load_enabled: + return "failed", "mod is not enabled" + + return "success", task.get_status() + + +def task_stop(mod_name): + """stop by mod name""" + ret = "success" + res = "" + + task = TasksMap.get_task_by_name(mod_name) + if task: + if not task.load_enabled: + return "failed", "mod is not enabled" + logging.info("%s stop", mod_name) + if task.runtime_status == EXITED_STATUS: + return "success", "task already stoped" + if task.runtime_status == WAITING_STATUS: + set_runtime_status(task.name, EXITED_STATUS) + return "success", "" + task.stop() + else: + ret = "failed" + res = "task not exist" + + return ret, res + + +def task_start(mod_name): + """start by mod name""" + ret = "success" + res = "" + + task = TasksMap.get_task_by_name(mod_name) + if task: + if not task.load_enabled: + return "failed", "mod is not enabled" + if task.runtime_status == RUNNING_STATUS: + return "failed", "task is running, please wait" + logging.info("%s start", mod_name) + result, msg = task.start() + ret = "success" if result else "failed" + res = msg + else: + ret = "failed" + res = "task not exist" + + return ret, res + + +def mod_list_show(): + """show mod list""" + ret = "success" + res_dict = {ONESHOT_TYPE: [], PERIOD_TYPE: []} + for key in res_dict: + type_list = TasksMap.tasks_dict.get(key) + for task_name in type_list: + task = type_list.get(task_name) + if not task.load_enabled: + continue + res_dict.get(key).append((task_name, task.runtime_status)) + res = json.dumps(res_dict) + return ret, res diff --git a/sysSentry-1.0.2/src/python/syssentry/cron_process.py b/sysSentry-1.0.2/src/python/syssentry/cron_process.py new file mode 100644 index 0000000000000000000000000000000000000000..23e26dc9efb09d689fca21f8d96aeb58d1a381b5 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/cron_process.py @@ -0,0 +1,112 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +period task. +""" +import io +import os +import time +import logging +import subprocess + +from .global_values import InspectTask +from .task_map import TasksMap, PERIOD_TYPE +from .mod_status import set_runtime_status, WAITING_STATUS, RUNNING_STATUS, \ + FAILED_STATUS, EXITED_STATUS + + +class PeriodTask(InspectTask): + """period task class""" + def __init__(self, name: str, task_type: str, task_start: str, task_stop: str, interval): + super().__init__(name, task_type, task_start, task_stop) + self.interval = int(interval) + self.last_exec_timestamp = 0 + self.runtime_status = WAITING_STATUS + + def stop(self): + self.period_enabled = False + cmd_list = self.task_stop.split() + try: + subprocess.Popen(cmd_list, stdout=subprocess.PIPE, close_fds=True) + except OSError: + logging.error("task stop Popen failed, invalid cmd") + if self.runtime_status != RUNNING_STATUS: + self.runtime_status = EXITED_STATUS + + def start(self): + if not self.period_enabled: + self.period_enabled = True + self.upgrade_period_timestamp() + + cmd_list = self.task_start.split() + try: + logfile = open(self.log_file, 'a') + os.chmod(self.log_file, 0o600) + except OSError: + logging.error("task %s log_file %s open failed", self.name, self.log_file) + logfile = subprocess.PIPE + try: + child = subprocess.Popen(cmd_list, stdout=logfile, + stderr=subprocess.STDOUT, close_fds=True) + except OSError: + logging.error("period task %s start Popen failed", self.name) + self.runtime_status = FAILED_STATUS + return False, "period task start popen failed, invalid command" + finally: + if isinstance(logfile, io.TextIOWrapper) and not logfile.closed: + logfile.close() + + self.pid = child.pid + logging.debug("start task %s pid %d", self.name, self.pid) + self.runtime_status = RUNNING_STATUS + if self.heartbeat_interval > 0: + self.last_heartbeat = time.perf_counter() + return True, "" + + def check_period_timestamp(self): + """check timestamp for period mod""" + if self.last_exec_timestamp == 0: + logging.debug("first time exec this task") + return True + cur_timestamp = time.perf_counter() + if cur_timestamp >= (self.interval + self.last_exec_timestamp): + logging.debug("check period time success") + return True + return False + + def upgrade_period_timestamp(self): + """upgrade timestamp for period mod""" + cur_timestamp = time.perf_counter() + + self.last_exec_timestamp = cur_timestamp + logging.debug("period current timestamp %d", self.last_exec_timestamp) + + +def period_tasks_handle(): + """period tasks handler""" + period_list = TasksMap.tasks_dict.get(PERIOD_TYPE) + for task_name in period_list: + task = period_list.get(task_name) + if not task.load_enabled: + continue + + if not task.period_enabled: + logging.debug("period not enabled") + continue + + if task.runtime_status == WAITING_STATUS and \ + task.check_period_timestamp(): + logging.info("period task exec! name: %s", task.name) + res, _ = task.start() + if res: + set_runtime_status(task.name, RUNNING_STATUS) + task.upgrade_period_timestamp() diff --git a/sysSentry-1.0.2/src/python/syssentry/global_values.py b/sysSentry-1.0.2/src/python/syssentry/global_values.py new file mode 100644 index 0000000000000000000000000000000000000000..e93591f7ca68bbc16801b651ee282db9d8331a9d --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/global_values.py @@ -0,0 +1,108 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +period task and global values. +""" +import io +import subprocess +import logging +import time +import os + + +SENTRY_RUN_DIR = "/var/run/sysSentry" +CTL_SOCKET_PATH = "/var/run/sysSentry/control.sock" +SYSSENTRY_CONF_PATH = "/etc/sysSentry" +INSPECT_CONF_PATH = "/etc/sysSentry/inspect.conf" +TASK_LOG_DIR = "/var/log/sysSentry" + +SENTRY_RUN_DIR_PERM = 0o750 + +TYPES_SET = ('oneshot', 'period') + +# cron process obj +CRON_PROCESS_OBJ = None +# cron task queue +CRON_QUEUE = None + +TASKS_STORAGE_PATH = "/etc/sysSentry/tasks" + + +class InspectTask: + """oneshot task class""" + def __init__(self, name: str, task_type: str, start_task: str, stop_task: str): + self.name = name + self.type = task_type + self.status = "ERROR" + # runtime information + self.runtime_status = "EXITED" + self.pid = -1 + # task attribute + self.task_start = start_task + self.task_stop = stop_task + # task heartbeat attribute + self.heartbeat_interval = -1 + self.last_heartbeat = -1 + # task progress attribute + self.cur_progress = 0 + # task log file + self.log_file = TASK_LOG_DIR + '/' + name + '.log' + self.period_enabled = True + # load enabled + self.load_enabled = True + + # start function we use async mode + # when we have called the start command, function return + def start(self): + """start""" + if not self.period_enabled: + self.period_enabled = True + if self.runtime_status in ("EXITED", "FAILED"): + cmd_list = self.task_start.split() + try: + logfile = open(self.log_file, 'a') + os.chmod(self.log_file, 0o600) + except OSError: + logging.error("task %s log_file %s open failed", self.name, self.log_file) + logfile = subprocess.PIPE + try: + child = subprocess.Popen(cmd_list, stdout=logfile, stderr=subprocess.STDOUT, close_fds=True) + except OSError: + logging.error("task %s start Popen error, invalid cmd") + self.runtime_status = "FAILED" + return False, "start command is invalid, popen failed" + finally: + if isinstance(logfile, io.TextIOWrapper) and not logfile.closed: + logfile.close() + + self.pid = child.pid + logging.debug("start task %s pid %d", self.name, self.pid) + self.runtime_status = "RUNNING" + if self.heartbeat_interval > 0: + self.last_heartbeat = time.perf_counter() + return True, "start task success" + return True, "task is running, please wait finish" + + def stop(self): + """stop""" + self.period_enabled = False + if self.runtime_status == "RUNNING": + cmd_list = self.task_stop.split() + try: + subprocess.Popen(cmd_list, stdout=subprocess.PIPE, close_fds=True) + except OSError: + logging.error("task %s stop Popen failed") + logging.debug("stop task %s", self.name) + + def get_status(self): + """get status""" + return self.runtime_status diff --git a/sysSentry-1.0.2/src/python/syssentry/heartbeat.py b/sysSentry-1.0.2/src/python/syssentry/heartbeat.py new file mode 100644 index 0000000000000000000000000000000000000000..137e2568993f30dd297804b060a9985f16563bc6 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/heartbeat.py @@ -0,0 +1,173 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +heartbeat for task. +""" +import signal +import time +import os +import logging +import socket + +from .mod_status import set_runtime_status, RUNNING_STATUS, FAILED_STATUS +from .global_values import SENTRY_RUN_DIR +from .task_map import TasksMap + +THB_SOCKET_PATH = "/var/run/sysSentry/heartbeat.sock" +THB_MAGIC = 'THB' +THB_MSG_HEAD_LEN = 6 +THB_MSG_MAGIC_LEN = 3 +THB_MSG_LEN_LEN = 3 + + +def hb_timeout_chk_interval(task): + """heartbeat timeout check interval""" + if task.runtime_status != RUNNING_STATUS: + return + + if task.last_heartbeat <= 0: + return + + cur_timestamp = time.perf_counter() + if cur_timestamp > task.last_heartbeat + task.heartbeat_interval: + logging.error("task %s heartbeat timeout, last heartbeat time %d", task.name, task.last_heartbeat) + set_runtime_status(task.name, FAILED_STATUS) + if task.pid > 0: + logging.info("killed heartbeat timeout task %s, pid is %d", task.name, task.pid) + try: + os.kill(task.pid, signal.SIGTERM) + except os.error as os_error: + logging.error("heartbeat timeout kill failed, %s", str(os_error)) + + +def heartbeat_timeout_chk(): + """heartbeat timeout check""" + tasks_dict = TasksMap.tasks_dict + + for task_type in tasks_dict: + for task_name in tasks_dict.get(task_type): + task = tasks_dict.get(task_type).get(task_name) + hb_timeout_chk_interval(task) + + +def thb_head_process(msg_head): + """heatbeat head process""" + ctl_magic = msg_head[:THB_MSG_MAGIC_LEN] + if ctl_magic != THB_MAGIC: + logging.error("recv heartbeat head magic invalid: %s", ctl_magic) + return -1 + + data_len_str = msg_head[THB_MSG_MAGIC_LEN:THB_MSG_HEAD_LEN] + try: + data_len = int(data_len_str) + except ValueError: + logging.error("heartbeat data len is invalid %s", data_len_str) + return -1 + + return data_len + + +def heartbeat_recv(heartbeat_socket: socket.socket): + """heartbeat receiver""" + try: + client_socket, _ = heartbeat_socket.accept() + except OSError: + logging.error("heartbeat accept failed") + return + + try: + msg_head = client_socket.recv(THB_MSG_HEAD_LEN) + except OSError: + logging.error("heartbeat recv head failed") + client_socket.close() + return + + try: + logging.debug("hb recv msg head: %s", msg_head.decode()) + data_len = thb_head_process(msg_head.decode()) + except UnicodeError: + logging.error("heartbeat data length reading failed") + client_socket.close() + return + + if data_len < 0: + logging.error("heartbeat msg head parse failed") + client_socket.close() + return + logging.debug("hb msg data length: %d", data_len) + + try: + task_name = client_socket.recv(data_len).decode() + except (OSError, UnicodeError): + logging.error("heartbeat recv msg failed") + client_socket.close() + return + + logging.debug("hb msg data %s", task_name) + + task = TasksMap.get_task_by_name(task_name) + if not task: + logging.error("heartbeat msg: cannot find mod by name %s", task_name) + client_socket.close() + return + + if task.runtime_status != RUNNING_STATUS: + logging.info("task %s is not running, but received heartbeat msg", task_name) + client_socket.close() + return + + if task.heartbeat_interval <= 0: + logging.debug("%s heartbeat not enabled", task.name) + client_socket.close() + return + + cur_timestamp = time.perf_counter() + task.last_heartbeat = cur_timestamp + logging.info("task %s heartbeat upgrade success, current time is %d", task.name, cur_timestamp) + + client_socket.close() + + +def heartbeat_fd_create(): + """create heartbeat fd""" + if not os.path.exists(SENTRY_RUN_DIR): + logging.debug("%s not exist", SENTRY_RUN_DIR) + return None + + try: + heartbeat_fd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + except socket.error: + logging.error("heartbeat fd create failed") + return None + + heartbeat_fd.setblocking(False) + if os.path.exists(THB_SOCKET_PATH): + os.remove(THB_SOCKET_PATH) + + try: + heartbeat_fd.bind(THB_SOCKET_PATH) + except OSError: + logging.error("heartbeat fd bind failed") + heartbeat_fd.close() + return None + + os.chmod(THB_SOCKET_PATH, 0o600) + try: + heartbeat_fd.listen(5) + except OSError: + logging.error("heartbeat fd listen failed") + heartbeat_fd.close() + return None + + logging.debug("%s bind and listen", THB_SOCKET_PATH) + + return heartbeat_fd diff --git a/sysSentry-1.0.2/src/python/syssentry/load_mods.py b/sysSentry-1.0.2/src/python/syssentry/load_mods.py new file mode 100644 index 0000000000000000000000000000000000000000..6bf38627a9cd07d6612b5a1f1624702ad52931f4 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/load_mods.py @@ -0,0 +1,307 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +load mod from file. +""" +import os +import logging +import configparser +import re + +from .sentry_config import SentryConfig + +from .global_values import TYPES_SET, InspectTask, TASKS_STORAGE_PATH, SYSSENTRY_CONF_PATH +from .task_map import TasksMap, ONESHOT_TYPE, PERIOD_TYPE +from .cron_process import PeriodTask +from .mod_status import set_task_status + +ONESHOT_CONF = 'oneshot' +PERIOD_CONF = 'period' + +CONF_TASK = 'common' +CONF_NAME = 'name' +CONF_TYPE = 'type' +CONF_ENABLED = 'enabled' +CONF_TASK_START = 'task_start' +CONF_TASK_STOP = 'task_stop' +CONF_TASK_RELOAD = 'task_reload' +CONF_PERIOD_INTERVAL = 'interval' +CONF_HEARTBEAT_INTERVAL = 'heartbeat_interval' +CONF_HEARTBEAT_ACTION = 'heartbeat_action' +CONF_TASK_RESTART = 'task_restart' + +MOD_FILE_SUFFIX = '.mod' +MOD_SUFFIX_LEN = 4 + +ENABLED_FLAGS_SET = ("yes", "no") + + +def mod_name_verify(mod_name): + """ + :param mod_path: + :return: + """ + mod_path_all = os.path.join(TASKS_STORAGE_PATH, mod_name + ".mod") + real_path = os.path.realpath(mod_path_all) + if not real_path.startswith(TASKS_STORAGE_PATH): + return False + + mod_base_name = os.path.basename(real_path) + if mod_base_name != mod_name + ".mod": + return False + + # add mod name character type check + pattern = r'^\w+$' + if not bool(re.match(pattern, mod_name)): + return False + + mod_path = os.path.join(TASKS_STORAGE_PATH, mod_base_name) + if mod_path != real_path: + return False + + if not os.path.exists(mod_path): + return False + + return True + + +def chk_enabled_conf(mod_conf): + """ + :param mod_conf: + :return: + """ + if CONF_ENABLED not in mod_conf[CONF_TASK]: + logging.error("enabled not in this mod file") + return False + enabled_flag = mod_conf[CONF_TASK][CONF_ENABLED] + if enabled_flag not in ENABLED_FLAGS_SET: + logging.error("enabled conf error %s", enabled_flag) + return False + + return True + + +def chk_type_conf(mod_conf): + """ + :param mod_conf: + :return: + """ + if CONF_TYPE not in mod_conf[CONF_TASK] or \ + CONF_TASK_START not in mod_conf[CONF_TASK] or \ + CONF_TASK_STOP not in mod_conf[CONF_TASK]: + return False + + if mod_conf[CONF_TASK][CONF_TYPE] not in TYPES_SET: + return False + + return True + + +def parse_heartbeat_conf(mod_conf): + """ + :param mod_conf: + :return: + """ + heartbeat_interval = -1 + try: + heartbeat_interval = int(mod_conf[CONF_TASK][CONF_HEARTBEAT_INTERVAL]) + except ValueError: + logging.error("heartbeat interval is invalid") + heartbeat_interval = -1 + + if heartbeat_interval <= 0: + logging.error("heartbeat interval %d is invalid", heartbeat_interval) + heartbeat_interval = -1 + + if heartbeat_interval < 60: + logging.warning("hearbeat_interval cannot be less than 60, set to 60") + heartbeat_interval = 60 + + return heartbeat_interval + + +def parse_period_delay(mod_conf): + """ + :param mod_conf: + :return: + """ + if CONF_PERIOD_INTERVAL not in mod_conf[CONF_TASK]: + cron_delay = SentryConfig.inspect_delay + logging.debug("period delay use global value %s", cron_delay) + return cron_delay + + try: + cron_delay = int(mod_conf[CONF_TASK][CONF_PERIOD_INTERVAL]) + except ValueError: + logging.error("period delay is invalid") + cron_delay = SentryConfig.inspect_delay + if cron_delay <= 0: + logging.error("period delay is invalid") + cron_delay = SentryConfig.inspect_delay + logging.debug("period delay is %s", cron_delay) + + return cron_delay + + +def parse_mod_conf(mod_name, mod_conf): + """ + :param mod_name: + :param mod_conf: + :return: + """ + if not mod_conf.has_section(CONF_TASK): + logging.error("common not in this mod file") + return None + if not chk_enabled_conf(mod_conf): + return None + if not chk_type_conf(mod_conf): + logging.error("mod %s: type conf is invalid", mod_name) + return None + + is_enabled = (mod_conf.get(CONF_TASK, CONF_ENABLED) == 'yes') + + task_type = mod_conf.get(CONF_TASK, CONF_TYPE) + task_start_cmd = mod_conf.get(CONF_TASK, CONF_TASK_START) + task_stop_cmd = mod_conf.get(CONF_TASK, CONF_TASK_STOP) + heartbeat_interval = -1 + logging.debug("task method: start: %s stop: %s", task_start_cmd, task_stop_cmd) + if CONF_HEARTBEAT_INTERVAL in mod_conf.options(CONF_TASK): + heartbeat_interval = parse_heartbeat_conf(mod_conf) + logging.debug("task heartbeat is enabled, interval is %d", heartbeat_interval) + + cron_delay = None + if task_type == PERIOD_CONF: + logging.debug("task is a period task") + cron_delay = parse_period_delay(mod_conf) + task = PeriodTask(mod_name, task_type.upper(), task_start_cmd, task_stop_cmd, cron_delay) + task.task_stop = task_stop_cmd + else: + task_type = ONESHOT_TYPE + task = InspectTask(mod_name, task_type, task_start_cmd, task_stop_cmd) + task.heartbeat_interval = heartbeat_interval + task.load_enabled = is_enabled + + return task + + +def load_tasks(): + """load tasks""" + logging.debug("enter load_tasks") + # mod files store in /etc/sysSentry/tasks/ + if not os.path.exists(SYSSENTRY_CONF_PATH): + logging.error("%s not existed", SYSSENTRY_CONF_PATH) + return "failed", "" + if not os.path.exists(TASKS_STORAGE_PATH): + logging.error("%s not existed", TASKS_STORAGE_PATH) + return "failed", "" + + mod_files = os.listdir(TASKS_STORAGE_PATH) + for mod_file in mod_files: + logging.debug("find mod, path is %s", mod_file) + if not mod_file.endswith(MOD_FILE_SUFFIX): + continue + mod_name = mod_file[:-MOD_SUFFIX_LEN] + + if not mod_name_verify(mod_name): + logging.error("mod name invalid: %s", mod_name) + continue + + try: + mod_conf = configparser.ConfigParser() + mod_conf.read(os.path.join(TASKS_STORAGE_PATH, mod_file)) + except configparser.Error: + logging.error("configparser parse configure file") + continue + + new_task = parse_mod_conf(mod_name, mod_conf) + if not new_task: + logging.error("mod %s load failed", mod_name) + continue + TasksMap.add_task(new_task, new_task.type, mod_name) + set_task_status(mod_name, "LOADED") + + return "success", "" + + +def chk_reload_type(mod_name, mod_conf): + """check reload type""" + if CONF_TASK not in mod_conf: + logging.error("common not in mod configure") + return False + + if CONF_TYPE not in mod_conf[CONF_TASK]: + logging.error("type not in mod configure") + return False + + new_type = mod_conf[CONF_TASK][CONF_TYPE].upper() + for task_type in TasksMap.tasks_dict: + if mod_name in TasksMap.tasks_dict[task_type]: + cur_task = TasksMap.tasks_dict[task_type][mod_name] + if cur_task.type != new_type: + logging.error("reload: type of mod %s is changed, cannot reload", mod_name) + return False + + return True + + +def reload_mod_by_name(mod_name): + """reload mod by name""" + if not os.path.exists(SYSSENTRY_CONF_PATH): + logging.error("%s not existed", SYSSENTRY_CONF_PATH) + return "failed", "conf dir not exist" + if not os.path.exists(TASKS_STORAGE_PATH): + logging.error("%s not existed", TASKS_STORAGE_PATH) + return "failed", "conf dir not exist" + + try: + mod_conf = configparser.ConfigParser() + mod_path = TASKS_STORAGE_PATH + "/" + mod_name + ".mod" + mod_conf.read(mod_path) + except configparser.Error: + logging.error("config parse failed") + return "failed", "config parse failed" + + if not chk_reload_type(mod_name, mod_conf): + return "failed", "type of mod is different from old type, reload failed" + + new_task = parse_mod_conf(mod_name, mod_conf) + if not new_task: + return "failed", "parse mod conf failed" + + if not TasksMap.is_task_exist(mod_name): + logging.debug("reload_single_mod cannot find %s", mod_name) + TasksMap.add_task(new_task, new_task.type, mod_name) + set_task_status(mod_name, "LOADED") + else: + task = TasksMap.get_task_by_name(mod_name) + task.task_start = new_task.task_start + task.task_stop = new_task.task_stop + task.load_enabled = new_task.load_enabled + task.heartbeat_interval = new_task.heartbeat_interval + if task.type == PERIOD_TYPE: + task.interval = new_task.interval + set_task_status(mod_name, "LOADED") + + return "success", "" + + +def reload_single_mod(mod_name): + """reload single mod by name""" + res = "success" + ret = "" + + if not mod_name_verify(mod_name): + return "failed", "mod name invalid" + + res, ret = reload_mod_by_name(mod_name) + + return res, ret diff --git a/sysSentry-1.0.2/src/python/syssentry/mod_status.py b/sysSentry-1.0.2/src/python/syssentry/mod_status.py new file mode 100644 index 0000000000000000000000000000000000000000..b8c7b830bcdb799ad702c0e8be38a95eedf0be65 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/mod_status.py @@ -0,0 +1,73 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +Manage mod status. +""" +import logging + +from .task_map import TasksMap, ONESHOT_TYPE, PERIOD_TYPE + +ONESHOT_MOD_STATUS = ("UNLOADED", "LOADED", "ERROR") +PERIOD_MOD_STATUS = ("UNLOADED", "LOADED", "ERROR") + +ONESHOT_RUNTIME_STATUS = ("RUNNING", "EXITED", "FAILED") +PERIOD_RUNTIME_STATUS = ("RUNNING", "WAITING", "FAILED", "EXITED") + +RUNNING_STATUS = "RUNNING" +EXITED_STATUS = "EXITED" +FAILED_STATUS = "FAILED" +WAITING_STATUS = "WAITING" + + +def set_task_status(task_name, status_code): + """set task status""" + task_type = TasksMap.get_task_type(task_name) + if not task_type: + return + + if task_type == ONESHOT_TYPE and status_code in ONESHOT_MOD_STATUS: + pass + elif task_type == PERIOD_TYPE and status_code in PERIOD_MOD_STATUS: + pass + else: + return + + TasksMap.tasks_dict.get(task_type).get(task_name).status = status_code + return + + +def set_runtime_status(task_name, status_code): + """set runtime status""" + task_type = TasksMap.get_task_type(task_name) + if not task_type: + logging.error("cannot find task by task name %s", task_name) + return + + if task_type == ONESHOT_TYPE and status_code in ONESHOT_RUNTIME_STATUS: + pass + elif task_type == PERIOD_TYPE and status_code in PERIOD_RUNTIME_STATUS: + pass + else: + logging.error("invaild task name") + return + + TasksMap.tasks_dict.get(task_type).get(task_name).runtime_status = status_code + return + + +def get_task_by_pid(pid): + """get task by pid""" + for task_type in TasksMap.tasks_dict: + for task_name in TasksMap.tasks_dict.get(task_type): + if TasksMap.tasks_dict.get(task_type).get(task_name).pid == pid: + return TasksMap.tasks_dict.get(task_type).get(task_name) + return None diff --git a/sysSentry-1.0.2/src/python/syssentry/sentry_config.py b/sysSentry-1.0.2/src/python/syssentry/sentry_config.py new file mode 100644 index 0000000000000000000000000000000000000000..ad1d2e49511dac08752de167f86d4477972f37d7 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/sentry_config.py @@ -0,0 +1,61 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +Read and save inspect.conf value. +""" +import configparser +import logging + + +DEFAULT_INSPECT_DELAY = 3 +INSPECT_CONF_PATH = "/etc/sysSentry/inspect.conf" + + +class SentryConfig: + """ + SentryConfig class, saving inspect.conf value + """ + inspect_delay = -1 + + @staticmethod + def init_param(conf_path=INSPECT_CONF_PATH): + """initialize reading params from inspect.conf""" + SentryConfig.inspect_delay = DEFAULT_INSPECT_DELAY + + try: + inspect_conf = configparser.ConfigParser() + inspect_conf.read(conf_path) + except configparser.Error: + logging.error("inspect configure file read failed") + return False + + if SentryConfig.check_conf(inspect_conf): + try: + insp_delay = int(inspect_conf['inspect']['Interval']) + except ValueError: + logging.error("inspect delay value not valid") + return False + logging.debug("inspect delay is %d", insp_delay) + SentryConfig.inspect_delay = insp_delay + return True + return False + + @staticmethod + def check_conf(inspect_conf): + """check if conf valid""" + if 'inspect' not in inspect_conf: + logging.debug("inspect config not exist") + return False + if 'Interval' not in inspect_conf['inspect']: + logging.debug("Interval conf not exist") + return False + return True diff --git a/sysSentry-1.0.2/src/python/syssentry/sentryctl b/sysSentry-1.0.2/src/python/syssentry/sentryctl new file mode 100644 index 0000000000000000000000000000000000000000..f6e636e42d51333530abe6a39d0448872c15c39a --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/sentryctl @@ -0,0 +1,149 @@ +#!/usr/bin/python3 +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +sentryctl: control command for sysSentry. +""" +import socket +import argparse +import json +import sys + +CTL_SOCKET_PATH = "/var/run/sysSentry/control.sock" +MAX_PARAM_LENGTH = 256 + + +def status_output_format(res_data): + """format output""" + print(f"status: {res_data}") + + +def mod_list_output_format(res_data): + """format output list""" + mod_list = json.loads(res_data) + print("oneshot:") + for mod in mod_list['ONESHOT']: + print(f"\t {mod}") + print("period:") + for mod in mod_list['PERIOD']: + print(f"\t {mod}") + print("") + + +def res_output_handle(res_struct, req_type): + """handle output""" + if req_type == 'mod_list': + mod_list_output_format(res_struct['data']) + elif req_type == 'get_status': + status_output_format(res_struct['data']) + elif res_struct['ret'] == "failed": + print(res_struct['data']) + + +def res_msg_serial(res_msg): + """serial res_msg""" + res_struct = json.loads(res_msg) + return res_struct + + +def client_send_and_recv(request_data): + """client socket send and recv message""" + try: + client_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + except socket.error: + print("sentryctl: client creat socket error") + return None + + try: + client_socket.connect(CTL_SOCKET_PATH) + except OSError: + client_socket.close() + print("sentryctl: client connect error") + return None + + req_data_len = len(request_data) + request_msg = "CTL" + str(req_data_len).zfill(3) + request_data + + try: + client_socket.send(request_msg.encode()) + res_data = client_socket.recv(6) + res_data = res_data.decode() + except (OSError, UnicodeError): + client_socket.close() + print("sentryctl: client communicate error") + return None + + res_magic = res_data[:3] + + if res_magic != "RES": + print("res msg format error") + return None + + try: + res_data_len = int(res_data[3:]) + res_msg_data = client_socket.recv(res_data_len) + res_msg_data = res_msg_data.decode() + return res_msg_data + except (OSError, ValueError, UnicodeError): + print("sentryctl: client recv res msg error") + finally: + client_socket.close() + + return None + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(prog='sentryctl', description='System inspect tools', + allow_abbrev=False) + subparsers = parser.add_subparsers(help="sentryctl: control cmdline for sysSentry", + dest='cmd_type') + parser_start = subparsers.add_parser('start', help='start specified task') + parser_start.add_argument('task_name') + parser_stop = subparsers.add_parser('stop', help='stop specified task') + parser_stop.add_argument('task_name') + parser_reload = subparsers.add_parser('reload', help='reload specified mod') + parser_reload.add_argument('task_name') + parser_status = subparsers.add_parser('status', help='get task status') + parser_status.add_argument('task_name') + parser_list = subparsers.add_parser('list', help='show all loaded task mod') + + client_args = parser.parse_args() + + if client_args.cmd_type == 'list': + req_msg_struct = {"type": "mod_list", "data":""} + elif client_args.cmd_type == 'start': + req_msg_struct = {"type": "start", "data": client_args.task_name} + elif client_args.cmd_type == 'stop': + req_msg_struct = {"type": "stop", "data": client_args.task_name} + elif client_args.cmd_type == 'status': + req_msg_struct = {"type": "get_status", "data": client_args.task_name} + elif client_args.cmd_type == 'reload': + req_msg_struct = {"type": "reload", "data": client_args.task_name} + else: + parser.print_help() + sys.exit(-1) + + if client_args.cmd_type != 'list' and len(client_args.task_name) > MAX_PARAM_LENGTH: + print(f"sentryctl: task name is longer than {MAX_PARAM_LENGTH}") + sys.exit(-1) + + request_message = json.dumps(req_msg_struct) + result_message = client_send_and_recv(request_message) + if not result_message: + print("sentryctl: client_send_and_recv failed") + sys.exit(-1) + + result_struct = res_msg_serial(result_message) + + if result_struct['ret'] != "success": + print(result_struct['ret']) + res_output_handle(result_struct, req_msg_struct['type']) diff --git a/sysSentry-1.0.2/src/python/syssentry/syssentry.py b/sysSentry-1.0.2/src/python/syssentry/syssentry.py new file mode 100644 index 0000000000000000000000000000000000000000..0e3f77370f7c5d6f4a7ca3617d90e73aeff4f867 --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/syssentry.py @@ -0,0 +1,356 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +main loop for syssentry. +""" +import sys +import signal +import traceback +import socket +import os +import json +import logging +import fcntl + +import select + +from .sentry_config import SentryConfig + +from .task_map import TasksMap +from .global_values import SENTRY_RUN_DIR, CTL_SOCKET_PATH, SENTRY_RUN_DIR_PERM +from .cron_process import period_tasks_handle +from .callbacks import mod_list_show, task_start, task_get_status, task_stop +from .mod_status import get_task_by_pid, set_runtime_status +from .load_mods import load_tasks, reload_single_mod +from .heartbeat import (heartbeat_timeout_chk, heartbeat_fd_create, + heartbeat_recv, THB_SOCKET_PATH) + +INSPECTOR = None + +CTL_MSG_HEAD_LEN = 6 +CTL_MSG_MAGIC_LEN = 3 +CTL_MSG_LEN_LEN = 3 +CTL_MAGIC = "CTL" +RES_MAGIC = "RES" + +CTL_LISTEN_QUEUE_LEN = 5 +SERVER_EPOLL_TIMEOUT = 0.3 + +# func contains one arg +type_func = { + 'start': task_start, + 'stop': task_stop, + 'get_status': task_get_status, + 'reload': reload_single_mod +} + +# func has no arg +type_func_void = { + 'mod_list': mod_list_show, +} + +DEV_NULL_PATH = '/dev/null' +ROOT_PATH = '/' + +SYSSENTRY_LOG_FILE = "/var/log/sysSentry/sysSentry.log" + +SYSSENTRY_PID_FILE = "/var/run/sysSentry/sysSentry.pid" +PID_FILE_FLOCK = None + + +def msg_data_process(msg_data): + """message data process""" + logging.debug("msg_data %s", msg_data) + try: + data_struct = json.loads(msg_data) + except json.JSONDecodeError: + logging.error("msg data process: json decode error") + return "Request message decode failed" + + if 'type' not in data_struct: + logging.error("recv message format error, type is not exist") + return "Request message format error" + + if 'data' not in data_struct: + logging.error("recv message format error, data is not exist") + return "Request message format error" + + cmd_type = data_struct['type'] + if cmd_type not in type_func and cmd_type not in type_func_void: + logging.error("recv invaild cmd type: %s", cmd_type) + return "Invaild cmd type" + + cmd_param = data_struct['data'] + logging.debug("msg_data_process cmd_type:%s cmd_param:%s", cmd_type, cmd_param) + if cmd_type in type_func: + ret, res_data = type_func[cmd_type](cmd_param) + else: + ret, res_data = type_func_void[cmd_type]() + res_msg_struct = {"ret": ret, "data": res_data} + res_msg = json.dumps(res_msg_struct) + + return res_msg + + +def msg_head_process(msg_head): + """message head process""" + ctl_magic = msg_head[:CTL_MSG_MAGIC_LEN] + if ctl_magic != CTL_MAGIC: + logging.error("recv msg head magic invalid: %s", ctl_magic) + return -1 + + data_len_str = msg_head[CTL_MSG_LEN_LEN:CTL_MSG_HEAD_LEN] + try: + data_len = int(data_len_str) + except ValueError: + logging.error("recv msg data len is invalid %s", data_len_str) + return -1 + + return data_len + + +def server_recv(server_socket: socket.socket): + """server receive""" + try: + client_socket, _ = server_socket.accept() + logging.debug("server_fd listen ok") + except socket.error: + logging.error("server accept failed") + return + + try: + msg_head = client_socket.recv(CTL_MSG_HEAD_LEN) + logging.debug("recv msg head: %s", msg_head.decode()) + data_len = msg_head_process(msg_head.decode()) + except (OSError, UnicodeError): + client_socket.close() + logging.error("server recv HEAD failed") + return + + logging.debug("msg data length: %d", data_len) + if data_len < 0: + client_socket.close() + logging.error("msg head parse failed") + return + + try: + msg_data = client_socket.recv(data_len) + msg_data_decode = msg_data.decode() + logging.debug("msg data %s", msg_data_decode) + except (OSError, UnicodeError): + client_socket.close() + logging.error("server recv MSG failed") + return + + res_data = msg_data_process(msg_data_decode) + logging.debug("res data %s", res_data) + + res_head = RES_MAGIC + res_data_len = str(len(res_data)).zfill(CTL_MSG_MAGIC_LEN) + res_head += res_data_len + logging.debug("res head %s", res_head) + + res_msg = res_head + res_data + logging.debug("res msg %s", res_msg) + + try: + client_socket.send(res_msg.encode()) + except OSError: + logging.error("server recv failed") + finally: + client_socket.close() + return + + +def server_fd_create(): + """create server fd""" + if not os.path.exists(SENTRY_RUN_DIR): + logging.error("%s not exist, failed", SENTRY_RUN_DIR) + return None + + try: + server_fd = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + server_fd.setblocking(False) + if os.path.exists(CTL_SOCKET_PATH): + os.remove(CTL_SOCKET_PATH) + + server_fd.bind(CTL_SOCKET_PATH) + os.chmod(CTL_SOCKET_PATH, 0o600) + server_fd.listen(CTL_LISTEN_QUEUE_LEN) + logging.debug("%s bind and listen", CTL_SOCKET_PATH) + except socket.error: + logging.error("server fd create failed") + server_fd = None + + return server_fd + + +def main_loop(): + """main loop""" + server_fd = server_fd_create() + if not server_fd: + return + + heartbeat_fd = heartbeat_fd_create() + if not heartbeat_fd: + server_fd.close() + return + + epoll_fd = select.epoll() + epoll_fd.register(server_fd.fileno(), select.EPOLLIN) + epoll_fd.register(heartbeat_fd.fileno(), select.EPOLLIN) + + logging.debug("start main loop") + while True: + try: + events_list = epoll_fd.poll(SERVER_EPOLL_TIMEOUT) + for event_fd, _ in events_list: + if event_fd == server_fd.fileno(): + server_recv(server_fd) + elif event_fd == heartbeat_fd.fileno(): + heartbeat_recv(heartbeat_fd) + else: + continue + + except socket.error: + pass + + # handle period task + period_tasks_handle() + # handle heartbeat msg + heartbeat_timeout_chk() + + +def release_pidfile(): + """ + :return: + """ + try: + pid_file_fd = open(SYSSENTRY_PID_FILE, 'w') + os.chmod(SYSSENTRY_PID_FILE, 0o600) + fcntl.flock(pid_file_fd, fcntl.LOCK_UN) + pid_file_fd.close() + PID_FILE_FLOCK.close() + os.unlink(SYSSENTRY_PID_FILE) + except (IOError, FileNotFoundError): + logging.error("Failed to release PID file lock") + + +def remove_sock_file(): + """remove sock file + """ + try: + os.unlink(THB_SOCKET_PATH) + os.unlink(CTL_SOCKET_PATH) + except FileNotFoundError: + pass + + +def sigchld_handler(signum, _f): + """child sig handler + """ + while True: + try: + child_pid, child_exit_code = os.waitpid(-1, os.WNOHANG) + logging.debug("sigchld pid :%d", child_pid) + task = get_task_by_pid(child_pid) + if not task: + logging.debug("pid %d cannot find task, ignore", child_pid) + break + logging.debug("task name %s", task.name) + if os.WIFEXITED(child_exit_code): + # exit normally with exit() syscall + if task.type == "PERIOD" and task.period_enabled: + set_runtime_status(task.name, "WAITING") + else: + set_runtime_status(task.name, "EXITED") + else: + # exit abnormally + if not task.period_enabled: + set_runtime_status(task.name, "EXITED") + else: + set_runtime_status(task.name, "FAILED") + except: + break + + +def sig_handler(signum, _f): + """ + :param signum: + :param _f: + :return: + """ + if signum not in (signal.SIGINT, signal.SIGTERM): + return + tasks_dict = TasksMap.tasks_dict + for task_type in tasks_dict: + for task_name in tasks_dict[task_type]: + task = tasks_dict[task_type][task_name] + task.stop() + if task.pid > 0: + try: + os.kill(task.pid, signal.SIGTERM) + except os.error as os_error: + logging.debug("sigterm kill error, %s", str(os_error)) + release_pidfile() + remove_sock_file() + sys.exit(0) + + +def chk_and_set_pidfile(): + """ + :return: + """ + try: + pid_file_fd = open(SYSSENTRY_PID_FILE, 'w') + os.chmod(SYSSENTRY_PID_FILE, 0o600) + fcntl.flock(pid_file_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + pid_file_fd.write(str(os.getpid())) + global PID_FILE_FLOCK + PID_FILE_FLOCK = pid_file_fd + return True + except IOError: + logging.error("Failed to get lock on pidfile") + + return False + + +def main(): + """main + """ + if not os.path.exists(SENTRY_RUN_DIR): + os.mkdir(SENTRY_RUN_DIR) + os.chmod(SENTRY_RUN_DIR, mode=SENTRY_RUN_DIR_PERM) + if not chk_and_set_pidfile(): + logging.error("get pid file lock failed, exist") + sys.exit(17) + + logging.basicConfig(filename=SYSSENTRY_LOG_FILE, level=logging.INFO) + os.chmod(SYSSENTRY_LOG_FILE, 0o600) + + try: + signal.signal(signal.SIGINT, sig_handler) + signal.signal(signal.SIGTERM, sig_handler) + signal.signal(signal.SIGHUP, sig_handler) + signal.signal(signal.SIGCHLD, sigchld_handler) + + logging.debug("finish main parse_args") + + _ = SentryConfig.init_param() + TasksMap.init_task_map() + load_tasks() + main_loop() + + except Exception: + logging.error('%s', traceback.format_exc()) + finally: + release_pidfile() diff --git a/sysSentry-1.0.2/src/python/syssentry/task_map.py b/sysSentry-1.0.2/src/python/syssentry/task_map.py new file mode 100644 index 0000000000000000000000000000000000000000..70aa19d878b199468e25fc248e3752f149cfa7ac --- /dev/null +++ b/sysSentry-1.0.2/src/python/syssentry/task_map.py @@ -0,0 +1,67 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +tasks map class and initialize function. +""" +import logging + +ONESHOT_TYPE = "ONESHOT" +PERIOD_TYPE = "PERIOD" + +TASKS_MAP = None + + +class TasksMap: + """task map class""" + tasks_dict = {} + + @classmethod + def init_task_map(cls): + """initialize TaskMap""" + cls.tasks_dict.update({ONESHOT_TYPE: {}, PERIOD_TYPE: {}}) + + @classmethod + def add_task(cls, task, task_type, task_name): + """add new task to tasks_dict""" + if task_type.upper() != PERIOD_TYPE and task_type.upper() != ONESHOT_TYPE: + return False + cls.tasks_dict.get(task_type).update({task_name: task}) + return True + + @classmethod + def is_task_exist(cls, task_name): + """check if task_name in tasks_dict""" + if task_name not in cls.tasks_dict.get(ONESHOT_TYPE) and \ + task_name not in cls.tasks_dict.get(PERIOD_TYPE): + return False + return True + + @classmethod + def get_task_type(cls, task_name): + """get task type by task_name""" + task_type = "" + if task_name in cls.tasks_dict.get(PERIOD_TYPE): + return PERIOD_TYPE + if task_name in cls.tasks_dict.get(ONESHOT_TYPE): + return ONESHOT_TYPE + return task_type + + @classmethod + def get_task_by_name(cls, task_name): + """get task by task_name""" + res = None + for task_type in cls.tasks_dict: + if task_name in cls.tasks_dict.get(task_type): + res = cls.tasks_dict.get(task_type).get(task_name) + logging.debug("getting task by name: %s", res) + break + return res diff --git a/sysSentry-1.0.2/src/python/xalarm/__init__.py b/sysSentry-1.0.2/src/python/xalarm/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/sysSentry-1.0.2/src/python/xalarm/xalarm_api.py b/sysSentry-1.0.2/src/python/xalarm/xalarm_api.py new file mode 100644 index 0000000000000000000000000000000000000000..94d76382df7cf44c7de7212df687078d118aa180 --- /dev/null +++ b/sysSentry-1.0.2/src/python/xalarm/xalarm_api.py @@ -0,0 +1,118 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. + +""" +Description: xalarm api +Author: +Create: 2023-11-02 +""" +import dataclasses +import struct + + +ALARM_TYPES = (0, 1, 2) +ALARM_LEVELS = (1, 2, 3, 4, 5) +ALARM_SOCK_PATH = "/var/run/xalarm/report" +MIN_ALARM_ID = 1001 +MAX_ALARM_ID = 1128 + + +@dataclasses.dataclass +class TimevalStu: + """Time value + """ + def __init__(self, tv_sec, tv_usec): + self.tv_sec = tv_sec + self.tv_usec = tv_usec + + +class Xalarm: + """Xalarm + """ + def __init__(self, alarm_id, alarm_type, alarm_level, + tv_sec, tv_usec, msg1): + self._alarm_id = alarm_id + self._alarm_type = alarm_type + self._alarm_level = alarm_level + self.timetamp = TimevalStu(tv_sec, tv_usec) + self._msg1 = msg1 + + @property + def alarm_id(self): + """alarm_id property + """ + return self._alarm_id + + @alarm_id.setter + def alarm_id(self, value): + """alarm_id setter + """ + if value < MIN_ALARM_ID or value > MAX_ALARM_ID: + raise ValueError("alarm_id must between {} and {}".format(MIN_ALARM_ID, MAX_ALARM_ID)) + self._alarm_id = value + + @property + def alarm_type(self): + """alarm_type property + """ + return self._alarm_type + + @alarm_type.setter + def alarm_type(self, value): + """alarm_type setter + """ + if value not in ALARM_TYPES: + raise ValueError("alarm_type must be normal, abnormal or event") + self._alarm_type = value + + @property + def alarm_level(self): + """alarm_level property + """ + return self._alarm_level + + @alarm_level.setter + def alarm_level(self, value): + """alarm_level setter + """ + if value not in ALARM_LEVELS: + raise ValueError("alarm_level must be 1, 2, 3, 4, 5") + self._alarm_level = value + + @property + def msg1(self): + """msg1 property + """ + return self._msg1 + + @msg1.setter + def msg1(self, msg): + """msg1 setter + """ + if len(msg) > 512: + raise ValueError("msg1 length must below 255") + self._msg1 = msg + + +def alarm_bin2stu(bin_data): + """alarm binary to struct + """ + struct_data = struct.unpack("@HBBll512s", bin_data) + + alarm_info = Xalarm(1001, 2, 1, 0, 0, "") + alarm_info.alarm_id = struct_data[0] + alarm_info.alarm_level = struct_data[1] + alarm_info.alarm_type = struct_data[2] + alarm_info.timetamp.tv_sec = struct_data[3] + alarm_info.timetamp.tv_usec = struct_data[4] + alarm_info.msg1 = struct_data[5] + + return alarm_info diff --git a/sysSentry-1.0.2/src/python/xalarm/xalarm_config.py b/sysSentry-1.0.2/src/python/xalarm/xalarm_config.py new file mode 100644 index 0000000000000000000000000000000000000000..8e56d10d90f4e9ec8aa1fb3b91c57bf3bcb077fa --- /dev/null +++ b/sysSentry-1.0.2/src/python/xalarm/xalarm_config.py @@ -0,0 +1,116 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. +""" +Description: xalarm config +Author: +Create: 2023-11-02 +""" + +import re +import dataclasses +import logging +from configparser import ConfigParser + + +MAIN_CONFIG_PATH = '/etc/sysSentry/xalarm.conf' +ALARM_ID_PATTERN = r'^\d+$' +ALARM_ID_RANGE_PATTERN = r'^\d+-\d+$' +MIN_ID_NUMBER = 1001 +MAX_ID_NUMBER = 1128 +MAX_ID_MASK_CAPACITY = 128 + + +@dataclasses.dataclass +class AlarmConfig: + """alarm config + """ + def __init__(self): + self.id_mask = [True for i in range(MAX_ID_MASK_CAPACITY)] + self.transfer_list = [] + + +def _is_id(item): + """ + check alarm id, an alarm id should in range (1001, 1128) + """ + if not re.match(ALARM_ID_PATTERN, item): + return False + return True + + +def _is_id_range(item): + """ + check alarm id range(eg: begin-end) + """ + if not re.match(ALARM_ID_RANGE_PATTERN, item): + return False + return True + + +def _parse_id_mask(raw_id_mask): + """parse id_mask in config + """ + id_mask = [False for i in range(MAX_ID_MASK_CAPACITY)] + + item_list = raw_id_mask.strip().split(',') + for item in item_list: + item = item.strip() + if _is_id(item): + tmp_id = int(item) + if tmp_id < MIN_ID_NUMBER or tmp_id > MAX_ID_NUMBER: + logging.info("invalid alarm id %s, ignored", item) + continue + id_mask[tmp_id - MIN_ID_NUMBER] = True + continue + if _is_id_range(item): + begin, end = item.split('-') + begin = MIN_ID_NUMBER if int(begin) < MIN_ID_NUMBER else int(begin) + end = MAX_ID_NUMBER if int(end) > MAX_ID_NUMBER else int(end) + if end < begin: + logging.info("invalid alarm id %s, ignored", item) + continue + for i in range(begin, end + 1): + id_mask[i - MIN_ID_NUMBER] = True + continue + logging.info("invalid alarm id %s, ignored", item) + return id_mask + + +def parse_id_mask(cfg): + """parse id_mask in config + """ + if 'filter' not in cfg.sections(): + logging.info("no filter conf") + return None + + filter_conf = cfg['filter'] + if 'id_mask' not in filter_conf: + logging.info("no id_mask conf") + return None + raw_id_mask = filter_conf['id_mask'] + + id_mask = _parse_id_mask(raw_id_mask) + return id_mask + + +def config_init(): + """config initialize + """ + alarm_config = AlarmConfig() + + cfg = ConfigParser() + cfg.read(MAIN_CONFIG_PATH) + + id_mask = parse_id_mask(cfg) + if id_mask: + alarm_config.id_mask = id_mask + + return alarm_config diff --git a/sysSentry-1.0.2/src/python/xalarm/xalarm_daemon.py b/sysSentry-1.0.2/src/python/xalarm/xalarm_daemon.py new file mode 100644 index 0000000000000000000000000000000000000000..00e8886c69e94b843ae72c14c2b1deba0016eee7 --- /dev/null +++ b/sysSentry-1.0.2/src/python/xalarm/xalarm_daemon.py @@ -0,0 +1,133 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. +""" +Description: xalarm daemon +Author: +Create: 2023-11-02 +""" + +import os +import sys +import logging +import signal +import fcntl +import socket + +from .xalarm_config import config_init +from .xalarm_server import server_loop, SOCK_FILE + +ALARM_DIR = "/var/run/xalarm" +ALARM_DIR_PERMISSION = 0o750 +ALARM_LOGFILE = '/var/log/sysSentry/xalarm.log' +XALARMD_PID_FILE = "/var/run/xalarm/xalarmd.pid" +PID_FILE_FLOCK = None + + +def chk_and_set_pidfile(): + """ + :return: + """ + try: + pid_file_fd = open(XALARMD_PID_FILE, 'w') + os.chmod(XALARMD_PID_FILE, 0o600) + fcntl.flock(pid_file_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + pid_file_fd.write(str(os.getpid())) + global PID_FILE_FLOCK + PID_FILE_FLOCK = pid_file_fd + return True + except IOError: + logging.error("Failed to get lock on pidfile") + + return False + + +def release_pidfile(): + """ + :return: + """ + try: + pid_file_fd = open(XALARMD_PID_FILE, 'w') + os.chmod(XALARMD_PID_FILE, 0o600) + fcntl.flock(pid_file_fd, fcntl.LOCK_UN) + pid_file_fd.close() + PID_FILE_FLOCK.close() + os.unlink(XALARMD_PID_FILE) + except (IOError, FileNotFoundError): + logging.error("Failed to release PID file lock") + + +def signal_handler(signum, _f): + """signal handler + """ + if signum == signal.SIGTERM: + try: + os.unlink(SOCK_FILE) + except FileNotFoundError: + pass + release_pidfile() + sys.exit(0) + + +def daemon_init(): + """daemon initialize + """ + pid = os.fork() + if pid > 0: + sys.exit(0) + + os.chdir('/') + os.umask(0) + os.setsid() + + with open('/dev/null') as read_null, open('/dev/null', 'a+') as write_null: + os.dup2(read_null.fileno(), sys.stdin.fileno()) + os.dup2(write_null.fileno(), sys.stdout.fileno()) + os.dup2(write_null.fileno(), sys.stderr.fileno()) + + if not chk_and_set_pidfile(): + logging.error("get pid file lock failed, exist") + sys.exit(17) + + logging.info("xalarm daemon init success") + + +def daemon_main(): + """daemon main + """ + daemon_init() + try: + alarm_config = config_init() + server_loop(alarm_config) + except socket.error: + release_pidfile() + + +def alarm_process_create(): + """alarm daemon process create + """ + if not os.path.exists(os.path.dirname(ALARM_LOGFILE)): + os.mkdir(os.path.dirname(ALARM_LOGFILE), 0o700) + + if not os.path.exists(ALARM_DIR): + os.mkdir(ALARM_DIR) + os.chmod(ALARM_DIR, ALARM_DIR_PERMISSION) + + + logging.basicConfig(filename=ALARM_LOGFILE, level=logging.INFO, + format='%(asctime)s|%(levelname)s| %(message)s') + + signal.signal(signal.SIGTERM, signal_handler) + + os.chmod(ALARM_LOGFILE, 0o600) + + logging.info("xalarm daemon init") + + daemon_main() diff --git a/sysSentry-1.0.2/src/python/xalarm/xalarm_server.py b/sysSentry-1.0.2/src/python/xalarm/xalarm_server.py new file mode 100644 index 0000000000000000000000000000000000000000..84db2733dd0f8986849c6501a613a481b39a7d55 --- /dev/null +++ b/sysSentry-1.0.2/src/python/xalarm/xalarm_server.py @@ -0,0 +1,71 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. +""" +Description: xalarm server +Author: +Create: 2023-11-02 +""" + +import socket +import os +import logging +from struct import error as StructParseError + +from .xalarm_api import alarm_bin2stu +from .xalarm_transfer import check_filter, transmit_alarm + + +ALARM_DIR = "/var/run/xalarm" +SOCK_FILE = "/var/run/xalarm/report" +ALARM_REPORT_LEN = 536 +ALARM_DIR_PERMISSION = 0o750 + + +def clear_sock_path(): + """unlink unix socket if exist + """ + if not os.path.exists(ALARM_DIR): + os.mkdir(ALARM_DIR) + os.chmod(ALARM_DIR, ALARM_DIR_PERMISSION) + if os.path.exists(SOCK_FILE): + os.unlink(SOCK_FILE) + + +def server_loop(alarm_config): + """alarm daemon process loop + """ + logging.info("server loop waiting for messages") + clear_sock_path() + + sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + sock.bind(SOCK_FILE) + os.chmod(SOCK_FILE, 0o600) + + while True: + try: + data, _ = sock.recvfrom(ALARM_REPORT_LEN) + if not data: + continue + if len(data) != ALARM_REPORT_LEN: + logging.debug("server receive report msg length wrong %d", + len(data)) + continue + + alarm_info = alarm_bin2stu(data) + logging.debug("server bin2stu msg") + if not check_filter(alarm_info, alarm_config): + continue + + transmit_alarm(data) + except (ValueError, StructParseError): + pass + + sock.close() diff --git a/sysSentry-1.0.2/src/python/xalarm/xalarm_transfer.py b/sysSentry-1.0.2/src/python/xalarm/xalarm_transfer.py new file mode 100644 index 0000000000000000000000000000000000000000..b590b4330762691fe22d628ee6186b014be41341 --- /dev/null +++ b/sysSentry-1.0.2/src/python/xalarm/xalarm_transfer.py @@ -0,0 +1,50 @@ +# coding: utf-8 +# Copyright (c) 2023 Huawei Technologies Co., Ltd. +# sysSentry is licensed under the Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# http://license.coscl.org.cn/MulanPSL2 +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR +# PURPOSE. +# See the Mulan PSL v2 for more details. +""" +Description: xalarm transfer +Author: +Create: 2023-11-02 +""" + +import socket +import logging + +USER_RECV_SOCK = "/var/run/xalarm/alarm" +MIN_ID_NUMBER = 1001 +MAX_ID_NUMBER = 1128 + + +def check_filter(alarm_info, alarm_filter): + """check id_mask for alarm messages forwarding + """ + if not alarm_filter: + return True + if alarm_info.alarm_id < MIN_ID_NUMBER or alarm_info.alarm_id > MAX_ID_NUMBER: + return False + index = alarm_info.alarm_id - MIN_ID_NUMBER + if not alarm_filter.id_mask[index]: + return False + return True + + +def transmit_alarm(bin_data): + """forward alarm message + """ + sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) + try: + sock.sendto(bin_data, USER_RECV_SOCK) + logging.debug("transfer alarm success") + except ConnectionRefusedError: + logging.debug("transfer sendto failed") + except FileNotFoundError: + logging.debug("transfer sendto failed") + finally: + sock.close()