diff --git a/CONTRIBUTORS.wrs b/CONTRIBUTORS.wrs new file mode 100644 index 00000000..c9eca717 --- /dev/null +++ b/CONTRIBUTORS.wrs @@ -0,0 +1,8 @@ +The following contributors from Wind River have developed the seed code in this +repository. We look forward to community collaboration and contributions for +additional features, enhancements and refactoring. + +Contributors: +============= +Eric Macdonald +Don Penney diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.rst b/README.rst new file mode 100644 index 00000000..433e7e0f --- /dev/null +++ b/README.rst @@ -0,0 +1,5 @@ +========= +stx-metal +========= + +StarlingX Bare Metal Management diff --git a/bsp-files/centos-ks-gen.pl b/bsp-files/centos-ks-gen.pl new file mode 100755 index 00000000..3e95683f --- /dev/null +++ b/bsp-files/centos-ks-gen.pl @@ -0,0 +1,297 @@ +#!/usr/bin/perl +# +# Copyright (c) 2017 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +use strict; +use Getopt::Long; +use POSIX qw(strftime); + +# Defines the current list of YOW boot servers +my %boot_servers = ("yow-tuxlab", "128.224.150.9", + "yow-tuxlab2", "128.224.151.254", + "yow", "128.224.150.9"); # obsolete; kept for backwards compatibility + +my $PLATFORM_RELEASE; +my $files_dir; +my $output_dir = 'generated'; +my $pxeboot_output_dir = 'pxeboot'; +my $extra_output_dir = 'extra_cfgs'; + +GetOptions("release=s" => \$PLATFORM_RELEASE, + "basedir=s" => \$files_dir); + +die "Please specify release with --release" if (!$PLATFORM_RELEASE); +if (!$files_dir) +{ + $files_dir = '.'; +} + +my $BOOT_SERVER = "none"; + +my $template_dir = "$files_dir/kickstarts"; + +system("mkdir -p ${output_dir}"); + +# Write USB image files +write_config_file("controller", + "${output_dir}/controller_ks.cfg", "filter_out_from_controller", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_controller.cfg", + "post_platform_conf_controller.cfg", + "post_common.cfg", + "post_kernel_controller.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_usb_controller.cfg"); +write_config_file("controller-compute", + "${output_dir}/smallsystem_ks.cfg", "filter_out_from_smallsystem", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_usb_controller.cfg"); +write_config_file("controller-compute-lowlatency", + "${output_dir}/smallsystem_lowlatency_ks.cfg", "filter_out_from_smallsystem_lowlatency", + "pre_common_head.cfg", + "pre_pkglist_lowlatency.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio_lowlatency.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_usb_controller.cfg"); + +system("mkdir -p ${pxeboot_output_dir}"); + +# Write PXE boot files +write_config_file("controller", + "${pxeboot_output_dir}/pxeboot_controller.cfg", "filter_out_from_controller", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_controller.cfg", + "post_platform_conf_controller.cfg", + "post_common.cfg", + "post_kernel_controller.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_pxeboot_controller.cfg"); +write_config_file("controller-compute", + "${pxeboot_output_dir}/pxeboot_smallsystem.cfg", "filter_out_from_smallsystem", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_pxeboot_controller.cfg"); +write_config_file("controller-compute-lowlatency", + "${pxeboot_output_dir}/pxeboot_smallsystem_lowlatency.cfg", "filter_out_from_smallsystem_lowlatency", + "pre_common_head.cfg", + "pre_pkglist_lowlatency.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio_lowlatency.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_pxeboot_controller.cfg"); + + +# Write same net files +write_config_file("controller", + "${output_dir}/net_controller_ks.cfg", "filter_out_from_controller", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_controller.cfg", + "post_platform_conf_controller.cfg", + "post_common.cfg", + "post_kernel_controller.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_net_controller.cfg", + "post_net_common.cfg"); +write_config_file("controller-compute", + "${output_dir}/net_smallsystem_ks.cfg", "filter_out_from_smallsystem", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_net_controller.cfg", + "post_net_common.cfg"); +write_config_file("controller-compute-lowlatency", + "${output_dir}/net_smallsystem_lowlatency_ks.cfg", "filter_out_from_smallsystem_lowlatency", + "pre_common_head.cfg", + "pre_pkglist_lowlatency.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio_lowlatency.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_net_controller.cfg", + "post_net_common.cfg"); +write_config_file("compute", + "${output_dir}/net_compute_ks.cfg", "filter_out_from_compute", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_compute.cfg", + "post_platform_conf_compute.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_no_pv_on_rootfs.cfg", + "post_net_common.cfg"); +write_config_file("compute-lowlatency", + "${output_dir}/net_compute_lowlatency_ks.cfg", "filter_out_from_compute_lowlatency", + "pre_common_head.cfg", + "pre_pkglist_lowlatency.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_compute.cfg", + "post_platform_conf_compute_lowlatency.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_no_pv_on_rootfs.cfg", + "post_net_common.cfg"); +write_config_file("storage", + "${output_dir}/net_storage_ks.cfg", "filter_out_from_storage", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_storage.cfg", + "post_platform_conf_storage.cfg", + "post_common.cfg", + "post_kernel_storage.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_net_common.cfg"); + +system("mkdir -p ${extra_output_dir}"); + +# write Ottawa Lab files +my $server; +foreach $server (keys %boot_servers) +{ + $BOOT_SERVER = $boot_servers{$server}; + + write_config_file("controller", + "${extra_output_dir}/${server}_controller.cfg", "filter_out_from_controller", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_controller.cfg", + "post_platform_conf_controller.cfg", + "post_common.cfg", + "post_kernel_controller.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_yow_controller.cfg"); + write_config_file("controller-compute", + "${extra_output_dir}/${server}_smallsystem.cfg", "filter_out_from_smallsystem", + "pre_common_head.cfg", + "pre_pkglist.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_yow_controller.cfg"); + write_config_file("controller-compute-lowlatency", + "${extra_output_dir}/${server}_smallsystem_lowlatency.cfg", "filter_out_from_smallsystem_lowlatency", + "pre_common_head.cfg", + "pre_pkglist_lowlatency.cfg", + "pre_disk_setup_common.cfg", + "pre_disk_aio.cfg", + "post_platform_conf_aio_lowlatency.cfg", + "post_common.cfg", + "post_kernel_aio_and_compute.cfg", + "post_lvm_pv_on_rootfs.cfg", + "post_system_aio.cfg", + "post_yow_controller.cfg"); +} + +exit 0; + +#------------------------# + +sub write_config_file { + my ($personality, $ksout, $filter_file, @templates) = @_; + my %filter; + if ($filter_file ne "") { + if (!(open(FILTER, "$files_dir/$filter_file"))) { + die "Could not open template $files_dir/$filter_file"; + } + while () { + chop(); + next if ($_ =~ /^#/); + $filter{$_} = 1; + } + close(FILTER); + } + print "Writing: $ksout\n"; + open(OUT, ">$ksout") || die "Could not write $ksout"; + + my $year = strftime "%Y", localtime; + print OUT "#\n"; + print OUT "# Copyright (c) $year Wind River Systems, Inc.\n"; + print OUT "# SPDX-License-Identifier: Apache-2.0\n"; + print OUT "#\n"; + print OUT "\n"; + + # Add functions header + foreach my $block ("\%pre", "\%post") { + if (!(open(FUNCTIONS, "$template_dir/functions.sh"))) { + die "Could not open functions.sh"; + } + print OUT "$block\n"; + while () { + s/xxxPLATFORM_RELEASExxx/$PLATFORM_RELEASE/g; + s/xxxBOOT_SERVERxxx/$BOOT_SERVER/g; + s/xxxYEARxxx/$year/g; + print OUT $_; + } + print OUT "\%end\n\n"; + close FUNCTIONS; + } + + my $template; + foreach $template (@templates) { + if (!(open(TEMPLATE_IN, "$template_dir/$template"))) { + die "Could not open template $template_dir/$template"; + } + print OUT "\n# Template from: $template\n"; + while () { + $_ =~ s/\n$//; + s/xxxPLATFORM_RELEASExxx/$PLATFORM_RELEASE/g; + s/xxxBOOT_SERVERxxx/$BOOT_SERVER/g; + s/xxxYEARxxx/$year/g; + + s/xxxPACKAGE_LISTxxx/\@platform-$personality\n\@updates-$personality/; + + print OUT "$_\n"; + } + close(TEMPLATE_IN); + } + + close(OUT); +} diff --git a/bsp-files/centos.syslinux.cfg b/bsp-files/centos.syslinux.cfg new file mode 100644 index 00000000..f6b05695 --- /dev/null +++ b/bsp-files/centos.syslinux.cfg @@ -0,0 +1,188 @@ +display splash.cfg +timeout 0 +F1 help.txt +F2 devices.txt +F3 splash.cfg +serial 0 115200 + +# Pull in the menu User Interface +ui vesamenu.c32 + +menu title Select kernel options and boot kernel +menu tabmsg Press [Tab] to edit, [Return] to select, [ESC] to return to previous menu + +# Dark grey +menu background #ff555555 + +# ----------------- NOTE ----------------- +# If you are updating label numbers, make sure that controllerconfig/clone.py +# is in sync with your changes (only serial console entries). +# STANDARD_STANDARD = '0' +# STANDARD_EXTENDED = 'S0' +# AIO_STANDARD = '2' +# AIO_EXTENDED = 'S2' +# AIO_LL_STANDARD = '4' +# AIO_LL_EXTENDED = 'S4' +# ---------------------------------------- + + +# Standard Controller menu +menu begin + menu title Standard Controller Configuration + # Serial Console submenu + menu begin + menu title Serial Console + label 0 + menu label STANDARD Security Boot Profile + text help + Standard Controller, console=ttyS0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=standard + + label S0 + menu label EXTENDED Security Boot Profile + text help + Standard Controller, console=ttyS0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=extended + menu end + + # Graphical Console submenu + menu begin + menu title Graphical Console + label 1 + menu label STANDARD Security Boot Profile + text help + Standard Controller, console=tty0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=standard + + label S1 + menu label EXTENDED Security Boot Profile + text help + Standard Controller, console=tty0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=extended + menu end +menu end + +menu SEPARATOR + +# AIO Controller menu +menu begin + menu title All-in-one Controller Configuration + # Serial Console submenu + menu begin + menu title Serial Console + label 2 + menu label STANDARD Security Boot Profile + text help + All-in-one Controller, console=ttyS0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=standard + + label S2 + menu label EXTENDED Security Boot Profile + text help + All-in-one Controller, console=ttyS0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + initrd initrd.img + # Security profile option + append rootwait console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=extended + menu end + + # Graphical Console submenu + menu begin + menu title Graphical Console + label 3 + menu label STANDARD Security Boot Profile + text help + All-in-one Controller, console=tty0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=standard + + label S3 + menu label EXTENDED Security Boot Profile + text help + All-in-one Controller, console=tty0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=extended + menu end +menu end + +menu SEPARATOR + +# AIO (Low Latency) Controller menu +menu begin + menu title All-in-one (lowlatency) Controller Configuration + # Serial Console submenu + menu begin + menu title Serial Console + label 4 + menu label STANDARD Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=ttyS0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=standard + + label S4 + menu label EXTENDED Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=ttyS0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=extended + menu end + + # Graphical Console submenu + menu begin + menu title Graphical Console + label 5 + menu label STANDARD Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=tty0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=standard + + label S5 + menu label EXTENDED Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=tty0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + initrd initrd.img + append rootwait console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 inst.gpt security_profile=extended + menu end +menu end diff --git a/bsp-files/filter_out_from_compute b/bsp-files/filter_out_from_compute new file mode 100644 index 00000000..80582593 --- /dev/null +++ b/bsp-files/filter_out_from_compute @@ -0,0 +1,263 @@ +ceilometer-api +ceilometer-alarm-evaluator +ceilometer-alarm-notifier +ceilometer-collector +ceilometer-tests +ceph-manager +cgcs-dpdk-rt +cgcs-dpdk-rt-dev +cgcs-dpdk-rt-staticdev +cgcs-dpdk-rt-apps +cgts-client +cgts-client-bash-completion +cgcs-patch-controller +cgts-mtce-control +cgts-mtce-storage +cgts-mtce-common-guestAgent +cgtssys +cinder +cinder-api +cinder-scheduler +cinder-tests +cinder-volume +computeconfig-subfunction +configvalidator +controllerconfig +corosync +createrepo +d2to1 +distributedcloud-dcmanager +distributedcloud-client-dcmanagerclient +distributedcloud-dcorch +drbd-tools +fm-doc +glance +glance-api +glance-registry +glance-tests +horizon +horizon-standalone +horizon-tests +heat-api-cfn +heat-api +heat-cfn +heat-common +heat-contrib-nova-flavor +heat-engine +heat-templates +heat-tests +io-monitor +isomd5sum +kernel-module-openvswitch +keystone +keystone-tests +ldapscripts +libconfig-general-perl +libssh2 +lighttpd-module-access +lighttpd-module-accesslog +lighttpd-module-dirlisting +lighttpd-module-indexfile +lighttpd-module-proxy +lighttpd-module-staticfile +lighttpd +nodejs +nova-api +nova-conductor +nova-consoleauth +nova-controller +nova-network +nova-novncproxy +nova-scheduler +nova-spicehtml5proxy +nova-tests +nova-api-proxy +nova-placement-api +novnc +net-snmp +openldap-backend-bdb +openldap-backend-dnssrv +openldap-backend-hdb +openldap-backend-ldap +openldap-backend-mdb +openldap-backend-meta +openldap-backend-monitor +openldap-backend-null +openldap-backend-passwd +openldap-backend-shell +openldap-backends +openldap-dbg +openldap-doc +openldap-overlay-proxycache +openldap-overlay-syncprov +openldap-servers +openldap-slapd +openstack-ras +pacemaker +pacemaker-cli +pacemaker-cluster-libs +pacemaker-libs +patch-alarm +patching-controller +pbr +pecan +postgresql-client +postgresql-contrib +postgresql-timezone +postgresql +pxe-network-installer +python-cephclient +python-cinder +python-django +python-django-appconf +python-django-compressor +python-django-openstack-auth +python-glance +python2-gunicorn +python-heatclient +python-heatclient-bash-completion +python-heat +python-horizon +python-keystone +python-lockfile +python-novnc +python-pam +python-passlib +python-pytz +python-swiftclient +python-wsme +fm-mgr +snmp-ext +sm +sm-api +sm-client +sm-common +sm-db +sm-tools +storageconfig +storage-topology +task-cloud-controller +tgt +nfv-plugins +nfv-vim +vm-topology +remote-clients +lighttpd-fastcgi +lighttpd-mod_geoip +lighttpd-mod_mysql_vhost +openstack-aodh-api +openstack-aodh-commmon +openstack-aodh-compat +openstack-aodh-evaluator +openstack-aodh-expirer +openstack-aodh-listener +openstack-aodh-notifier +openstack-cinder +openstack-cinder-doc +openstack-dashboard +openstack-glance +openstack-glance-doc +openstack-heat-api +openstack-heat-api-cfn +openstack-heat-api-cloudwatch +openstack-heat-common +openstack-heat-engine +openstack-ironic-api +openstack-ironic-common +openstack-ironic-conductor +python-ironic-tests +python-ironic-inspector-client +python-ironic-lib +python2-ironicclient +openstack-keystone +openstack-keystone-doc +openstack-murano-api +openstack-murano-cf-api +openstack-murano-common +openstack-murano-doc +openstack-murano-engine +openstack-murano-ui +openstack-murano-ui-doc +python2-muranoclient +python-muranoclient-doc +openstack-magnum-api +openstack-magnum-common +openstack-magnum-conductor +openstack-magnum-doc +openstack-magnum-ui +python2-magnumclient +python-magnum +python-magnumclient-doc +python-magnumclient-tests +python-magnum-tests +python-magnum-ui-doc +openstack-neutron-common +openstack-neutron-ml2 +openstack-nova-api +openstack-nova-cells +openstack-nova-conductor +openstack-nova-console +openstack-nova-doc +openstack-nova-network +openstack-nova-novncproxy +openstack-nova-objectstore +openstack-nova-scheduler +openstack-nova-serialproxy +openstack-nova-spicehtml5proxy +openstack-nova-placement-api +openstack-panko-api +openstack-panko-common +openstack-panko-doc +python-aodh +python-aodhclient +python-ceilometerclient-doc +python-cinder +python-cinderclient-doc +python-glance +python-heatclient +python-keystone +python-novaclient-doc +python-panko +python2-pankoclient +configutilities +drbd-bash-completion +drbd-udev +drbd-utils +drbd-heartbeat +drbd-pacemaker +drbd +kmod-drbd +python-networking-odl +tis-extensions-controller +wrs-heat-templates +python-django-horizon +kernel-rt +kernel-module-igb-uio-rt +kernel-rt-kvm +kmod-e1000e-rt +kmod-i40e-rt +kmod-ixgbe-rt +kmod-tpm-rt +kmod-integrity-rt +mlnx-ofa_kernel-rt-modules +rtctl +rt-setup +qat17-rt +kernel-rt-tools +kernel-rt-tools-libs +NaviCLI-Linux-64-x86-en_US +kmod-drbd-rt +snmp-audittrail +wrs-ssl +tpm2-tools +tss2 +tpm2-openssl-engine +python2-networking-bgpvpn +python-networking-bgpvpn-dashboard +python-networking-bgpvpn-heat +python2-neutron-dynamic-routing +python2-ryu +python-ryu-common +platform-kickstarts +python-3parclient +python-lefthandclient diff --git a/bsp-files/filter_out_from_compute_lowlatency b/bsp-files/filter_out_from_compute_lowlatency new file mode 100644 index 00000000..fbbb6f20 --- /dev/null +++ b/bsp-files/filter_out_from_compute_lowlatency @@ -0,0 +1,265 @@ +ceilometer-api +ceilometer-alarm-evaluator +ceilometer-alarm-notifier +ceilometer-collector +ceilometer-tests +ceph-manager +cgcs-dpdk +cgcs-dpdk-dev +cgcs-dpdk-staticdev +cgcs-dpdk-apps +cgts-client +cgts-client-bash-completion +cgcs-patch-controller +cgts-mtce-control +cgts-mtce-storage +cgts-mtce-common-guestAgent +cgtssys +cinder +cinder-api +cinder-scheduler +cinder-tests +cinder-volume +computeconfig-subfunction +configvalidator +controllerconfig +corosync +createrepo +d2to1 +distributedcloud-dcmanager +distributedcloud-client-dcmanagerclient +distributedcloud-dcorch +drbd-tools +fm-doc +glance +glance-api +glance-registry +glance-tests +horizon +horizon-standalone +horizon-tests +heat-api-cfn +heat-api +heat-cfn +heat-common +heat-contrib-nova-flavor +heat-engine +heat-templates +heat-tests +io-monitor +isomd5sum +kernel-module-openvswitch +keystone +keystone-tests +ldapscripts +libconfig-general-perl +libssh2 +lighttpd-module-access +lighttpd-module-accesslog +lighttpd-module-dirlisting +lighttpd-module-indexfile +lighttpd-module-proxy +lighttpd-module-staticfile +lighttpd +nodejs +nova-api +nova-conductor +nova-consoleauth +nova-controller +nova-network +nova-novncproxy +nova-scheduler +nova-spicehtml5proxy +nova-tests +nova-api-proxy +nova-placement-api +novnc +net-snmp +neutron-plugin-ml2 +neutron-server +neutron-tests +openldap-backend-bdb +openldap-backend-dnssrv +openldap-backend-hdb +openldap-backend-ldap +openldap-backend-mdb +openldap-backend-meta +openldap-backend-monitor +openldap-backend-null +openldap-backend-passwd +openldap-backend-shell +openldap-backends +openldap-dbg +openldap-doc +openldap-overlay-proxycache +openldap-overlay-syncprov +openldap-servers +openldap-slapd +openstack-ras +pacemaker +pacemaker-cli +pacemaker-cluster-libs +pacemaker-libs +patch-alarm +patching-controller +pbr +pecan +postgresql-client +postgresql-contrib +postgresql-timezone +postgresql +pxe-network-installer +python-cephclient +python-cinder +python-django +python-django-appconf +python-django-compressor +python-django-openstack-auth +python-glance +python2-gunicorn +python-heatclient +python-heatclient-bash-completion +python-heat +python-horizon +python-keystone +python-lockfile +python-novnc +python-pam +python-passlib +python-pytz +python-swiftclient +python-wsme +fm-mgr +snmp-ext +sm +sm-api +sm-client +sm-common +sm-db +sm-tools +storageconfig +storage-topology +task-cloud-controller +tgt +nfv-plugins +nfv-vim +vm-topology +remote-clients +lighttpd-fastcgi +lighttpd-mod_geoip +lighttpd-mod_mysql_vhost +openstack-aodh-api +openstack-aodh-commmon +openstack-aodh-compat +openstack-aodh-evaluator +openstack-aodh-expirer +openstack-aodh-listener +openstack-aodh-notifier +openstack-cinder +openstack-cinder-doc +openstack-dashboard +openstack-glance +openstack-glance-doc +openstack-heat-api +openstack-heat-api-cfn +openstack-heat-api-cloudwatch +openstack-heat-common +openstack-heat-engine +openstack-ironic-api +openstack-ironic-common +openstack-ironic-conductor +python-ironic-tests +python-ironic-inspector-client +python-ironic-lib +python2-ironicclient +openstack-keystone +openstack-keystone-doc +openstack-murano-api +openstack-murano-cf-api +openstack-murano-common +openstack-murano-doc +openstack-murano-engine +openstack-murano-ui +openstack-murano-ui-doc +python2-muranoclient +python-muranoclient-doc +openstack-magnum-api +openstack-magnum-common +openstack-magnum-conductor +openstack-magnum-doc +openstack-magnum-ui +python2-magnumclient +python-magnum +python-magnumclient-doc +python-magnumclient-tests +python-magnum-tests +python-magnum-ui-doc +openstack-neutron-common +openstack-neutron-plugin-ml2 +openstack-neutron-server +openstack-nova-api +openstack-nova-cells +openstack-nova-conductor +openstack-nova-console +openstack-nova-doc +openstack-nova-network +openstack-nova-novncproxy +openstack-nova-objectstore +openstack-nova-scheduler +openstack-nova-serialproxy +openstack-nova-spicehtml5proxy +openstack-nova-placement-api +openstack-panko-api +openstack-panko-common +openstack-panko-doc +python-aodh +python-aodhclient +python-ceilometerclient-doc +python-cinder +python-cinderclient-doc +python-glance +python-heatclient +python-keystone +python-novaclient-doc +python-panko +python2-pankoclient +configutilities +drbd-bash-completion +drbd-udev +drbd-utils +drbd-heartbeat +drbd-pacemaker +drbd +kmod-drbd +python-networking-odl +tis-extensions-controller +wrs-heat-templates +python-django-horizon +kernel +kernel-module-igb-uio +kmod-e1000e +kmod-i40e +kmod-i40evf +kmod-ixgbe +kmod-ixgbevf +kmod-tpm +kmod-integrity +mlnx-ofa_kernel-modules +qat17 +kernel-tools +kernel-tools-libs +NaviCLI-Linux-64-x86-en_US +kmod-drbd-rt +snmp-audittrail +wrs-ssl +tpm2-tools +tss2 +python2-networking-bgpvpn +python-networking-bgpvpn-dashboard +python-networking-bgpvpn-heat +python2-neutron-dynamic-routing +python2-ryu +python-ryu-common +platform-kickstarts +python-3parclient +python-lefthandclient diff --git a/bsp-files/filter_out_from_controller b/bsp-files/filter_out_from_controller new file mode 100644 index 00000000..bb706bb5 --- /dev/null +++ b/bsp-files/filter_out_from_controller @@ -0,0 +1,52 @@ +task-cloud-compute +compute-huge +computeconfig +computeconfig-standalone +computeconfig-subfunction +guest-scale-helper +heartbeat +storageconfig +kernel-module-openvswitch +openstack-neutron-sriov-nic-agent +platform-util-noncontroller +ceilometer-compute +openstack-ceilometer-compute +cgcs-dpdk +cgcs-dpdk-rt +cgcs-dpdk-dev +cgcs-dpdk-rt-dev +cgcs-dpdk-staticdev +cgcs-dpdk-rt-staticdev +cgcs-dpdk-rt-apps +cgts-mtce-compute +cgts-mtce-storage +cgts-mtce-common-guestServer +host-guest-comm +host-guest-comm-dev +nfscheck +radvd +remote-clients +config-gate-compute +kernel-rt +kernel-module-igb-uio +kernel-module-igb-uio-rt +kernel-rt-kvm +kmod-e1000e-rt +kmod-i40e-rt +kmod-ixgbe-rt +kmod-tpm-rt +kmod-integrity-rt +mlnx-ofa_kernel-rt-modules +rtctl +rt-setup +qat17-rt +kernel-rt-tools +kernel-rt-tools-libs +kmod-drbd-rt +libtpms +swtpm +swtpm-tools +swtpm-cuse +swtpm-libs +OVMF +openvswitch diff --git a/bsp-files/filter_out_from_smallsystem b/bsp-files/filter_out_from_smallsystem new file mode 100644 index 00000000..ca885748 --- /dev/null +++ b/bsp-files/filter_out_from_smallsystem @@ -0,0 +1,24 @@ +cgcs-dpdk-rt +cgcs-dpdk-rt-apps +cgts-mtce-storage +computeconfig-standalone +kernel-module-openvswitch +platform-util-noncontroller +storageconfig +nfscheck +remote-clients +kernel-rt +kernel-module-igb-uio-rt +kernel-rt-kvm +kmod-e1000e-rt +kmod-i40e-rt +kmod-ixgbe-rt +kmod-tpm-rt +kmod-integrity-rt +mlnx-ofa_kernel-rt-modules +rtctl +rt-setup +qat17-rt +kernel-rt-tools +kernel-rt-tools-libs +kmod-drbd-rt diff --git a/bsp-files/filter_out_from_smallsystem_lowlatency b/bsp-files/filter_out_from_smallsystem_lowlatency new file mode 100644 index 00000000..75a2b9da --- /dev/null +++ b/bsp-files/filter_out_from_smallsystem_lowlatency @@ -0,0 +1,23 @@ +cgcs-dpdk +cgcs-dpdk-apps +cgts-mtce-storage +computeconfig-standalone +kernel-module-openvswitch +platform-util-noncontroller +storageconfig +nfscheck +remote-clients +kernel +kernel-module-igb-uio +kmod-e1000e +kmod-i40e +kmod-i40evf +kmod-ixgbe +kmod-ixgbevf +kmod-tpm +kmod-integrity +mlnx-ofa_kernel-modules +qat17 +kernel-tools +kernel-tools-libs +kmod-drbd diff --git a/bsp-files/filter_out_from_storage b/bsp-files/filter_out_from_storage new file mode 100644 index 00000000..073e0b31 --- /dev/null +++ b/bsp-files/filter_out_from_storage @@ -0,0 +1,303 @@ +ceilometer-alarm-evaluator +ceilometer-alarm-notifier +ceilometer-api +ceilometer-collector +ceilometer-compute +ceilometer-tests +ceph-manager +cgcs-dpdk +cgcs-dpdk-rt +cgcs-dpdk-dev +cgcs-dpdk-rt-dev +cgcs-dpdk-staticdev +cgcs-dpdk-rt-staticdev +cgcs-dpdk-rt-apps +cgts-client +cgts-client-bash-completion +cgcs-patch-controller +cgts-mtce-compute +cgts-mtce-control +cgts-mtce-common-guestServer +cgts-mtce-common-guestAgent +cgtssys +cinder +cinder-api +cinder-scheduler +cinder-tests +cinder-volume +compute-huge +computeconfig +computeconfig-standalone +computeconfig-subfunction +configvalidator +controllerconfig +createrepo +d2to1 +distributedcloud-dcmanager +distributedcloud-client-dcmanagerclient +distributedcloud-dcorch +erlang +fm-doc +glance +glance-api +glance-registry +glance-tests +glusterfs +glusterfs-api +glusterfs-client-xlators +glusterfs-libs +guest-scale-helper +haproxy +heartbeat +heat-api +heat-api-cfn +heat-cfn +heat-common +heat-contrib-nova-flavor +heat-engine +heat-templates +heat-tests +horizon +horizon-standalone +horizon-tests +host-guest-comm +io-monitor +io-scheduler +isomd5sum +ipxe-roms-qemu +kernel-module-openvswitch +keystone +keystone-tests +libconfig-general-perl +libguestfs +libssh2 +lighttpd-module-access +lighttpd-module-accesslog +lighttpd-module-dirlisting +lighttpd-module-indexfile +lighttpd-module-proxy +lighttpd-module-staticfile +lighttpd +lighttpd-mod_geoip +lighttpd-fastcgi +lighttpd-mod_mysql_vhost +libvirt +libvirt-daemon +libvirt-daemon-config-network +libvirt-daemon-config-nwfilter +libvirt-daemon-driver-interface +libvirt-daemon-driver-lxc +libvirt-daemon-driver-network +libvirt-daemon-driver-nodedev +libvirt-daemon-driver-nwfilter +libvirt-daemon-driver-qemu +libvirt-daemon-driver-qemu +libvirt-daemon-driver-secret +libvirt-daemon-driver-storage +libvirt-daemon-kvm +libvirt-docs +nodejs +nova-api +nova-common +nova-compute +nova-compute-preclean +nova-compute-setup +nova-conductor +nova-consoleauth +nova-controller +nova-network +nova-novncproxy +nova-scheduler +nova-spicehtml5proxy +nova-tests +nova-api-proxy +nova-placement-api +novnc +net-snmp +openstack-aodh-api +openstack-aodh-commmon +openstack-aodh-compat +openstack-aodh-evaluator +openstack-aodh-expirer +openstack-aodh-listener +openstack-aodh-notifier +openstack-ceilometer-alarm +openstack-ceilometer-central +openstack-ceilometer-collector +openstack-ceilometer-compute +openstack-ceilometer-ipmi +openstack-ceilometer-notification +openstack-cinder +openstack-cinder-doc +openstack-dashboard +openstack-glance +openstack-glance-doc +openstack-heat-api +openstack-heat-api-cfn +openstack-heat-api-cloudwatch +openstack-heat-common +openstack-heat-engine +openstack-ironic-api +openstack-ironic-common +openstack-ironic-conductor +python-ironic-tests +python-ironic-inspector-client +python-ironic-lib +python2-ironicclient +openstack-keystone +openstack-keystone-doc +openstack-murano-api +openstack-murano-cf-api +openstack-murano-common +openstack-murano-doc +openstack-murano-engine +openstack-murano-ui +openstack-murano-ui-doc +python2-muranoclient +python-muranoclient-doc +openstack-magnum-api +openstack-magnum-common +openstack-magnum-conductor +openstack-magnum-doc +openstack-magnum-ui +python2-magnumclient +python-magnum +python-magnumclient-doc +python-magnumclient-tests +python-magnum-tests +python-magnum-ui-doc +openstack-neutron +openstack-neutron-common +openstack-neutron-sriov-nic-agent +openstack-neutron-ml2 +openstack-nova-api +openstack-nova-cells +openstack-nova-common +openstack-nova-compute +openstack-nova-conductor +openstack-nova-console +openstack-nova-doc +openstack-nova-network +openstack-nova-novncproxy +openstack-nova-objectstore +openstack-nova-scheduler +openstack-nova-serialproxy +openstack-nova-spicehtml5proxy +openstack-nova-placement-api +openstack-panko-api +openstack-panko-common +openstack-panko-doc +openstack-ras +patch-alarm +patching-controller +pbr +pecan +postgresql +postgresql-client +postgresql-contrib +postgresql-timezone +pxe-network-installer +python-aodh +python-aodhclient +python-ceilometerclient +python-cephclient +python-cinder +python-cinderclient +python-django +python-django-appconf +python-django-compressor +python-django-openstack-auth +python-glance +python-glanceclient +python2-gunicorn +python-heat +python-heatclient +python-heatclient-bash-completion +python-horizon +python-keystone +python-libguestfs +python-lockfile +python-netclient +python-neutron +python-neutron-lib +python2-neutronclient +python-nova +python2-novaclient +python-novnc +python-openstackclient +python-pam +python-panko +python2-pankoclient +python-passlib +python-pytz +python-swiftclient +python-wsme +qemu-img-ev +qemu-kvm-common-ev +qemu-kvm-ev +qemu-kvm-tools-ev +radvd +rubygem-rdoc +snmp-ext +task-cloud-compute +task-cloud-controller +tgt +fm-mgr +sm +sm-api +sm-client +sm-common +sm-db +sm-tools +storage-topology +nfv-common +nfv-plugins +nfv-vim +nfv-tools +vm-topology +remote-clients +python-networking-odl +config-gate-compute +tis-extensions-controller +wrs-heat-templates +python-django-horizon +libmlx5 +kernel-rt +kernel-module-igb-uio +kernel-module-igb-uio-rt +kernel-rt-kvm +kmod-e1000e-rt +kmod-i40e-rt +kmod-ixgbe-rt +kmod-tpm-rt +kmod-integrity-rt +mlnx-ofa_kernel-rt-modules +rtctl +rt-setup +qat17-rt +kernel-rt-tools +kernel-rt-tools-libs +NaviCLI-Linux-64-x86-en_US +kmod-drbd-rt +snmp-audittrail +wrs-ssl +tpm2-tools +tss2 +tpm2-openssl-engine +libtpms +swtpm +swtpm-tools +swtpm-cuse +swtpm-libs +OVMF +python2-networking-bgpvpn +python-networking-bgpvpn-dashboard +python-networking-bgpvpn-heat +python2-neutron-dynamic-routing +python2-ryu +python-ryu-common +python2-networking-sfc +openvswitch +platform-kickstarts +python-3parclient +python-lefthandclient diff --git a/bsp-files/grub.cfg b/bsp-files/grub.cfg new file mode 100644 index 00000000..f5c9fe4e --- /dev/null +++ b/bsp-files/grub.cfg @@ -0,0 +1,155 @@ +default=2 +timeout=-1 + +search --no-floppy --set=root -l 'oe_iso_boot' + +# ---------------------- NOTE ---------------------- +# If you are updating menus, make sure that controllerconfig/clone.py +# is in sync with your changes (only serial console ids). +# STANDARD_STANDARD = 'standard>serial>' + +# sysinv_constants.SYSTEM_SECURITY_PROFILE_STANDARD +# STANDARD_EXTENDED = 'standard>serial>' + +# sysinv_constants.SYSTEM_SECURITY_PROFILE_EXTENDED +# AIO_STANDARD = 'standard>aio>' + +# sysinv_constants.SYSTEM_SECURITY_PROFILE_STANDARD +# AIO_EXTENDED = 'standard>aio>' + +# sysinv_constants.SYSTEM_SECURITY_PROFILE_EXTENDED +# AIO_LL_STANDARD = 'standard>aio-lowlat>' + +# sysinv_constants.SYSTEM_SECURITY_PROFILE_STANDARD +# AIO_LL_EXTENDED = 'standard>aio-lowlat>' + +# sysinv_constants.SYSTEM_SECURITY_PROFILE_EXTENDED +# SUBMENUITEM_TBOOT = 'tboot' +# SUBMENUITEM_SECUREBOOT = 'secureboot' +# -------------------------------------------------- + + +# Menu 0 +menuentry 'Select kernel options and boot kernel' { + echo " " +} + +# Create a space in the menu +menuentry ' ' { + echo " " +} + +# Standard Controller menu +submenu 'UEFI Standard Controller Configuration' --id=standard { + submenu 'Serial Console' --id=serial { + menuentry 'STANDARD Security Profile' --id=standard { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=standard + initrdefi /initrd.img + } + submenu 'EXTENDED Security Profile' --id=extended { + menuentry 'Secure Boot Profile' --id=secureboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=false + initrdefi /initrd.img + } + menuentry 'Trusted Boot Profile' --id=tboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=true + initrdefi /initrd.img + } + } + } + + submenu 'Graphical Console' --id=graphical { + menuentry 'STANDARD Security Profile' --id=standard { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 serial inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=standard + initrdefi /initrd.img + } + submenu 'EXTENDED Security Profile' --id=extended { + menuentry 'Secure Boot Profile' --id=secureboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 serial inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=false + initrdefi /initrd.img + } + menuentry 'Trusted Boot Profile' --id=tboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 serial inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=true + initrdefi /initrd.img + } + } + } +} + +# Create a space in the menu +menuentry ' '{ + echo " " +} + +# AIO Controller menu +submenu 'UEFI All-in-one Controller Configuration' --id=aio { + submenu 'Serial Console' --id=serial { + menuentry 'STANDARD Security Profile' --id=standard { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=standard + initrdefi /initrd.img + } + submenu 'EXTENDED Security Profile' --id=extended { + menuentry 'Secure Boot Profile' --id=secureboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=false + initrdefi /initrd.img + } + menuentry 'Trusted Boot Profile' --id=tboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=true + initrdefi /initrd.img + } + } + } + + submenu 'Graphical Console' --id=graphical { + menuentry 'STANDARD Security Profile' --id=standard { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=standard + initrdefi /initrd.img + } + submenu 'EXTENDED Security Profile' --id=extended { + menuentry 'Secure Boot Profile' --id=secureboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=false + initrdefi /initrd.img + } + menuentry 'Trusted Boot Profile' --id=tboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=true + initrdefi /initrd.img + } + } + } +} + +# Create a space in the menu +menuentry ' '{ + echo " " +} + +# AIO (lowlatency) Controller menu +submenu 'UEFI All-in-one (lowlatency) Controller Configuration' --id=aio-lowlat { + submenu 'Serial Console' --id=serial { + menuentry 'STANDARD Security Profile' --id=standard { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=standard + initrdefi /initrd.img + } + submenu 'EXTENDED Security Profile' --id=extended { + menuentry 'Secure Boot Profile' --id=secureboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=false + initrdefi /initrd.img + } + menuentry 'Trusted Boot Profile' --id=tboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=ttyS0,115200 inst.text serial inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=true + initrdefi /initrd.img + } + } + } + + submenu 'Graphical Console' --id=graphical { + menuentry 'STANDARD Security Profile' --id=standard { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=standard + initrdefi /initrd.img + } + submenu 'EXTENDED Security Profile' --id=extended { + menuentry 'Secure Boot Profile' --id=secureboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=false + initrdefi /initrd.img + } + menuentry 'Trusted Boot Profile' --id=tboot { + linuxefi /vmlinuz inst.ks=hd:LABEL=oe_iso_boot:/smallsystem_lowlatency_ks.cfg boot_device=sda rootfs_device=sda biosdevname=0 usbcore.autosuspend=-1 console=tty0 inst.text inst.stage2=hd:LABEL=oe_iso_boot inst.gpt security_profile=extended tboot=true + initrdefi /initrd.img + } + } + } +} diff --git a/bsp-files/kickstarts/functions.sh b/bsp-files/kickstarts/functions.sh new file mode 100644 index 00000000..41b48f65 --- /dev/null +++ b/bsp-files/kickstarts/functions.sh @@ -0,0 +1,72 @@ +# This file defines functions that can be used in %pre and %post kickstart sections, by including: +# . /tmp/ks-functions.sh +# + +cat </tmp/ks-functions.sh +# +# Copyright (c) xxxYEARxxx Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +function get_by_path() +{ + local disk=\$(cd /dev ; readlink -f \$1) + for p in /dev/disk/by-path/*; do + if [ "\$disk" = "\$(readlink -f \$p)" ]; then + echo \$p + return + fi + done +} + +function get_disk() +{ + echo \$(cd /dev ; readlink -f \$1) +} + +function report_pre_failure_with_msg() +{ + local msg=\$1 + echo -e '\n\nInstallation failed.\n' + echo "\$msg" + + exit 1 +} + +function report_post_failure_with_msg() +{ + local msg=\$1 + cat <> /etc/motd + +Installation failed. +\$msg + +EOF + echo "\$msg" >/etc/platform/installation_failed + + echo -e '\n\nInstallation failed.\n' + echo "\$msg" + + exit 1 +} + +function report_post_failure_with_logfile() +{ + local logfile=\$1 + cat <> /etc/motd + +Installation failed. +Please see \$logfile for details of failure + +EOF + echo \$logfile >/etc/platform/installation_failed + + echo -e '\n\nInstallation failed.\n' + cat \$logfile + + exit 1 +} + +END_FUNCTIONS + diff --git a/bsp-files/kickstarts/post_clone_iso_ks.cfg b/bsp-files/kickstarts/post_clone_iso_ks.cfg new file mode 100644 index 00000000..6553b181 --- /dev/null +++ b/bsp-files/kickstarts/post_clone_iso_ks.cfg @@ -0,0 +1,41 @@ + +# clone post installation script +%post --nochroot +if [ -d /mnt/install/source ]; then + srcdir=/mnt/install/source +else + srcdir=/run/install/repo +fi + +if [ -d $srcdir/clone-archive ]; then + cp -r $srcdir/clone-archive /mnt/sysimage/ + cp $srcdir/install_clone /mnt/sysimage/usr/bin/install_clone + chmod 500 /mnt/sysimage/usr/bin/install_clone +fi +%end + + +# clone post installation script to start install-clone service +%post --erroronfail + +# Build install-clone service file here, so that it is patchable. +cat << EOF > /usr/lib/systemd/system/install-clone.service +[Unit] +Description=Titanium install-clone service +After=hostw.service +Before=serial-getty@ttyS0.service getty@tty1.service +[Service] +User=root +Type=oneshot +RemainAfterExit=yes +Environment=PYTHONUNBUFFERED=1 +ExecStart=/usr/bin/install_clone +StandardOutput=syslog+console +[Install] +WantedBy=multi-user.target +EOF + +systemctl enable install-clone + +%end + diff --git a/bsp-files/kickstarts/post_common.cfg b/bsp-files/kickstarts/post_common.cfg new file mode 100644 index 00000000..fa5ebe33 --- /dev/null +++ b/bsp-files/kickstarts/post_common.cfg @@ -0,0 +1,104 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Turn off locale support for i18n if is not installed +if [ ! -d /usr/share/i18n ] ; then + rm -f /etc/sysconfig/i18n +fi +# Unset the hostname +rm /etc/hostname + +# If using a serial install make sure to add a getty on the tty1 +conarg=`cat /proc/cmdline |xargs -n1 echo |grep console= |grep ttyS` +if [ -n "$conarg" ] ; then + echo "1:2345:respawn:/sbin/mingetty tty1" >> /etc/inittab +fi + +#### SECURITY PROFILE HANDLING (Post Installation) #### +# Check if the Security profile mode is enabled +# and load the appropriate kernel modules +secprofile=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$secprofile" ]; then + echo "In Extended Security profile mode. Loading IMA kernel module" + systemctl enable auditd.service + # Add the securityfs mount for the IMA Runtime measurement list + echo "securityfs /sys/kernel/security securityfs defaults,nodev 0 0" >> /etc/fstab +else + # Disable audit daemon in the Standard Security Profile + systemctl disable auditd +fi + + +# Configure smart package manager channels +rm -rf /var/lib/smart +mkdir /var/lib/smart +/usr/bin/smart channel -y \ + --add rpmdb type=rpm-sys name="RPM Database" +/usr/bin/smart channel -y \ + --add base type=rpm-md name="Base" baseurl=http://controller/feed/rel-xxxPLATFORM_RELEASExxx +/usr/bin/smart channel -y \ + --add updates type=rpm-md name="Patches" baseurl=http://controller/updates/rel-xxxPLATFORM_RELEASExxx + +# Configure smart to use rpm --nolinktos option +/usr/bin/smart config --set rpm-nolinktos=true + +# Configure smart to use rpm --nosignature option +/usr/bin/smart config --set rpm-check-signatures=false + +# Delete the CentOS yum repo files +rm -f /etc/yum.repos.d/CentOS-* + +# Persist the boot device naming as UDEV rules so that if the network device +# order changes post-install that we will still be able to DHCP from the +# correct interface to reach the active controller. For most nodes only the +# management/boot interface needs to be persisted but because we require both +# controllers to be identically configured and controller-0 and controller-1 +# are installed differently (e.g., controller-0 from USB and controller-1 from +# network) it is not possible to know which interface to persist for +# controller-0. The simplest solution is to persist all interfaces. +# +mkdir -p /etc/udev/rules.d +echo "# Persisted network interfaces from anaconda installer" > /etc/udev/rules.d/70-persistent-net.rules +for dir in /sys/class/net/*; do + if [ -e ${dir}/device ]; then + dev=$(basename ${dir}) + mac_address=$(cat /sys/class/net/${dev}/address) + echo "ACTION==\"add\", SUBSYSTEM==\"net\", DRIVERS==\"?*\", ATTR{address}==\"${mac_address}\", NAME=\"${dev}\"" >> /etc/udev/rules.d/70-persistent-net.rules + fi +done + +# Mark the wrsroot password as expired immediately +chage -d 0 wrsroot + +# Lock the root password +passwd -l root + +# Enable tmpfs mount for /tmp +# delete /var/tmp so that it can similinked in +rm -rf /var/tmp +systemctl enable tmp.mount + +# Disable automount of /dev/hugepages +systemctl mask dev-hugepages.mount + +# Disable firewall +systemctl disable firewalld + +# Disable libvirtd +systemctl disable libvirtd.service + +# Enable rsyncd +systemctl enable rsyncd.service + +# Allow root to run sudo from a non-tty (for scripts running as root that run sudo cmds) +echo 'Defaults:root !requiretty' > /etc/sudoers.d/root + +# Make fstab just root read/writable +chmod 600 /etc/fstab + +# Create first_boot flag +touch /etc/platform/.first_boot + +%end diff --git a/bsp-files/kickstarts/post_kernel_aio_and_compute.cfg b/bsp-files/kickstarts/post_kernel_aio_and_compute.cfg new file mode 100644 index 00000000..8ec5cf7a --- /dev/null +++ b/bsp-files/kickstarts/post_kernel_aio_and_compute.cfg @@ -0,0 +1,98 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Source the generated platform.conf +. /etc/platform/platform.conf + +# Update grub with custom kernel bootargs +source /etc/init.d/cpumap_functions.sh +n_cpus=$(cat /proc/cpuinfo 2>/dev/null | \ + awk '/^[pP]rocessor/ { n +=1 } END { print (n>0) ? n : 1}') +n_numa=$(ls -d /sys/devices/system/node/node* 2>/dev/null | wc -l) +KERN_OPTS=" iommu=pt usbcore.autosuspend=-1" + +# Add kernel options for hugepages +if grep -q pdpe1gb /proc/cpuinfo +then + KERN_OPTS="${KERN_OPTS} hugepagesz=1G hugepages=${n_numa}" + KERN_OPTS="${KERN_OPTS} hugepagesz=2M hugepages=0 default_hugepagesz=2M" +else + KERN_OPTS="${KERN_OPTS} hugepagesz=2M hugepages=0 default_hugepagesz=2M" +fi + +# If this is an all-in-one system, we need at least 4 CPUs +if [ "$system_type" = "All-in-one" -a ${n_cpus} -lt 4 ]; then + report_post_failure_with_msg "ERROR: At least 4 CPUs are required for controller+compute node." +fi + +# Add kernel options for cpu isolation / affinity +if [ ${n_cpus} -gt 1 ] +then + base_cpulist=$(platform_expanded_cpu_list) + base_cpumap=$(cpulist_to_cpumap ${base_cpulist} ${n_cpus}) + avp_cpulist=$(vswitch_expanded_cpu_list) + norcu_cpumap=$(invert_cpumap ${base_cpumap} ${n_cpus}) + norcu_cpulist=$(cpumap_to_cpulist ${norcu_cpumap} ${n_cpus}) + + if [[ "$subfunction" =~ lowlatency ]]; then + KERN_OPTS="${KERN_OPTS} isolcpus=${norcu_cpulist}" + KERN_OPTS="${KERN_OPTS} nohz_full=${norcu_cpulist}" + else + KERN_OPTS="${KERN_OPTS} isolcpus=${avp_cpulist}" + fi + KERN_OPTS="${KERN_OPTS} rcu_nocbs=${norcu_cpulist}" + KERN_OPTS="${KERN_OPTS} kthread_cpus=${base_cpulist}" + KERN_OPTS="${KERN_OPTS} irqaffinity=${base_cpulist}" + # Update vswitch.conf + sed -i "s/^VSWITCH_CPU_LIST=.*/VSWITCH_CPU_LIST=\"${avp_cpulist}\"/" /etc/vswitch/vswitch.conf +fi + +# Add kernel options to ensure an selinux is disabled +KERN_OPTS="${KERN_OPTS} selinux=0 enforcing=0" + +# Add kernel options to set NMI watchdog +if [[ "$subfunction" =~ lowlatency ]]; then + KERN_OPTS="${KERN_OPTS} nmi_watchdog=0 softlockup_panic=0" +else + KERN_OPTS="${KERN_OPTS} nmi_watchdog=panic,1 softlockup_panic=1" +fi + +if [[ "$(dmidecode -s system-product-name)" =~ ^ProLiant.*Gen8$ ]]; then + KERN_OPTS="${KERN_OPTS} intel_iommu=on,eth_no_rmrr" +else + KERN_OPTS="${KERN_OPTS} intel_iommu=on" +fi + +# Add kernel option to disable biosdevname if enabled +# As this may already be in GRUB_CMDLINE_LINUX, only add if it is not already present +grep -q '^GRUB_CMDLINE_LINUX=.*biosdevname=0' /etc/default/grub +if [ $? -ne 0 ]; then + KERN_OPTS="${KERN_OPTS} biosdevname=0" +fi + +# Add kernel options to disable kvm-intel.eptad on Broadwell +# Broadwell: Model: 79, Model name: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz +if grep -q -E "^model\s+:\s+79$" /proc/cpuinfo +then + KERN_OPTS="${KERN_OPTS} kvm-intel.eptad=0" +fi + +KERN_OPTS="${KERN_OPTS} cgroup_disable=memory" + +# Add kernel option to avoid jiffies_lock contention on real-time kernel +if [[ "$subfunction" =~ lowlatency ]]; then + KERN_OPTS="${KERN_OPTS} skew_tick=1" +fi + +perl -pi -e 's/(GRUB_CMDLINE_LINUX=.*)\"/\1'"$KERN_OPTS"'\"/g' /etc/default/grub + +if [ -d /sys/firmware/efi ] ; then + grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg +else + grub2-mkconfig -o /boot/grub2/grub.cfg +fi + +%end + diff --git a/bsp-files/kickstarts/post_kernel_controller.cfg b/bsp-files/kickstarts/post_kernel_controller.cfg new file mode 100644 index 00000000..f782b6c4 --- /dev/null +++ b/bsp-files/kickstarts/post_kernel_controller.cfg @@ -0,0 +1,38 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +## Custom kernel options +KERN_OPTS=" intel_iommu=off usbcore.autosuspend=-1" + +## Setup the loop module to support up to 15 partitions so that we can enable the +## customer to manually resize images if needed. +## +KERN_OPTS="${KERN_OPTS} loop.max_part=15" + +## Add kernel options to ensure an selinux is disabled +KERN_OPTS="${KERN_OPTS} selinux=0 enforcing=0" + +# Add kernel options to ensure NMI watchdog is enabled, if supported +KERN_OPTS="${KERN_OPTS} nmi_watchdog=panic,1 softlockup_panic=1" + +# Add kernel option to disable biosdevname if enabled +# As this may already be in GRUB_CMDLINE_LINUX, only add if it is not already present +grep -q '^GRUB_CMDLINE_LINUX=.*biosdevname=0' /etc/default/grub +if [ $? -ne 0 ]; then + KERN_OPTS="${KERN_OPTS} biosdevname=0" +fi + +KERN_OPTS="${KERN_OPTS} cgroup_disable=memory" + +perl -pi -e 's/(GRUB_CMDLINE_LINUX=.*)\"/\1'"$KERN_OPTS"'\"/g' /etc/default/grub + +if [ -d /sys/firmware/efi ] ; then + grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg +else + grub2-mkconfig -o /boot/grub2/grub.cfg +fi + +%end + diff --git a/bsp-files/kickstarts/post_kernel_storage.cfg b/bsp-files/kickstarts/post_kernel_storage.cfg new file mode 100644 index 00000000..7ede2eb9 --- /dev/null +++ b/bsp-files/kickstarts/post_kernel_storage.cfg @@ -0,0 +1,32 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +## Custom kernel options +KERN_OPTS=" intel_iommu=off usbcore.autosuspend=-1" +## Add kernel options to ensure an selinux is disabled +KERN_OPTS="${KERN_OPTS} selinux=0 enforcing=0" + +# Add kernel options to ensure NMI watchdog is enabled, if supported +KERN_OPTS="${KERN_OPTS} nmi_watchdog=panic,1 softlockup_panic=1" + +# Add kernel option to disable biosdevname if enabled +# As this may already be in GRUB_CMDLINE_LINUX, only add if it is not already present +grep -q '^GRUB_CMDLINE_LINUX=.*biosdevname=0' /etc/default/grub +if [ $? -ne 0 ]; then + KERN_OPTS="${KERN_OPTS} biosdevname=0" +fi + +KERN_OPTS="${KERN_OPTS} cgroup_disable=memory" + +perl -pi -e 's/(GRUB_CMDLINE_LINUX=.*)\"/\1'"$KERN_OPTS"'\"/g' /etc/default/grub + +if [ -d /sys/firmware/efi ] ; then + grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg +else + grub2-mkconfig -o /boot/grub2/grub.cfg +fi + +%end + diff --git a/bsp-files/kickstarts/post_lvm_no_pv_on_rootfs.cfg b/bsp-files/kickstarts/post_lvm_no_pv_on_rootfs.cfg new file mode 100644 index 00000000..f933d2bb --- /dev/null +++ b/bsp-files/kickstarts/post_lvm_no_pv_on_rootfs.cfg @@ -0,0 +1,12 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# uncomment the global_filter line in lvm.conf +perl -0777 -i.bak -pe 's:(# This configuration option has an automatic default value\.\n)\t# global_filter:$1 global_filter:m' /etc/lvm/lvm.conf + +# Edit the LVM config so LVM does not look for LVs (we have none on compute nodes) +sed -i "s#^\( *\)global_filter = \[.*#\1global_filter = [ \"r|.*|\" ]#" /etc/lvm/lvm.conf +%end + diff --git a/bsp-files/kickstarts/post_lvm_pv_on_rootfs.cfg b/bsp-files/kickstarts/post_lvm_pv_on_rootfs.cfg new file mode 100644 index 00000000..bf7bd705 --- /dev/null +++ b/bsp-files/kickstarts/post_lvm_pv_on_rootfs.cfg @@ -0,0 +1,17 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# uncomment the global_filter line in lvm.conf +perl -0777 -i.bak -pe 's:(# This configuration option has an automatic default value\.\n)\t# global_filter:$1 global_filter:m' /etc/lvm/lvm.conf + +# Determine which disk we created our PV on (i.e. the root disk) +ROOTDISK=$(get_by_path $(pvdisplay --select 'vg_name=cgts-vg' -C -o pv_name --noheadings)) +if [ -z "$ROOTDISK" ]; then + report_post_failure_with_msg "ERROR: failed to identify rootdisk via pvdisplay" +fi +# Edit the LVM config so LVM only looks for LVs on the root disk +sed -i "s#^\( *\)global_filter = \[.*#\1global_filter = [ \"a|${ROOTDISK}|\", \"r|.*|\" ]#" /etc/lvm/lvm.conf +%end + diff --git a/bsp-files/kickstarts/post_net_common.cfg b/bsp-files/kickstarts/post_net_common.cfg new file mode 100755 index 00000000..2db90a44 --- /dev/null +++ b/bsp-files/kickstarts/post_net_common.cfg @@ -0,0 +1,127 @@ +repo --name=base --baseurl=http://pxecontroller/feed/rel-xxxPLATFORM_RELEASExxx/ +repo --name=updates --baseurl=http://pxecontroller/updates/rel-xxxPLATFORM_RELEASExxx/ + +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Obtain the boot interface from the PXE boot +BOOTIF=`cat /proc/cmdline |xargs -n1 echo |grep BOOTIF=` +if [ -d /sys/firmware/efi ] ; then + BOOTIF=${BOOTIF#BOOTIF=} +else + BOOTIF=${BOOTIF#BOOTIF=01-} + BOOTIF=${BOOTIF//-/:} +fi + +mgmt_dev=none +mgmt_vlan=0 +if [ -n "$BOOTIF" ] ; then + ndev=`ip link show |grep -B 1 $BOOTIF |head -1 |awk '{print $2}' |sed -e 's/://'` + if [ -n "$ndev" ] ; then + mgmt_dev=$ndev + # Retrieve the management VLAN from sysinv if it exists + mgmt_vlan=`curl -sf http://pxecontroller:6385/v1/isystems/mgmtvlan` + if [ $? -ne 0 ] + then + report_post_failure_with_msg "ERROR: Unable to communicate with System Inventory REST API. Aborting installation." + fi + else + report_post_failure_with_msg "ERROR: Unable to determine mgmt interface from BOOTIF=$BOOTIF." + fi +else + report_post_failure_with_msg "ERROR: BOOTIF is not set. Unable to determine mgmt interface." +fi + +if [ $mgmt_vlan -eq 0 ] ; then + + # Persist the boot device to the platform configuration. This will get + # overwritten later if the management_interface is on a bonded interface. + echo management_interface=$mgmt_dev >> /etc/platform/platform.conf + + # Build networking scripts + cat << EOF > /etc/sysconfig/network-scripts/ifcfg-lo +DEVICE=lo +IPADDR=127.0.0.1 +NETMASK=255.0.0.0 +NETWORK=127.0.0.0 +BROADCAST=127.255.255.255 +ONBOOT=yes +NAME=loopback +EOF + + cat << EOF > /etc/sysconfig/network-scripts/ifcfg-$mgmt_dev +DEVICE=$mgmt_dev +BOOTPROTO=dhcp +ONBOOT=yes +LINKDELAY=20 +EOF + +else + + # Check whether to use inet or inet6 + ipv6_addr=$(dig +short AAAA controller) + if [[ -n "$ipv6_addr" ]] + then + mgmt_address_family=inet6 + ipv6init=yes + dhcpv6c=yes + dhclientargs=-1 + else + mgmt_address_family=inet + ipv6init=no + dhcpv6c=no + dhclientargs= + fi + + # Persist the boot device to the platform configuration. This will get + # overwritten later if the management_interface is on a bonded interface. + echo management_interface=$mgmt_dev.$mgmt_vlan >> /etc/platform/platform.conf + + # Build networking scripts + cat << EOF > /etc/sysconfig/network-scripts/ifcfg-lo +DEVICE=lo +IPADDR=127.0.0.1 +NETMASK=255.0.0.0 +NETWORK=127.0.0.0 +BROADCAST=127.255.255.255 +ONBOOT=yes +NAME=loopback +EOF + + cat << EOF > /etc/sysconfig/network-scripts/ifcfg-$mgmt_dev +DEVICE=$mgmt_dev +BOOTPROTO=none +ONBOOT=yes +LINKDELAY=20 +EOF + + cat << EOF > /etc/sysconfig/network-scripts/ifcfg-$mgmt_dev.$mgmt_vlan +DEVICE=$mgmt_dev.$mgmt_vlan +BOOTPROTO=dhcp +DHCLIENTARGS=$dhclientargs +IPV6INIT=$ipv6init +DHCPV6C=$dhcpv6c +ONBOOT=yes +VLAN=yes +LINKDELAY=20 +EOF + + # Reject DHCPOFFER from DHCP server that doesn't send + # wrs-install-uuid option + echo "require wrs-install-uuid;" >>/etc/dhcp/dhclient.conf + echo "require dhcp6.wrs-install-uuid;" >>/etc/dhcp/dhclient.conf + + # Bring up the mgmt vlan so that a dhcp lease is acquired and an address is + # setup prior to the post-install reboot. This is so that the timing of the IP + # address allocation is similar to how normal/non-pxe installation works. + mgmt_iface=$mgmt_dev.$mgmt_vlan + dhclient_family=$([[ $mgmt_address_family == "inet" ]] && echo -4 || echo -6) + ip link add link $mgmt_dev name $mgmt_iface type vlan id $mgmt_vlan + ip link set up dev $mgmt_iface + dhclient $dhclient_family $mgmt_iface || true + +fi + +%end diff --git a/bsp-files/kickstarts/post_net_controller.cfg b/bsp-files/kickstarts/post_net_controller.cfg new file mode 100644 index 00000000..c3e4b8f6 --- /dev/null +++ b/bsp-files/kickstarts/post_net_controller.cfg @@ -0,0 +1,79 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Retrieve the installation uuid from the controller we booted from +INSTALL_UUID=`curl -sf http://pxecontroller/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid` +if [ $? -ne 0 ] +then + INSTALL_UUID=unknown +fi + +grep -q INSTALL_UUID /etc/platform/platform.conf +if [ $? -ne 0 ]; then + echo "INSTALL_UUID=$INSTALL_UUID" >> /etc/platform/platform.conf +fi + +cd /www/pages +# Sync software repository +feed_url=http://pxecontroller/feed/ +anaconda_logdir=/var/log/anaconda +mkdir -p $anaconda_logdir + +echo "Mirroring software repository (may take several minutes)..." >/dev/console +wget --mirror --no-parent --no-host-directories --reject 'index.html*' --reject '*.log' $feed_url/ -o $anaconda_logdir/wget-feed-mirror.log \ + || report_post_failure_with_logfile $anaconda_logdir/wget-feed-mirror.log + +# Sync patching repository +updates_url=http://pxecontroller/updates/ +wget --mirror --no-parent --no-host-directories --reject 'index.html*' --reject '*.log' $updates_url/ -o $anaconda_logdir/wget-updates-mirror.log \ + || report_post_failure_with_logfile $anaconda_logdir/wget-updates-mirror.log +echo "Done" >/dev/console + +shopt -s nullglob + +# Check whether a second release is installed +. /etc/build.info +CURRENT_REL_DIR=rel-${SW_VERSION} +OTHER_REL_DIR= +for REL_DIR in /www/pages/feed/*; do + if [[ ! $REL_DIR =~ "${SW_VERSION}" ]]; then + OTHER_REL_DIR=`basename $REL_DIR` + OTHER_REL_VERSION=${OTHER_REL_DIR:4} + break + fi +done + +# If second release is installed, find the latest version of the installer +# RPM and install the pxeboot files we require to boot hosts with that release. +if [ ! -z "$OTHER_REL_DIR" ]; then + PATCH_RPM=`find /www/pages/updates/${OTHER_REL_DIR}/Packages -name 'pxe-network-installer*' | sort -V | tail -1` + BASE_RPM=`find /www/pages/feed/${OTHER_REL_DIR}/Packages -name 'pxe-network-installer*' | sort -V | tail -1` + + if [ ! -z "$PATCH_RPM" ]; then + INSTALL_RPM=$PATCH_RPM + elif [ ! -z "$BASE_RPM" ]; then + INSTALL_RPM=$BASE_RPM + else + report_post_failure_with_msg "ERROR: Unable to find pxe-network-installer RPM for $OTHER_REL_DIR. Aborting installation." + fi + + echo "Installing pxeboot files for release $OTHER_REL_DIR from $INSTALL_RPM" >/dev/console + TMP_RPM=/tmp/pxe-network-installer + mkdir $TMP_RPM + pushd $TMP_RPM + /usr/bin/rpm2cpio $INSTALL_RPM | cpio -idm \ + || report_post_failure_with_msg "Failed to extract pxe-network-installer" + + cp -r $TMP_RPM/usr / \ + || report_post_failure_with_msg "Failed to copy pxe-network-installer /usr" + cp -r $TMP_RPM/pxeboot/$OTHER_REL_DIR /pxeboot/ \ + || report_post_failure_with_msg "Failed to copy pxe-network-installer /pxeboot/$OTHER_REL_DIR" + cp $TMP_RPM/pxeboot/pxelinux.cfg.files/*-$OTHER_REL_VERSION /pxeboot/pxelinux.cfg.files/ \ + || report_post_failure_with_msg "Failed to copy pxe-network-installer pxelinux.cfg files" + + rm -rf $TMP_RPM +fi + +%end diff --git a/bsp-files/kickstarts/post_platform_conf_aio.cfg b/bsp-files/kickstarts/post_platform_conf_aio.cfg new file mode 100644 index 00000000..b0660cc4 --- /dev/null +++ b/bsp-files/kickstarts/post_platform_conf_aio.cfg @@ -0,0 +1,22 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Set the security profile mode +secprofile="standard" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + secprofile="extended" +fi + +mkdir -p -m 0775 /etc/platform +cat < /etc/platform/platform.conf +nodetype=controller +subfunction=controller,compute +system_type=All-in-one +security_profile=$secprofile +EOF + +%end + diff --git a/bsp-files/kickstarts/post_platform_conf_aio_lowlatency.cfg b/bsp-files/kickstarts/post_platform_conf_aio_lowlatency.cfg new file mode 100644 index 00000000..048f07a6 --- /dev/null +++ b/bsp-files/kickstarts/post_platform_conf_aio_lowlatency.cfg @@ -0,0 +1,22 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Set the security profile mode +secprofile="standard" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + secprofile="extended" +fi + +mkdir -p -m 0775 /etc/platform +cat < /etc/platform/platform.conf +nodetype=controller +subfunction=controller,compute,lowlatency +system_type=All-in-one +security_profile=$secprofile +EOF + +%end + diff --git a/bsp-files/kickstarts/post_platform_conf_compute.cfg b/bsp-files/kickstarts/post_platform_conf_compute.cfg new file mode 100644 index 00000000..35c82522 --- /dev/null +++ b/bsp-files/kickstarts/post_platform_conf_compute.cfg @@ -0,0 +1,34 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Retrieve the installation uuid from the controller we booted from +INSTALL_UUID=`curl -sf http://pxecontroller/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid` +if [ $? -ne 0 ] +then + INSTALL_UUID=unknown +fi + +# Set the security profile mode +secprofile="standard" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + secprofile="extended" +fi + +mkdir -p -m 0775 /etc/platform +cat < /etc/platform/platform.conf +nodetype=compute +subfunction=compute +system_type=Standard +security_profile=$secprofile +INSTALL_UUID=$INSTALL_UUID +EOF + +# mount the platform directory from the controller +cat >> /etc/fstab < /etc/platform/platform.conf +nodetype=compute +subfunction=compute,lowlatency +system_type=Standard +security_profile=$secprofile +INSTALL_UUID=$INSTALL_UUID +EOF + +# mount the platform directory from the controller +cat >> /etc/fstab < /etc/platform/platform.conf +nodetype=controller +subfunction=controller +system_type=Standard +security_profile=$secprofile +EOF + +%end + diff --git a/bsp-files/kickstarts/post_platform_conf_storage.cfg b/bsp-files/kickstarts/post_platform_conf_storage.cfg new file mode 100644 index 00000000..5b22f183 --- /dev/null +++ b/bsp-files/kickstarts/post_platform_conf_storage.cfg @@ -0,0 +1,29 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Retrieve the installation uuid from the controller we booted from +INSTALL_UUID=`curl -sf http://pxecontroller/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid` +if [ $? -ne 0 ] +then + INSTALL_UUID=unknown +fi + +# Set the security profile mode +secprofile="standard" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + secprofile="extended" +fi + +mkdir -p -m 0775 /etc/platform +cat < /etc/platform/platform.conf +nodetype=storage +subfunction=storage +system_type=Standard +security_profile=$secprofile +INSTALL_UUID=$INSTALL_UUID +EOF + +%end diff --git a/bsp-files/kickstarts/post_pxeboot_controller.cfg b/bsp-files/kickstarts/post_pxeboot_controller.cfg new file mode 100644 index 00000000..918115af --- /dev/null +++ b/bsp-files/kickstarts/post_pxeboot_controller.cfg @@ -0,0 +1,114 @@ +%pre --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +echo "repo --name=base --baseurl=xxxHTTP_URLxxx/" > /tmp/repo-include +echo "repo --name=updates --baseurl=xxxHTTP_URLxxx/patches/" > /tmp/repo-include +%end + +# Repository arguments from %pre +%include /tmp/repo-include + + +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Obtain the boot interface from the PXE boot +BOOTIF=`cat /proc/cmdline |xargs -n1 echo |grep BOOTIF=` +if [ -d /sys/firmware/efi ] ; then + BOOTIF=${BOOTIF#BOOTIF=} +else + BOOTIF=${BOOTIF#BOOTIF=01-} + BOOTIF=${BOOTIF//-/:} +fi + +mgmt_dev=none +if [ -n "$BOOTIF" ] ; then + ndev=`ip link show |grep -B 1 $BOOTIF |head -1 |awk '{print $2}' |sed -e 's/://'` + if [ -n "$ndev" ] ; then + mgmt_dev=$ndev + else + report_post_failure_with_msg "ERROR: Unable to determine mgmt interface from BOOTIF=$BOOTIF." + fi +else + report_post_failure_with_msg "ERROR: BOOTIF is not set. Unable to determine mgmt interface." +fi + +# Persist the boot device to the platform configuration. This will get +# overwritten when config_controller is run. +echo management_interface=$mgmt_dev >> /etc/platform/platform.conf + +# Build networking scripts +cat << EOF > /etc/sysconfig/network-scripts/ifcfg-lo +DEVICE=lo +IPADDR=127.0.0.1 +NETMASK=255.0.0.0 +NETWORK=127.0.0.0 +BROADCAST=127.255.255.255 +ONBOOT=yes +NAME=loopback +EOF + +cat << EOF > /etc/sysconfig/network-scripts/ifcfg-$mgmt_dev +DEVICE=$mgmt_dev +BOOTPROTO=dhcp +ONBOOT=yes +EOF + +%end + +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +anaconda_logdir=/var/log/anaconda +mkdir -p $anaconda_logdir + +cd /www/pages +mkdir -p feed/rel-xxxPLATFORM_RELEASExxx/Packages +mkdir -p feed/rel-xxxPLATFORM_RELEASExxx/repodata +cd feed/rel-xxxPLATFORM_RELEASExxx +feed_url=xxxHTTP_URLxxx +declare -i cut_dirs=NUM_DIRS +echo "Mirroring software repository (may take several minutes)..." >/dev/console +wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$cut_dirs $feed_url/Packages/ -o $anaconda_logdir/rpmget.log \ + || report_post_failure_with_logfile $anaconda_logdir/rpmget.log +wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$cut_dirs $feed_url/repodata/ -o $anaconda_logdir/rpmget_repo.log \ + || report_post_failure_with_logfile $anaconda_logdir/rpmget_repo.log +wget $feed_url/isolinux.cfg --append $anaconda_logdir/wget_kickstarts.log \ + || report_post_failure_with_logfile $anaconda_logdir/wget_kickstarts.log +echo "Done" >/dev/console + +patches_url=xxxHTTP_URLxxx/patches +wget -q --spider ${patches_url}/ +if [ $? -eq 0 ]; then + echo "Downloading patches..." >/dev/console + mkdir -p updates/rel-xxxPLATFORM_RELEASExxx/Packages + mkdir -p updates/rel-xxxPLATFORM_RELEASExxx/repodata + declare -i patches_cut_dirs=$((cut_dirs+1)) + + wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$patches_cut_dirs $patches_url/Packages/ -o $anaconda_logdir/patches_rpmget.log \ + || report_post_failure_with_logfile $anaconda_logdir/patches_rpmget.log + wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$patches_cut_dirs $patches_url/repodata/ -o $anaconda_logdir/patches_rpmget_repo.log \ + || report_post_failure_with_logfile $anaconda_logdir/patches_rpmget_repo.log + + mkdir -p /opt/patching/metadata + mkdir -p /opt/patching/packages/xxxPLATFORM_RELEASExxx + cd /opt/patching + wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$patches_cut_dirs $patches_url/metadata/ -o $anaconda_logdir/patches_rpmget_metadata.log \ + || report_post_failure_with_logfile $anaconda_logdir/patches_rpmget_metadata.log + find /www/pages/updates/rel-xxxPLATFORM_RELEASExxx/Packages -name '*.rpm' \ + | xargs --no-run-if-empty -I files cp --preserve=all files /opt/patching/packages/xxxPLATFORM_RELEASExxx/ + + echo "Done" >/dev/console +fi + +# Create a uuid specific to this installation +INSTALL_UUID=`uuidgen` +echo $INSTALL_UUID > /www/pages/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid +echo "INSTALL_UUID=$INSTALL_UUID" >> /etc/platform/platform.conf +%end diff --git a/bsp-files/kickstarts/post_system_aio.cfg b/bsp-files/kickstarts/post_system_aio.cfg new file mode 100644 index 00000000..ac61e5a0 --- /dev/null +++ b/bsp-files/kickstarts/post_system_aio.cfg @@ -0,0 +1,35 @@ +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Source the generated platform.conf +. /etc/platform/platform.conf + +## Reserve more memory for base processes since the controller has higher +## memory requirements but cap it to better handle systems with large +## amounts of memory +TOTALMEM=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024)}') + +if [ -e /sys/devices/system/node/node0 ]; then + RESERVEDMEM=$(grep MemTotal /sys/devices/system/node/node0/meminfo | awk '{printf "%d\n", $4/1024}') +else + RESERVEDMEM=$(grep MemTotal /proc/meminfo | awk '{print int($2/1024/4)}') +fi + +if [ ${RESERVEDMEM} -lt 6144 ]; then + RESERVEDMEM=6144 +elif [ ${RESERVEDMEM} -gt 14500 ]; then + RESERVEDMEM=14500 +elif [ ${RESERVEDMEM} -gt 8192 ]; then + RESERVEDMEM=8192 +fi + +sed -i -e "s#\(COMPUTE_BASE_RESERVED\)=.*#\1=(\"node0:${RESERVEDMEM}MB:1\" \"node1:2000MB:0\" \"node2:2000MB:0\" \"node3:2000MB:0\")#g" /etc/nova/compute_reserved.conf + +# Update COMPUTE_CPU_LIST +N_CPUS=$(cat /proc/cpuinfo 2>/dev/null | awk '/^[pP]rocessor/ { n +=1 } END { print (n>0) ? n : 1}') +sed -i "s/^COMPUTE_CPU_LIST=.*/COMPUTE_CPU_LIST=\"0-$((N_CPUS-1))\"/" /etc/nova/compute_reserved.conf + +%end + diff --git a/bsp-files/kickstarts/post_usb_controller.cfg b/bsp-files/kickstarts/post_usb_controller.cfg new file mode 100644 index 00000000..f8d97c5c --- /dev/null +++ b/bsp-files/kickstarts/post_usb_controller.cfg @@ -0,0 +1,80 @@ +%pre --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +if [ -d /mnt/install/source ]; then + srcdir=/mnt/install/source +else + srcdir=/run/install/repo +fi + +touch /tmp/repo-include + +if [ -d ${srcdir}/patches ]; then + echo "repo --name=updates --baseurl=file://${srcdir}/patches/" > /tmp/repo-include +fi + +%end + +# Repository arguments from %pre +%include /tmp/repo-include + +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +mgmt_dev=none + +# Persist the boot device to the platform configuration. This will get +# overwritten when config_controller is run. +echo management_interface=$mgmt_dev >> /etc/platform/platform.conf + +# Build networking scripts +cat << EOF > /etc/sysconfig/network-scripts/ifcfg-lo +DEVICE=lo +IPADDR=127.0.0.1 +NETMASK=255.0.0.0 +NETWORK=127.0.0.0 +BROADCAST=127.255.255.255 +ONBOOT=yes +NAME=loopback +EOF + +%end + + +# Note, this section is different and replaced with a wget +# if doing the initial install off the network +%post --nochroot +if [ -d /mnt/install/source ]; then + srcdir=/mnt/install/source +else + srcdir=/run/install/repo +fi + +if [ -d $srcdir/Packages ] ; then + mkdir -p /mnt/sysimage/www/pages/feed/rel-xxxPLATFORM_RELEASExxx + cp -r $srcdir/Packages /mnt/sysimage/www/pages/feed/rel-xxxPLATFORM_RELEASExxx/Packages + cp -r $srcdir/repodata /mnt/sysimage/www/pages/feed/rel-xxxPLATFORM_RELEASExxx/repodata + cp $srcdir/*.cfg /mnt/sysimage/www/pages/feed/rel-xxxPLATFORM_RELEASExxx +fi + +if [ -d $srcdir/patches ]; then + mkdir -p /mnt/sysimage/www/pages/updates/rel-xxxPLATFORM_RELEASExxx + cp -r $srcdir/patches/Packages /mnt/sysimage/www/pages/updates/rel-xxxPLATFORM_RELEASExxx/Packages + cp -r $srcdir/patches/repodata /mnt/sysimage/www/pages/updates/rel-xxxPLATFORM_RELEASExxx/repodata + mkdir -p /mnt/sysimage/opt/patching + cp -r $srcdir/patches/metadata /mnt/sysimage/opt/patching/metadata + mkdir -p /mnt/sysimage/opt/patching/packages/xxxPLATFORM_RELEASExxx + + find /mnt/sysimage/www/pages/updates/rel-xxxPLATFORM_RELEASExxx/Packages -name '*.rpm' \ + | xargs --no-run-if-empty -I files cp --preserve=all files /mnt/sysimage/opt/patching/packages/xxxPLATFORM_RELEASExxx/ +fi + +# Create a uuid specific to this installation +INSTALL_UUID=`uuidgen` +echo $INSTALL_UUID > /mnt/sysimage/www/pages/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid +echo "INSTALL_UUID=$INSTALL_UUID" >> /mnt/sysimage/etc/platform/platform.conf +%end diff --git a/bsp-files/kickstarts/post_yow_controller.cfg b/bsp-files/kickstarts/post_yow_controller.cfg new file mode 100644 index 00000000..b8bd8e2e --- /dev/null +++ b/bsp-files/kickstarts/post_yow_controller.cfg @@ -0,0 +1,115 @@ +%pre --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +echo "repo --name=base --baseurl=http://xxxBOOT_SERVERxxx/umalab/`hostname`_feed/" > /tmp/repo-include +echo "repo --name=updates --baseurl=http://xxxBOOT_SERVERxxx/umalab/`hostname`_feed/patches" > /tmp/repo-include +%end + +# Repository arguments from %pre +%include /tmp/repo-include + + +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# Obtain the boot interface from the PXE boot +BOOTIF=`cat /proc/cmdline |xargs -n1 echo |grep BOOTIF=` +if [ -d /sys/firmware/efi ] ; then + BOOTIF=${BOOTIF#BOOTIF=} +else + BOOTIF=${BOOTIF#BOOTIF=01-} + BOOTIF=${BOOTIF//-/:} +fi + +mgmt_dev=none +if [ -n "$BOOTIF" ] ; then + ndev=`ip link show |grep -B 1 $BOOTIF |head -1 |awk '{print $2}' |sed -e 's/://'` + if [ -n "$ndev" ] ; then + mgmt_dev=$ndev + else + report_post_failure_with_msg "ERROR: Unable to determine mgmt interface from BOOTIF=$BOOTIF." + fi +else + report_post_failure_with_msg "ERROR: BOOTIF is not set. Unable to determine mgmt interface." +fi + +# Persist the boot device to the platform configuration. This will get +# overwritten when config_controller is run. +echo management_interface=$mgmt_dev >> /etc/platform/platform.conf + +# Build networking scripts +cat << EOF > /etc/sysconfig/network-scripts/ifcfg-lo +DEVICE=lo +IPADDR=127.0.0.1 +NETMASK=255.0.0.0 +NETWORK=127.0.0.0 +BROADCAST=127.255.255.255 +ONBOOT=yes +NAME=loopback +EOF + +cat << EOF > /etc/sysconfig/network-scripts/ifcfg-$mgmt_dev +DEVICE=$mgmt_dev +BOOTPROTO=dhcp +ONBOOT=yes +LINKDELAY=20 +EOF + +%end + +%post --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +anaconda_logdir=/var/log/anaconda +mkdir -p $anaconda_logdir + +cd /www/pages +mkdir -p feed/rel-xxxPLATFORM_RELEASExxx/Packages +mkdir -p feed/rel-xxxPLATFORM_RELEASExxx/repodata +cd feed/rel-xxxPLATFORM_RELEASExxx +feed_url=http://xxxBOOT_SERVERxxx/umalab/`hostname`_feed +declare -i cut_dirs=2 +echo "Mirroring software repository (may take several minutes)..." >/dev/console +wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$cut_dirs $feed_url/Packages/ -o $anaconda_logdir/rpmget.log \ + || report_post_failure_with_logfile $anaconda_logdir/rpmget.log +wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$cut_dirs $feed_url/repodata/ -o $anaconda_logdir/rpmget_repo.log \ + || report_post_failure_with_logfile $anaconda_logdir/rpmget_repo.log +wget $feed_url/isolinux.cfg --append $anaconda_logdir/wget_kickstarts.log \ + || report_post_failure_with_logfile $anaconda_logdir/wget_kickstarts.log + +# Check for patches +patches_url=http://xxxBOOT_SERVERxxx/umalab/`hostname`_feed/patches +wget -q --spider ${patches_url}/ +if [ $? -eq 0 ]; then + cd /www/pages + mkdir -p updates/rel-xxxPLATFORM_RELEASExxx/Packages + mkdir -p updates/rel-xxxPLATFORM_RELEASExxx/repodata + cd updates/rel-xxxPLATFORM_RELEASExxx + declare -i patches_cut_dirs=$((cut_dirs+1)) + wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$patches_cut_dirs $patches_url/Packages/ -o $anaconda_logdir/patches_rpmget.log \ + || report_post_failure_with_logfile $anaconda_logdir/patches_rpmget.log + wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$patches_cut_dirs $patches_url/repodata/ -o $anaconda_logdir/patches_rpmget_repo.log \ + || report_post_failure_with_logfile $anaconda_logdir/patches_rpmget_repo.log + + mkdir -p /opt/patching/metadata + mkdir -p /opt/patching/packages/xxxPLATFORM_RELEASExxx + cd /opt/patching + wget --mirror --no-parent --no-host-directories --reject 'index.html*' --cut-dirs=$patches_cut_dirs $patches_url/metadata/ -o $anaconda_logdir/patches_rpmget_metadata.log \ + || report_post_failure_with_logfile $anaconda_logdir/patches_rpmget_metadata.log + find /www/pages/updates/rel-xxxPLATFORM_RELEASExxx/Packages -name '*.rpm' \ + | xargs --no-run-if-empty -I files cp --preserve=all files /opt/patching/packages/xxxPLATFORM_RELEASExxx/ + + echo "Done" >/dev/console +fi + +# Create a uuid specific to this installation +INSTALL_UUID=`uuidgen` +echo $INSTALL_UUID > /www/pages/feed/rel-xxxPLATFORM_RELEASExxx/install_uuid +echo "INSTALL_UUID=$INSTALL_UUID" >> /etc/platform/platform.conf +%end diff --git a/bsp-files/kickstarts/pre_common_head.cfg b/bsp-files/kickstarts/pre_common_head.cfg new file mode 100644 index 00000000..88edab48 --- /dev/null +++ b/bsp-files/kickstarts/pre_common_head.cfg @@ -0,0 +1,72 @@ +%pre --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# First, parse /proc/cmdline to find the boot args +set -- `cat /proc/cmdline` +for I in $*; do case "$I" in *=*) eval $I 2>/dev/null;; esac; done + +append= +if [ -n "$console" ] ; then + append="console=$console" +fi + +if [ -n "$security_profile" ]; then + append="$append security_profile=$security_profile" +fi + +#### SECURITY PROFILE HANDLING (Pre Installation) #### +if [ -n "$security_profile" ] && [ "$security_profile" == "extended" ]; then + # IMA specific boot options: + # Enable Kernel auditing + append="$append audit=1" +else + # we need to blacklist the IMA and Integrity Modules + # on standard security profile + append="$append module_blacklist=integrity,ima" + + # Disable Kernel auditing in Standard Security Profile mode + append="$append audit=0" +fi + +if [ -n "$tboot" ]; then + append="$append tboot=$tboot" +else + append="$append tboot=false" +fi + +boot_device_arg= +if [ -n "$boot_device" ] ; then + boot_device_arg="--boot-drive=$(get_by_path $boot_device)" +fi + +echo "bootloader --location=mbr $boot_device_arg --timeout=5 --append=\"$append\"" > /tmp/bootloader-include + +echo "timezone --nontp --utc UTC" >/tmp/timezone-include +%end + +#version=DEVEL +install +lang en_US.UTF-8 +keyboard us +%include /tmp/timezone-include +# set to 'x' so we can use shadow password +rootpw --iscrypted x +selinux --disabled +authconfig --enableshadow --passalgo=sha512 +firewall --service=ssh + +# The following is the partition information you requested +# Note that any partitions you deleted are not expressed +# here so unless you clear all partitions first, this is +# not guaranteed to work +zerombr + +# Disk layout from %pre +%include /tmp/part-include +# Bootloader parms from %pre +%include /tmp/bootloader-include + +reboot --eject + diff --git a/bsp-files/kickstarts/pre_disk_aio.cfg b/bsp-files/kickstarts/pre_disk_aio.cfg new file mode 100755 index 00000000..54a819b1 --- /dev/null +++ b/bsp-files/kickstarts/pre_disk_aio.cfg @@ -0,0 +1,102 @@ + +## NOTE: updates to partition sizes need to be also reflected in +## _controller_filesystem_limits() in sysinv/api/controllers/v1/istorconfig.py +## +## NOTE: When adding partitions, we currently have a max of 4 primary partitions. +## If more than 4 partitions are required, we can use a max of 3 --asprimary, +## to allow 1 primary logical partition with extended partitions +## +## NOTE: Max default PV size must align with the default controllerfs sizes +## +## BACKUP_OVERHEAD = 20 +## +## Physical install +## - DB size is doubled to allow for upgrades +## +## DEFAULT_IMAGE_STOR_SIZE = 10 +## DEFAULT_DATABASE_STOR_SIZE = 20 +## DEFAULT_IMG_CONVERSION_STOR_SIZE = 20 +## BACKUP = DEFAULT_DATABASE_STOR_SIZE + DEFAULT_IMAGE_STOR_SIZE +## + BACKUP_OVERHEAD = 50 +## LOG_VOL_SIZE = 8192 +## SCRATCH_VOL_SIZE = 8192 +## RABBIT = 2048 +## PLATFORM = 2048 +## ANCHOR = 1024 +## EXTENSION = 1024 +## RESERVED_PE = 16 (based on pesize=32768) +## +## CGCS_PV_SIZE = 10240 + 2*20480 + 20480 + 51200 + 8196 + +## 8196 + 2048 + 2048 + 1024 + 1024 + 16 = 145424 +## +## small install - uses is_virtual check +## - DB size is doubled to allow for upgrades +## +## DEFAULT_VIRTUAL_IMAGE_STOR_SIZE = 8 +## DEFAULT_VIRTUAL_DATABASE_STOR_SIZE = 5 +## DEFAULT_VIRTUAL_IMG_CONVERSION_STOR_SIZE = 8 +## DEFAULT_VIRTUAL_BACKUP_STOR_SIZE = 5 +## +## LOG_VOL_SIZE = 4096 +## SCRATCH_VOL_SIZE = 4096 +## RABBIT = 2048 +## PLATFORM = 2048 +## ANCHOR = 1024 +## EXTENSION = 1024 +## RESERVED_PE = 16 (based on pesize=32768) +## +## CGCS_PV_SIZE = 8192 + 2*5120 + 8192 + 5120 + 4096 + +## 4096 + 2048 + 2048 + 1024 + 1024 +16 = 46096 +## +## NOTE: To maintain upgrade compatability within the volume group, keep the +## undersized LOG_VOL_SIZE and SCRATCH_VOL_SIZE, but size the minimally size +## physical volume correctly. +## +## R4 AIO installations: +## - R4 (case #1): /boot (0.5G), / (20G), +## cgts-vg PV (239G), /local_pv (239G) +## - R4 (case #2): /boot (0.5G), / (20G), +## cgts-vg PV (239G), cgts-vg (239G) +## +## Upgrade migration will start with R5 install and create a partition to align +## above so filesystems within the volume group will be able to maintain their +## sizes in R5 +## - R5 install : /boot (0.5G), / (20G), +## cgts-vg PV (142G), un-partitioned (336G) +## - R5 (case #1): /boot (0.5G), / (20G), +## cgts-vg PV (142G), cgts-vg PV (97G), unpartitioned (239G) +## - R5 (case #2): /boot (0.5G), / (20G), +## cgts-vg PV (142G), cgts-vg PV (336G) +## +sz=$(blockdev --getsize64 $(get_disk $rootfs_device)) +if [ $sz -le $((161*$gb)) ] ; then + ## This covers vbox or any 55g < disk < 162gb: < 55g won't install + LOG_VOL_SIZE=4000 + SCRATCH_VOL_SIZE=4000 + ROOTFS_SIZE=10000 + CGCS_PV_SIZE=46096 +else + LOG_VOL_SIZE=8000 + SCRATCH_VOL_SIZE=8000 + ROOTFS_SIZE=20000 + CGCS_PV_SIZE=145424 +fi + +ROOTFS_OPTIONS="defaults" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + # Enable iversion labelling for rootfs when IMA is enabled + ROOTFS_OPTIONS="${ROOTFS_OPTIONS},iversion" +fi + +cat<>/tmp/part-include +part /boot --fstype=ext4 --asprimary --size=500 --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" +part pv.253004 --grow --size=500 --maxsize=$CGCS_PV_SIZE --ondrive=$(get_disk $rootfs_device) +volgroup cgts-vg --pesize=32768 pv.253004 +logvol /var/log --fstype=ext4 --vgname=cgts-vg --size=$LOG_VOL_SIZE --name=log-lv +logvol /scratch --fstype=ext4 --vgname=cgts-vg --size=$SCRATCH_VOL_SIZE --name=scratch-lv +part / --fstype=ext4 --asprimary --size=$ROOTFS_SIZE --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" +EOF + +%end + diff --git a/bsp-files/kickstarts/pre_disk_compute.cfg b/bsp-files/kickstarts/pre_disk_compute.cfg new file mode 100755 index 00000000..032e2b19 --- /dev/null +++ b/bsp-files/kickstarts/pre_disk_compute.cfg @@ -0,0 +1,31 @@ + +sz=$(blockdev --getsize64 $(get_disk $rootfs_device)) +if [ $sz -le $((80*$gb)) ] ; then + ## Less than 80GB use a 10GB root partition + LOG_VOL_SIZE=4000 + SCRATCH_VOL_SIZE=4000 + ROOTFS_SIZE=10000 +else + ## Use a 20GB root partition + LOG_VOL_SIZE=4000 + SCRATCH_VOL_SIZE=4000 + ROOTFS_SIZE=20000 +fi + +ROOTFS_OPTIONS="defaults" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + # Enable iversion labelling for rootfs when IMA is enabled + ROOTFS_OPTIONS="${ROOTFS_OPTIONS},iversion" +fi + +cat<>/tmp/part-include +part /boot --fstype=ext4 --asprimary --size=500 --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" +part / --fstype=ext4 --asprimary --size=$ROOTFS_SIZE --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" +part /var/log --fstype=ext4 --size=$LOG_VOL_SIZE --ondrive=$(get_disk $rootfs_device) +part /scratch --fstype=ext4 --size=$SCRATCH_VOL_SIZE --ondrive=$(get_disk $rootfs_device) + +EOF + +%end + diff --git a/bsp-files/kickstarts/pre_disk_controller.cfg b/bsp-files/kickstarts/pre_disk_controller.cfg new file mode 100755 index 00000000..e4217e75 --- /dev/null +++ b/bsp-files/kickstarts/pre_disk_controller.cfg @@ -0,0 +1,34 @@ + +## NOTE: updates to partition sizes need to be also reflected in +## _controller_filesystem_limits() in sysinv/api/controllers/v1/istorconfig.py + +sz=$(blockdev --getsize64 $(get_disk $rootfs_device)) +if [ $sz -le $((60*$gb)) ] ; then + LOG_VOL_SIZE=4000 + SCRATCH_VOL_SIZE=4000 + ROOTFS_SIZE=10000 +else + LOG_VOL_SIZE=8000 + SCRATCH_VOL_SIZE=8000 + ROOTFS_SIZE=20000 +fi + +ROOTFS_OPTIONS="defaults" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + # Enable iversion labelling for rootfs when IMA is enabled + ROOTFS_OPTIONS="${ROOTFS_OPTIONS},iversion" +fi + +cat<>/tmp/part-include +part /boot --fstype=ext4 --asprimary --size=500 --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" +part pv.253004 --grow --asprimary --size=500 --ondrive=$(get_disk $rootfs_device) +volgroup cgts-vg --pesize=32768 pv.253004 +logvol /var/log --fstype=ext4 --vgname=cgts-vg --size=$LOG_VOL_SIZE --name=log-lv +logvol /scratch --fstype=ext4 --vgname=cgts-vg --size=$SCRATCH_VOL_SIZE --name=scratch-lv +part / --fstype=ext4 --asprimary --size=$ROOTFS_SIZE --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" + +EOF + +%end + diff --git a/bsp-files/kickstarts/pre_disk_setup_common.cfg b/bsp-files/kickstarts/pre_disk_setup_common.cfg new file mode 100644 index 00000000..173b9b1a --- /dev/null +++ b/bsp-files/kickstarts/pre_disk_setup_common.cfg @@ -0,0 +1,154 @@ +%pre --erroronfail + +# Source common functions +. /tmp/ks-functions.sh + +# This is a really fancy way of finding the first usable disk for the +# install and not stomping on the USB device if it comes up first + +# First, parse /proc/cmdline to find the boot args +set -- `cat /proc/cmdline` +for I in $*; do case "$I" in *=*) eval $I 2>/dev/null;; esac; done + +# Find either the ISO or USB device first chopping off partition +ISO_DEV=`readlink /dev/disk/by-label/oe_iso_boot` +sdev=`echo $ISO_DEV | sed -e 's/.$//'` +if [ -e /dev/disk/by-label/$sdev ] ; then + ISO_DEV=$sdev +fi +USB_DEV=`readlink /dev/disk/by-label/wr_usb_boot` +sdev=`echo $USB_DEV | sed -e 's/.$//'` +if [ -e /dev/disk/by-label/$sdev ] ; then + USB_DEV=$sdev +fi + +# Temporary, until lab pxelinux.cfg files are updated to specify install devices +if [ -z "$rootfs_device" -o -z "$boot_device" ] +then + INST_HDD="" + # Prefer a vd* device if this is kvm/qemu + for e in vda vdb sda sdb nvme0n1; do + if [ -e /dev/$e -a "$ISO_DEV" != "../../$e" -a "$USB_DEV" != "../../$e" ] ; then + INST_HDD=$e + break + fi + done + + # Set variables to $INST_HDD if not set + rootfs_device=${rootfs_device:-$INST_HDD} + boot_device=${boot_device:-$INST_HDD} +fi + +# Convert to by-path +orig_rootfs_device=$rootfs_device +rootfs_device=$(get_by_path $rootfs_device) + +orig_boot_device=$boot_device +boot_device=$(get_by_path $boot_device) + +if [ ! -e "$rootfs_device" -o ! -e "$boot_device" ] ; then + # Touch this file to prevent Anaconda from dying an ungraceful death + touch /tmp/part-include + + report_pre_failure_with_msg "ERROR: Specified installation ($orig_rootfs_device) or boot ($orig_boot_device) device is invalid." +fi + +# Ensure specified device is not a USB drive +udevadm info --query=property --name=$rootfs_device |grep -q '^ID_BUS=usb' || \ + udevadm info --query=property --name=$boot_device |grep -q '^ID_BUS=usb' +if [ $? -eq 0 ]; then + # Touch this file to prevent Anaconda from dying an ungraceful death + touch /tmp/part-include + + report_pre_failure_with_msg "ERROR: Specified installation ($orig_rootfs_device) or boot ($orig_boot_device) device is a USB drive." +fi + +# Deactivate existing volume groups to avoid Anaconda issues with pre-existing groups +vgs --noheadings -o vg_name | xargs --no-run-if-empty -n 1 vgchange -an + +ONLYUSE_HDD="" +if [ "$(curl -sf http://pxecontroller:6385/v1/upgrade/$(hostname)/in_upgrade 2>/dev/null)" = "true" ]; then + # In an upgrade, only wipe the disk with the rootfs and boot partition + echo "In upgrade, wiping only $rootfs_device" + WIPE_HDD="$(get_disk $rootfs_device)" + ONLYUSE_HDD="$(basename $(get_disk $rootfs_device))" + if [ "$(get_disk $rootfs_device)" != "$(get_disk $boot_device)" ]; then + WIPE_HDD="$WIPE_HDD,$(get_disk $boot_device)" + ONLYUSE_HDD="$ONLYUSE_HDD,$(basename $(get_disk $boot_device))" + fi +else + # Make a list of all the hard drives that are to be wiped + WIPE_HDD="" + for f in /dev/disk/by-path/* + do + dev=$(readlink -f $f) + lsblk --nodeps --pairs $dev | grep -q 'TYPE="disk"' + if [ $? -ne 0 ] + then + continue + fi + + # Avoid wiping USB drives + udevadm info --query=property --name=$dev |grep -q '^ID_BUS=usb' && continue + + devname=$(basename $dev) + if [ -e $dev -a "$ISO_DEV" != "../../$devname" -a "$USB_DEV" != "../../$devname" ] ; then + if [ -n "$WIPE_HDD" ] ; then + WIPE_HDD=$WIPE_HDD,$dev + else + WIPE_HDD=$dev + fi + fi + done + echo "Not in upgrade, wiping all disks: $WIPE_HDD" +fi + +for dev in ${WIPE_HDD//,/ } +do + # Clearing previous GPT tables or LVM data + # Delete the first few bytes at the start and end of the partition. This is required with + # GPT partitions, they save partition info at the start and the end of the block. + # Do this for each partition on the disk, as well. + partitions=$(lsblk -rip $dev -o TYPE,NAME |awk '$1 == "part" {print $2}') + for p in $partitions $dev + do + echo "Pre-wiping $p from kickstart" + dd if=/dev/zero of=$p bs=512 count=34 + dd if=/dev/zero of=$p bs=512 count=34 seek=$((`blockdev --getsz $p` - 34)) + done +done + +# Check for remaining cgts-vg PVs, which could potentially happen +# in an upgrade where we're not wiping all disks. +# If we ever create other volume groups from kickstart in the future, +# include them in this search as well. +partitions=$(pvs --select 'vg_name=cgts-vg' -o pv_name --noheading | grep -v '\[unknown\]') +for p in $partitions +do + echo "Pre-wiping $p from kickstart (cgts-vg present)" + dd if=/dev/zero of=$p bs=512 count=34 + dd if=/dev/zero of=$p bs=512 count=34 seek=$((`blockdev --getsz $p` - 34)) +done + +let -i gb=1024*1024*1024 + +cat</tmp/part-include +clearpart --all --drives=$WIPE_HDD --initlabel +EOF + +if [ -n "$ONLYUSE_HDD" ]; then + cat<>/tmp/part-include +ignoredisk --only-use=$ONLYUSE_HDD +EOF +fi + +if [ -d /sys/firmware/efi ] ; then + cat<>/tmp/part-include +part /boot/efi --fstype=efi --size=300 --ondrive=$(get_disk $boot_device) +EOF +else + cat<>/tmp/part-include +part biosboot --asprimary --fstype=biosboot --size=1 --ondrive=$(get_disk $boot_device) +EOF +fi + diff --git a/bsp-files/kickstarts/pre_disk_storage.cfg b/bsp-files/kickstarts/pre_disk_storage.cfg new file mode 100755 index 00000000..5cabf645 --- /dev/null +++ b/bsp-files/kickstarts/pre_disk_storage.cfg @@ -0,0 +1,31 @@ + +sz=$(blockdev --getsize64 $(get_disk $rootfs_device)) +if [ $sz -le $((60*$gb)) ] ; then + LOG_VOL_SIZE=4000 + SCRATCH_VOL_SIZE=4000 + ROOTFS_SIZE=10000 +else + LOG_VOL_SIZE=8000 + SCRATCH_VOL_SIZE=8000 + ROOTFS_SIZE=20000 +fi + +ROOTFS_OPTIONS="defaults" +profile_mode=`cat /proc/cmdline |xargs -n1 echo |grep security_profile= | grep extended` +if [ -n "$profile_mode" ]; then + # Enable iversion labelling for rootfs when IMA is enabled + ROOTFS_OPTIONS="${ROOTFS_OPTIONS},iversion" +fi + +cat<>/tmp/part-include +part /boot --fstype=ext4 --asprimary --size=500 --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" +part pv.253004 --grow --asprimary --size=500 --ondrive=$(get_disk $rootfs_device) +volgroup cgts-vg --pesize=32768 pv.253004 +logvol /var/log --fstype=ext4 --vgname=cgts-vg --size=$LOG_VOL_SIZE --name=log-lv +logvol /scratch --fstype=ext4 --vgname=cgts-vg --size=$SCRATCH_VOL_SIZE --name=scratch-lv +part / --fstype=ext4 --asprimary --size=$ROOTFS_SIZE --ondrive=$(get_disk $rootfs_device) --fsoptions="$ROOTFS_OPTIONS" + +EOF + +%end + diff --git a/bsp-files/kickstarts/pre_pkglist.cfg b/bsp-files/kickstarts/pre_pkglist.cfg new file mode 100644 index 00000000..021f0d35 --- /dev/null +++ b/bsp-files/kickstarts/pre_pkglist.cfg @@ -0,0 +1,6 @@ +%packages +@core +@base +xxxPACKAGE_LISTxxx +%end + diff --git a/bsp-files/kickstarts/pre_pkglist_lowlatency.cfg b/bsp-files/kickstarts/pre_pkglist_lowlatency.cfg new file mode 100644 index 00000000..49e7d395 --- /dev/null +++ b/bsp-files/kickstarts/pre_pkglist_lowlatency.cfg @@ -0,0 +1,8 @@ +%packages +@core +@base +-kernel +-kernel-tools +xxxPACKAGE_LISTxxx +%end + diff --git a/bsp-files/pkg-list.pl b/bsp-files/pkg-list.pl new file mode 100755 index 00000000..06731781 --- /dev/null +++ b/bsp-files/pkg-list.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl +use strict; + +#my $file_in = `ls -tr bitbake_build/tmp/work/*/*/*/installed_pkgs.txt |tail -1`; +my $file_in = `ls -tr bitbake_build/tmp/work/intel_x86_64-wrs-linux/wrlinux-image-cgcs-base/*/installed_pkgs.txt |tail -1`; +$file_in = $ARGV[0] if ($ARGV[0] ne ""); + +open(FILES_IN, $file_in) || die "Could not open list of files"; + +my %pkgs; +while () { + chop; + my @v = split(); + my $pkg = $v[0]; + my $arch = $v[1]; + # Fix up any lib32 packages + if ($pkg =~ /lib32-(.*)$/) { + $pkg = "$1"; + $arch = "lib32_x86"; + } + $pkgs{"$pkg.$arch"} = "1"; +} +close(FILES_IN); + +# Print all packages in sorted unique order with architecture +foreach (sort keys %pkgs) { + if (/(.*)\.(.*)/) { + my $pkg = $1; + my $arch = $2; + print "$pkg $arch\n"; + } +} + +exit 0; diff --git a/bsp-files/platform_comps.py b/bsp-files/platform_comps.py new file mode 100644 index 00000000..54e345b8 --- /dev/null +++ b/bsp-files/platform_comps.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python + +""" +Copyright (c) 2018 Wind River Systems, Inc. + +SPDX-License-Identifier: Apache-2.0 + +""" + +import getopt +import os +import platform +import subprocess +import sys +import xml.etree.ElementTree as ElementTree + +def usage(): + print "Usage: %s --groups --pkgdir " \ + % os.path.basename(sys.argv[0]) + exit(1) + +def add_text_tag_to_xml(parent, + name, + text): + """ + Utility function for adding a text tag to an XML object + :param parent: Parent element + :param name: Element name + :param text: Text value + :return:The created element + """ + tag = ElementTree.SubElement(parent, name) + tag.text = text + tag.tail = '\n ' + return tag + + +def add_group(comps, personality, rpmlist=None, filter_dir=None, filter=None): + """ + Add a software group to the comps.xml + :param comps: comps element + :param personality: Personality of node for group + :param rpmlist: List of all rpms in the base load + :param filter_dir: Path to filter files + :param filter: Name of filter file to use + """ + + if rpmlist is not None: + # Define a base platform group + groupname = "platform-%s" % personality + desc = "Platform packages for %s" % personality + else: + # Define an empty patch group + groupname = "updates-%s" % personality + desc = "Patches for %s" % personality + + group = ElementTree.SubElement(comps, 'group') + group.tail = '\n' + + add_text_tag_to_xml(group, 'id', groupname) + add_text_tag_to_xml(group, 'default', "false") + add_text_tag_to_xml(group, 'uservisible', "true") + add_text_tag_to_xml(group, 'display_order', "1024") + add_text_tag_to_xml(group, 'name', groupname) + add_text_tag_to_xml(group, 'description', desc) + + package_element = ElementTree.SubElement(group, + 'packagelist') + package_element.tail = '\n ' + + if rpmlist is not None: + # Read the filter file + f = open(os.path.join(filter_dir, filter), 'r') + filtered = f.read().split() + f.close() + + for pkg in sorted(rpmlist): + if pkg not in filtered: + tag = ElementTree.SubElement(package_element, + 'packagereq', + type="mandatory") + tag.text = pkg + tag.tail = '\n ' + + +def main(): + try: + opts, remainder = getopt.getopt(sys.argv[1:], + '', + ['pkgdir=', + 'groups=']) + except getopt.GetoptError: + usage() + + pkgdir = None + groups_file = None + + # Filters are colocated with this script + filter_dir = os.path.dirname(sys.argv[0]) + + for opt, arg in opts: + if opt == "--pkgdir": + pkgdir = arg + elif opt == "--groups": + groups_file = arg + + if pkgdir is None or groups_file is None: + usage() + + # Get the pkglist + cmd = "find %s -name '*.rpm' | xargs rpm -qp --queryformat '%%{NAME}\n'" % pkgdir + rpmlist = subprocess.check_output(cmd, shell=True).split() + + tree = ElementTree.parse(groups_file) + comps = tree.getroot() + comps.tail = '\n' + + add_group(comps, 'controller', rpmlist, filter_dir, 'filter_out_from_controller') + add_group(comps, 'controller-compute', rpmlist, filter_dir, 'filter_out_from_smallsystem') + add_group(comps, 'controller-compute-lowlatency', rpmlist, filter_dir, 'filter_out_from_smallsystem_lowlatency') + add_group(comps, 'compute', rpmlist, filter_dir, 'filter_out_from_compute') + add_group(comps, 'compute-lowlatency', rpmlist, filter_dir, 'filter_out_from_compute_lowlatency') + add_group(comps, 'storage', rpmlist, filter_dir, 'filter_out_from_storage') + + add_group(comps, 'controller') + add_group(comps, 'controller-compute') + add_group(comps, 'controller-compute-lowlatency') + add_group(comps, 'compute') + add_group(comps, 'compute-lowlatency') + add_group(comps, 'storage') + + tree.write(groups_file, encoding="UTF-8") + + +if __name__ == "__main__": + main() + diff --git a/bsp-files/pxeboot.cfg b/bsp-files/pxeboot.cfg new file mode 100644 index 00000000..bde20cd1 --- /dev/null +++ b/bsp-files/pxeboot.cfg @@ -0,0 +1,180 @@ +SERIAL 0 115200 +TIMEOUT 100 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +label 0 + menu label ^1) Boot from hard drive + COM32 chain.c32 + APPEND hd0 + +# Standard Controller menu +menu begin + menu title Standard Controller Configuration + # Serial Console submenu + menu begin + menu title Serial Console + label 1 + menu label STANDARD Security Boot Profile + text help + Standard Controller, console=ttyS0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=standard + ipappend 2 + + label S1 + menu label EXTENDED Security Boot Profile + text help + Standard Controller, console=ttyS0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=extended + ipappend 2 + menu end + + # Graphical Console submenu + menu begin + menu title Graphical Console + label 2 + menu label STANDARD Security Boot Profile + text help + Standard Controller, console=tty0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=standard + ipappend 2 + + label S2 + menu label EXTENDED Security Boot Profile + text help + Standard Controller, console=tty0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=extended + ipappend 2 + menu end +menu end + +# AIO Controller menu +menu begin + menu title All-in-one Controller Configuration + # Serial Console submenu + menu begin + menu title Serial Console + label 3 + menu label STANDARD Security Boot Profile + text help + All-in-one Controller, console=ttyS0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=standard + ipappend 2 + + label S3 + menu label EXTENDED Security Boot Profile + text help + All-in-one Controller, console=ttyS0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=extended + ipappend 2 + menu end + + # Graphical Console submenu + menu begin + menu title Graphical Console + label 4 + menu label STANDARD Security Boot Profile + text help + All-in-one Controller, console=tty0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=standard + ipappend 2 + + label S4 + menu label EXTENDED Security Boot Profile + text help + All-in-one Controller, console=tty0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=extended + ipappend 2 + menu end +menu end + +# AIO (Low Latency) Controller menu +menu begin + menu title All-in-one (lowlatency) Controller Configuration + # Serial Console submenu + menu begin + menu title Serial Console + label 5 + menu label STANDARD Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=ttyS0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=ttyS0,115200n8 inst.gpt security_profile=standard + ipappend 2 + + label S5 + menu label EXTENDED Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=ttyS0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=ttyS0,115200n8 inst.gpt security_profile=extended + ipappend 2 + menu end + + # Graphical Console submenu + menu begin + menu title Graphical Console + label 6 + menu label STANDARD Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=tty0 + Standard Security Profile Enabled (default setting) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=standard + ipappend 2 + + label S6 + menu label EXTENDED Security Boot Profile + text help + All-in-one (lowlatency) Controller, console=tty0 + Extended Security Profile Enabled (will impact performance) + endtext + kernel vmlinuz + append initrd=initrd.img bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=extended + ipappend 2 + menu end +menu end diff --git a/bsp-files/pxeboot_grub.cfg b/bsp-files/pxeboot_grub.cfg new file mode 100644 index 00000000..997d3cde --- /dev/null +++ b/bsp-files/pxeboot_grub.cfg @@ -0,0 +1,104 @@ +timeout=10 +default=0 + +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +pxe_root=${root} + +menuentry '1) UEFI Boot from hard drive' { + insmod part_gpt + insmod chain + # The EFI bootloader is located in /boot/efi/EFI/centos/ + # /boot/efi being the mount + # /dev/sda1 307016 9680 297336 4% /boot/efi + set root=(hd0,gpt1) + chainloader /EFI/centos/grubx64.efi +} + +# Standard Controller menu +submenu 'UEFI Standard Controller' { + submenu 'Serial Console' { + menuentry 'STANDARD Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=standard + initrdefi initrd.img + } + menuentry 'EXTENDED Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=extended tboot=true + initrdefi initrd.img + } + } + + submenu 'Graphical Console' { + menuentry 'STANDARD Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=standard + initrdefi initrd.img + } + menuentry 'EXTENDED Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_controller.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=extended tboot=true + initrdefi initrd.img + } + } +} + +# AIO Controller menu +submenu 'UEFI All-in-one Controller' { + submenu 'Serial Console' { + menuentry 'STANDARD Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=standard + initrdefi initrd.img + } + menuentry 'EXTENDED Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=extended tboot=true + initrdefi initrd.img + } + } + + submenu 'Graphical Console' { + menuentry 'STANDARD Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=standard + initrdefi initrd.img + } + menuentry 'EXTENDED Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=extended tboot=true + initrdefi initrd.img + } + } +} + +# AIO (lowlatency) Controller menu +submenu 'UEFI All-in-one (lowlatency) Controller' { + submenu 'Serial Console' { + menuentry 'STANDARD Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=standard + initrdefi initrd.img + } + menuentry 'EXTENDED Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text serial console=ttyS0,115200n8 inst.gpt security_profile=extended tboot=true + initrdefi initrd.img + } + } + + submenu 'Graphical Console' { + menuentry 'STANDARD Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=standard + initrdefi initrd.img + } + menuentry 'EXTENDED Security Boot Profile' { + set root=${pxe_root} + linuxefi vmlinuz bootifonly=1 devfs=nomount inst.repo=xxxHTTP_URLxxx inst.ks=xxxHTTP_URLxxx/pxeboot_smallsystem_lowlatency.cfg ksdevice=$net_default_mac BOOTIF=$net_default_mac boot_device=sda rootfs_device=sda biosdevname=0 inst.text console=tty0 inst.gpt security_profile=extended tboot=true + initrdefi initrd.img + } + } +} diff --git a/bsp-files/pxeboot_setup.sh b/bsp-files/pxeboot_setup.sh new file mode 100755 index 00000000..35f3d870 --- /dev/null +++ b/bsp-files/pxeboot_setup.sh @@ -0,0 +1,111 @@ +#!/bin/bash + +OPTIND=1 + +BASE_URL="" +TFTP_DIR="" +WORKING_DIR="" +COPY_DIR="" +ISODIR=$(dirname `readlink -f $0`) + +usage() { + echo "Usage: $0 -u [-t ] or [-w ]" 1>&2; + exit 0; +} + +while getopts ":u:t:w:" opt; do + case "$opt" in + u) + BASE_URL=${OPTARG} + ;; + t) + TFTP_DIR=${OPTARG} + ;; + w) + WORKING_DIR=${OPTARG} + ;; + *) + usage + ;; + esac +done + +shift $((OPTIND-1)) + +if [ -z "$BASE_URL" ]; then + echo "HTTP base URL is required: -u " + exit 0 +fi + +if [ -z "$TFTP_DIR" ] && [ -z "$WORKING_DIR" ]; then + echo "Either tftp pxeboot directory or working directory has to be specified:" + echo "-t or -w " + exit 0 +elif [ -n "$TFTP_DIR" ]; then + if [ -n "$WORKING_DIR" ]; then + echo "tftp pxeboot directory is supplied, working directory will be ignored." + fi + COPY_DIR=$TFTP_DIR +elif [ -n "$WORKING_DIR" ]; then + COPY_DIR=$WORKING_DIR +fi + +if [ ! -d ${COPY_DIR} ] ; then + if [ -w "$(dirname $COPY_DIR)" ]; then + echo "Create ${COPY_DIR}" + mkdir ${COPY_DIR} + chmod +w ${COPY_DIR} + if [ $? -ne 0 ]; then + echo "Can't create ${COPY_DIR}" + exit 1 + fi + else + echo "$COPY_DIR parent directory is not writeable." + exit 0 + fi +else + echo "$COPY_DIR already exists" + exit 0 +fi + +#Copy the vmlinuz and initrd files to the destination directory +cp ${ISODIR}/vmlinuz ${COPY_DIR}/ +cp ${ISODIR}/initrd.img ${COPY_DIR}/ + +#Copy the contents of distribution to the destination directory +cp -r ${ISODIR}/* ${COPY_DIR}/ + +#Find the number of directories in the URL +dirpath=$(echo ${BASE_URL#"http://"}) +DIRS=$(grep -o "/" <<< "$dirpath" | wc -l) + +#Escape path for sed +BASE_URL="${BASE_URL//\//\\/}" + +#Copy pxeboot files +mkdir -p ${COPY_DIR}/EFI/centos/x86_64-efi/ +cp -Rf ${COPY_DIR}/pxeboot/* ${COPY_DIR}/ + +#Rename the UEFI grub config +mv ${COPY_DIR}/pxeboot_grub.cfg ${COPY_DIR}/grub.cfg + +#Variable replacement +sed -i "s#xxxHTTP_URLxxx#${BASE_URL}#g; + s#xxxHTTP_URL_PATCHESxxx#${BASE_URL}/patches#g; + s#NUM_DIRS#${DIRS}#g" \ + ${COPY_DIR}/pxeboot.cfg \ + ${COPY_DIR}/grub.cfg \ + ${COPY_DIR}/pxeboot_controller.cfg \ + ${COPY_DIR}/pxeboot_smallsystem.cfg \ + ${COPY_DIR}/pxeboot_smallsystem_lowlatency.cfg + +# Delete unnecessary files +rm -Rf ${COPY_DIR}/EFI/BOOT +rm -Rf ${COPY_DIR}/pxeboot + +if [ -n "$TFTP_DIR" ]; then + #Create pxelinux.cfg directory and default link + mkdir ${TFTP_DIR}/pxelinux.cfg + chmod 755 ${TFTP_DIR}/pxelinux.cfg + ln -s ../pxeboot.cfg ${TFTP_DIR}/pxelinux.cfg/default +fi diff --git a/bsp-files/upgrades/import.sh b/bsp-files/upgrades/import.sh new file mode 100644 index 00000000..0d863ae8 --- /dev/null +++ b/bsp-files/upgrades/import.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Copyright (c) 2015-2017 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# This script is run during the load-import command +# It is used to copy the required files from the iso to the +# controller. + + +set -e + +exec 2>>/var/log/load-import.log +set -x +echo "$(date): Starting execution: $0 $@" + +cleanup() { + rm -rf $TMP_RPM +} +rollback() { + rm -rf $FEED_DIR +} + +error() { + local parent_lineno="$1" + local err_code="${2}" + echo "Error executing import script at line: ${parent_lineno} with error code: ${err_code}" + rollback + exit "${err_code}" +} + +trap 'error ${LINENO} $?' ERR +trap cleanup 0 + +SCRIPT_DIR=$(dirname $0) +ISO_DIR=$(dirname $SCRIPT_DIR) + +source $SCRIPT_DIR/version +source /etc/build.info + +FEED_DIR=/www/pages/feed/rel-$VERSION +CURRENT_FEED_DIR=/www/pages/feed/rel-$SW_VERSION +TMP_RPM=/tmp/cpio + +rm -rf $TMP_RPM +rm -rf $FEED_DIR + +mkdir -p $FEED_DIR + +cp -rp $ISO_DIR/Packages $ISO_DIR/repodata $ISO_DIR/LiveOS $FEED_DIR/ + +cp -p $CURRENT_FEED_DIR/install_uuid $FEED_DIR/ + +if [ -d $ISO_DIR/patches ]; then + mkdir -p /www/pages/updates/rel-${VERSION} + cp -r ${ISO_DIR}/patches/Packages ${ISO_DIR}/patches/repodata /www/pages/updates/rel-${VERSION}/ + rsync -ac ${ISO_DIR}/patches/metadata/ /opt/patching/metadata/ + mkdir -p /opt/patching/packages/${VERSION} + + find /www/pages/updates/rel-${VERSION}/Packages -name '*.rpm' \ + | xargs --no-run-if-empty -I files cp --preserve=all files /opt/patching/packages/${VERSION}/ +fi + diff --git a/bsp-files/upgrades/metadata.xml b/bsp-files/upgrades/metadata.xml new file mode 100644 index 00000000..ed2598f1 --- /dev/null +++ b/bsp-files/upgrades/metadata.xml @@ -0,0 +1,24 @@ + + + xxxSW_VERSIONxxx + + + 17.06 + TC_17.06_PATCH_0001 + TC_17.06_PATCH_0002 + TC_17.06_PATCH_0003 + TC_17.06_PATCH_0004 + TC_17.06_PATCH_0005 + TC_17.06_PATCH_0006 + TC_17.06_PATCH_0007 + TC_17.06_PATCH_0008 + TC_17.06_PATCH_0009 + TC_17.06_PATCH_0010 + TC_17.06_PATCH_0011 + TC_17.06_PATCH_0012 + TC_17.06_PATCH_0013 + TC_17.06_PATCH_0014 + TC_17.06_PATCH_0015 + + + diff --git a/installer/initrd/README b/installer/initrd/README new file mode 100644 index 00000000..d9ddfd1e --- /dev/null +++ b/installer/initrd/README @@ -0,0 +1,254 @@ +There are three prebuilt files that we can update when we need to make changes +to the installer: +- vmlinuz - The kernel +- initrd.img - Initial initrd loaded when the installer boots. Has kernel + modules, etc, and loads the squashfs.img +- squashfs.img - Provides the rootfs for the installer, which includes + components like anaconda + +The original stock CentOS files are found: +/import/mirrors/CentOS/7.4.1708/os/x86_64/isolinux/initrd.img +/import/mirrors/CentOS/7.4.1708/os/x86_64/LiveOS/squashfs.img + +# NOTE: before updating these files, assure that you've had a successful build +for the necessary files used in "kernel-rpms" and "rootfs-rpms". +# here are build procedures: + +# kernel, kernel modules will be generated by this step +build-pkgs + +# anaconda-*.tis.*.rpm rpm-*.tis*.rpm will be generated by this step +build-srpms --installer && build-rpms --installer + +# systemd-*.tis.*.rpm and bind-utils-9.9.4-61.el7.x86_64.rpm, ima-evm-utils-1.0-1.el7.x86_64.rpm +# will be available after this step done +build-iso + +=========== +vmlinuz: +We're using the runtime kernel for this, so when we update the installer, we +just grab the kernel from build server or your own build environment. + +Note -- The kernel to be used should be signed. The Jenkins builds will +produce signed kernels, but if you are concerned about the signature (for +example, if you are concerned that a developer kernel is being used or if +the signing server is behaving odd) then you can verify the integrity of +the kernel by going onto yow-cgts3-lx and using the command: + +sbverify --cert [CERT] vmlinuz + +The certificate specfied as the argument can be found in +$MY_REPO/addons/wr-cgcs/layers/cgcs/recipes-extended/shim-unsigned/files/tis-shim.crt + +=========== +initrd.img: +When we update the kernel and kernel modules for the installer, we need to +update the initrd.img. This is a manual procedure currently, and must be done +as **root**. + +# First, extract the initrd.img: + +ORIG_INITRD=$PWD/initrd.img +mkdir initrd.work +cd initrd.work +xzcat $ORIG_INITRD | cpio -i + +# Make the necessary changes, and rebuild the initrd + +# We want to include our kernel and required modules in the initrd. Copy their RPMs from +# the Jenkins build or local build folders (~/export/dist/isolinux/Packages/ and ~/std/rpmbuild/RPMS/) +# to ../kernel-rpms, to be extracted with rpm2cpio: +# kernel +# kmod-i40e +# kmod-ixgbe +# kmod-e1000e +# kmod-tpm +# mlnx-ofa_kernel-modules +# +# Also adding in dmidecode for debug purposes + + +# Delete the old kernel files: +rm -rf boot/ etc/modules-load.d/ etc/ld.so.conf.d/kernel-3.10.0-693.2.2.el7.tis.29.x86_64.conf lib/modules/3.10.0-693.2.2.el7.tis.29.x86_64/ + +# Extract the RPMs from the build system +# FYI, here are RPMs in "kernel-rpms": + +# ls kernel-rpms/ +kernel-3.10.0-693.2.2.el7.33.tis.x86_64.rpm kmod-i40e-rt-2.4.3-0.tis.6.x86_64.rpm mlnx-ofa_kernel-4.3-OFED.4.3.1.0.1.1.g8509e41.tis.1.x86_64.rpm +kernel-rt-3.10.0-693.2.2.rt56.623.el7.tis.39.x86_64.rpm kmod-ixgbe-5.2.3-0.tis.2.x86_64.rpm mlnx-ofa_kernel-devel-4.3-OFED.4.3.1.0.1.1.g8509e41.tis.1.x86_64.rpm +kmod-e1000e-3.3.6-0.tis.1.x86_64.rpm kmod-ixgbe-rt-5.2.3-0.tis.2.x86_64.rpm mlnx-ofa_kernel-modules-4.3-OFED.4.3.1.0.1.1.g8509e41.tis.1.x86_64.rpm +kmod-e1000e-rt-3.3.6-0.tis.1.x86_64.rpm kmod-tpm-4.12-0.tis.5.x86_64.rpm +kmod-i40e-2.4.3-0.tis.6.x86_64.rpm kmod-tpm-rt-4.12-0.tis.5.x86_64.rpm + + +for f in ../kernel-rpms/*.rpm ; do rpm2cpio $f | cpio -idu; done + +# In a chroot, run depmods. The command is available from the kmod-i40e for syntax/args: +# [root@yow-cgts4-lx initrd.work]# rpm -qp --scripts ../kernel-rpms/kmod-i40e-* |grep depmod +# /usr/sbin/depmod -aeF "/boot/System.map-3.10.0-327.36.2.el7.9.tis.x86_64" "3.10.0-327.36.2.el7.9.tis.x86_64" > /dev/null || : +# /usr/sbin/depmod -aeF "/boot/System.map-3.10.0-327.36.2.el7.9.tis.x86_64" "3.10.0-327.36.2.el7.9.tis.x86_64" > /dev/null || : + +chroot . +# need be replaced, for example, 3.10.0-693.2.2.el7.33.tis.x86_64 +/usr/sbin/depmod -aeF "/boot/System.map-" "" +exit + +# Remove the bisodevname package from initrd and squashfs +rm -f ./usr/lib/udev/rules.d/71-biosdevname.rules ./usr/sbin/biosdevname + +# Rebuild the initrd +find . \ + | cpio -o -H newc \ + | xz --check=crc32 --x86 --lzma2=dict=512KiB \ + > ../new-initrd.img + + + +=========== +squashfs.img: +If we want to make changes to the rootfs of the installer (ie. update anaconda), +we need to update the squashfs.img file. This file can be mounted, and contains +a rootfs image: LiveOS/rootfs.img + +# Build the TIS-modified installer RPMs first (see anaconda jiggery-pokery at end of this file): +build-srpms --installer && build-rpms --installer + +# We also need TIS-built systemd for NVME support, so copy the following from Jenkins build: +systemd-219-42.el7_4.1.tis.10.x86_64.rpm +systemd-libs-219-42.el7_4.1.tis.10.x86_64.rpm +systemd-sysv-219-42.el7_4.1.tis.10.x86_64.rpm + +# We need to update the following RPMs in the rootfs +ima-evm-utils-1.0-1.el7.x86_64.rpm +rpm-4.14.0-1.tis.1.x86_64.rpm +rpm-build-4.14.0-1.tis.1.x86_64.rpm +rpm-build-libs-4.14.0-1.tis.1.x86_64.rpm +rpm-libs-4.14.0-1.tis.1.x86_64.rpm +rpm-plugin-systemd-inhibit-4.14.0-1.tis.1.x86_64.rpm +rpm-python-4.14.0-1.tis.1.x86_64.rpm + +# We also now need bind-utils in the squashfs, due to the anaconda-preexec we've added. +bind-utils-9.9.4-51.el7.x86_64.rpm + +# Mount the squashfs.img and copy the rootfs out: +ORIG_SQUASHFS=$PWD/squashfs.img +mkdir squashfs.mnt +mount -o loop -t squashfs $ORIG_SQUASHFS squashfs.mnt +mkdir LiveOS +cp squashfs.mnt/LiveOS/rootfs.img LiveOS/ +umount squashfs.mnt + +# Now mount the rootfs.img file: +mkdir squashfs.work +mount -o loop LiveOS/rootfs.img squashfs.work +cd squashfs.work + +# You can now make changes as needed, and they're reflected in the rootfs.img + +# For anaconda, ignore these RPMs that are built: +# anaconda-debuginfo +# anaconda-dracut +# anaconda-widgets-devel +# anaconda-gui +# + +# FYI, here are RPMs from "rootfs-rpms": +ls rootfs-rpms/ +anaconda-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm rpm-4.14.0-1.tis.1.x86_64.rpm +anaconda-core-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm rpm-build-4.14.0-1.tis.1.x86_64.rpm +anaconda-debuginfo-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm rpm-build-libs-4.14.0-1.tis.1.x86_64.rpm +anaconda-dracut-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm rpm-libs-4.14.0-1.tis.1.x86_64.rpm +anaconda-gui-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm rpm-plugin-systemd-inhibit-4.14.0-1.tis.1.x86_64.rpm +anaconda-tui-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm rpm-python-4.14.0-1.tis.1.x86_64.rpm +anaconda-widgets-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm systemd-219-42.el7_4.1.tis.10.x86_64.rpm +anaconda-widgets-devel-21.48.22.121-1.el7.centos.tis.5.x86_64.rpm systemd-libs-219-42.el7_4.1.tis.10.x86_64.rpm +bind-utils-9.9.4-61.el7.x86_64.rpm systemd-sysv-219-42.el7_4.1.tis.10.x86_64.rpm +ima-evm-utils-1.0-1.el7.x86_64.rpm + +# IMPORTANT Note: when copying “systemd-219-42.el7_4.1.tis.10.x86_64.rpm” from build target folders to “rootfs-rpms”, +# we need to get it from “../export/dist/isolinux/Packages/systemd-219-42.el7_4.1.tis.10.x86_64.rpm”, instead of other +# folders (for example, ../std/rpmbuild/RPMS/systemd-219-42.el7_4.1.tis.10.x86_64.rpm), they are actually having +# different sizes and delta in contents. + +# Extract the rest into the squashfs +rm -rf usr/lib64/python2.7/site-packages/pyanaconda/ +rm -rf usr/lib64/python2.7/site-packages/rpm/ +# get files from RPMs and copy them into corresponding folders +for f in ../rootfs-rpms/*.rpm ; do rpm2cpio $f | cpio -idu; done +#find old .pyo files and delete them +find usr/lib64/python2.7/site-packages/pyanaconda/ usr/lib64/python2.7/site-packages/rpm/ -name *.pyo | xargs rm + + +# IMPORTANT Note, please do NOT forget the following step: +# MUST HAVE!!! Update the kernel and related kernel modules, same as what was done for "initrd.img" updating +for f in ../kernel-rpms/*.rpm ; do rpm2cpio $f | cpio -idu; done + +# Remove the bisodevname package from initrd and squashfs +rm -f ./usr/lib/udev/rules.d/71-biosdevname.rules ./usr/sbin/biosdevname + +cd .. +umount squashfs.work + +# Build/rebuild a new squashfs.img (output file is test.squashfs.img in this +# example) +# Note: You may need to install "squashfs-tools" in advance +#remove the old version named test.squashfs.img +rm -f test.squashfs.img +#make the new squashfs image named "test.squashfs.img" or another name +mksquashfs LiveOS test.squashfs.img -keep-as-directory -comp xz -b 1M + + +=========== +To test with design build, update the following files with paths to your test +files and filenames: +recipes-installer/pxe-network-installer/centos/build_srpm.data +recipes-installer/pxe-network-installer/centos/pxe-network-installer.spec + + +=========== +Delivering changes: +Copy the updated vmlinuz (from kernel rpm), initrd.img, and squashfs.img files, +with appropriate version suffixes, to mirror folder where you placethese files. + +Update the pxe-network-installer files to point to the new versions. + + +=========== +NOTE: The following jiggery-pokery is no longer required after recent mirror updates. +I'm keeping the text here, though, for future reference. Just in case. + +Jiggery-pokery required to build anaconda after rebase to 7.3: + +The anaconda build reports a dependency error: + +12:45:41 Error: Package: libgudev1-219-19.el7_2.13.x86_64 (TisCentos7Distro) +12:45:41 Requires: systemd-libs = 219-19.el7_2.13 +12:45:41 Installed: systemd-libs-219-30.el7_3.6.x86_64 (@TisCentos7Distro) +12:45:41 systemd-libs = 219-30.el7_3.6 +12:45:41 Available: systemd-libs-219-19.el7_2.13.x86_64 (TisCentos7Distro) +12:45:41 systemd-libs = 219-19.el7_2.13 +12:45:41 You could try using --skip-broken to work around the problem +12:45:41 You could try running: rpm -Va --nofiles --nodigest + +Our build system is setup to install the highest versions of packages, but there's a dependency +that has a version-specific dependency to an older version of the RPM, so it requires a little +massaging to get the anaconda RPM to build. + +Step 1: Add a symlink into the cgcs-centos-repo dir: +ln -s /import/mirrors/CentOS/tis-r4-CentOS/mitaka/Binary/x86_64/systemd-libs-219-19.el7_2.13.x86_64.rpm \ + $MY_REPO/cgcs-centos-repo/Binary/x86_64/ + +Step 2: Try to build, so the repodata is updated (this will still fail) +build-srpms --installer && build-rpms --installer + +Step 3: Short-circuit the update_cgcs_repo function in build-rpms to avoid repodata update and mock env clearout + +Step 4: Manually install RPM in mock env +mock -r installer/${MY_BUILD_ENVIRONMENT}-installer.cfg --copyin systemd-libs-219-19.el7_2.13.x86_64.rpm systemd-libs-219-19.el7_2.13.x86_64.rpm +mock -r installer/${MY_BUILD_ENVIRONMENT}-installer.cfg --shell +rpm -i --force systemd-libs-219-19.el7_2.13.x86_64.rpm + +Step 5: Build with success! +build-srpms --installer && build-rpms --installer + diff --git a/installer/pxe-network-installer/centos/build_srpm.data b/installer/pxe-network-installer/centos/build_srpm.data new file mode 100644 index 00000000..02ff9f30 --- /dev/null +++ b/installer/pxe-network-installer/centos/build_srpm.data @@ -0,0 +1,12 @@ +COPY_LIST="pxe-network-installer//* \ + $CGCS_BASE/mwa-beas/bsp-files/grub.cfg \ + $CGCS_BASE/mwa-beas/bsp-files/kickstarts/post_clone_iso_ks.cfg \ + $SRC_BASE/cgcs-centos-repo/Binary/images/efiboot.img \ + /import/mirrors/CentOS/tis-installer/initrd.img-stx-0.1 \ + /import/mirrors/CentOS/tis-installer/squashfs.img-stx-0.1 \ + /import/mirrors/CentOS/tis-installer/vmlinuz-stx-0.1 \ +" + +TIS_PATCH_VER=25 +BUILD_IS_BIG=4 +BUILD_IS_SLOW=4 diff --git a/installer/pxe-network-installer/centos/pxe-network-installer.spec b/installer/pxe-network-installer/centos/pxe-network-installer.spec new file mode 100644 index 00000000..5defd020 --- /dev/null +++ b/installer/pxe-network-installer/centos/pxe-network-installer.spec @@ -0,0 +1,155 @@ +Summary: TIS Network Installation +Name: pxe-network-installer +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown + +%define tis_image_version stx-0.1 + +Source0: LICENSE + +Source001: vmlinuz-%{tis_image_version} +Source002: initrd.img-%{tis_image_version} +Source003: squashfs.img-%{tis_image_version} + +Source010: pxeboot-update.sh +Source011: grub.cfg +Source012: efiboot.img +Source013: post_clone_iso_ks.cfg + +Source030: default +Source031: default.static +Source032: centos-pxe-controller-install +Source033: centos-pxe-compute-install +Source034: centos-pxe-smallsystem-install +Source035: centos-pxe-storage-install +Source036: centos-pxe-compute_lowlatency-install +Source037: centos-pxe-smallsystem_lowlatency-install + +Source050: pxe-grub.cfg +Source051: pxe-grub.cfg.static +Source052: efi-centos-pxe-controller-install +Source053: efi-centos-pxe-compute-install +Source054: efi-centos-pxe-smallsystem-install +Source055: efi-centos-pxe-storage-install +Source056: efi-centos-pxe-compute_lowlatency-install +Source057: efi-centos-pxe-smallsystem_lowlatency-install + + +BuildRequires: syslinux +BuildRequires: grub2 + +Requires: grub2-efi-pxeboot + +%description +TIS Network Installation + +%files +%defattr(-,root,root,-) + +%install +install -v -d -m 755 %{buildroot}/pxeboot +install -v -d -m 755 %{buildroot}/pxeboot/pxelinux.cfg.files +install -v -d -m 755 %{buildroot}/pxeboot/rel-%{platform_release} +install -v -d -m 755 %{buildroot}/pxeboot/EFI +install -v -d -m 755 %{buildroot}/pxeboot/EFI/centos +install -v -d -m 755 %{buildroot}/pxeboot/EFI/centos/x86_64-efi + +install -v -m 644 %{_sourcedir}/vmlinuz-%{tis_image_version} \ + %{buildroot}/pxeboot/rel-%{platform_release}/installer-bzImage_1.0 +install -v -m 644 %{_sourcedir}/initrd.img-%{tis_image_version} \ + %{buildroot}/pxeboot/rel-%{platform_release}/installer-intel-x86-64-initrd_1.0 +ln -s installer-bzImage_1.0 %{buildroot}/pxeboot/rel-%{platform_release}/installer-bzImage +ln -s installer-intel-x86-64-initrd_1.0 %{buildroot}/pxeboot/rel-%{platform_release}/installer-initrd + +install -v -D -m 644 %{_sourcedir}/squashfs.img-%{tis_image_version} \ + %{buildroot}/www/pages/feed/rel-%{platform_release}/LiveOS/squashfs.img + +install -v -d -m 755 %{buildroot}%{_sbindir} + +install -v -m 755 %{_sourcedir}/pxeboot-update.sh %{buildroot}%{_sbindir}/pxeboot-update-%{platform_release}.sh + +install -v -m 644 %{_sourcedir}/post_clone_iso_ks.cfg \ + %{buildroot}/pxeboot/post_clone_iso_ks.cfg + +install -v -m 644 %{_sourcedir}/default \ + %{buildroot}/pxeboot/pxelinux.cfg.files/default +install -v -m 644 %{_sourcedir}/default.static \ + %{buildroot}/pxeboot/pxelinux.cfg.files/default.static +install -v -m 644 %{_sourcedir}/centos-pxe-controller-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-controller-install-%{platform_release} +install -v -m 644 %{_sourcedir}/centos-pxe-compute-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-compute-install-%{platform_release} +install -v -m 644 %{_sourcedir}/centos-pxe-smallsystem-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-smallsystem-install-%{platform_release} +install -v -m 644 %{_sourcedir}/centos-pxe-storage-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-storage-install-%{platform_release} +install -v -m 644 %{_sourcedir}/centos-pxe-compute_lowlatency-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-compute_lowlatency-install-%{platform_release} +install -v -m 644 %{_sourcedir}/centos-pxe-smallsystem_lowlatency-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-smallsystem_lowlatency-install-%{platform_release} + + +# UEFI support +install -v -m 644 %{_sourcedir}/pxe-grub.cfg \ + %{buildroot}/pxeboot/pxelinux.cfg.files/grub.cfg +install -v -m 644 %{_sourcedir}/pxe-grub.cfg.static \ + %{buildroot}/pxeboot/pxelinux.cfg.files/grub.cfg.static +# Copy EFI boot image. It will be used to create ISO on the Controller. +install -v -m 644 %{_sourcedir}/efiboot.img \ + %{buildroot}/pxeboot/rel-%{platform_release}/ +install -v -m 644 %{_sourcedir}/efi-centos-pxe-controller-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-controller-install-%{platform_release} +install -v -m 644 %{_sourcedir}/efi-centos-pxe-compute-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-compute-install-%{platform_release} +install -v -m 644 %{_sourcedir}/efi-centos-pxe-smallsystem-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-smallsystem-install-%{platform_release} +install -v -m 644 %{_sourcedir}/efi-centos-pxe-storage-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-storage-install-%{platform_release} +install -v -m 644 %{_sourcedir}/efi-centos-pxe-compute_lowlatency-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-compute_lowlatency-install-%{platform_release} +install -v -m 644 %{_sourcedir}/efi-centos-pxe-smallsystem_lowlatency-install \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-smallsystem_lowlatency-install-%{platform_release} + + +sed -i "s/xxxSW_VERSIONxxx/%{platform_release}/g" \ + %{buildroot}/pxeboot/pxelinux.cfg.files/pxe-* \ + %{buildroot}/pxeboot/pxelinux.cfg.files/efi-pxe-* + +# Copy files from the syslinux pkg +install -v -m 0644 \ + %{_datadir}/syslinux/menu.c32 \ + %{_datadir}/syslinux/vesamenu.c32 \ + %{_datadir}/syslinux/chain.c32 \ + %{_datadir}/syslinux/linux.c32 \ + %{_datadir}/syslinux/reboot.c32 \ + %{_datadir}/syslinux/pxechain.com \ + %{_datadir}/syslinux/pxelinux.0 \ + %{_datadir}/syslinux/gpxelinux.0 \ + %{buildroot}/pxeboot + +# Copy files from grub2. Centos UEFI bootloader expect these files +install -v -m 0644 \ + %{_prefix}/lib/grub/i386-pc/command.lst \ + %{_prefix}/lib/grub/i386-pc/fs.lst \ + %{_prefix}/lib/grub/i386-pc/crypto.lst \ + %{_prefix}/lib/grub/i386-pc/terminal.lst \ + %{buildroot}/pxeboot/EFI/centos/x86_64-efi +# Copy Titanium grub.cfg. It will be used to create ISO on the Controller. +install -v -m 0644 %{_sourcedir}/grub.cfg \ + %{buildroot}/pxeboot/EFI/ + +# UEFI bootloader expect the grub.cfg file to be in /pxeboot/ so create a symlink for it +ln -s pxelinux.cfg/grub.cfg %{buildroot}/pxeboot/grub.cfg + +%files +%license ../SOURCES/LICENSE +%defattr(-,root,root,-) +%dir /pxeboot +/pxeboot/* +%{_sbindir}/pxeboot-update-%{platform_release}.sh +/www/pages/feed/rel-%{platform_release}/LiveOS/squashfs.img + diff --git a/installer/pxe-network-installer/pxe-network-installer/LICENSE b/installer/pxe-network-installer/pxe-network-installer/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/installer/pxe-network-installer/pxe-network-installer/centos-pxe-compute-install b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-compute-install new file mode 100644 index 00000000..bfbfcfa0 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-compute-install @@ -0,0 +1,27 @@ +SERIAL 0 115200 +TIMEOUT 50 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +LABEL 1 + MENU LABEL ^1) Compute + MENU DEFAULT + KERNEL rel-xxxSW_VERSIONxxx/installer-bzImage + APPEND initrd=rel-xxxSW_VERSIONxxx/installer-initrd bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_compute_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 xxxAPPEND_OPTIONSxxx + IPAPPEND 2 + diff --git a/installer/pxe-network-installer/pxe-network-installer/centos-pxe-compute_lowlatency-install b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-compute_lowlatency-install new file mode 100644 index 00000000..2b2f0dd1 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-compute_lowlatency-install @@ -0,0 +1,27 @@ +SERIAL 0 115200 +TIMEOUT 50 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +LABEL 1 + MENU LABEL ^1) Lowlatency Compute + MENU DEFAULT + KERNEL rel-xxxSW_VERSIONxxx/installer-bzImage + APPEND initrd=rel-xxxSW_VERSIONxxx/installer-initrd bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_compute_lowlatency_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 xxxAPPEND_OPTIONSxxx + IPAPPEND 2 + diff --git a/installer/pxe-network-installer/pxe-network-installer/centos-pxe-controller-install b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-controller-install new file mode 100644 index 00000000..111051f3 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-controller-install @@ -0,0 +1,27 @@ +SERIAL 0 115200 +TIMEOUT 50 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +LABEL 1 + MENU LABEL ^1) Standard Controller + MENU DEFAULT + KERNEL rel-xxxSW_VERSIONxxx/installer-bzImage + APPEND initrd=rel-xxxSW_VERSIONxxx/installer-initrd bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_controller_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 xxxAPPEND_OPTIONSxxx + IPAPPEND 2 + diff --git a/installer/pxe-network-installer/pxe-network-installer/centos-pxe-smallsystem-install b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-smallsystem-install new file mode 100644 index 00000000..717f4b4b --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-smallsystem-install @@ -0,0 +1,27 @@ +SERIAL 0 115200 +TIMEOUT 50 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +LABEL 1 + MENU LABEL ^1) All-in-one + MENU DEFAULT + KERNEL rel-xxxSW_VERSIONxxx/installer-bzImage + APPEND initrd=rel-xxxSW_VERSIONxxx/installer-initrd bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_smallsystem_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 xxxAPPEND_OPTIONSxxx + IPAPPEND 2 + diff --git a/installer/pxe-network-installer/pxe-network-installer/centos-pxe-smallsystem_lowlatency-install b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-smallsystem_lowlatency-install new file mode 100644 index 00000000..a4b339fc --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-smallsystem_lowlatency-install @@ -0,0 +1,27 @@ +SERIAL 0 115200 +TIMEOUT 50 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +LABEL 1 + MENU LABEL ^1) All-in-one (lowlatency) + MENU DEFAULT + KERNEL rel-xxxSW_VERSIONxxx/installer-bzImage + APPEND initrd=rel-xxxSW_VERSIONxxx/installer-initrd bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_smallsystem_lowlatency_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 xxxAPPEND_OPTIONSxxx + IPAPPEND 2 + diff --git a/installer/pxe-network-installer/pxe-network-installer/centos-pxe-storage-install b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-storage-install new file mode 100644 index 00000000..58e924fb --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/centos-pxe-storage-install @@ -0,0 +1,27 @@ +SERIAL 0 115200 +TIMEOUT 50 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +LABEL 1 + MENU LABEL ^1) Storage + MENU DEFAULT + KERNEL rel-xxxSW_VERSIONxxx/installer-bzImage + APPEND initrd=rel-xxxSW_VERSIONxxx/installer-initrd bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_storage_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 xxxAPPEND_OPTIONSxxx + IPAPPEND 2 + diff --git a/installer/pxe-network-installer/pxe-network-installer/default b/installer/pxe-network-installer/pxe-network-installer/default new file mode 100644 index 00000000..4c49036c --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/default @@ -0,0 +1,38 @@ +SERIAL 0 115200 +TIMEOUT 100 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 +MENU AUTOBOOT Automatic retry in # seconds + +MENU COLOR UNSEL 36;44 +MENU COLOR SEL 36;44 +MENU COLOR DISABLED 36;44 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +MENU SEPARATOR + +LABEL Waiting for this node to be configured. + MENU DISABLE + +MENU SEPARATOR + +LABEL Please configure the personality for this node from the + MENU DISABLE + +LABEL controller node in order to proceed. + MENU DEFAULT + KERNEL pxelinux.0 diff --git a/installer/pxe-network-installer/pxe-network-installer/default.static b/installer/pxe-network-installer/pxe-network-installer/default.static new file mode 100644 index 00000000..7d36ba55 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/default.static @@ -0,0 +1,47 @@ +SERIAL 0 115200 +TIMEOUT 100 +DEFAULT menu.c32 + +# Menu Configuration +MENU WIDTH 80 +MENU MARGIN 10 +MENU PASSWORDMARGIN 3 +MENU ROWS 12 +MENU TABMSGROW 18 +MENU CMDLINEROW 18 +MENU ENDROW 24 +MENU PASSWORDROW 11 +MENU TIMEOUTROW 20 +MENU AUTOBOOT Automatic retry in # seconds + +MENU COLOR UNSEL 36;44 +MENU COLOR SEL 36;44 +MENU COLOR DISABLED 36;44 + +PROMPT 0 +NOESCAPE 1 +NOCOMPLETE 1 +ALLOWOPTIONS 0 + +MENU SEPARATOR + +LABEL Waiting for this node to be configured. + MENU DISABLE + +MENU SEPARATOR + +LABEL This system has been configured with static management + MENU DISABLE + +LABEL and infrastructure IP address allocation. This requires + MENU DISABLE + +LABEL that the node be manually provisioned in System + MENU DISABLE + +LABEL Inventory using the 'system host-add' CLI, GUI, or + MENU DISABLE + +LABEL sysinv-api equivalent. + MENU DISABLE + KERNEL pxelinux.0 diff --git a/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-compute-install b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-compute-install new file mode 100755 index 00000000..63a04a56 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-compute-install @@ -0,0 +1,9 @@ +default=0 +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +menuentry '1) UEFI Compute' { + linuxefi rel-xxxSW_VERSIONxxx/installer-bzImage bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_compute_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 ksdevice=$net_default_mac BOOTIF=$net_default_mac xxxAPPEND_OPTIONSxxx + initrdefi rel-xxxSW_VERSIONxxx/installer-initrd +} diff --git a/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-compute_lowlatency-install b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-compute_lowlatency-install new file mode 100755 index 00000000..8c985758 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-compute_lowlatency-install @@ -0,0 +1,9 @@ +default=0 +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +menuentry '1) UEFI Lowlatency Compute' { + linuxefi rel-xxxSW_VERSIONxxx/installer-bzImage bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_compute_lowlatency_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 ksdevice=$net_default_mac BOOTIF=$net_default_mac xxxAPPEND_OPTIONSxxx + initrdefi rel-xxxSW_VERSIONxxx/installer-initrd +} diff --git a/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-controller-install b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-controller-install new file mode 100755 index 00000000..189ef47b --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-controller-install @@ -0,0 +1,9 @@ +default=0 +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +menuentry '1) UEFI Standard Controller' { + linuxefi rel-xxxSW_VERSIONxxx/installer-bzImage bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_controller_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 ksdevice=$net_default_mac BOOTIF=$net_default_mac xxxAPPEND_OPTIONSxxx + initrdefi rel-xxxSW_VERSIONxxx/installer-initrd +} diff --git a/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-smallsystem-install b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-smallsystem-install new file mode 100755 index 00000000..4382aec8 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-smallsystem-install @@ -0,0 +1,9 @@ +default=0 +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +menuentry '1) UEFI All-in-one' { + linuxefi rel-xxxSW_VERSIONxxx/installer-bzImage bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_smallsystem_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 ksdevice=$net_default_mac BOOTIF=$net_default_mac xxxAPPEND_OPTIONSxxx + initrdefi rel-xxxSW_VERSIONxxx/installer-initrd +} diff --git a/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-smallsystem_lowlatency-install b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-smallsystem_lowlatency-install new file mode 100755 index 00000000..d0cc674d --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-smallsystem_lowlatency-install @@ -0,0 +1,9 @@ +default=0 +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +menuentry '1) UEFI All-in-one (lowlatency)' { + linuxefi rel-xxxSW_VERSIONxxx/installer-bzImage bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_smallsystem_lowlatency_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 ksdevice=$net_default_mac BOOTIF=$net_default_mac xxxAPPEND_OPTIONSxxx + initrdefi rel-xxxSW_VERSIONxxx/installer-initrd +} diff --git a/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-storage-install b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-storage-install new file mode 100755 index 00000000..4a76af22 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/efi-centos-pxe-storage-install @@ -0,0 +1,9 @@ +default=0 +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +menuentry '1) UEFI Storage' { + linuxefi rel-xxxSW_VERSIONxxx/installer-bzImage bootifonly=1 devfs=nomount inst.repo=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/ inst.ks=http://pxecontroller/feed/rel-xxxSW_VERSIONxxx/net_storage_ks.cfg usbcore.autosuspend=-1 biosdevname=0 rd.net.timeout.dhcp=120 ksdevice=$net_default_mac BOOTIF=$net_default_mac xxxAPPEND_OPTIONSxxx + initrdefi rel-xxxSW_VERSIONxxx/installer-initrd +} diff --git a/installer/pxe-network-installer/pxe-network-installer/pxe-grub.cfg b/installer/pxe-network-installer/pxe-network-installer/pxe-grub.cfg new file mode 100755 index 00000000..1487632d --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/pxe-grub.cfg @@ -0,0 +1,56 @@ +default=0 + +# If the default menu fails then menu entry 5 is used. +fallback=5 + +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +mac=$net_default_mac + +# net_default_mac is the network interface that was used to load grub. +# We need to convert from 01:00:1e:67:56:9d:c1 to 01-00-1e-67-56-9d-c1 to +# match the config file format. + +regexp --set=new '(^..)' "$mac" +conf=$new +regexp --set=new '^.{3}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{6}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{9}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{12}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{15}(.{2})' "$mac" +conf=$conf-$new + +# First try to load the mac config, if it does not exist yet (its created when a +# personality is assigned to a node) then grub.conf is loaded again. We timeout +# for 10 sec between re-tries. + +# Menu 0 +menuentry 'Waiting for this node to be configured.' { + insmod net + insmod efinet + configfile pxelinux.cfg/efi-01-$conf +} +menuentry ' ' { + echo " " +} +menuentry 'Please configure the personality for this node from the' { + echo " " +} +menuentry 'controller node in order to proceed.' { + echo " " +} +menuentry ' ' { + echo " " +} +# Menu 5 +menuentry 'Node not configured.' { + insmod net + insmod efinet + configfile grub.cfg +} diff --git a/installer/pxe-network-installer/pxe-network-installer/pxe-grub.cfg.static b/installer/pxe-network-installer/pxe-network-installer/pxe-grub.cfg.static new file mode 100755 index 00000000..45c19571 --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/pxe-grub.cfg.static @@ -0,0 +1,70 @@ +default=0 + +# If the default menu fails then menu entry 8 is used. +fallback=8 + +timeout=10 +GRUB_HIDDEN_TIMEOUT=0 +GRUB_TIMEOUT_STYLE='countdown' + +mac=$net_default_mac + +# net_default_mac is the network interface that was used to load grub. +# We need to convert from 01:00:1e:67:56:9d:c1 to 01-00-1e-67-56-9d-c1 to +# match the config file format. + +regexp --set=new '(^..)' "$mac" +conf=$new +regexp --set=new '^.{3}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{6}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{9}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{12}(.{2})' "$mac" +conf=$conf-$new +regexp --set=new '^.{15}(.{2})' "$mac" +conf=$conf-$new + +# First try to load the mac config, if it does not exist yet (its created when a +# personality is assigned to a node) then grub.conf is loaded again. We timeout +# for 10 sec between re-tries. + +# Menu 0 +menuentry 'Waiting for this node to be configured.' { + insmod net + insmod efinet + configfile pxelinux.cfg/efi-01-$conf +} +menuentry ' ' { + echo " " +} +menuentry 'This system has been configured with static management' { + echo " " +} +menuentry 'and infrastructure IP address allocation. This requires' { + echo " " +} +menuentry 'that the node be manually provisioned in System' { + echo " " +} +menuentry "Inventory using the 'system host-add' CLI, GUI, or" { + echo " " +} + +# Menu 6 +menuentry 'sysinv-api equivalent.' { + echo " " +} + +# Menu 7 +menuentry ' ' { + echo " " +} + +# Menu 8 +menuentry 'Node not configured.' { + insmod net + insmod efinet + configfile grub.cfg +} diff --git a/installer/pxe-network-installer/pxe-network-installer/pxeboot-update.sh b/installer/pxe-network-installer/pxe-network-installer/pxeboot-update.sh new file mode 100755 index 00000000..5664af2d --- /dev/null +++ b/installer/pxe-network-installer/pxe-network-installer/pxeboot-update.sh @@ -0,0 +1,172 @@ +#!/bin/bash +# +# Copyright (c) 2016-2017 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# Using a specified template, generate a node-specific pxeboot.cfg file +# for BIOS and UEFI mode. This script logs to user.log +# +# Command example; +# /usr/sbin/pxeboot-update-18.03.sh -i /pxeboot/pxelinux.cfg.files/pxe-controller-install-18.03 +# -o /pxeboot/pxelinux.cfg/01-08-00-27-3e-f8-05 -b sda -r sda -t -c ttyS0,115200 +# + +function usage() +{ + cat >&2 < : Specify template to use + -o : Specify output filename + -t : Use text install (optional) + -g : Use graphical install (optional) + -c : Specify serial console (optional) + -b : Specify boot device + -r : Specify rootfs device + -u : Base url for TIS install progress notification + -s : Specify Security Profile mode (optional) + -T : Specify whether or not to use tboot (optional) + +EOF +} + +declare text_install="inst.text" + +function generate_config() +{ + input=$1 + output=$2 + + if [ ! -f "$input" ] + then + logger --stderr -t $0 "Error: Input file $input does not exist" + exit 1 + fi + + if [ ! -w $(dirname $output) ] + then + logger --stderr -t $0 "Error: Destination directory $(dirname $output) not writeable" + exit 1 + fi + + if [ -e $output -a ! -w $output ] + then + logger --stderr -t $0 "Error: Destination file $output_file_efi exists and is not writeable" + exit 1 + fi + + sed -e "s#xxxAPPEND_OPTIONSxxx#$APPEND_OPTIONS#" $input > $output + + if [ $? -ne 0 -o ! -f $output ] + then + logger --stderr -t $0 "Error: Failed to generate pxeboot file $output" + exit 1 + fi +} + +parms=$@ +logger -t $0 " $parms" + +while getopts "i:o:tgc:b:r:u:s:T:h" opt +do + case $opt in + i) + input_file=$OPTARG + input_file_efi=$(dirname $input_file)/efi-$(basename $input_file) + ;; + o) + output_file=$OPTARG + output_file_efi=$(dirname $output_file)/efi-$(basename $output_file) + ;; + t) + text_install="inst.text" + ;; + g) + # We currently do not support Graphics install with Centos. Enforce + # the text install. + # text_install="inst.graphical" + text_install="inst.text" + ;; + c) + console=$OPTARG + ;; + b) + boot_device=$OPTARG + ;; + r) + rootfs_device=$OPTARG + ;; + u) + tisnotify=$OPTARG + ;; + s) + security_profile=$OPTARG + ;; + T) + tboot=$OPTARG + ;; + h) + usage + exit 1 + ;; + *) + usage + exit 1 + ;; + esac +done + +# Validate parameters +if [ -z "$input_file" \ + -o -z "$input_file_efi" \ + -o -z "$output_file" \ + -o -z "$output_file_efi" \ + -o -z "$boot_device" \ + -o -z "$rootfs_device" ] +then + logger --stderr -t $0 "Error: One or more mandatory options not specified: $@" + usage + exit 1 +fi + +APPEND_OPTIONS="boot_device=$boot_device rootfs_device=$rootfs_device" + +if [ -n "$text_install" ] +then + APPEND_OPTIONS="$APPEND_OPTIONS $text_install" +fi + +if [ -n "$console" ] +then + APPEND_OPTIONS="$APPEND_OPTIONS console=$console" +fi + +if [ -n "$tisnotify" ] +then + APPEND_OPTIONS="$APPEND_OPTIONS tisnotify=$tisnotify" +fi + +# We now require GPT partitions for all disks regardless of size +APPEND_OPTIONS="$APPEND_OPTIONS inst.gpt" + +if [ -n "$security_profile" ] +then + APPEND_OPTIONS="$APPEND_OPTIONS security_profile=$security_profile" +fi + +generate_config $input_file $output_file + +# for extended security profile UEFI boot only, +# a tboot option will be passed to target boot option menu +if [ "$security_profile" == "extended" -a -n "$tboot" ] +then + APPEND_OPTIONS="$APPEND_OPTIONS tboot=$tboot" +fi + +generate_config $input_file_efi $output_file_efi + +exit 0 diff --git a/kickstart/LICENSE b/kickstart/LICENSE new file mode 100755 index 00000000..d6456956 --- /dev/null +++ b/kickstart/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/kickstart/centos/build_srpm.data b/kickstart/centos/build_srpm.data new file mode 100644 index 00000000..15b87a79 --- /dev/null +++ b/kickstart/centos/build_srpm.data @@ -0,0 +1,3 @@ +SRC_DIR="${CGCS_BASE}/mwa-beas/bsp-files" +COPY_LIST="$PKG_BASE/LICENSE" +TIS_PATCH_VER=0 diff --git a/kickstart/centos/platform-kickstarts.spec b/kickstart/centos/platform-kickstarts.spec new file mode 100644 index 00000000..94204259 --- /dev/null +++ b/kickstart/centos/platform-kickstarts.spec @@ -0,0 +1,64 @@ +Name: platform-kickstarts +Version: 1.0.0 +Release: %{tis_patch_ver}%{?_tis_dist} +Summary: Platform Kickstarts +License: Apache-2.0 +Packager: Wind River +URL: unknown + +Source0: %{name}-%{version}.tar.gz +Source1: LICENSE + +BuildArch: noarch + +%description +Platform kickstart files + +BuildRequires: perl +BuildRequires: perl(Getopt::Long) +BuildRequires: perl(POSIX) + +%define feed_dir /www/pages/feed/rel-%{platform_release} + +%prep +%setup + +%build +./centos-ks-gen.pl --release %{platform_release} +cp %{SOURCE1} . + +%install + +install -d -m 0755 %{buildroot}%{feed_dir} +install -m 0444 generated/* %{buildroot}%{feed_dir}/ + +install -d -m 0755 %{buildroot}/pxeboot +install -D -m 0444 pxeboot/* %{buildroot}/pxeboot + +install -d -m 0755 %{buildroot}/extra_cfgs +install -D -m 0444 extra_cfgs/* %{buildroot}/extra_cfgs + +%files +%defattr(-,root,root,-) +%license LICENSE +%{feed_dir} + +%package pxeboot +Summary: Kickstarts for pxeboot server + +%description pxeboot +Kickstarts for pxeboot server + +%files pxeboot +%defattr(-,root,root,-) +/pxeboot/ + +%package extracfgs +Summary: Extra lab-usage kickstarts + +%description extracfgs +Extra lab-usage kickstarts + +%files extracfgs +%defattr(-,root,root,-) +/extra_cfgs/ diff --git a/mtce-common/LICENSE b/mtce-common/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/mtce-common/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/mtce-common/PKG-INFO b/mtce-common/PKG-INFO new file mode 100644 index 00000000..8fd02144 --- /dev/null +++ b/mtce-common/PKG-INFO @@ -0,0 +1,16 @@ +Metadata-Version: 1.1 +Name: cgts-mtce-common +Version: 1.0 +Summary: Titanium Cloud Platform Common Node Maintenance Package +Home-page: +Author: Windriver +Author-email: info@windriver.com +License: Apache-2.0 + +Description: Maintenance common package containing host maintenace and heatbeat + agent/client daemons as well as the hardware and process monitor + daemons, hardware watchdog process, guest heartbeat agent/client + daemons, resource and file system daemons as well as initialization + and support files for each. + +Platform: UNKNOWN diff --git a/mtce-common/centos/build_srpm.data b/mtce-common/centos/build_srpm.data new file mode 100644 index 00000000..951eace4 --- /dev/null +++ b/mtce-common/centos/build_srpm.data @@ -0,0 +1,3 @@ +SRC_DIR="cgts-mtce-common-1.0" +TIS_PATCH_VER=133 +BUILD_IS_SLOW=5 diff --git a/mtce-common/centos/cgts-mtce-common.spec b/mtce-common/centos/cgts-mtce-common.spec new file mode 100644 index 00000000..98e1564d --- /dev/null +++ b/mtce-common/centos/cgts-mtce-common.spec @@ -0,0 +1,768 @@ +Summary: Titanuim Server Common Maintenance Package +Name: cgts-mtce-common +Version: 1.0 +Release: %{tis_patch_ver}%{?_tis_dist} +License: Apache-2.0 +Group: base +Packager: Wind River +URL: unknown + +Source0: %{name}-%{version}.tar.gz + +BuildRequires: libssh2 +BuildRequires: libssh2-devel +BuildRequires: json-c +BuildRequires: json-c-devel +BuildRequires: fm-common +BuildRequires: fm-common-dev +BuildRequires: openssl +BuildRequires: openssl-devel +BuildRequires: libevent +BuildRequires: libevent-devel +BuildRequires: fm-mgr +BuildRequires: expect +BuildRequires: postgresql +BuildRequires: libuuid-devel +BuildRequires: guest-client-devel +BuildRequires: systemd-devel +BuildRequires: cppcheck +Requires: util-linux +Requires: /bin/bash +Requires: /bin/systemctl +Requires: dpkg +Requires: time +Requires: cgts-mtce-common-rmon >= 1.0 +Requires: libevent-2.0.so.5()(64bit) +Requires: expect +Requires: libfmcommon.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.14)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.9)(64bit) +Requires: fm-common >= 1.0 +Requires: libamon.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: /bin/sh +Requires: cgts-mtce-common-pmon >= 1.0 +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libc.so.6(GLIBC_2.14)(64bit) +Requires: libjson-c.so.2()(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librmonapi.so.1()(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: libevent >= 2.0.21 +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libuuid.so.1()(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6(GLIBC_2.4)(64bit) +Requires: libc.so.6()(64bit) +Requires: libssh2.so.1()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) +Requires: /usr/bin/expect +Requires: python-rtslib + +%description +Titanium Cloud Host Maintenance services. A suite of daemons that provide +host maintainability and a high level of fault detection with automatic +notification and recovery.The Maintenance Service (mtcAgent/mtcClient) +manages hosts according to an abbreviated version of the CCITT X.731 ITU +specification. The Heartbeat Service (hbsAgent/hbsClient) adds fast failure +detection over the management and infstructure networks. The Process +Monitor service (pmond) add both passive and active process monitoring and +automatic recovery of stopped or killed processes. The File System Monitor +Service (fsmond) adds detection and reporting of local file system +problems. The Hardware Monitor Service (hwmond) adds present and predictive +hardware failure detection, reporting and recovery. The Resource Monitor +Service (rmond) adds resource monitoring with present and predictive +failure and overload detection and reporting. The Guest Services +(guestAgent/guestServer) daemons control access into and heartbeat of guest +VMs on the compute. The Host Watchdog (hostwd) daemon watches for errors in +pmond and logs system information on error. All of these maintenance +services improve MTTD of node failures as well as resource overload and out +of spec operating conditions that can reduce outage time through automated +notification and recovery thereby improving overall platform availability +for the customer. + +%package -n cgts-mtce-common-pmon +Summary: Titanuim Server Maintenance Process Monitor Package +Group: base +BuildRequires: cppcheck +Requires: util-linux +Requires: /bin/bash +Requires: /bin/systemctl +Requires: dpkg +Requires: time +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: libfmcommon.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.7)(64bit) +Requires: fm-common >= 1.0 +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: /bin/sh +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libc.so.6(GLIBC_2.14)(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6(GLIBC_2.4)(64bit) +Requires: libc.so.6()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) +Provides: libamon.so.1()(64bit) + +%description -n cgts-mtce-common-pmon +Titanium Cloud Maintenance Process Monitor service (pmond) with +passive (pid), active (msg) and status (qry) process monitoring with +automatic recovery and failure reporting of registered failed processes. + +%package -n cgts-mtce-common-rmon +Summary: Titanuim Server Maintenance Resource Monitor Package +Group: base +Requires: /bin/bash +Requires: util-linux +Requires: /bin/systemctl +Requires: dpkg +Requires: time +Requires: libjson-c.so.2()(64bit) +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: libevent-2.0.so.5()(64bit) +Requires: libfmcommon.so.1()(64bit) +Requires: librmonapi.so.1()(64bit) +Requires: fm-common >= 1.0 +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: /bin/sh +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libc.so.6(GLIBC_2.14)(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: libevent >= 2.0.21 +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libuuid.so.1()(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) +Provides: librmonapi.so.1()(64bit) + +%description -n cgts-mtce-common-rmon +Titanium Cloud Host Maintenance Resource Monitor Service (rmond) adds +threshold based monitoring with predictive severity level alarming for +out of tolerance utilization of critical resourses such as memory, cpu +file system, interface state, etc. + +%package -n cgts-mtce-common-hwmon +Summary: Titanuim Server Maintenance Hardware Monitor Package +Group: base +Requires: dpkg +Requires: time +Requires: /bin/bash +Requires: libjson-c.so.2()(64bit) +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libfmcommon.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.14)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.9)(64bit) +Requires: fm-common >= 1.0 +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: /bin/sh +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libc.so.6(GLIBC_2.14)(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: libevent >= 2.0.21 +Requires: libevent-2.0.so.5()(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6()(64bit) +Requires: libssh2.so.1()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) + +%description -n cgts-mtce-common-hwmon +Titanium Cloud Host Maintenance Hardware Monitor Service (hwmond) adds +in and out of service hardware sensor monitoring, alarming and recovery +handling. + +%package -n cgts-mtce-common-guestAgent +Summary: Titanuim Server Maintenance Guest Agent Package +Group: base +Requires: dpkg +Requires: time +Requires: libjson-c.so.2()(64bit) +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libfmcommon.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.9)(64bit) +Requires: fm-common >= 1.0 +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: /bin/sh +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libc.so.6(GLIBC_2.14)(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: libevent >= 2.0.21 +Requires: libevent-2.0.so.5()(64bit) +Requires: libuuid.so.1()(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) + +%description -n cgts-mtce-common-guestAgent +Titanium Cloud Host Maintenance Guest Agent Service assists in +VM guest heartbeat control and failure reporting at the controller +level. + +%package -n cgts-mtce-common-guestServer +Summary: Titanuim Server Maintenance Guest Server Package +Group: base +Requires: util-linux +Requires: /bin/bash +Requires: /bin/systemctl +Requires: dpkg +Requires: libjson-c.so.2()(64bit) +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libfmcommon.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.9)(64bit) +Requires: fm-common >= 1.0 +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: /bin/sh +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libc.so.6(GLIBC_2.14)(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: libevent >= 2.0.21 +Requires: libevent-2.0.so.5()(64bit) +Requires: libuuid.so.1()(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6(GLIBC_2.4)(64bit) +Requires: libc.so.6()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) + +%description -n cgts-mtce-common-guestServer +Titanium Cloud Maintenance Guest Server assists in VM guest +heartbeat control and failure reporting at the compute level. + +%package -n cgts-mtce-common-hostw +Summary: Titanuim Server Common Maintenance Package +Group: base +Requires: util-linux +Requires: /bin/bash +Requires: /bin/systemctl +Requires: dpkg +Requires: libstdc++.so.6(CXXABI_1.3)(64bit) +Requires: libc.so.6(GLIBC_2.2.5)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit) +Requires: librt.so.1()(64bit) +Requires: libc.so.6(GLIBC_2.3)(64bit) +Requires: libpthread.so.0(GLIBC_2.2.5)(64bit) +Requires: librt.so.1(GLIBC_2.3.3)(64bit) +Requires: libgcc_s.so.1(GCC_3.0)(64bit) +Requires: librt.so.1(GLIBC_2.2.5)(64bit) +Requires: libm.so.6()(64bit) +Requires: rtld(GNU_HASH) +Requires: libstdc++.so.6()(64bit) +Requires: libc.so.6()(64bit) +Requires: libgcc_s.so.1()(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit) +Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit) +Requires: libpthread.so.0()(64bit) + +%description -n cgts-mtce-common-hostw +Titanium Cloud Host Maintenance services. A suite of daemons that provide +host maintainability and a high level of fault detection with automatic +notification and recovery.The Maintenance Service (mtcAgent/mtcClient) +manages hosts according to an abbreviated version of the CCITT X.731 ITU +specification. The Heartbeat Service (hbsAgent/hbsClient) adds fast failure +detection over the management and infstructure networks. The Process +Monitor service (pmond) add both passive and active process monitoring and +automatic recovery of stopped or killed processes. The File System Monitor +Service (fsmond) adds detection and reporting of local file system +problems. The Hardware Monitor Service (hwmond) adds present and predictive +hardware failure detection, reporting and recovery. The Resource Monitor +Service (rmond) adds resource monitoring with present and predictive +failure and overload detection and reporting. The Guest Services +(guestAgent/guestServer) daemons control access into and heartbeat of guest +VMs on the compute. The Host Watchdog (hostwd) daemon watches for errors in +pmond and logs system information on error. All of these maintenance +services improve MTTD of node failures as well as resource overload and out +of spec operating conditions that can reduce outage time through automated +notification and recovery thereby improving overall platform availability +for the customer. + +%define local_dir /usr/local +%define local_bindir %{local_dir}/bin +%define local_sbindir %{local_dir}/sbin +%define local_etc_pmond %{_sysconfdir}/pmon.d +%define local_etc_rmond %{_sysconfdir}/rmon.d +%define local_etc_goenabledd %{_sysconfdir}/goenabled.d +%define local_etc_servicesd %{_sysconfdir}/services.d +%define local_etc_logrotated %{_sysconfdir}/logrotate.d +%define bmc_profilesd %{_sysconfdir}/bmc/server_profiles.d +%define ocf_resourced /usr/lib/ocf/resource.d + +%prep +%setup + +# Build for main cgts-mtce-common package +%build +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` +make MAJOR=$MAJOR MINOR=$MINOR %{?_smp_mflags} build + +%global _buildsubdir %{_builddir}/%{name}-%{version} + +# Install for main cgts-mtce-common package +%install + +VER=%{version} +MAJOR=`echo $VER | awk -F . '{print $1}'` +MINOR=`echo $VER | awk -F . '{print $2}'` + +install -m 755 -d %{buildroot}%{_sysconfdir} +install -m 755 -d %{buildroot}/usr +install -m 755 -d %{buildroot}/%{_bindir} +install -m 755 -d %{buildroot}/usr/local +install -m 755 -d %{buildroot}%{local_bindir} +install -m 755 -d %{buildroot}/usr/local/sbin +install -m 755 -d %{buildroot}/%{_sbindir} +install -m 755 -d %{buildroot}/lib +install -m 755 -d %{buildroot}%{_sysconfdir}/mtc +install -m 755 -d %{buildroot}%{_sysconfdir}/mtc/tmp + +# Resource Agent Stuff +install -m 755 -d %{buildroot}/usr/lib +install -m 755 -d %{buildroot}/usr/lib/ocf +install -m 755 -d %{buildroot}/usr/lib/ocf/resource.d +install -m 755 -d %{buildroot}/usr/lib/ocf/resource.d/platform +install -m 755 -p -D %{_buildsubdir}/scripts/mtcAgent %{buildroot}/usr/lib/ocf/resource.d/platform/mtcAgent +install -m 755 -p -D %{_buildsubdir}/scripts/hbsAgent %{buildroot}/usr/lib/ocf/resource.d/platform/hbsAgent +install -m 755 -p -D %{_buildsubdir}/hwmon/scripts/ocf/hwmon %{buildroot}/usr/lib/ocf/resource.d/platform/hwmon +install -m 755 -p -D %{_buildsubdir}/guest/scripts/guestAgent.ocf %{buildroot}/usr/lib/ocf/resource.d/platform/guestAgent + +# config files +install -m 644 -p -D %{_buildsubdir}/scripts/mtc.ini %{buildroot}%{_sysconfdir}/mtc.ini +install -m 644 -p -D %{_buildsubdir}/scripts/mtc.conf %{buildroot}%{_sysconfdir}/mtc.conf +install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmond.conf %{buildroot}%{_sysconfdir}/mtc/fsmond.conf +install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmond.conf %{buildroot}%{_sysconfdir}/mtc/hwmond.conf +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmond.conf %{buildroot}%{_sysconfdir}/mtc/pmond.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmond.conf %{buildroot}%{_sysconfdir}/mtc/rmond.conf +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guest.ini %{buildroot}%{_sysconfdir}/mtc/guestAgent.ini +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guest.ini %{buildroot}%{_sysconfdir}/mtc/guestServer.ini +install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostwd.conf %{buildroot}%{_sysconfdir}/mtc/hostwd.conf + +install -m 755 -d %{buildroot}/%{_sysconfdir}/etc/bmc/server_profiles.d +install -m 644 -p -D %{_buildsubdir}/scripts/sensor_hp360_v1_ilo_v4.profile %{buildroot}/%{_sysconfdir}/bmc/server_profiles.d/sensor_hp360_v1_ilo_v4.profile +install -m 644 -p -D %{_buildsubdir}/scripts/sensor_hp380_v1_ilo_v4.profile %{buildroot}/%{_sysconfdir}/bmc/server_profiles.d/sensor_hp380_v1_ilo_v4.profile +install -m 644 -p -D %{_buildsubdir}/scripts/sensor_quanta_v1_ilo_v4.profile %{buildroot}/%{_sysconfdir}/bmc/server_profiles.d/sensor_quanta_v1_ilo_v4.profile + +# binaries +install -m 755 -p -D %{_buildsubdir}/maintenance/mtcAgent %{buildroot}/%{local_bindir}/mtcAgent +install -m 755 -p -D %{_buildsubdir}/maintenance/mtcClient %{buildroot}/%{local_bindir}/mtcClient +install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsAgent %{buildroot}/%{local_bindir}/hbsAgent +install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsClient %{buildroot}/%{local_bindir}/hbsClient +install -m 755 -p -D %{_buildsubdir}/guest/guestServer %{buildroot}/%{local_bindir}/guestServer +install -m 755 -p -D %{_buildsubdir}/guest/guestAgent %{buildroot}/%{local_bindir}/guestAgent +install -m 755 -p -D %{_buildsubdir}/pmon/pmond %{buildroot}/%{local_bindir}/pmond +install -m 755 -p -D %{_buildsubdir}/hostw/hostwd %{buildroot}/%{local_bindir}/hostwd +install -m 755 -p -D %{_buildsubdir}/rmon/rmond %{buildroot}/%{local_bindir}/rmond +install -m 755 -p -D %{_buildsubdir}/fsmon/fsmond %{buildroot}/%{local_bindir}/fsmond +install -m 755 -p -D %{_buildsubdir}/hwmon/hwmond %{buildroot}/%{local_bindir}/hwmond +install -m 755 -p -D %{_buildsubdir}/mtclog/mtclogd %{buildroot}/%{local_bindir}/mtclogd +install -m 755 -p -D %{_buildsubdir}/alarm/mtcalarmd %{buildroot}/%{local_bindir}/mtcalarmd +install -m 755 -p -D %{_buildsubdir}/rmon/rmon_resource_notify/rmon_resource_notify %{buildroot}/%{local_bindir}/rmon_resource_notify +install -m 755 -p -D %{_buildsubdir}/scripts/wipedisk %{buildroot}/%{local_bindir}/wipedisk +install -m 755 -p -D %{_buildsubdir}/common/fsync %{buildroot}/%{_sbindir}/fsync +install -m 700 -p -D %{_buildsubdir}/pmon/scripts/pmon-restart %{buildroot}/%{local_sbindir}/pmon-restart +install -m 700 -p -D %{_buildsubdir}/pmon/scripts/pmon-start %{buildroot}/%{local_sbindir}/pmon-start +install -m 700 -p -D %{_buildsubdir}/pmon/scripts/pmon-stop %{buildroot}/%{local_sbindir}/pmon-stop + +# test tools +install -m 755 %{_buildsubdir}/hwmon/scripts/show_hp360 %{buildroot}/%{_sbindir}/show_hp360 +install -m 755 %{_buildsubdir}/hwmon/scripts/show_hp380 %{buildroot}/%{_sbindir}/show_hp380 +install -m 755 %{_buildsubdir}/hwmon/scripts/show_quanta %{buildroot}/%{_sbindir}/show_quanta + +# init script files +install -m 755 -p -D %{_buildsubdir}/scripts/mtcClient %{buildroot}%{_sysconfdir}/init.d/mtcClient +install -m 755 -p -D %{_buildsubdir}/scripts/hbsClient %{buildroot}%{_sysconfdir}/init.d/hbsClient +install -m 755 -p -D %{_buildsubdir}/guest/scripts/guestServer %{buildroot}%{_sysconfdir}/init.d/guestServer +install -m 755 -p -D %{_buildsubdir}/guest/scripts/guestAgent %{buildroot}%{_sysconfdir}/init.d/guestAgent +install -m 755 -p -D %{_buildsubdir}/hwmon/scripts/lsb/hwmon %{buildroot}%{_sysconfdir}/init.d/hwmon +install -m 755 -p -D %{_buildsubdir}/fsmon/scripts/fsmon %{buildroot}%{_sysconfdir}/init.d/fsmon +install -m 755 -p -D %{_buildsubdir}/scripts/mtclog %{buildroot}%{_sysconfdir}/init.d/mtclog +install -m 755 -p -D %{_buildsubdir}/pmon/scripts/pmon %{buildroot}%{_sysconfdir}/init.d/pmon +install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon %{buildroot}%{_sysconfdir}/init.d/rmon +install -m 755 -p -D %{_buildsubdir}/hostw/scripts/hostw %{buildroot}%{_sysconfdir}/init.d/hostw +install -m 755 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.init %{buildroot}%{_sysconfdir}/init.d/mtcalarm + +# install -m 755 -p -D %{_buildsubdir}/scripts/config %{buildroot}%{_sysconfdir}/init.d/config + +# TODO: Init hack. Should move to proper module +install -m 755 -p -D %{_buildsubdir}/scripts/hwclock.sh %{buildroot}%{_sysconfdir}/init.d/hwclock.sh +install -m 644 -p -D %{_buildsubdir}/scripts/hwclock.service %{buildroot}%{_unitdir}/hwclock.service + +# systemd service files +install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.service %{buildroot}%{_unitdir}/fsmon.service +install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmon.service %{buildroot}%{_unitdir}/hwmon.service +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.service %{buildroot}%{_unitdir}/rmon.service +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmon.service %{buildroot}%{_unitdir}/pmon.service +install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostw.service %{buildroot}%{_unitdir}/hostw.service +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guestServer.service %{buildroot}%{_unitdir}/guestServer.service +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guestAgent.service %{buildroot}%{_unitdir}/guestAgent.service +install -m 644 -p -D %{_buildsubdir}/scripts/mtcClient.service %{buildroot}%{_unitdir}/mtcClient.service +install -m 644 -p -D %{_buildsubdir}/scripts/hbsClient.service %{buildroot}%{_unitdir}/hbsClient.service +install -m 644 -p -D %{_buildsubdir}/scripts/mtclog.service %{buildroot}%{_unitdir}/mtclog.service +install -m 644 -p -D %{_buildsubdir}/scripts/goenabled.service %{buildroot}%{_unitdir}/goenabled.service +install -m 644 -p -D %{_buildsubdir}/scripts/runservices.service %{buildroot}%{_unitdir}/runservices.service +install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.service %{buildroot}%{_unitdir}/mtcalarm.service + +# go enabled stuff +install -m 755 -d %{buildroot}%{local_etc_goenabledd} +install -m 755 -p -D %{_buildsubdir}/scripts/goenabled %{buildroot}%{_sysconfdir}/init.d/goenabled + +# start or stop services test script +install -m 755 -d %{buildroot}%{local_etc_servicesd} +install -m 755 -d %{buildroot}%{local_etc_servicesd}/controller +install -m 755 -d %{buildroot}%{local_etc_servicesd}/compute +install -m 755 -d %{buildroot}%{local_etc_servicesd}/storage +install -m 755 -p -D %{_buildsubdir}/scripts/mtcTest %{buildroot}/%{local_etc_servicesd}/compute +install -m 755 -p -D %{_buildsubdir}/scripts/mtcTest %{buildroot}/%{local_etc_servicesd}/controller +install -m 755 -p -D %{_buildsubdir}/scripts/mtcTest %{buildroot}/%{local_etc_servicesd}/storage +install -m 755 -p -D %{_buildsubdir}/scripts/runservices %{buildroot}%{_sysconfdir}/init.d/runservices + +# test tools +install -m 755 -p -D %{_buildsubdir}/scripts/dmemchk.sh %{buildroot}%{local_sbindir} + +# process monitor config files +install -m 755 -d %{buildroot}%{local_etc_pmond} +install -m 644 -p -D %{_buildsubdir}/scripts/mtcClient.conf %{buildroot}%{local_etc_pmond}/mtcClient.conf +install -m 644 -p -D %{_buildsubdir}/scripts/hbsClient.conf %{buildroot}%{local_etc_pmond}/hbsClient.conf +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/acpid.conf %{buildroot}%{local_etc_pmond}/acpid.conf +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/sshd.conf %{buildroot}%{local_etc_pmond}/sshd.conf +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/ntpd.conf %{buildroot}%{local_etc_pmond}/ntpd.conf +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/syslog-ng.conf %{buildroot}%{local_etc_pmond}/syslog-ng.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.conf %{buildroot}%{local_etc_pmond}/rmon.conf +install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.conf %{buildroot}%{local_etc_pmond}/fsmon.conf +install -m 644 -p -D %{_buildsubdir}/scripts/mtclogd.conf %{buildroot}%{local_etc_pmond}/mtclogd.conf +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guestServer.pmon %{buildroot}%{local_etc_pmond}/guestServer.conf +install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.pmon.conf %{buildroot}%{local_etc_pmond}/mtcalarm.conf + +# resource monitor config files +install -m 755 -d %{buildroot}%{local_etc_rmond} +install -m 755 -d %{buildroot}%{_sysconfdir}/rmonapi.d +install -m 755 -d %{buildroot}%{_sysconfdir}/rmonfiles.d +install -m 755 -d %{buildroot}%{_sysconfdir}/rmon_interfaces.d +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/remotelogging_resource.conf %{buildroot}%{local_etc_rmond}/remotelogging_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/cpu_resource.conf %{buildroot}%{local_etc_rmond}/cpu_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/memory_resource.conf %{buildroot}%{local_etc_rmond}/memory_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/filesystem_resource.conf %{buildroot}%{local_etc_rmond}/filesystem_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/cinder_virtual_resource.conf %{buildroot}%{local_etc_rmond}/cinder_virtual_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/nova_virtual_resource.conf %{buildroot}%{local_etc_rmond}/nova_virtual_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/oam_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/management_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/management_resource.conf +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/infrastructure_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf +install -m 755 -p -D %{_buildsubdir}/rmon/scripts/query_ntp_servers.sh %{buildroot}%{_sysconfdir}/rmonfiles.d/query_ntp_servers.sh +install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon_reload_on_cpe.sh %{buildroot}%{local_etc_goenabledd}/rmon_reload_on_cpe.sh + +# log rotation +install -m 755 -d %{buildroot}%{_sysconfdir}/logrotate.d +install -m 644 -p -D %{_buildsubdir}/scripts/mtce.logrotate %{buildroot}%{local_etc_logrotated}/mtce.logrotate +install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostw.logrotate %{buildroot}%{local_etc_logrotated}/hostw.logrotate +install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmon.logrotate %{buildroot}%{local_etc_logrotated}/pmon.logrotate +install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.logrotate %{buildroot}%{local_etc_logrotated}/rmon.logrotate +install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.logrotate %{buildroot}%{local_etc_logrotated}/fsmon.logrotate +install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmon.logrotate %{buildroot}%{local_etc_logrotated}/hwmon.logrotate +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guestAgent.logrotate %{buildroot}%{local_etc_logrotated}/guestAgent.logrotate +install -m 644 -p -D %{_buildsubdir}/guest/scripts/guestServer.logrotate %{buildroot}%{local_etc_logrotated}/guestServer.logrotate +install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.logrotate %{buildroot}%{local_etc_logrotated}/mtcalarm.logrotate + +install -m 755 -p -D %{_buildsubdir}/public/libamon.so.$MAJOR %{buildroot}%{_libdir}/libamon.so.$MAJOR +cd %{buildroot}%{_libdir} ; ln -s libamon.so.$MAJOR libamon.so.$MAJOR.$MINOR +cd %{buildroot}%{_libdir} ; ln -s libamon.so.$MAJOR libamon.so + +install -m 755 -p -D %{_buildsubdir}/rmon/rmonApi/librmonapi.so.$MAJOR %{buildroot}%{_libdir}/librmonapi.so.$MAJOR +cd %{buildroot}%{_libdir} ; ln -s librmonapi.so.$MAJOR librmonapi.so.$MAJOR.$MINOR +cd %{buildroot}%{_libdir} ; ln -s librmonapi.so.$MAJOR librmonapi.so + +install -m 755 -d %{buildroot}/var +install -m 755 -d %{buildroot}/var/run + +# Enable all services in systemd +%post +/bin/systemctl enable fsmon.service +/bin/systemctl enable mtcClient.service +/bin/systemctl enable hbsClient.service +/bin/systemctl enable mtclog.service +/bin/systemctl enable iscsid.service +/bin/systemctl enable rsyncd.service +/bin/systemctl enable goenabled.service +/bin/systemctl enable mtcalarm.service + +%post -n cgts-mtce-common-hostw +/bin/systemctl enable hostw.service + +%post -n cgts-mtce-common-pmon +/bin/systemctl enable pmon.service + +%post -n cgts-mtce-common-guestServer +/bin/systemctl enable guestServer.service + +%post -n cgts-mtce-common-rmon +/bin/systemctl enable rmon.service + + +############################### +# Maintenance Common RPM Files +############################### + +%files +%license LICENSE + +%defattr(-,root,root,-) + +# create the mtc and its tmp dir +%dir %{_sysconfdir}/mtc +%dir %{_sysconfdir}/mtc/tmp + +# SM OCF Start/Stop/Monitor Scripts +%{ocf_resourced}/platform/mtcAgent +%{ocf_resourced}/platform/hbsAgent + +# Config files +%config(noreplace)/etc/mtc.ini + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc.conf +%{_sysconfdir}/mtc/fsmond.conf + +# Mainteance Process Monitor Config Files +%{local_etc_pmond}/sshd.conf +%{local_etc_pmond}/ntpd.conf +%{local_etc_pmond}/mtcClient.conf +%{local_etc_pmond}/acpid.conf +%{local_etc_pmond}/hbsClient.conf +%{local_etc_pmond}/syslog-ng.conf +%{local_etc_pmond}/fsmon.conf +%{local_etc_pmond}/mtclogd.conf +%{local_etc_pmond}/mtcalarm.conf + +# Mainteance log rotation config files +%{local_etc_logrotated}/fsmon.logrotate +%{local_etc_logrotated}/mtce.logrotate +%{local_etc_logrotated}/mtcalarm.logrotate + +# Maintenance start/stop services scripts +%{local_etc_servicesd}/controller/mtcTest +%{local_etc_servicesd}/storage/mtcTest +%{local_etc_servicesd}/compute/mtcTest + +# BMC profile Files +%{bmc_profilesd}/sensor_hp360_v1_ilo_v4.profile +%{bmc_profilesd}/sensor_quanta_v1_ilo_v4.profile +%{bmc_profilesd}/sensor_hp380_v1_ilo_v4.profile + +# Init scripts +%{_sysconfdir}/init.d/runservices +%{_sysconfdir}/init.d/goenabled +%{_sysconfdir}/init.d/fsmon +%{_sysconfdir}/init.d/mtclog +%{_sysconfdir}/init.d/hbsClient +%{_sysconfdir}/init.d/mtcClient +%{_sysconfdir}/init.d/mtcalarm +%{_sysconfdir}/init.d/hwclock.sh + +%{_unitdir}/runservices.service +%{_unitdir}/goenabled.service +%{_unitdir}/mtclog.service +%{_unitdir}/mtcalarm.service +%{_unitdir}/fsmon.service +%{_unitdir}/mtcClient.service +%{_unitdir}/hbsClient.service +%{_unitdir}/hwclock.service + +# Binaries +%{local_bindir}/mtcAgent +%{local_bindir}/fsmond +%{local_bindir}/hbsAgent +%{local_bindir}/mtclogd +%{local_bindir}/mtcalarmd +%{local_bindir}/hbsClient +%{local_bindir}/mtcClient +%{local_bindir}/wipedisk +%{local_sbindir}/dmemchk.sh +%{_sbindir}/fsync + +############################### +# Process Monitor RPM Files +############################### +%files -n cgts-mtce-common-pmon + +%defattr(-,root,root,-) + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc/pmond.conf + +%{local_etc_logrotated}/pmon.logrotate +%{_unitdir}/pmon.service +%{local_sbindir}/pmon-restart +%{local_sbindir}/pmon-start +%{local_sbindir}/pmon-stop + +/usr/lib64/libamon.so.1.0 +/usr/lib64/libamon.so.1 +/usr/lib64/libamon.so + +%{_sysconfdir}/init.d/pmon +%{local_bindir}/pmond + +############################### +# Resource Monitor RPM Files +############################### +%files -n cgts-mtce-common-rmon + +%defattr(-,root,root,-) + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc/rmond.conf + +%{local_etc_pmond}/rmon.conf +%{local_etc_logrotated}/rmon.logrotate +%{_unitdir}/rmon.service + +%{local_etc_rmond}/filesystem_resource.conf +%{local_etc_rmond}/cpu_resource.conf +%{local_etc_rmond}/remotelogging_resource.conf +%{local_etc_rmond}/memory_resource.conf +%{local_etc_rmond}/cinder_virtual_resource.conf +%{local_etc_rmond}/nova_virtual_resource.conf + +%{_sysconfdir}/rmon_interfaces.d/management_resource.conf +%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf +%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf +%{_sysconfdir}/rmonfiles.d/query_ntp_servers.sh + +/usr/lib64/librmonapi.so.1.0 +/usr/lib64/librmonapi.so.1 +/usr/lib64/librmonapi.so + +%dir %{_sysconfdir}/rmonapi.d + +%{_sysconfdir}/init.d/rmon +%{local_bindir}/rmond +%{local_bindir}/rmon_resource_notify +%{local_etc_goenabledd}/rmon_reload_on_cpe.sh + +############################### +# Hardware Monitor RPM Files +############################### +%files -n cgts-mtce-common-hwmon + +%defattr(-,root,root,-) + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc/hwmond.conf + +%{_unitdir}/hwmon.service +%{local_etc_logrotated}/hwmon.logrotate +%{ocf_resourced}/platform/hwmon + +%{_sbindir}/show_hp380 +%{_sbindir}/show_hp360 +%{_sbindir}/show_quanta + +%{_sysconfdir}/init.d/hwmon +%{local_bindir}/hwmond + +############################### +# Guest Agent RPM Files +############################### +%files -n cgts-mtce-common-guestAgent + +%defattr(-,root,root,-) + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc/guestAgent.ini + +%{_unitdir}/guestAgent.service +%{local_etc_logrotated}/guestAgent.logrotate +%{ocf_resourced}/platform/guestAgent + +%{_sysconfdir}/init.d/guestAgent +%{local_bindir}/guestAgent + +############################### +# Guest Server RPM Files +############################### +%files -n cgts-mtce-common-guestServer + +%defattr(-,root,root,-) + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc/guestServer.ini + +%{local_etc_pmond}/guestServer.conf +%{local_etc_logrotated}/guestServer.logrotate +%{_unitdir}/guestServer.service + +%{_sysconfdir}/init.d/guestServer +%{local_bindir}/guestServer + + +############################### +# Host Watchdog RPM Files +############################### +%files -n cgts-mtce-common-hostw + +%defattr(-,root,root,-) + +# Config files - Non-Modifiable +%{_sysconfdir}/mtc/hostwd.conf + +%{local_etc_logrotated}/hostw.logrotate +%{_unitdir}/hostw.service +%{_sysconfdir}/init.d/hostw +%{local_bindir}/hostwd diff --git a/mtce-common/cgts-mtce-common-1.0/.gitignore b/mtce-common/cgts-mtce-common-1.0/.gitignore new file mode 100644 index 00000000..4e5d65ff --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/.gitignore @@ -0,0 +1,4 @@ +*.swp +*.o +*.a +*~ diff --git a/mtce-common/cgts-mtce-common-1.0/LICENSE b/mtce-common/cgts-mtce-common-1.0/LICENSE new file mode 100644 index 00000000..d6456956 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/mtce-common/cgts-mtce-common-1.0/Makefile b/mtce-common/cgts-mtce-common-1.0/Makefile new file mode 100755 index 00000000..f942d70c --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (c) 2013-2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +VER=1 +VER_MJR=1 + +build: + @(cd public ; make lib VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd rmon/rmonApi ; make lib VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd daemon ; make lib VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd common ; make lib fsync VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd alarm ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd heartbeat ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd maintenance ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd hwmon ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd mtclog ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd pmon ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd guest ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd fsmon ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd rmon ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd rmon/rmon_resource_notify ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + @(cd hostw ; make build VER=$(VER) VER_MJR=$(VER_MJR)) + +clean: + @( cd public ; make clean ) + @( cd rmon/rmonApi ; make clean ) + @( cd daemon ; make clean ) + @( cd common ; make clean ) + @( cd alarm ; make clean ) + @( cd mtclog ; make clean ) + @( cd hwmon ; make clean ) + @( cd pmon ; make clean ) + @( cd guest ; make clean ) + @( cd fsmon ; make clean ) + @( cd heartbeat ; make clean ) + @( cd maintenance ; make clean ) + @( cd rmon ; make clean ) + @( cd rmon/rmon_resource_notify ; make clean ) + @( cd hostw ; make clean ) + @( rm -rf release ) + +backup: clean + mkdir -p ~/mtce + cp -a * ~/mtce diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/Makefile b/mtce-common/cgts-mtce-common-1.0/alarm/Makefile new file mode 100755 index 00000000..210de21b --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/Makefile @@ -0,0 +1,44 @@ +SRCS = alarmInit.cpp alarmData.cpp alarmHdlr.cpp alarmMgr.cpp alarmUtil.cpp alarm.cpp +OBJS = $(SRCS:.cpp=.o) +LDLIBS = -lstdc++ -ldaemon -lcommon -lfmcommon -ljson-c -lrt -lcrypto -luuid +INCLUDES = -I../daemon -I../common -I../smash -I../maintenance -I../public -I. -I.. +CCFLAGS = -g -O2 -Wall -Wextra -Werror + +STATIC_ANALYSIS_TOOL = cppcheck +STATIC_ANALYSIS_TOOL_EXISTS = $(shell [[ -e `which $(STATIC_ANALYSIS_TOOL)` ]] && echo 1 || echo 0) + +BINS = mtcalarmd + + +.cpp.o: + $(CXX) $(INCLUDES) $(CCFLAGS) $(EXTRACCFLAGS) -c $< -o $@ + +all: clean_bins static_analysis common daemon process library + +static_analysis: +ifeq ($(STATIC_ANALYSIS_TOOL_EXISTS), 1) + $(STATIC_ANALYSIS_TOOL) --language=c++ --enable=warning -U__AREA__ -DWANT_FIT_TESTING *.cpp *.h +else + echo "Warning: '$(STATIC_ANALYSIS_TOOL)' static analysis tool not installed ; bypassing ..." +endif + +build: clean_bins static_analysis ${OBJS} library process + +common: + ( cd ../common ; make clean ; make lib VER=$(VER) VER_MJR=$(VER_MJR)) + +daemon: + ( cd ../daemon ; make clean ; make lib VER=$(VER) VER_MJR=$(VER_MJR)) + +library: + ar rcs libalarm.a alarm.o $(EXTRAARFLAGS) + +process: $(OBJS) + $(CXX) $(CCFLAGS) ${OBJS} -L../daemon -L../common $(LDLIBS) -o mtcalarmd + +clean_bins: + @rm -f $(BINS) + +clean: + @rm -f $(OBJ) $(BINS) *.o *.a + diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarm.cpp b/mtce-common/cgts-mtce-common-1.0/alarm/alarm.cpp new file mode 100644 index 00000000..6b113f89 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarm.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud 'Heartbeat Agent' Alarm Module + */ + +#include +#include +#include +#include +#include + +using namespace std; + +#ifdef __AREA__ +#undef __AREA__ +#endif +#define __AREA__ "alm" + +#include "daemon_common.h" +#include "nodeBase.h" /* for ... fail codes */ +#include "jsonUtil.h" +#include "alarm.h" /* for ... module header */ + +static msgClassSock * user_sock_ptr = NULL ; + +/* A call to this API is required in advance of sending an alarm request */ +int alarm_register_user ( msgClassSock * sock_ptr ) +{ + int rc = PASS ; + if ( sock_ptr && sock_ptr->getFD() && sock_ptr->sock_ok() ) + { + ilog ("Registered with maintenance alarm service\n"); + user_sock_ptr = sock_ptr ; + } + else + { + elog ("Failed to register with maintenance alarm service\n"); + rc = FAIL_SOCKET_BIND ; + } + return (rc); +} + +/* Construct an alarm request json string in the following form + {\"mtcalarm\":[{\"alarmid\":\"200.009\",\"hostname\":\"compute-3\",\"operation\":\"set\",\"severity\":\"major\",\"entity\":\"Infrastructure\",\"prefix\":\"service=heartbeat\"}, {\"alarmid\":\"200.005\",\"hostname\":\"compute-3\",\"operation\":\"set\",\"severity\":\"major\",\"entity\":\"Management\",\"prefix\":\"service=heartbeat\"}]}" + + or + + { \"mtcalarm\": + [ + { + \"alarmid\":\"200.009\", + \"hostname\":\"compute-3\", + \"operation\":\"set\", + \"severity\":\"major\", + \"entity\":\"Infrastructure\", + \"prefix\":\"service=heartbeat\" + } + ] + } + +*/ +int alarm_ ( string hostname, const char * id, EFmAlarmStateT state, EFmAlarmSeverityT severity, const char * entity, string prefix ) +{ + int rc = PASS ; + char request [MAX_ALARM_REQ_MSG_SIZE] ; + string msg_type ; + string sev ; + + if ( state == FM_ALARM_STATE_MSG ) + msg_type = "msg" ; + else if ( state == FM_ALARM_STATE_SET ) + msg_type = "set" ; + else + msg_type = "clear" ; + + switch ( severity ) + { + case FM_ALARM_SEVERITY_CLEAR: + sev = "clear" ; + break ; + case FM_ALARM_SEVERITY_WARNING: + sev = "warning"; + break ; + case FM_ALARM_SEVERITY_MINOR: + sev = "minor"; + break ; + case FM_ALARM_SEVERITY_MAJOR: + sev = "major"; + break ; + case FM_ALARM_SEVERITY_CRITICAL: + sev = "critical"; + break ; + default : + sev = "unknown"; + break ; + } + + snprintf ( request, MAX_ALARM_REQ_MSG_SIZE, "{\"mtcalarm\":[{\"alarmid\":\"%s\",\"hostname\":\"%s\",\"operation\":\"%s\",\"severity\":\"%s\",\"entity\":\"%s\",\"prefix\":\"%s\"}]}", + id, + hostname.data(), + msg_type.data(), + sev.data(), + entity, + prefix.data()); + size_t len = strlen(request) ; + + /* Retrying up to 3 times if the send fails */ + for ( int i = 0 ; i < 3 ; i++ ) + { + int bytes = user_sock_ptr->write((char*)&request[0], len ); + if ( bytes <= 0 ) + { + elog("%s failed to send alarm request (%d:%m)\n", hostname.c_str(), errno ); + elog("... %s\n", request); + rc = FAIL_SOCKET_SENDTO ; + } + else if ( ((int)len) != bytes ) + { + elog ("%s failed to send complete alarm message (%d:%ld)\n", hostname.c_str(), bytes, len ); + } + else + { + ilog ("%s %s\n", hostname.c_str(), request); + return ( PASS ) ; + } + daemon_signal_hdlr (); + + usleep (1000); + } + return (rc); +} + + +int alarm_clear ( string hostname, const char * alarm_id_ptr , string entity ) +{ + string prefix = "" ; + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_CLEAR, FM_ALARM_SEVERITY_CLEAR, entity.data(), prefix.data() )); +} + +int alarm_warning ( string hostname, const char * alarm_id_ptr , string entity ) +{ + string prefix = "" ; + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_SET, FM_ALARM_SEVERITY_WARNING, entity.data(), prefix.data() )); +} + +int alarm_minor ( string hostname, const char * alarm_id_ptr , string entity ) +{ + string prefix = "" ; + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_SET, FM_ALARM_SEVERITY_MINOR, entity.data(), prefix.data() )); +} + +int alarm_major ( string hostname, const char * alarm_id_ptr , string entity ) +{ + string prefix = "" ; + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_SET, FM_ALARM_SEVERITY_MAJOR, entity.data(), prefix.data() )); +} + +int alarm_critical ( string hostname, const char * alarm_id_ptr , string entity ) +{ + string prefix = "" ; + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_SET, FM_ALARM_SEVERITY_CRITICAL, entity.data(), prefix.data() )); +} + +int alarm_warning_log ( string hostname, const char * alarm_id_ptr , string entity , string prefix ) +{ + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_MSG, FM_ALARM_SEVERITY_WARNING, entity.data(), prefix.data() )); +} + +int alarm_minor_log ( string hostname, const char * alarm_id_ptr , string entity , string prefix ) +{ + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_MSG, FM_ALARM_SEVERITY_MINOR, entity.data(), prefix.data() )); +} + +int alarm_major_log ( string hostname, const char * alarm_id_ptr , string entity , string prefix ) +{ + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_MSG, FM_ALARM_SEVERITY_MAJOR, entity.data(), prefix.data() )); +} + +int alarm_critical_log ( string hostname, const char * alarm_id_ptr , string entity , string prefix ) +{ + return (alarm_ ( hostname, alarm_id_ptr, FM_ALARM_STATE_MSG, FM_ALARM_SEVERITY_CRITICAL, entity.data(), prefix.data() )); +} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarm.h b/mtce-common/cgts-mtce-common-1.0/alarm/alarm.h new file mode 100644 index 00000000..9e29c971 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarm.h @@ -0,0 +1,166 @@ +#ifndef __INCLUDE_ALARM_H__ +#define __INCLUDE_ALARM_H__ + +/* + * Copyright (c) 2016-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud Maintenance Alarm Service Header + */ + +#include "nodeBase.h" +#include "nodeUtil.h" /* for ... common utilities */ + +#include "msgClass.h" /* for ... msgClassSock type definition */ + +/* external APIs */ +#include "fmAPI.h" + +#define ENTITY_PREFIX ((const char *)"host=") + +#define MAX_ALARMS (10) +#define MAX_ALARM_REQ_PER_MSG (4) +#define MAX_ALARM_REQ_MSG_SIZE (500) +#define MAX_ALARM_REQ_SIZE (MAX_ALARM_REQ_PER_MSG*MAX_ALARM_REQ_MSG_SIZE) + +#define SWERR_ALARM_ID ((const char *)"200.000") /* Do No Use */ +#define LOCK_ALARM_ID ((const char *)"200.001") +#define ENABLE_ALARM_ID ((const char *)"200.004") +#define MGMNT_HB_ALARM_ID ((const char *)"200.005") +#define PMOND_ALARM_ID ((const char *)"200.006") +#define SENSOR_ALARM_ID ((const char *)"200.007") /* Sensor read alarm ; i.e. the sensor read value bad */ +#define INFRA_HB_ALARM_ID ((const char *)"200.009") +#define BM_ALARM_ID ((const char *)"200.010") +#define CONFIG_ALARM_ID ((const char *)"200.011") +#define CH_CONT_ALARM_ID ((const char *)"200.012") /* Combo Host Controller Failure - with Active Compute */ +#define CH_COMP_ALARM_ID ((const char *)"200.013") /* Combo Host Compute Failure - on last Controller */ +#define SENSORCFG_ALARM_ID ((const char *)"200.014") /* Sensor configuration alarm ; i.e. could not add */ +#define SENSORGROUP_ALARM_ID ((const char *)"200.015") /* Sensor Group Read Error */ + +#define EVENT_LOG_ID ((const char *)"200.020") +#define COMMAND_LOG_ID ((const char *)"200.021") +#define STATECHANGE_LOG_ID ((const char *)"200.022") +#define SERVICESTATUS_LOG_ID ((const char *)"200.023") /* log used to report service failure events against */ + + +/** Heartbeat Alarm Abstract Reference IDs */ +typedef enum +{ + HBS_ALARM_ID__HB_MGMNT = 0, + HBS_ALARM_ID__HB_INFRA = 1, + HBS_ALARM_ID__PMOND = 2, + HBS_ALARM_ID__SERVICE = 3, + HBS_ALARM_ID__LAST = 4, +} alarm_id_enum ; + +string alarmUtil_getId_str ( alarm_id_enum alarm_id_num ); +int alarmUtil_getId_enum ( string alarm_id_str, alarm_id_enum & alarm_id_num ); + +/** Converts FM severity to representative string */ +string alarmUtil_getSev_str ( EFmAlarmSeverityT severity ); +EFmAlarmSeverityT alarmUtil_getSev_enum ( string severity ); + +#ifndef __MODULE_PRIVATE__ + +int alarm_register_user ( msgClassSock * sock_ptr ); + +/* Public API */ +int alarm_ ( string hostname, const char * id, EFmAlarmStateT state, EFmAlarmSeverityT severity, const char * entity, string prefix ); +int alarm_clear ( string hostname, const char * id_ptr, string entity ); +int alarm_warning ( string hostname, const char * id_ptr, string entity ); +int alarm_minor ( string hostname, const char * id_ptr, string entity ); +int alarm_major ( string hostname, const char * id_ptr, string entity ); +int alarm_critical ( string hostname, const char * id_ptr, string entity ); +int alarm_critical_log ( string hostname, const char * id_ptr, string entity ); +int alarm_major_log ( string hostname, const char * id_ptr, string entity ); +int alarm_minor_log ( string hostname, const char * id_ptr, string entity ); +int alarm_warning_log ( string hostname, const char * id_ptr, string entity, string prefix ); +int alarm_log ( string hostname, const char * id_ptr, string entity ); + +#else + + +typedef struct +{ + SFmAlarmDataT alarm ; + string name ; + string instc_prefix ; /* Instance prefix i.e. "=sensor." or "=process." */ + string critl_reason ; + string minor_reason ; + string major_reason ; + string clear_reason ; +} alarmUtil_type ; + + +#define MAX_FAILED_B2B_RECEIVES_B4_RESTART (5) + + +/* Test Commandss + * +STR="{\"mtcalarm\":[{\"alarmid\":\"200.009\",\"hostname\":\"compute-3\",\"operation\":\"clear\",\"severity\":\"clear\",\"entity\":\"Infrastructure\",\"prefix\":\"service=heartbeat\"}, {\"alarmid\":\"200.005\",\"hostname\":\"compute-3\",\"operation\":\"set\",\"severity\":\"major\",\"entity\":\"Management\",\"prefix\":\"service=heartbeat\"}]}" +PROTOCOL="UDP4-DATAGRAM" +ADDRESS="127.0.0.1" +port="2122" +echo "${STR}" | socat - ${PROTOCOL}:${ADDRESS}:${port} +*/ + +#define MTCALARM_REQ_LABEL ((const char *)"mtcalarm") + +#define MTCALARM_REQ_KEY__OPERATION ((const char *)"operation") +#define MTCALARM_REQ_KEY__HOSTNAME ((const char *)"hostname") +#define MTCALARM_REQ_KEY__ALARMID ((const char *)"alarmid") +#define MTCALARM_REQ_KEY__SEVERITY ((const char *)"severity") +#define MTCALARM_REQ_KEY__ENTITY ((const char *)"entity") +#define MTCALARM_REQ_KEY__PREFIX ((const char *)"prefix") + +/* in alarmData.cpp */ +void alarmData_init ( void ); +alarmUtil_type * alarmData_getAlarm_ptr ( string alarm_id_str ); + +/* in alarmUtil.cpp */ +// EFmAlarmSeverityT mtcAlarm_state ( string hostname, alarm_id_enum id ); + + +/* in alarmHdlr.cpp */ +int alarmHdlr_request_handler ( char * msg_ptr ); + +/* in alarmMgr.cpp */ +int alarmMgr_manage_alarm ( string alarmid , + string hostname, + string operation, + string severity, + string entity, + string prefix); + +/* Clear all alarms against this host */ +void alarmUtil_clear_all ( string hostname ); + +/** + * Query the specified alarm severity level. + * Severity levels are specified in fmAPI.h + **/ +EFmAlarmSeverityT alarmUtil_query ( string hostname, + string identity, + string instance ); + +int alarmUtil_query_identity ( string identity, + SFmAlarmDataT * alarm_list_ptr, + unsigned int alarms_max ); + +int alarmUtil_clear ( string hostname, string alarm_id, string entity ); +int alarmUtil_critical ( string hostname, string alarm_id, string entity ); +int alarmUtil_major ( string hostname, string alarm_id, string entity ); +int alarmUtil_minor ( string hostname, string alarm_id, string entity ); +int alarmUtil_warning ( string hostname, string alarm_id, string entity ); +int alarmUtil_critical_log ( string hostname, string alarm_id, string entity ); +int alarmUtil_major_log ( string hostname, string alarm_id, string entity ); +int alarmUtil_minor_log ( string hostname, string alarm_id, string entity ); +int alarmUtil_warning_log ( string hostname, string alarm_id, string entity, string prefix ); + +#endif // _MODULE_PRIVATE_ +#endif // __INCLUDE_ALARM_H__ diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarmData.cpp b/mtce-common/cgts-mtce-common-1.0/alarm/alarmData.cpp new file mode 100644 index 00000000..b9c12851 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarmData.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2016-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud Maintenance Alarm Daemon Utility + **/ + +#include +#include +#include +#include +#include + +using namespace std; + +#ifdef __AREA__ +#undef __AREA__ +#endif +#define __AREA__ "alm" + +#define __MODULE_PRIVATE__ + +#include "daemon_common.h" /* */ +#include "alarm.h" /* for ... this module header */ + +/* TODO: Replace this with YAML Parsing */ +static alarmUtil_type alarm_list[HBS_ALARM_ID__LAST] ; + +alarmUtil_type * alarmData_getAlarm_ptr ( string alarm_id_str ) +{ + alarm_id_enum id = HBS_ALARM_ID__LAST ; + if ( alarmUtil_getId_enum ( alarm_id_str, id ) == PASS ) + { + if ( id < HBS_ALARM_ID__LAST ) + { + return (&alarm_list[id]) ; + } + } + wlog ("failed to find alarm data for '%s'\n", alarm_id_str.c_str() ); + return (NULL); +} + +typedef struct +{ + const char * identity_str ; + alarm_id_enum identity_num ; +} alarm_id_table_type ; + +alarm_id_table_type alarm_id_table[HBS_ALARM_ID__LAST]; + + +void alarmData_init ( void ) +{ + alarmUtil_type * ptr ; + + alarm_id_table[HBS_ALARM_ID__HB_MGMNT].identity_str = MGMNT_HB_ALARM_ID ; + alarm_id_table[HBS_ALARM_ID__HB_MGMNT].identity_num = HBS_ALARM_ID__HB_MGMNT ; + alarm_id_table[HBS_ALARM_ID__HB_INFRA].identity_str = INFRA_HB_ALARM_ID; + alarm_id_table[HBS_ALARM_ID__HB_INFRA].identity_num = HBS_ALARM_ID__HB_INFRA; + alarm_id_table[HBS_ALARM_ID__PMOND].identity_str = PMOND_ALARM_ID; + alarm_id_table[HBS_ALARM_ID__PMOND].identity_num = HBS_ALARM_ID__PMOND; + alarm_id_table[HBS_ALARM_ID__SERVICE].identity_str = SERVICESTATUS_LOG_ID; + alarm_id_table[HBS_ALARM_ID__SERVICE].identity_num = HBS_ALARM_ID__SERVICE; + + /** Management Network Heartbeat Alarm ************************************/ + + ptr = &alarm_list[HBS_ALARM_ID__HB_MGMNT]; + memset (&ptr->alarm, 0, (sizeof(SFmAlarmDataT))); + snprintf(&ptr->alarm.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", MGMNT_HB_ALARM_ID); + + ptr->name = "Management Network' Heartbeat" ; + ptr->instc_prefix = "network=" ; + + ptr->critl_reason = "experienced a persistent critical 'Management Network' " + "communication failure."; + ptr->major_reason = + ptr->minor_reason = "is experiencing intermittent 'Management Network' " + "communication failures that have exceeded its lower alarming threshold."; + + ptr->clear_reason = "'Management Network' Heartbeat has 'resumed' if host is 'unlocked' " + "or 'stopped' if host is 'locked or deleted'"; + + ptr->alarm.alarm_type = FM_ALARM_COMM ; + ptr->alarm.probable_cause = FM_ALARM_LOSS_OF_SIGNAL ; + ptr->alarm.inhibit_alarms = FM_FALSE; + ptr->alarm.service_affecting = FM_TRUE ; + ptr->alarm.suppression = FM_TRUE ; + + ptr->alarm.severity = FM_ALARM_SEVERITY_CLEAR ; /* Dynamic */ + ptr->alarm.alarm_state = FM_ALARM_STATE_CLEAR ; /* Dynamic */ + + snprintf( ptr->alarm.proposed_repair_action, FM_MAX_BUFFER_LENGTH, + "Check 'Management Network' connectivity and support for multicast messaging." + "If problem consistently occurs after that and Host is reset, then" + "contact next level of support or lock and replace failing Host."); + + /** Infrastructure Network Heartbeat Alarm ************************************/ + + ptr = &alarm_list[HBS_ALARM_ID__HB_INFRA]; + memset (&ptr->alarm, 0, (sizeof(SFmAlarmDataT))); + snprintf(&ptr->alarm.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", INFRA_HB_ALARM_ID); + + ptr->name = "Infrastructure Network' Heartbeat" ; + ptr->instc_prefix = "network=" ; + + ptr->critl_reason = "experienced a persistent critical 'Infrastructure Network' " + "communication failure."; + + ptr->major_reason = + ptr->minor_reason = "is experiencing intermittent 'Infrastructure Network' " + "communication failures that have exceeded its lower alarming threshold."; + + ptr->clear_reason = "'Infrastructure Network' Heartbeat has 'resumed' if host is 'unlocked' " + "or 'stopped' if host is 'locked or deleted'"; + + ptr->alarm.alarm_type = FM_ALARM_COMM ; + ptr->alarm.probable_cause = FM_ALARM_LOSS_OF_SIGNAL ; + ptr->alarm.inhibit_alarms = FM_FALSE; + ptr->alarm.service_affecting = FM_TRUE ; + ptr->alarm.suppression = FM_TRUE ; + + ptr->alarm.severity = FM_ALARM_SEVERITY_CLEAR ; /* Dynamic */ + ptr->alarm.alarm_state = FM_ALARM_STATE_CLEAR ; /* Dynamic */ + + snprintf( ptr->alarm.proposed_repair_action, FM_MAX_BUFFER_LENGTH, + "Check 'Infrastructure Network' connectivity and support for multicast messaging." + "If problem consistently occurs after that and Host is reset, then" + "contact next level of support or lock and replace failing Host."); + + /** Process Failure Alarm ****************************************************/ + + ptr = &alarm_list[HBS_ALARM_ID__PMOND]; + memset (&ptr->alarm, 0, (sizeof(SFmAlarmDataT))); + snprintf(&ptr->alarm.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", PMOND_ALARM_ID); + + ptr->name = "Process Monitor Failure" ; + ptr->instc_prefix = "process=" ; + + ptr->critl_reason = + ptr->minor_reason = + ptr->major_reason = "'Process Monitor' (pmond) process is not running or functioning properly. " + "The system is trying to recover this process." ; + ptr->clear_reason = "Process Monitor has been successfully recovered and is functioning properly."; + + ptr->alarm.alarm_type = FM_ALARM_OPERATIONAL ; + ptr->alarm.probable_cause = FM_ALARM_CAUSE_UNKNOWN; + ptr->alarm.inhibit_alarms = FM_FALSE; + ptr->alarm.service_affecting = FM_FALSE; + ptr->alarm.suppression = FM_TRUE ; + + ptr->alarm.severity = FM_ALARM_SEVERITY_CLEAR ; /* Dynamic */ + ptr->alarm.alarm_state = FM_ALARM_STATE_CLEAR ; /* Dynamic */ + + snprintf (ptr->alarm.proposed_repair_action, FM_MAX_BUFFER_LENGTH, + "If this alarm does not automatically clear after some time and " + "continues to be asserted after Host is locked and unlocked then " + "contact next level of support for root cause analysis and recovery."); + + /** Service Status Log ****************************************************/ + + ptr = &alarm_list[HBS_ALARM_ID__SERVICE]; + memset (&ptr->alarm, 0, (sizeof(SFmAlarmDataT))); + snprintf(&ptr->alarm.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", SERVICESTATUS_LOG_ID); + + ptr->name = "Service Status" ; + + ptr->minor_reason = + ptr->major_reason = + ptr->critl_reason = + ptr->clear_reason = ""; + + ptr->alarm.alarm_type = FM_ALARM_TYPE_UNKNOWN ; + ptr->alarm.probable_cause = FM_ALARM_CAUSE_UNKNOWN ; + ptr->alarm.inhibit_alarms = FM_FALSE ; + ptr->alarm.service_affecting = FM_FALSE ; + ptr->alarm.suppression = FM_FALSE ; + + ptr->alarm.severity = FM_ALARM_SEVERITY_CLEAR ; /* Dynamic */ + ptr->alarm.alarm_state = FM_ALARM_STATE_MSG ; /* Dynamic */ + + snprintf ( ptr->alarm.proposed_repair_action, FM_MAX_BUFFER_LENGTH, "%s", ""); +} + +/* Translate alarm identity enum to alarm identity string */ +string _getIdentity ( alarm_id_enum id ) +{ + if ( id < HBS_ALARM_ID__LAST ) + return ( alarm_id_table[id].identity_str) ; + return ("200.000"); +} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarmHdlr.cpp b/mtce-common/cgts-mtce-common-1.0/alarm/alarmHdlr.cpp new file mode 100644 index 00000000..8c2f7438 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarmHdlr.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2016-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud Maintenance Alarm Manager Daemon Handler + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for close and usleep */ +#include /* for ... json-c json string parsing */ + +using namespace std; + +#define __MODULE_PRIVATE__ + +#include "alarm.h" /* module header */ +#include "jsonUtil.h" /* for ... jsonUtil_ utiltiies */ +#include "nodeTimers.h" /* for ... maintenance timers */ +#include "daemon_common.h" /* for UNUSED() */ + +void daemon_sigchld_hdlr ( void ) { ; } + + +/** Daemon timer handler */ +void _timer_handler ( int sig, siginfo_t *si, void *uc) +{ + timer_t * tid_ptr = (void**)si->si_value.sival_ptr ; + UNUSED(sig); + UNUSED(uc); + if ( !(*tid_ptr) ) + { + return ; + } + else + { + mtcTimer_stop_tid_int_safe (tid_ptr); + } +} + +int alarmHdlr_request_handler ( char * msg_ptr ) +{ + int rc = FAIL_JSON_PARSE ; + struct json_object *raw_obj = json_tokener_parse( msg_ptr ); + jlog ("Alarm Request: %s\n", msg_ptr ); + if ( raw_obj ) + { + int elements ; + + /* Check response sanity */ + rc = jsonUtil_array_elements ( msg_ptr, MTCALARM_REQ_LABEL, elements ); + if ( elements ) + { + #define PARSE_FAILURE ((const char *)"failed to parse value for key") + string alarmid = "" ; + string hostname = "" ; + string operation = "" ; + string severity = "" ; + string entity = "" ; + string prefix = "" ; + string alarm_req = "" ; + + for ( int i = 0 ; i < elements ; i++ ) + { + if ( ( rc = jsonUtil_get_array_idx ( msg_ptr, MTCALARM_REQ_LABEL, i, alarm_req ) ) == PASS ) + { + if (( rc = jsonUtil_get_key_val ( (char*)alarm_req.data(), MTCALARM_REQ_KEY__ALARMID, alarmid )) != PASS ) + { + elog ("%s '%s'\n", PARSE_FAILURE, MTCALARM_REQ_KEY__ALARMID); + } + else if (( rc = jsonUtil_get_key_val ( (char*)alarm_req.data(), MTCALARM_REQ_KEY__HOSTNAME, hostname )) != PASS ) + { + elog ("%s '%s'\n", PARSE_FAILURE, MTCALARM_REQ_KEY__HOSTNAME); + } + else if (( rc = jsonUtil_get_key_val ( (char*)alarm_req.data(), MTCALARM_REQ_KEY__OPERATION, operation )) != PASS ) + { + elog ("%s '%s'\n", PARSE_FAILURE, MTCALARM_REQ_KEY__OPERATION); + } + else if (( rc = jsonUtil_get_key_val ( (char*)alarm_req.data(), MTCALARM_REQ_KEY__SEVERITY, severity)) != PASS ) + { + elog ("%s '%s'\n", PARSE_FAILURE, MTCALARM_REQ_KEY__SEVERITY); + } + else if (( rc = jsonUtil_get_key_val ( (char*)alarm_req.data(), MTCALARM_REQ_KEY__ENTITY, entity )) != PASS ) + { + elog ("%s '%s'\n", PARSE_FAILURE, MTCALARM_REQ_KEY__ENTITY); + } + else if (( rc = jsonUtil_get_key_val ( (char*)alarm_req.data(), MTCALARM_REQ_KEY__PREFIX, prefix)) != PASS ) + { + elog ("%s '%s'\n", PARSE_FAILURE, MTCALARM_REQ_KEY__PREFIX); + } + else + { + jlog ("Alarm Message has %d requests\n", elements ); + rc = alarmMgr_manage_alarm ( alarmid, + hostname, + tolowercase(operation), + tolowercase(severity), + entity, + prefix); + } + if ( rc ) break ; + } + else + { + wlog ("failed to get index '%d of %d' from alarm request", i, elements); + } + } /* for loop */ + } + else + { + elog ("failed to find '%s' label in json object\n", MTCALARM_REQ_LABEL ); + elog (" ... %s\n", msg_ptr ); + rc = FAIL_JSON_OBJECT ; + } + } + else + { + elog ("failed to parse json request\n"); + elog (" ... %s\n", msg_ptr ); + rc = FAIL_JSON_OBJECT ; + } + if (raw_obj) json_object_put(raw_obj); + return (rc); +} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarmInit.cpp b/mtce-common/cgts-mtce-common-1.0/alarm/alarmInit.cpp new file mode 100644 index 00000000..dcf29332 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarmInit.cpp @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2016-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud Maintenance Alarm Manager Daemon Initialization + */ + +#include +#include +#include +#include +#include +#include +#include +#include /* for close and usleep */ + +using namespace std; + +#define __MODULE_PRIVATE__ + +#include "daemon_ini.h" /* Ini Parser Header */ +#include "daemon_common.h" /* Common definitions and types for daemons */ +#include "daemon_option.h" /* Common options for daemons */ + +#include "alarm.h" /* module header */ +#include "msgClass.h" /* for ... socket message setup */ + +/** Local Identity */ +static string my_hostname = "" ; +static string my_local_ip = "" ; +static string my_float_ip = "" ; + + +/** Maintenance Alarm request socket and port - UDP over lo */ +msgClassSock * mtcalarm_req_sock_ptr = NULL ; +int mtcalarm_req_port = 0 ; + + +/** Common Daemon Config Struct */ +static daemon_config_type _config ; +daemon_config_type * daemon_get_cfg_ptr () { return &_config ; } + + +/* Cleanup exit handler */ +void daemon_exit ( void ) +{ + daemon_dump_info (); + daemon_files_fini (); + + /* Close sockets */ + if ( mtcalarm_req_sock_ptr ) + { + delete (mtcalarm_req_sock_ptr ); + mtcalarm_req_sock_ptr = NULL ; + mtcalarm_req_port = 0 ; + } + exit (0); +} + + +/** Client Config mask */ +#define CONFIG_CLIENT_MASK (CONFIG_CLIENT_PULSE_PORT) + +/* Startup config read */ +static int _config_handler ( void * user, + const char * section, + const char * name, + const char * value) +{ + daemon_config_type* config_ptr = (daemon_config_type*)user; + + if (MATCH("client", "mtcalarm_req_port")) + { + config_ptr->mtcalarm_req_port = atoi(value); + config_ptr->mask |= CONFIG_CLIENT_PULSE_PORT ; + } + else + { + return (PASS); + } + return (FAIL); +} + +/* Configure the daemon */ +int daemon_configure ( void ) +{ + int rc = FAIL ; + + if (ini_parse(MTCE_CONF_FILE, _config_handler, &_config) < 0) + { + elog("Failed to load '%s'\n", MTCE_CONF_FILE ); + return(FAIL_LOAD_INI); + } + + get_debug_options ( MTCE_CONF_FILE, &_config ); + + /* Verify loaded config against an expected mask + * as an ini file fault detection method */ + if ( _config.mask != CONFIG_CLIENT_MASK ) + { + elog ("Client configuration failed (%x)\n", + (( -1 ^ _config.mask ) & CONFIG_CLIENT_MASK) ); + rc = FAIL_INI_CONFIG ; + } + else + { + ilog("Alarm Port : %d\n", _config.mtcalarm_req_port ); + rc = PASS ; + } + + return (rc); +} + +/****************************/ +/* Initialization Utilities */ +/****************************/ + +int daemon_socket_init ( void ) +{ + int rc = PASS ; + + /***********************************************************/ + /* Setup the Alarm Request Receiver Socket */ + /***********************************************************/ + + mtcalarm_req_sock_ptr = new msgClassRx ( LOOPBACK_IP, _config.mtcalarm_req_port, IPPROTO_UDP); + if (rc) + return (rc) ; + if (mtcalarm_req_sock_ptr) + mtcalarm_req_sock_ptr->sock_ok(true); + + return (rc); +} + + +/* The main heartbeat service loop */ +int daemon_init ( string iface, string nodeType_str ) +{ + int rc = PASS ; + UNUSED(nodeType_str); + + /* Assign interface to config */ + _config.mgmnt_iface = (char*)iface.data() ; + + if ((rc = daemon_files_init ()) != PASS) + { + elog ("daemon_files_init failed (rc:%d)\n", rc ); + return ( FAIL_FILES_INIT ); + } + + /* Bind signal handlers */ + if ((rc = daemon_signal_init ()) != PASS) + { + elog ("daemon_signal_init failed (rc:%d)\n", rc ); + return ( FAIL_SIGNAL_INIT ); + } + + /************************************************************************ + * There is no point continuing with init ; i.e. running daemon_configure, + * initializing sockets and trying to query for an ip address until the + * daemon's configuration requirements are met. Here we wait for those + * flag files to be present before continuing. + ************************************************************************ + * Wait for /etc/platform/.initial_config_complete & /var/run/.goenabled */ + daemon_wait_for_file ( CONFIG_COMPLETE_FILE , 0); + daemon_wait_for_file ( GOENABLED_MAIN_READY , 0); + + /* Configure the client */ + if ((rc = daemon_configure ()) != PASS) + { + elog ("daemon_configure failed (rc:%d)\n", rc ); + rc = FAIL_DAEMON_CONFIG ; + } + + /* Setup messaging sockets */ + else if ((rc = daemon_socket_init ()) != PASS) + { + elog ("daemon_socket_init failed (rc:%d)\n", rc ); + rc = FAIL_SOCKET_INIT; + } + + alarmData_init (); + + return (rc); +} + +void daemon_service_run ( void ) +{ + int rc = PASS ; + if (( mtcalarm_req_sock_ptr ) && ( mtcalarm_req_sock_ptr->getFD() )) + { + std::list socks ; + + /* For select dispatch */ + struct timeval waitd ; + fd_set readfds; + + int failed_receiver_log_throttle = 0 ; + int failed_receiver_b2b_count = 0 ; + int failed_socket_log_throttle = 0 ; + + socks.clear(); + socks.push_front (mtcalarm_req_sock_ptr->getFD()); + socks.sort(); + + /* Run service forever */ + for ( ; ; ) + { + daemon_signal_hdlr (); + waitd.tv_sec = 0; + waitd.tv_usec = SOCKET_WAIT; + + /* Initialize the master fd_set */ + FD_ZERO(&readfds); + FD_SET( mtcalarm_req_sock_ptr->getFD(), &readfds); + rc = select( socks.back()+1, &readfds, NULL, NULL, &waitd); + if (( rc < 0 ) || ( rc == 0 )) + { + if (( rc < 0 ) && ( errno != EINTR )) + { + wlog_throttled ( failed_socket_log_throttle, 100, + "Socket Select Failed (%d:%m)\n", errno); + } + } + + if ( FD_ISSET(mtcalarm_req_sock_ptr->getFD(), &readfds)) + { + failed_socket_log_throttle = 0 ; + if ( mtcalarm_req_sock_ptr && ( mtcalarm_req_sock_ptr->sock_ok() == true )) + { + char msg [MAX_ALARM_REQ_SIZE] ; + memset ( &msg , 0, MAX_ALARM_REQ_MSG_SIZE ); + int bytes = mtcalarm_req_sock_ptr->read((char*)&msg, MAX_ALARM_REQ_SIZE-1 ); + if ( bytes > 0 ) + { + failed_receiver_b2b_count = 0 ; + failed_receiver_log_throttle = 0 ; + if ( ( rc = alarmHdlr_request_handler ( msg )) != PASS ) + { + wlog ("failed to handle alarm request (rc:%d)\n", rc ); + } + } + else if ( bytes < 0 ) + { + failed_receiver_b2b_count++ ; + wlog_throttled ( failed_receiver_log_throttle, 20, "alarm request receive error ; thresholeded ; (%d:%m)\n", errno ); + } + else + { + failed_receiver_b2b_count++ ; + wlog_throttled ( failed_receiver_log_throttle, 20, "alarm request receive ; no data\n" ); + } + } + else + { + elog ("alarm request socket error ; fatal\n"); + failed_receiver_b2b_count = MAX_FAILED_B2B_RECEIVES_B4_RESTART ; + } + + if ( failed_receiver_b2b_count >= MAX_FAILED_B2B_RECEIVES_B4_RESTART ) + { + /* exit and allow process restart by pmond */ + elog ("max (%d) alarm request receive errors reached ; forcing process restart\n", MAX_FAILED_B2B_RECEIVES_B4_RESTART ); + break ; + } + } + } + } + else + { + elog ("alarm request socket error ; not initialized ; exiting\n"); + } + daemon_exit(); +} + +/* Push daemon state to log file */ +void daemon_dump_info ( void ) +{ + daemon_dump_membuf_banner (); + daemon_dump_membuf(); +} + +const char MY_DATA [100] = { "eieio\n" } ; +const char * daemon_stream_info ( void ) +{ + return (&MY_DATA[0]); +} + +/*************************************************************************** + * * + * Module Test Head * + * * + ***************************************************************************/ + +/** Teat Head Entry */ +int daemon_run_testhead ( void ) +{ + int rc = PASS; + return (rc); +} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarmMgr.cpp b/mtce-common/cgts-mtce-common-1.0/alarm/alarmMgr.cpp new file mode 100644 index 00000000..817e20b1 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarmMgr.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud Maintenance Alarm Manager Daemon Manager + */ + +#include +#include +#include +#include + +using namespace std; + +#define __MODULE_PRIVATE__ + +#include "alarm.h" /* module header */ + +int alarmMgr_manage_alarm ( string alarmid, + string hostname, + string operation, + string severity, + string entity, + string prefix) +{ + int rc = PASS ; + string action = operation ; + action.append (" alarm"); + EFmAlarmSeverityT sev ; + + ilog ("Alarm: alarmid:%s hostname:%s operation:%s severity:%s entity:%s prefix:%s\n", + alarmid.c_str(), + hostname.c_str(), + operation.c_str(), + severity.c_str(), + entity.c_str(), + prefix.c_str()); + + sev = alarmUtil_getSev_enum ( severity ); + if (!operation.compare("msg")) + { + if ( sev == FM_ALARM_SEVERITY_WARNING ) + { + //if ( prefix.compare("none")) + alarmUtil_warning_log ( hostname, alarmid, entity, prefix ); + //else + // mtcAlarm_warning_log ( hostname, id, entity ); + } + else if ( sev == FM_ALARM_SEVERITY_MINOR ) + { + rc = alarmUtil_minor_log ( hostname, alarmid, entity ); + } + else if ( sev == FM_ALARM_SEVERITY_MAJOR) + { + rc = alarmUtil_major_log ( hostname, alarmid, entity ); + } + else if ( sev == FM_ALARM_SEVERITY_CRITICAL ) + { + rc = alarmUtil_critical_log ( hostname, alarmid, entity ); + } + else + { + rc = FAIL_INVALID_OPERATION ; + wlog ("Unsupported log severity '%d:%s'\n", sev, severity.c_str()); + } + action="create log" ; + } + + /* Get the state */ + else if ( !operation.compare("clear")) + { + rc = alarmUtil_clear ( hostname, alarmid, entity ); + } + + else if ( !operation.compare("set") ) + { + if ( sev == FM_ALARM_SEVERITY_WARNING ) + rc = alarmUtil_warning ( hostname, alarmid, entity ); + else if ( sev == FM_ALARM_SEVERITY_MINOR ) + rc = alarmUtil_minor ( hostname, alarmid, entity ); + else if ( sev == FM_ALARM_SEVERITY_MAJOR ) + rc = alarmUtil_major ( hostname, alarmid, entity ); + else if ( sev == FM_ALARM_SEVERITY_CRITICAL ) + rc = alarmUtil_critical ( hostname, alarmid, entity ); + else + { + rc = FAIL_INVALID_OPERATION ; + } + } + else + { + rc = FAIL_BAD_CASE ; + } + if ( rc ) + { + elog ("%s failed to %s '%s:%s'\n", hostname.c_str(), action.c_str(), alarmid.c_str(), entity.c_str() ) + } + + return (rc); +} + diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/alarmUtil.cpp b/mtce-common/cgts-mtce-common-1.0/alarm/alarmUtil.cpp new file mode 100644 index 00000000..11eb882e --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/alarmUtil.cpp @@ -0,0 +1,500 @@ +/* + * Copyright (c) 2013 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGCS Platform common Alarm utilities + */ + +#define __MODULE_PRIVATE__ + +#include "daemon_common.h" /* for ... daemon_is_file_present */ + +#include "nodeBase.h" +#include "nodeUtil.h" /* for ... get_mtclogd_sockPtr */ +#include "alarm.h" /* for ... alarm Utilities */ + + +string alarmUtil_getSev_str ( EFmAlarmSeverityT sev ) +{ + switch ( sev ) + { + case FM_ALARM_SEVERITY_CLEAR: return ("clear"); + case FM_ALARM_SEVERITY_WARNING: return ("warning"); + case FM_ALARM_SEVERITY_MINOR: return ("minor"); + case FM_ALARM_SEVERITY_MAJOR: return ("major"); + case FM_ALARM_SEVERITY_CRITICAL:return ("critical"); + default : return ("unknown"); + } +} + +EFmAlarmSeverityT alarmUtil_getSev_enum ( string sev ) +{ + if ( !sev.compare("clear")) return (FM_ALARM_SEVERITY_CLEAR) ; + if ( !sev.compare("warning")) return (FM_ALARM_SEVERITY_WARNING); + if ( !sev.compare("minor")) return (FM_ALARM_SEVERITY_MINOR); + if ( !sev.compare("major")) return (FM_ALARM_SEVERITY_MAJOR); + if ( !sev.compare("critical")) return (FM_ALARM_SEVERITY_CRITICAL); + wlog ("Unsupported severity '%s'\n", sev.c_str() ); + return (FM_ALARM_SEVERITY_CLEAR) ; +} + +int alarmUtil_getId_enum ( string alarmid, alarm_id_enum & id ) +{ + /* Get the ID */ + if ( alarmid.compare(INFRA_HB_ALARM_ID) == 0 ) + { + id = HBS_ALARM_ID__HB_INFRA ; + } + else if ( alarmid.compare(MGMNT_HB_ALARM_ID) == 0 ) + { + id = HBS_ALARM_ID__HB_MGMNT ; + } + else if ( alarmid.compare(PMOND_ALARM_ID) == 0 ) + { + id = HBS_ALARM_ID__PMOND ; + } + else if ( alarmid.compare(SERVICESTATUS_LOG_ID) == 0 ) + { + id = HBS_ALARM_ID__SERVICE ; + } + else + { + wlog ("Unsupported alarm id '%s'\n", alarmid.c_str()); + return (FAIL_BAD_PARM); + } + return (PASS); +} + +/* update the passed in alarm struct's instance_id entity path for the specified host */ +void _build_entity_path ( string & hostname, string & instance, SFmAlarmDataT & alarm ) +{ + snprintf ( &alarm.entity_type_id[0], FM_MAX_BUFFER_LENGTH, "system.host" ); + + if ( instance.empty() ) + { + snprintf ( &alarm.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s", + ENTITY_PREFIX, hostname.data()); + } + else + { + snprintf ( &alarm.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s.%s", + ENTITY_PREFIX, hostname.data(), instance.data()); + } +} + +void alarmUtil_clear_all ( string hostname ) +{ + SFmAlarmDataT alarm ; + string instance = "" ; + + _build_entity_path ( hostname, instance, alarm ); + + /* This will clear all the alarms for this host ; + * even ones that are raised against this host by other daemons */ + fm_clear_all ( &alarm.entity_instance_id ); +} + +/****************************************************************************** + * + * Name : alarmUtil_query + * + * Description: Utility will query a specific alarm for its current severity + * + * @param : identity may be 200.xxx + * + * @param : instance may be + * + * host= + * + * example: + * + * hostname=compute-1 + * + * host=.= + * + * example: + * + * hostname=compute-1.process=mtcClient + * + * hostname=compute-1.sensor=Fan_PSU2 + * + * Updates : None + * + * Returns : FM severity code for the specified alarm. + * FM_ALARM_SEVERITY_CLEAR if it not set. + * + ******************************************************************************/ +EFmAlarmSeverityT alarmUtil_query ( string hostname, + string identity, + string instance ) +{ + SFmAlarmDataT alarm_query ; + AlarmFilter alarm_filter ; + EFmErrorT rc ; + + memset(&alarm_query, 0, sizeof(alarm_query)); + memset(&alarm_filter, 0, sizeof(alarm_filter)); + + snprintf ( &alarm_filter.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", identity.data()); + + if ( instance.empty() ) + { + snprintf ( &alarm_filter.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s", + ENTITY_PREFIX, hostname.data()); + } + else + { + snprintf ( &alarm_filter.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s.%s", + ENTITY_PREFIX, hostname.data(), instance.data()); + } + + alog ("entity_instance:%s\n", alarm_filter.entity_instance_id ); + if (( rc = fm_get_fault ( &alarm_filter, &alarm_query )) == FM_ERR_OK ) + { + dlog ("Found with Severity: %d\n", alarm_query.severity ); + return (alarm_query.severity) ; + } + else if ( rc != FM_ERR_ENTITY_NOT_FOUND ) + { + elog ("%s fm_get_fault returned error (%d)\n", hostname.c_str(), rc ); + } + return (FM_ALARM_SEVERITY_CLEAR); +} + +int alarmUtil_query_identity ( string identity, SFmAlarmDataT * alarm_list_ptr, unsigned int max_alarms ) +{ + int rc = 0 ; + + if ( max_alarms == 0 ) + { + slog ("max alarms is zero !\n"); + } + else if ( identity.empty() ) + { + slog ("empty alarm 'identity'\n"); + } + else if ( alarm_list_ptr ) + { + AlarmFilter alarm_filter ; + + memset(&alarm_filter, 0, sizeof(alarm_filter)); + snprintf ( alarm_filter.alarm_id, FM_MAX_BUFFER_LENGTH, "%s", identity.data()); + rc = fm_get_faults_by_id ( &alarm_filter.alarm_id, alarm_list_ptr, &max_alarms ); + alog ("%s fm_get_faults_by_id rc = %d\n", alarm_filter.alarm_id, rc ); + if ( rc == FM_ERR_OK ) + { + return (PASS); + } + else if ( rc == FM_ERR_ENTITY_NOT_FOUND ) + { + return (RETRY); + } + else + { + return (FAIL); + } + } + else + { + slog ("caller supplied null alarm_list_ptr\n"); + } + return (FAIL_NULL_POINTER); +} + + +/********************************************************************************* + * + * Name : alarmUtil + * + * Purpose : Primary module API used to set/clear severity alarms and logs in FM. + * + * Description : Other maintenance services are expected to use ths interface to + * + * + ********************************************************************************/ +int alarmUtil ( string & hostname, + string & identity, + string & instance, + SFmAlarmDataT & alarm ) +{ + int rc = PASS ; + + // msgSock_type * mtclogd_ptr = get_mtclogd_sockPtr() ; + + /* Don't report events while we are in reset mode */ + if ( daemon_is_file_present ( NODE_RESET_FILE ) ) + { + return (rc); + } + + _build_entity_path ( hostname, instance, alarm ); + +#ifdef WANT_ALARM_QUERY + + /* See if the alarm is already in the requested state */ + EFmAlarmSeverityT curr_sev = alarmUtil_query ( hostname, identity, instance ) ; + + /* If its not a log message and we are already at this + * severity level then ignore the call */ + if (( alarm.alarm_state != FM_ALARM_STATE_MSG ) && + ( curr_sev == alarm.severity )) + { + ilog ("%s %s %s already at desired (%s) severity level\n", + hostname.c_str(), + identity.c_str(), + instance.c_str(), + alarmUtil_getSev_str(alarm.severity).c_str()); + return (rc); + } +#endif + + snprintf(&alarm.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", identity.data()); + + if (( alarm.alarm_state == FM_ALARM_STATE_SET ) || + ( alarm.alarm_state == FM_ALARM_STATE_MSG )) + { + if ( alarm.alarm_state == FM_ALARM_STATE_SET ) + { + alog ("%s setting %s %s alarm\n", hostname.c_str(), alarm.alarm_id, alarm.entity_instance_id ); + } + else + { + alog ("%s creating %s %s log\n", hostname.c_str(), alarm.alarm_id, alarm.entity_instance_id ); + } + + /* Debug Logs */ + alog ("%s Alarm Reason: %s\n", hostname.c_str(), alarm.reason_text ); + alog ("%s Alarm Action: %s\n", hostname.c_str(), alarm.proposed_repair_action ); + alog ("%s Alarm Ident : %s : %s\n", hostname.c_str(), alarm.entity_type_id, alarm.entity_instance_id ); + alog ("%s Alarm State : state:%d sev:%d type:%d cause:%d sa:%c supp:%c\n", + hostname.c_str(), + alarm.alarm_state, + alarm.severity, + alarm.alarm_type, + alarm.probable_cause, + alarm.service_affecting ? 'Y' : 'N', + alarm.suppression ? 'Y' : 'N' ); + + ilog ( "fm_set_fault: %s %s state:%d sev:%d type:%d cause:%d sa:%c supp:%c", + hostname.c_str(), + alarm.alarm_id, + alarm.alarm_state, + alarm.severity, + alarm.alarm_type, + alarm.probable_cause, + alarm.service_affecting ? 'Y' : 'N', + alarm.suppression ? 'Y' : 'N' ); + + rc = fm_set_fault ( &alarm , NULL ); + if ( rc != FM_ERR_OK ) + { + wlog ("%s fm_set_fault call failed for alarm %s (rc:%d) ; retrying\n", hostname.c_str(), alarm.alarm_id, rc); + usleep (100000); /* sleep 100 msec */ + rc = fm_set_fault ( &alarm , NULL ); + if ( rc != FM_ERR_OK ) + { + elog ("%s failed to set alarm %s (rc:%d) ; giving up\n", hostname.c_str(), alarm.alarm_id, rc); + rc = FAIL ; + } + } + } + else + { + AlarmFilter filter ; memset(&filter, 0, sizeof(filter)); + + /* Setup the alarm filter */ + snprintf(filter.alarm_id, FM_MAX_BUFFER_LENGTH, "%s", alarm.alarm_id); + snprintf(filter.entity_instance_id, FM_MAX_BUFFER_LENGTH, "%s", alarm.entity_instance_id); + + alog ( "fm_clear_fault: %s %s:%s", hostname.c_str(), alarm.entity_instance_id, alarm.alarm_id ); + + ilog ("%s clearing %s %s alarm\n", hostname.c_str(), alarm.alarm_id, alarm.entity_instance_id); + if ( ( rc = fm_clear_fault ( &filter )) != FM_ERR_OK ) + { + if ( rc != FM_ERR_ENTITY_NOT_FOUND ) + { + elog ("%s failed to fm_clear_fault (rc:%d)\n", hostname.c_str(), rc ); + rc = FAIL ; + } + else + { + rc = PASS ; + } + } + } + + return (rc); +} + +/* Clear the specified hosts's alarm */ +int alarmUtil_clear ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_CLEAR ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_CLEAR ; + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} + +/** Assert a specified hosts's alarm with a CRITICAL severity level */ +int alarmUtil_critical ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_CRITICAL ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_SET ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->critl_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} + + +/** Assert a specified host's alarm with a MAJOR severity level */ +int alarmUtil_major ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_MAJOR ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_SET ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->major_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} +/** Assert a specified host's alarm with a MINOR severity level */ +int alarmUtil_minor ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_MINOR ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_SET ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->minor_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} + +/** Assert a specified host's alarm with a WARNING severity level */ +int alarmUtil_warning ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_WARNING ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_SET ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->minor_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} + +/** Create CRITICAL log */ +int alarmUtil_critical_log ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_CRITICAL ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_MSG ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->critl_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} + + +/** Create MAJOR log */ +int alarmUtil_major_log ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_MAJOR ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_MSG ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->major_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} +/** Create MINOR log */ +int alarmUtil_minor_log ( string hostname, string alarm_id , string entity ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(entity); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_MINOR ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_MSG ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), alarm_ptr->minor_reason.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} + +/** Create WARNING log */ +int alarmUtil_warning_log ( string hostname, string alarm_id, string entity, string prefix ) +{ + alarmUtil_type * alarm_ptr = alarmData_getAlarm_ptr(alarm_id); + if ( alarm_ptr ) + { + string instance = alarm_ptr->instc_prefix ; + instance.append(prefix); + + alarm_ptr->alarm.severity = FM_ALARM_SEVERITY_WARNING ; + alarm_ptr->alarm.alarm_state = FM_ALARM_STATE_MSG ; + + snprintf ( alarm_ptr->alarm.reason_text, FM_MAX_BUFFER_LENGTH, "%s %s", hostname.data(), entity.data()); + + return ( alarmUtil ( hostname, alarm_id, instance, alarm_ptr->alarm )); + } + return (FAIL_NULL_POINTER); +} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.init b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.init new file mode 100644 index 00000000..4d33179e --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.init @@ -0,0 +1,108 @@ +#! /bin/sh +# +# Copyright (c) 2013-2014 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +# +# chkconfig: 2345 95 95 +# +### BEGIN INIT INFO +# Provides: mtcalarm +# Default-Start: 3 5 +# Default-Stop: 0 1 2 6 +# Short-Description: Maintenance Alarm Daemon +### END INIT INFO + +. /etc/init.d/functions + +DAEMON_NAME="mtcalarmd" +DAEMON="/usr/local/bin/${DAEMON_NAME}" +PIDFILE="/var/run/${DAEMON_NAME}.pid" +PLATFORM_CONF="/etc/platform/platform.conf" + +IFACE="" + +# Linux Standard Base (LSB) Error Codes +RETVAL=0 +GENERIC_ERROR=1 +INVALID_ARGS=2 +UNSUPPORTED_FEATURE=3 +NOT_INSTALLED=5 +NOT_RUNNING=7 + +PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin +export PATH + +if [ ! -e "${DAEMON}" ] ; then + logger "${DAEMON} is missing" + exit ${NOT_INSTALLED} +fi + +case "$1" in + start) + logger "Starting ${DAEMON_NAME}" + echo -n "Starting ${DAEMON_NAME}: " + if [ -n "`pidof ${DAEMON_NAME}`" ] ; then + echo -n "is already running " + RETVAL=0 + else + start-stop-daemon --start -b -x ${DAEMON} -- -l + RETVAL=$? + fi + if [ ${RETVAL} -eq 0 ] ; then + pid=`pidof ${DAEMON_NAME}` + echo "OK" + logger "${DAEMON} (${pid})" + else + echo "FAIL" + RETVAL=${GENERIC_ERROR} + fi + ;; + + stop) + logger "Stopping ${DAEMON_NAME}" + echo -n "Stopping ${DAEMON_NAME}: " + if [ -n "`pidof ${DAEMON_NAME}`" ] ; then + killproc ${DAEMON_NAME} + fi + if [ -n "`pidof ${DAEMON_NAME}`" ] ; then + echo "FAIL" + RETVAL=${NOT_RUNNING} + else + echo "OK" + fi + rm -f ${PIDFILE} + ;; + + restart) + $0 stop + $0 start + ;; + + status) + pid=`pidof ${DAEMON_NAME}` + RETVAL=$? + if [ ${RETVAL} -eq 0 ] ; then + echo "${DAEMON_NAME} is running" + else + echo "${DAEMON_NAME} is NOT running" + RETVAL=${NOT_RUNNING} + fi + ;; + + reload) + pkill -hup ${DAEMON_NAME} + ;; + + condrestart) + $0 restart + ;; + + *) + echo "usage: $0 { start | stop | status | restart | condrestart | reload | status }" + ;; +esac + +exit ${RETVAL} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.logrotate b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.logrotate new file mode 100644 index 00000000..c1b91aa2 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.logrotate @@ -0,0 +1,17 @@ +#daily +nodateext +start 1 +compress +copytruncate +notifempty +missingok + +/var/log/mtcalarmd.log +{ + size 10M + rotate 20 + sharedscripts + postrotate + systemctl reload syslog-ng > /dev/null 2>&1 || true + endscript +} diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.pmon.conf b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.pmon.conf new file mode 100644 index 00000000..8e132dce --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.pmon.conf @@ -0,0 +1,17 @@ +[process] +process = mtcalarmd +service = mtcalarm +pidfile = /var/run/mtcalarmd.pid +script = /etc/init.d/mtcalarmd +style = lsb ; ocf or lsb +severity = major ; minor, major, critical +restarts = 3 ; restart retries before error assertion +interval = 1 ; number of seconds to wait between restarts +debounce = 3 ; number of seconds that a process needs to remain + ; running before degrade is removed and retry count + ; is cleared. +startuptime = 1 ; Seconds to wait after process start before starting the debounce monitor +mode = passive ; Monitoring mode: passive (default) or active + ; passive: process death monitoring (default: always) + ; active : heartbeat monitoring, i.e. request / response messaging + ; ignore : do not monitor or stop monitoring diff --git a/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.service b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.service new file mode 100644 index 00000000..d97fa7b6 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/alarm/scripts/mtcalarm.service @@ -0,0 +1,14 @@ +[Unit] +Description=Titanium Cloud Maintenance Alarm Handler Client +After=network.target syslog.service config.service +Before=pmon.service + +[Service] +Type=forking +ExecStart=/etc/rc.d/init.d/mtcalarm start +ExecStop=/etc/rc.d/init.d/mtcalarm stop +ExecReload=/etc/rc.d/init.d/mtcalarm reload +PIDFile=/var/run/mtcalarmd.pid + +[Install] +WantedBy=multi-user.target diff --git a/mtce-common/cgts-mtce-common-1.0/common/Makefile b/mtce-common/cgts-mtce-common-1.0/common/Makefile new file mode 100755 index 00000000..f8d2962f --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/Makefile @@ -0,0 +1,91 @@ +# +# Copyright (c) 2013-2016 Wind River Systems, Inc. +# +# SPDX-License-Identifier: Apache-2.0 +# + +SRCS = regexUtil.cpp \ + timeUtil.cpp \ + ipmiUtil.cpp \ + pingUtil.cpp \ + keyClass.cpp \ + hostClass.cpp \ + nodeClass.cpp \ + nodeBase.cpp \ + nodeTimers.cpp \ + nodeUtil.cpp \ + hostUtil.cpp \ + nodeEvent.cpp \ + alarmUtil.cpp \ + nlEvent.cpp \ + jsonUtil.cpp \ + httpUtil.cpp \ + tokenUtil.cpp \ + msgClass.cpp + +COMMON_OBJS = regexUtil.o \ + timeUtil.o \ + pingUtil.o \ + keyClass.o \ + keyClass.cpp \ + hostClass.o \ + nodeClass.o \ + nodeBase.o \ + nodeTimers.o \ + nodeUtil.o \ + hostUtil.o \ + nodeEvent.o \ + alarmUtil.o \ + nlEvent.o \ + jsonUtil.o \ + httpUtil.o \ + tokenUtil.o \ + msgClass.o + +OBJS = $(SRCS:.cpp=.o) +LDLIBS += -lstdc++ -ldaemon -lcommon -lfmcommon -lrt -lpq -levent -ljson-c -lcrypto -luuid + +INCLUDES = -I../daemon -I../alarm -I../maintenance -I../heartbeat -I.. -I. +CCFLAGS = -g -O2 -Wall -Wextra -Werror -std=c++11 + +STATIC_ANALYSIS_TOOL = cppcheck +STATIC_ANALYSIS_TOOL_EXISTS = $(shell [[ -e `which $(STATIC_ANALYSIS_TOOL)` ]] && echo 1 || echo 0) + +ifeq (,$(shell which ${CC})) +CC=g++ +endif + +.cpp.o: + $(CXX) $(CCFLAGS) $(INCLUDES) $(EXTRACCFLAGS) -c $< -o $@ + +static_analysis: +ifeq ($(STATIC_ANALYSIS_TOOL_EXISTS), 1) + $(STATIC_ANALYSIS_TOOL) --language=c++ --enable=warning -U__AREA__ -UWANT_FIT_TESTING *.cpp *.h +else + echo "Warning: '$(STATIC_ANALYSIS_TOOL)' static analysis tool not installed ; bypassing ..." +endif + +lib: clean threadUtil static_analysis $(OBJS) library + +build: threadUtil static_analysis $(OBJS) library + +threadUtil: + $(CXX) -c threadUtil.cpp $(CCFLAGS) $(INCLUDES) $(EXTRACCFLAGS) $(LDLIBS) -lpthread -o threadUtil.o + ar rcs libthreadUtil.a threadUtil.o $(EXTRAARFLAGS) + +library: + ar rcs libcommon.a $(COMMON_OBJS) $(EXTRAARFLAGS) + ar rcs libipmiUtil.a ipmiUtil.o $(EXTRAARFLAGS) + ar rcs libpingUtil.a pingUtil.o $(EXTRAARFLAGS) + ar rcs libnodeBase.a nodeBase.o $(EXTRAARFLAGS) + ar rcs libregexUtil.a regexUtil.o $(EXTRAARFLAGS) + ar rcs libhostUtil.a hostUtil.o $(EXTRAARFLAGS) + +testhead: + $(CCFLAGS) $(INCLUDES) -L../daemon -L../common -L. $(LDLIBS) -lpingUtil -lnodeBase -lregexUtil -lhostUtil + +fsync: fsync.o + $(CC) fsync.o -L../daemon -L../common -L. -ldaemon -lcommon -o fsync + +clean: + @rm -f *.o *.a fsync *.o diff --git a/mtce-common/cgts-mtce-common-1.0/common/alarmUtil.cpp b/mtce-common/cgts-mtce-common-1.0/common/alarmUtil.cpp new file mode 100644 index 00000000..09b4eca1 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/alarmUtil.cpp @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGCS Platform common Alarm utilities + */ + +#include "daemon_common.h" /* for ... daemon_is_file_present */ + +#include "nodeBase.h" +#include "nodeUtil.h" /* for ... get_mtclogd_sockPtr */ +#include "alarmUtil.h" /* for ... alarmUtilClass and Utilities */ + + +alarmUtilClass __alarmObject ; + +/* module init */ +void alarmUtil_init ( void ) +{ + snprintf ( &__alarmObject.varlog_filename[0], MAX_FILENAME_LEN, "/var/log/%s_alarm.log", + program_invocation_short_name ); +} + +/********************** alarmUtilClass API Implementation ************************/ + +alarmUtilClass::alarmUtilClass() +{ + temp_str[0] = '\0'; + varlog_filename[0] = '\0'; + //ilog ("class constructor\n"); + alarmUtil_init (); +} + +alarmUtilClass::~alarmUtilClass() +{ + // ilog ("class destructor\n"); +} + +/***************************** Open API Implementation ***************************/ + +string alarmUtil_getSev_str ( EFmAlarmSeverityT sev ) +{ + switch ( sev ) + { + case FM_ALARM_SEVERITY_CLEAR: return ("clear"); + case FM_ALARM_SEVERITY_WARNING: return ("warning"); + case FM_ALARM_SEVERITY_MINOR: return ("minor"); + case FM_ALARM_SEVERITY_MAJOR: return ("major"); + case FM_ALARM_SEVERITY_CRITICAL:return ("critical"); + default : return ("unknown"); + } +} + +EFmAlarmSeverityT alarmUtil_getSev_enum ( string sev ) +{ + if ( !sev.compare("clear")) return (FM_ALARM_SEVERITY_CLEAR) ; + if ( !sev.compare("warning")) return (FM_ALARM_SEVERITY_WARNING); + if ( !sev.compare("minor")) return (FM_ALARM_SEVERITY_MINOR); + if ( !sev.compare("major")) return (FM_ALARM_SEVERITY_MAJOR); + if ( !sev.compare("critical")) return (FM_ALARM_SEVERITY_CRITICAL); + wlog ("Unsupported severity '%s'\n", sev.c_str() ); + return (FM_ALARM_SEVERITY_CLEAR) ; +} + + +/* update the passed in alarm struct's instance_id entity path for the specified host */ +void _build_entity_path ( string & hostname, string & instance, SFmAlarmDataT & alarm ) +{ + snprintf ( &alarm.entity_type_id[0], FM_MAX_BUFFER_LENGTH, "system.host" ); + + if ( instance.empty() ) + { + snprintf ( &alarm.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s", + ENTITY_PREFIX, hostname.data()); + } + else + { + snprintf ( &alarm.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s.%s", + ENTITY_PREFIX, hostname.data(), instance.data()); + } +} + +void alarmUtil_clear_all ( string hostname ) +{ + SFmAlarmDataT alarm ; + string instance = "" ; + + _build_entity_path ( hostname, instance, alarm ); + + /* This will clear all the alarms for this host ; + * even ones that are raised against this host by other daemons */ + fm_clear_all_async ( &alarm.entity_instance_id ); +} + +/****************************************************************************** + * + * Name : alarmUtil_query + * + * Description: Utility will query a specific alarm for its current severity + * + * @param : identity may be 200.xxx + * + * @param : instance may be + * + * host= + * + * example: + * + * hostname=compute-1 + * + * host=.= + * + * example: + * + * hostname=compute-1.process=mtcClient + * + * hostname=compute-1.sensor=Fan_PSU2 + * + * Updates : None + * + * Returns : FM severity code for the specified alarm. + * FM_ALARM_SEVERITY_CLEAR if it not set. + * + ******************************************************************************/ +EFmAlarmSeverityT alarmUtil_query ( string & hostname, + string & identity, + string & instance ) +{ + SFmAlarmDataT alarm_query ; + AlarmFilter alarm_filter ; + EFmErrorT rc ; + + memset(&alarm_query, 0, sizeof(alarm_query)); + memset(&alarm_filter, 0, sizeof(alarm_filter)); + + snprintf ( &alarm_filter.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", identity.data()); + + if ( instance.empty() ) + { + snprintf ( &alarm_filter.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s", + ENTITY_PREFIX, hostname.data()); + } + else + { + snprintf ( &alarm_filter.entity_instance_id[0], FM_MAX_BUFFER_LENGTH, "%s%s.%s", + ENTITY_PREFIX, hostname.data(), instance.data()); + } + + alog ("entity_instance:%s\n", alarm_filter.entity_instance_id ); + if (( rc = fm_get_fault ( &alarm_filter, &alarm_query )) == FM_ERR_OK ) + { + dlog ("Found with Severity: %d\n", alarm_query.severity ); + return (alarm_query.severity) ; + } + else if ( rc != FM_ERR_ENTITY_NOT_FOUND ) + { + elog ("%s fm_get_fault returned error (%d)\n", hostname.c_str(), rc ); + } + return (FM_ALARM_SEVERITY_CLEAR); +} + +int alarmUtil_query_identity ( string identity, SFmAlarmDataT * alarm_list_ptr, unsigned int max_alarms ) +{ + int rc = 0 ; + + if ( max_alarms == 0 ) + { + slog ("max alarms is zero !\n"); + } + else if ( identity.empty() ) + { + slog ("empty alarm 'identity'\n"); + } + else if ( alarm_list_ptr ) + { + AlarmFilter alarm_filter ; + + memset(&alarm_filter, 0, sizeof(alarm_filter)); + snprintf ( alarm_filter.alarm_id, FM_MAX_BUFFER_LENGTH, "%s", identity.data()); + rc = fm_get_faults_by_id ( &alarm_filter.alarm_id, alarm_list_ptr, &max_alarms ); + alog ("%s fm_get_faults_by_id rc = %d\n", alarm_filter.alarm_id, rc ); + if ( rc == FM_ERR_OK ) + { + return (PASS); + } + else if ( rc == FM_ERR_ENTITY_NOT_FOUND ) + { + return (RETRY); + } + else + { + return (FAIL); + } + } + else + { + slog ("caller supplied null alarm_list_ptr\n"); + } + return (FAIL_NULL_POINTER); +} + + +/********************************************************************************* + * + * Name : alarmUtil + * + * Purpose : Primary module API used to set/clear severity alarms and logs in FM. + * + * Description : Other maintenance services are expected to use ths interface to + * + * + ********************************************************************************/ +int alarmUtil ( string & hostname, + string & identity, + string & instance, + SFmAlarmDataT & alarm ) +{ + int rc = PASS ; + + // msgSock_type * mtclogd_ptr = get_mtclogd_sockPtr() ; + + /* Don't report events while we are in reset mode */ + if ( daemon_is_file_present ( NODE_RESET_FILE ) ) + { + return (rc); + } + + _build_entity_path ( hostname, instance, alarm ); + +#ifdef WANT_ALARM_QUERY + + /* See if the alarm is already in the requested state */ + EFmAlarmSeverityT curr_sev = alarmUtil_query ( hostname, identity, instance ) ; + + /* If its not a log message and we are already at this + * severity level then ignore the call */ + if (( alarm.alarm_state != FM_ALARM_STATE_MSG ) && + ( curr_sev == alarm.severity )) + { + alog ("%s %s %s already at desired (%s) severity level\n", + hostname.c_str(), + identity.c_str(), + instance.c_str(), + alarmUtil_getSev_str(alarm.severity).c_str()); + return (rc); + } + +#endif + + snprintf(&alarm.alarm_id[0], FM_MAX_BUFFER_LENGTH, "%s", identity.data()); + + if (( alarm.alarm_state == FM_ALARM_STATE_SET ) || + ( alarm.alarm_state == FM_ALARM_STATE_MSG )) + { + if ( alarm.alarm_state == FM_ALARM_STATE_SET ) + { + alog ("%s setting %s %s alarm\n", hostname.c_str(), alarm.alarm_id, alarm.entity_instance_id ); + } + else + { + alog ("%s creating %s %s log\n", hostname.c_str(), alarm.alarm_id, alarm.entity_instance_id ); + } + + /* Debug Logs */ + alog ("%s Alarm Reason: %s\n", hostname.c_str(), alarm.reason_text ); + alog ("%s Alarm Action: %s\n", hostname.c_str(), alarm.proposed_repair_action ); + alog ("%s Alarm Ident : %s : %s\n", hostname.c_str(), alarm.entity_type_id, alarm.entity_instance_id ); + alog ("%s Alarm State : state:%d sev:%d type:%d cause:%d sa:%c supp:%c\n", + hostname.c_str(), + alarm.alarm_state, + alarm.severity, + alarm.alarm_type, + alarm.probable_cause, + alarm.service_affecting ? 'Y' : 'N', + alarm.suppression ? 'Y' : 'N' ); + + snprintf (&__alarmObject.temp_str[0], MAX_API_LOG_LEN-1, + "\n%s [%5d] fm_set_fault: %s %s state:%d sev:%d type:%d cause:%d sa:%c supp:%c", + pt(), getpid(), hostname.c_str(), alarm.alarm_id, alarm.alarm_state, + alarm.severity, + alarm.alarm_type, + alarm.probable_cause, + alarm.service_affecting ? 'Y' : 'N', + alarm.suppression ? 'Y' : 'N' ); + + //send_log_message ( mtclogd_ptr, hostname.data(), &__alarmObject.varlog_filename[0], + // &__alarmObject.temp_str[0] ); + + nodeUtil_latency_log ( hostname, NODEUTIL_LATENCY_MON_START , 0 ); + rc = fm_set_fault_async ( &alarm , NULL ); + nodeUtil_latency_log ( hostname, "fm_set_fault - alarm - common" , LATENCY_1SEC ); + + snprintf (&__alarmObject.temp_str[0], MAX_API_LOG_LEN-1, + "%s [%5d] fm_set_fault: %s returned %d", + pt(), getpid(), hostname.c_str(), rc ); + + //send_log_message ( mtclogd_ptr, hostname.data(), &__alarmObject.varlog_filename[0], + // &__alarmObject.temp_str[0] ); + + if ( rc != FM_ERR_OK ) + { + elog ("%s failed to set alarm %s (rc:%d)\n", hostname.c_str(), alarm.alarm_id, rc); + rc = FAIL ; + } + } + else // ( alarm.alarm_state == FM_ALARM_STATE_CLEAR ) + { + AlarmFilter filter ; memset(&filter, 0, sizeof(filter)); + + /* Setup the alarm filter */ + snprintf(filter.alarm_id, FM_MAX_BUFFER_LENGTH, "%s", alarm.alarm_id); + snprintf(filter.entity_instance_id, FM_MAX_BUFFER_LENGTH, "%s", alarm.entity_instance_id); + + snprintf (&__alarmObject.temp_str[0], MAX_API_LOG_LEN-1, "\n%s [%5d] fm_clear_fault: %s %s:%s", + pt(), getpid(), hostname.c_str(), alarm.entity_instance_id, alarm.alarm_id ); + + // send_log_message ( mtclogd_ptr, hostname.data(), &__alarmObject.varlog_filename[0], + // &__alarmObject.temp_str[0] ); + + alog ("%s clearing %s %s alarm\n", hostname.c_str(), alarm.alarm_id, alarm.entity_instance_id); + nodeUtil_latency_log ( hostname, NODEUTIL_LATENCY_MON_START , 0 ); + if ( ( rc = fm_clear_fault_async ( &filter )) != FM_ERR_OK ) + { + if ( rc != FM_ERR_ENTITY_NOT_FOUND ) + { + elog ("%s failed to fm_clear_fault (rc:%d)\n", hostname.c_str(), rc ); + rc = FAIL ; + } + } + nodeUtil_latency_log ( hostname, "fm_clear_fault - common" , LATENCY_1SEC ); + } + + return (rc); +} + +/* Clear the specified hosts's alarm */ +int alarmUtil_clear ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_CLEAR ; + alarm.alarm_state = FM_ALARM_STATE_CLEAR ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/************************* A L A R M I N G **************************/ + +/** Assert a specified hosts's alarm with a CRITICAL severity level */ +int alarmUtil_critical ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_CRITICAL ; + alarm.alarm_state = FM_ALARM_STATE_SET ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/** Assert a specified host's alarm with a MAJOR severity level */ +int alarmUtil_major ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_MAJOR ; + alarm.alarm_state = FM_ALARM_STATE_SET ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/** Assert a specified host's alarm with a MINOR severity level */ +int alarmUtil_minor ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_MINOR ; + alarm.alarm_state = FM_ALARM_STATE_SET ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/** Assert a specified host's mtce alarm with a WARNING severity level */ +int alarmUtil_warning ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_WARNING ; + alarm.alarm_state = FM_ALARM_STATE_SET ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/*************************** L O G G I N G **********************************/ + +/** Create a CRITICAL log */ +int alarmUtil_critical_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_CRITICAL ; + alarm.alarm_state = FM_ALARM_STATE_MSG ; + return ( alarmUtil ( hostname,identity, instance, alarm )); +} + +/** Create a MAJOR log */ +int alarmUtil_major_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_MAJOR ; + alarm.alarm_state = FM_ALARM_STATE_MSG ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/** Create a MINOR log */ +int alarmUtil_minor_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_MINOR ; + alarm.alarm_state = FM_ALARM_STATE_MSG ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/** Create a WARNING log */ +int alarmUtil_warning_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.severity = FM_ALARM_SEVERITY_WARNING ; + alarm.alarm_state = FM_ALARM_STATE_MSG ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} + +/** Create a neutral log */ +int alarmUtil_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ) +{ + alarm.alarm_state = FM_ALARM_STATE_MSG ; + return ( alarmUtil ( hostname, identity, instance, alarm )); +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/alarmUtil.h b/mtce-common/cgts-mtce-common-1.0/common/alarmUtil.h new file mode 100644 index 00000000..d9ca7ce4 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/alarmUtil.h @@ -0,0 +1,142 @@ +#ifndef __ALARMUTIL_H__ +#define __ALARMUTIL_H__ + +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform Common Maintenance 'Alarm' Header + */ + +#include +#include +#include +#include +#include + +//using namespace std; + +/* external header APIs */ +#include "nodeBase.h" +#include "fmAPI.h" /* for fm_set_fault, fm_clear_fault, etc */ + +#define ENTITY_PREFIX ((const char *)"host=") + +#define MAX_ALARMS (10) + +#define SWERR_ALARM_ID ((const char *)"200.000") /* Do No Use */ +#define LOCK_ALARM_ID ((const char *)"200.001") +#define ENABLE_ALARM_ID ((const char *)"200.004") +#define MGMNT_HB_ALARM_ID ((const char *)"200.005") +#define PMOND_ALARM_ID ((const char *)"200.006") +#define SENSOR_ALARM_ID ((const char *)"200.007") /* Sensor read alarm ; i.e. the sensor read value bad */ +#define INFRA_HB_ALARM_ID ((const char *)"200.009") +#define BM_ALARM_ID ((const char *)"200.010") +#define CONFIG_ALARM_ID ((const char *)"200.011") +#define CH_CONT_ALARM_ID ((const char *)"200.012") /* Combo Host Controller Failure - with Active Compute */ +#define CH_COMP_ALARM_ID ((const char *)"200.013") /* Combo Host Compute Failure - on last Controller */ +#define SENSORCFG_ALARM_ID ((const char *)"200.014") /* Sensor configuration alarm ; i.e. could not add */ +#define SENSORGROUP_ALARM_ID ((const char *)"200.015") /* Sensor Group Read Error */ + +#define EVENT_LOG_ID ((const char *)"200.020") +#define COMMAND_LOG_ID ((const char *)"200.021") +#define STATECHANGE_LOG_ID ((const char *)"200.022") +#define SERVICESTATUS_LOG_ID ((const char *)"200.023") /* log used to report service failure events against */ + +/** + * TODO: This class is more of a place holder for + * more centralized management of alarms + * It is useless in its present form. + **/ +class alarmUtilClass +{ + private: + + public: + + alarmUtilClass(); + ~alarmUtilClass(); + + char temp_str [MAX_API_LOG_LEN] ; + char varlog_filename[MAX_FILENAME_LEN]; +}; + +typedef struct +{ + SFmAlarmDataT alarm ; + string name ; + string instc_prefix ; /* Instance prefix i.e. "=sensor." or "=process." */ + string critl_reason ; + string minor_reason ; + string major_reason ; + string clear_reason ; +} alarmUtil_type ; + +/** Converts FM severity to representative string */ +string alarmUtil_getSev_str ( EFmAlarmSeverityT sev ); +EFmAlarmSeverityT alarmUtil_getSev_enum ( string sev ); + +/* Clear all alarms against this host */ +void alarmUtil_clear_all ( string hostname ); + +/** + * Query the specified alarm severity level. + * Severity levels are specified in fmAPI.h + **/ +EFmAlarmSeverityT alarmUtil_query ( string & hostname, + string & identity, + string & instance ); + +int alarmUtil_query_identity ( string identity, + SFmAlarmDataT * alarm_list_ptr, + unsigned int alarms_max ); + +int alarmUtil_clear ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/************************* A L A R M I N G **************************/ + +/** + * Assert a unique identity alarm or log against specified + * hostname/instance using the supplied alarm data + **/ +int alarmUtil (string & hostname, string & identity, string & instance, SFmAlarmDataT & alarm); + +/** Return a string that represents the specified severity enum */ +string alarmUtil_getSev_str ( EFmAlarmSeverityT sev ); + +/** Assert a specified host's alarm with a CRITICAL severity level */ +int alarmUtil_critical ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Assert a specified host's alarm with a MAJOR severity level */ +int alarmUtil_major ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Assert a specified host's alarm with a MINOR severity level */ +int alarmUtil_minor ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Assert a specified host's mtce alarm with a WARNING severity level */ +int alarmUtil_warning ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + + +/*************************** L O G G I N G **********************************/ + +/** Create a CRITICAL log */ +int alarmUtil_critical_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Create a MAJOR log */ +int alarmUtil_major_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Create a MINOR log */ +int alarmUtil_minor_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Create a WARNING log */ +int alarmUtil_warning_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +/** Create a neutral customer log */ +int alarmUtil_log ( string hostname, string identity, string instance, SFmAlarmDataT & alarm ); + +#endif /* __ALARMUTIL_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/fitCodes.h b/mtce-common/cgts-mtce-common-1.0/common/fitCodes.h new file mode 100644 index 00000000..2f041d5e --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/fitCodes.h @@ -0,0 +1,170 @@ +#ifndef __INCLUDE_FITCODES_H__ +#define __INCLUDE_FITCODES_H__ +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform Common Fault Insertion Code Definitions + */ + +/************************************************************************************* + * + * These definitions are used for fault insertion testing. + * + * Here are examples of how they are used, + * + * - touch the 'no_reboot' file on the mtcClient to cause it to + * servie the reboot request but don't actually reboot + * + * - touch the 'no_mgmnt_ack' file on the mtcClient to cause + * it to handle command requests but drop/not send the ack message + * if it came in on themanagement network ; same for infra + * + * - touch the 'no_mtcAlive file to tell mtcClient to stop sending + * its mtcAlive messages while this file is present. + * + **************************************************************************************/ + +/** + * This is the Fault Insertion Dir - Code that looks for multiple fit files need not + * bother if the dir is not present + **/ +#define MTC_CMD_FIT__DIR ("/var/run/fit") + + +#define MTC_CMD_FIT__NO_REBOOT ("/var/run/fit/no_reboot") /* mtcClient */ +#define MTC_CMD_FIT__NO_RESET ("/var/run/fit/no_reset") /* mtcClient */ +#define MTC_CMD_FIT__NO_WIPEDISK ("/var/run/fit/no_wipedisk") /* mtcClient */ +#define MTC_CMD_FIT__NO_MGMNT_ACK ("/var/run/fit/no_mgmnt_ack") /* mtcClient */ +#define MTC_CMD_FIT__NO_INFRA_ACK ("/var/run/fit/no_infra_ack") /* mtcClient */ +#define MTC_CMD_FIT__NO_MTCALIVE ("/var/run/fit/no_mtcalive") /* mtcClient */ +#define MTC_CMD_FIT__MGMNT_RXSOCK ("/var/run/fit/mgmnt_rxsock") /* mtcClient */ +#define MTC_CMD_FIT__MGMNT_TXSOCK ("/var/run/fit/mgmnt_txsock") /* mtcClient */ +#define MTC_CMD_FIT__INFRA_RXSOCK ("/var/run/fit/infra_rxsock") /* mtcClient */ +#define MTC_CMD_FIT__INFRA_TXSOCK ("/var/run/fit/infra_txsock") /* mtcClient */ +#define MTC_CMD_FIT__RMON_SOCK ("/var/run/fit/rmon_sock") /* mtcClient */ +#define MTC_CMD_FIT__AMON_SOCK ("/var/run/fit/amon_sock") /* mtcClient */ +#define MTC_CMD_FIT__NO_INFRA_RSP ("/var/run/fit/no_infra_rsp") /* hbsClient */ +#define MTC_CMD_FIT__NO_MGMNT_RSP ("/var/run/fit/no_mgmnt_rsp") /* hbsClient */ +#define MTC_CMD_FIT__LINKLIST ("/var/run/fit/linklist") /* hbsAgent */ +#define MTC_CMD_FIT__HBSSILENT ("/var/run/fit/hbs_silent_fault") /* hbsAgent */ +#define MTC_CMD_FIT__SENSOR_DATA ("/var/run/fit/sensor_data") /* hwmond */ +#define MTC_CMD_FIT__POWER_CMD ("/var/run/fit/power_cmd_result") /* mtcAgent */ +#define MTC_CMD_FIT__MC_INFO ("/var/run/fit/mc_info") /* mtcAgent */ +#define MTC_CMD_FIT__POWER_STATUS ("/var/run/fit/power_status") /* mtcAgent */ +#define MTC_CMD_FIT__RESTART_CAUSE ("/var/run/fit/restart_cause") /* mtcAgent */ +#define MTC_CMD_FIT__UPTIME ("/var/run/fit/uptime") /* mtcAgent */ +#define MTC_CMD_FIT__LOUD_BM_PW ("/var/run/fit/loud_bm_pw") /* mtcAgent & hwmond */ +#define MTC_CMD_FIT__START_SVCS ("/var/run/fit/host_services") /* mtcClient */ +#define MTC_CMD_FIT__NO_HS_ACK ("/var/run/fit/no_hs_ack") /* mtcClient */ +#define MTC_CMD_FIT__GOENABLE_AUDIT ("/var/run/fit/goenable_audit") /* mtcAgent */ + +/***************************************************** + * Fault Insertion Codes + *****************************************************/ + +/***************************************************************************** + * + * the fit /var/run/fit/fitinfo file contains the following format, + * - code and process are required + * - other fields are optional + * - no spaces, exclude <> + * + * proc= + * code= + * host= + * name= + * data= + * + *****************************************************************************/ + +/*********************** Common FIT Codes **********************************/ + +#define FIT_CODE__NONE (0) +#define FIT_CODE__CORRUPT_TOKEN (1) +#define FIT_CODE__ADD_DELETE (2) +#define FIT_CODE__STUCK_TASK (3) +#define FIT_CODE__AVOID_N_FAIL_IPMITOOL_REQUEST (4) +#define FIT_CODE__THREAD_TIMEOUT (5) +#define FIT_CODE__THREAD_SEGFAULT (6) +#define FIT_CODE__SIGNAL_NOEXIT (7) +#define FIT_CODE__STRESS_THREAD (8) +#define FIT_CODE__DO_NOTHING_THREAD (9) +#define FIT_CODE__EMPTY_BM_PASSWORD (10) +#define FIT_CODE__INVALIDATE_MGMNT_IP (11) +#define FIT_CODE__INVALIDATE_INFRA_IP (12) +#define FIT_CODE__WORK_QUEUE (13) +#define FIT_CODE__NO_READY_EVENT (14) +#define FIT_CODE__NO_PULSE_REQUEST (15) +#define FIT_CODE__NO_PULSE_RESPONSE (16) + +#define FIT_CODE__FAST_PING_AUDIT_HOST (20) +#define FIT_CODE__FAST_PING_AUDIT_ALL (21) + +#define FIT_CODE__TRANSLATE_LOCK_TO_FORCELOCK (30) +#define FIT_CODE__LOCK_HOST (31) +#define FIT_CODE__FORCE_LOCK_HOST (32) +#define FIT_CODE__UNLOCK_HOST (33) + +#define FIT_CODE__FM_SET_ALARM (40) +#define FIT_CODE__FM_GET_ALARM (41) +#define FIT_CODE__FM_QRY_ALARMS (42) + +#define FIT_CODE__IPMI_COMMAND_SEND (60) +#define FIT_CODE__IPMI_COMMAND_RECV (61) + +#define FIT_CODE__START_HOST_SERVICES (70) +#define FIT_CODE__STOP_HOST_SERVICES (71) + +/***************** Process Fit Codes ********************************/ + +/* Hardware Monitor FIT Codes */ +#define FIT_CODE__HWMON__CORRUPT_TOKEN (101) +#define FIT_CODE__HWMON__AVOID_TOKEN_REFRESH (102) +#define FIT_CODE__HWMON__THREAD_TIMEOUT (103) +#define FIT_CODE__HWMON__AVOID_SENSOR_QUERY (104) +#define FIT_CODE__HWMON__SENSOR_STATUS (105) +#define FIT_CODE__HWMON__STARTUP_STATES_FAILURE (106) + +#define FIT_CODE__HWMON__HTTP_LOAD_SENSORS (120) +#define FIT_CODE__HWMON__HTTP_ADD_SENSOR (121) +#define FIT_CODE__HWMON__HTTP_DEL_SENSOR (122) +#define FIT_CODE__HWMON__HTTP_MOD_SENSOR (123) + +#define FIT_CODE__HWMON__ADD_SENSOR (130) +#define FIT_CODE__HWMON__BAD_SENSOR (131) +#define FIT_CODE__HWMON__GET_SENSOR (132) + +#define FIT_CODE__HWMON__CREATE_ORPHAN_SENSOR_ALARM (136) + + +#define FIT_CODE__HWMON__HTTP_LOAD_GROUPS (140) +#define FIT_CODE__HWMON__HTTP_ADD_GROUP (141) +#define FIT_CODE__HWMON__HTTP_DEL_GROUP (142) +#define FIT_CODE__HWMON__HTTP_MOD_GROUP (143) +#define FIT_CODE__HWMON__HTTP_GROUP_SENSORS (144) + +#define FIT_CODE__HWMON__ADD_GROUP (150) +#define FIT_CODE__HWMON__BAD_GROUP (151) +#define FIT_CODE__HWMON__GET_GROUP (152) + +#define FIT_CODE__HWMON__CREATE_ORPHAN_GROUP_ALARM (156) + +#define FIT_CODE__HWMON__NO_DATA (160) + +#define FIT_CODE__HWMON__RAISE_SENSOR_ALARM (170) +#define FIT_CODE__HWMON__CLEAR_SENSOR_ALARM (171) +#define FIT_CODE__HWMON__RAISE_GROUP_ALARM (172) +#define FIT_CODE__HWMON__CLEAR_GROUP_ALARM (173) + +#define FIT_CODE__HWMON__SET_DB_SENSOR_STATUS (175) +#define FIT_CODE__HWMON__SET_DB_SENSOR_STATE (176) +#define FIT_CODE__HWMON__SET_DB_GROUP_STATUS (177) +#define FIT_CODE__HWMON__SET_DB_GROUP_STATE (178) + +#endif /* __INCLUDE_FITCODES_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/fsync.c b/mtce-common/cgts-mtce-common-1.0/common/fsync.c new file mode 100644 index 00000000..6ce29efd --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/fsync.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2014 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +#include +#include +#include +#include +#include + +/* helper app to fsync a single file/directory */ + +int main(int argc, char **argv) +{ + int fd,rc; + + if (argc != 2) { + printf("usage: %s \n", argv[0]); + return -1; + } + + fd = open(argv[1], O_RDONLY); + if (fd == -1) { + printf("unable to open file %s: %m\n", argv[1]); + return -1; + } + + rc = fsync(fd); + if (rc == -1) { + printf("error fsyncing file %s: %m\n", argv[1]); + } + + if (close(fd) == -1) { + printf("error closing file %s: %m\n", argv[1]); + } + + return rc; +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/hostClass.cpp b/mtce-common/cgts-mtce-common-1.0/common/hostClass.cpp new file mode 100644 index 00000000..e9324f37 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/hostClass.cpp @@ -0,0 +1,454 @@ +/* + * Copyright (c) 2015 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +/** + * @file + * Wind River CGTS Platform Host Base Class Member Implementation. + */ + +#include +#include +#include +#include +#include /* for ENODEV, EFAULT and ENXIO */ +#include /* for close and usleep */ + +using namespace std; + +#ifdef __AREA__ +#undef __AREA__ +#define __AREA__ "~~~" +#endif + +#include "nodeBase.h" +#include "hostClass.h" +#include "nodeUtil.h" + + +hostBaseClass::hostBaseClass() /* constructor */ +{ + for(unsigned int i = 0; i < MAX_HOSTS; ++i) + { + host_ptrs[i] = NULL; + } + bm_provisioned= false; + head = tail = NULL; + memory_allocs = 0 ; + memory_used = 0 ; + hosts = 0 ; + service = 0 ; + + /* Start with null identity */ + my_hostname.clear() ; + my_local_ip.clear() ; + my_float_ip.clear() ; +} + +hostBaseClass::~hostBaseClass() /* destructor */ +{ + host * ptr = head ; + host * temp_ptr = ptr ; + while ( ptr != NULL ) + { + temp_ptr = ptr ; + ptr = ptr->next ; + delHost (temp_ptr); + } + if ( memory_used != 0 ) + { + elog ( "Apparent Memory Leak - Allocs:%d and Bytes:%d\n", + memory_allocs, memory_used ); + } + else + { + dlog ( "No Memory Leaks\n\n"); + } +} + +/* + * Allocates memory for a new host and stores its the address in host_ptrs + * + * @param void + * @return pointer to the newly allocted host memory + */ +struct hostBaseClass::host * hostBaseClass::newHost ( void ) +{ + struct hostBaseClass::host * host_ptr = NULL ; + + if ( memory_allocs == 0 ) + { + memset ( host_ptrs, 0 , sizeof(struct host *)*MAX_HOSTS); + } + + // find an empty spot + for ( int i = 0 ; i < MAX_HOSTS ; i++ ) + { + if ( host_ptrs[i] == NULL ) + { + host_ptrs[i] = host_ptr = new host ; + memory_allocs++ ; + memory_used += sizeof (struct hostBaseClass::host); + // ilog ("%p:%p - mem after new: allocs:%d used:%d\n", host_ptr , host_ptrs[i], memory_allocs, memory_used); + return host_ptr ; + } + } + elog ( "Failed to save new host pointer address\n" ); + return host_ptr ; +} + + +/* Frees the memory of a pre-allocated host and removes + * it from the host_ptrs list + * @param host * pointer to the host memory address to be freed + * @return int return code { PASS or -EINVAL } + */ +int hostBaseClass::delHost ( struct hostBaseClass::host * host_ptr ) +{ + if ( memory_allocs > 0 ) + { + for ( int i = 0 ; i < MAX_NODES ; i++ ) + { + if ( host_ptrs[i] == host_ptr ) + { + // ilog ("%p:%p - mem before del: allocs:%d used:%d\n", host_ptr , host_ptrs[i], memory_allocs, memory_used); + delete host_ptr ; + host_ptrs[i] = NULL ; + memory_allocs-- ; + memory_used -= sizeof (struct hostBaseClass::host); + return PASS ; + } + } + elog ( "Error: Unable to validate memory address being freed\n" ); + } + else + elog ( "Error: Free memory called when there is no memory to free\n" ); + + return -EINVAL ; +} + + /* + * Allocate new host and tack it on the end of the host_list + */ +struct +hostBaseClass::host* hostBaseClass::addHost( string hostname ) +{ + /* verify host is not already provisioned */ + struct host * ptr = getHost ( hostname ); + if ( ptr ) + { + if ( remHost ( hostname ) ) + { + /* Should never get here but if we do then */ + /* something is seriously wrong */ + elog ("Error: Unable to remove host during reprovision\n"); + return static_cast(NULL); + } + } + + /* allocate memory for new host */ + ptr = newHost (); + if( ptr == NULL ) + { + elog ( "Error: Failed to allocate memory for new host\n" ); + return static_cast(NULL); + } + + /* Init the new host */ + ptr->hostname = hostname ; + + /* If the host list is empty add it to the head */ + if( head == NULL ) + { + head = ptr ; + tail = ptr ; + ptr->prev = NULL ; + ptr->next = NULL ; + } + else + { + /* link the new_host to the tail of the host_list + * then mark the next field as the end of the host_list + * adjust tail to point to the last host + */ + tail->next = ptr ; + ptr->prev = tail ; + ptr->next = NULL ; + tail = ptr ; + } + + hosts++ ; + + return ptr ; +} + +struct hostBaseClass::host* hostBaseClass::getHost ( string hostname ) +{ + /* check for empty list condition */ + if ( head == NULL ) + return NULL ; + + for ( struct host * ptr = head ; ; ptr = ptr->next ) + { + if ( !hostname.compare ( ptr->hostname )) + { + // ilog ("%s %p\n", hostname.c_str(), ptr ); + return ptr ; + } + else if ( !hostname.compare ( ptr->uuid )) + { + // ilog ("%s %p\n", hostname.c_str(), ptr ); + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return static_cast(NULL); +} + +/* Remove a hist from the linked list of hosts - may require splice action */ +int hostBaseClass::remHost( string hostname ) +{ + if ( hostname.c_str() == NULL ) + return -ENODEV ; + + if ( head == NULL ) + return -ENXIO ; + + struct host * ptr = getHost ( hostname ); + + if ( ptr == NULL ) + return -EFAULT ; + + /* If the host is the head host */ + if ( ptr == head ) + { + /* only one host in the list case */ + if ( head == tail ) + { + dlog ("Single Host -> Head Case\n"); + head = NULL ; + tail = NULL ; + } + else + { + dlog ("Multiple Hosts -> Head Case\n"); + head = head->next ; + head->prev = NULL ; + } + } + /* if not head but tail then there must be more than one + * host in the list so go ahead and chop the tail. + */ + else if ( ptr == tail ) + { + dlog ("Multiple Host -> Tail Case\n"); + tail = tail->prev ; + tail->next = NULL ; + } + else + { + dlog ("Multiple Host -> Full Splice Out\n"); + ptr->prev->next = ptr->next ; + ptr->next->prev = ptr->prev ; + } + delHost ( ptr ); + hosts-- ; + return (PASS) ; +} + + + +/****************************************************************************************** + ****************************************************************************************** + *****************************************************************************************/ + + + +int hostBaseClass::add_host ( node_inv_type & inv ) +{ + int rc = FAIL ; + struct hostBaseClass::host * host_ptr = static_cast(NULL); + + if (( inv.name.empty()) || + ( !inv.name.compare ("none")) || + ( !inv.name.compare ("None"))) + { + wlog ("Refusing to add host with 'null' or 'invalid' hostname (%s)\n", + inv.uuid.c_str()); + return (FAIL_INVALID_HOSTNAME) ; + } + + host_ptr = hostBaseClass::getHost(inv.name); + if ( host_ptr ) + { + dlog ("%s Already provisioned\n", host_ptr->hostname.c_str()); + + /* Send back a retry in case the add needs to be converted to a modify */ + return (RETRY); + } + /* Otherwise add it as a new host */ + else + { + if ( daemon_get_cfg_ptr()->debug_level > 1 ) + print_inv ( inv ); + + host_ptr = hostBaseClass::addHost(inv.name); + if ( host_ptr ) + { + host_ptr->ip = inv.ip ; + host_ptr->mac = inv.mac ; + host_ptr->uuid = inv.uuid ; + + host_ptr->type = inv.type ; + host_ptr->nodetype = CGTS_NODE_NULL ; + + host_ptr->retries = 0 ; + host_ptr->toggle = false ; + + /* Add to the end of inventory */ + hostlist.push_back ( host_ptr->hostname ); + dlog ("%s Added Host Base\n", inv.name.c_str()); + rc = PASS ; + } + else + { + elog ("%s Host Base Add Failed\n", inv.name.c_str()); + rc = FAIL_NULL_POINTER ; + } + } + return (rc); +} + +int hostBaseClass::rem_host ( string hostname ) +{ + int rc = FAIL ; + if ( ! hostname.empty() ) + { + hostlist.remove ( hostname ); + rc = hostBaseClass::remHost ( hostname ); + } + return ( rc ); +} + +int hostBaseClass::del_host ( string hostname ) +{ + int rc = FAIL_DEL_UNKNOWN ; + hostBaseClass::host * host_ptr = hostBaseClass::getHost( hostname ); + if ( host_ptr ) + { + rc = rem_host ( host_ptr->hostname ); + if ( rc == PASS ) + { + dlog ("%s Deleted\n", host_ptr->hostname.c_str()); + print_node_info(); + } + else + { + elog ("%s Delete Failed (rc:%d)\n", hostname.c_str(), rc ); + } + } + else + { + wlog ("Unknown hostname: %s\n", hostname.c_str()); + } + return (rc); +} + +/** Get this hosts uuid address */ +string hostBaseClass::get_uuid ( string hostname ) +{ + hostBaseClass::host * host_ptr ; + host_ptr = hostBaseClass::getHost ( hostname ); + if ( host_ptr != NULL ) + { + return (host_ptr->uuid ); + } + elog ("%s uuid lookup failed\n", hostname.c_str() ); + return (""); +} + +/** Get this hosts uuid address */ +string hostBaseClass::get_hostname ( string uuid ) +{ + hostBaseClass::host * host_ptr ; + host_ptr = hostBaseClass::getHost ( uuid ); + if ( host_ptr != NULL ) + { + return (host_ptr->hostname ); + } + elog ("%s hostname lookup failed\n", uuid.c_str() ); + return (""); +} + +/** Get this hosts ip address */ +string hostBaseClass::get_ip ( string hostname ) +{ + hostBaseClass::host * host_ptr ; + host_ptr = hostBaseClass::getHost ( hostname ); + if ( host_ptr != NULL ) + { + return (host_ptr->ip ); + } + elog ("%s ip lookup failed\n", hostname.c_str() ); + return (""); +} + +static string null_str = "" ; +string hostBaseClass::get_hostaddr ( string hostname ) +{ + hostBaseClass::host* host_ptr ; + host_ptr = hostBaseClass::getHost ( hostname ); + if ( host_ptr != NULL ) + { + return ( host_ptr->ip ); + } + return ( null_str ); +} + + + +void hostBaseClass::print_node_info ( void ) +{ + fflush (stdout); + fflush (stderr); +} + +void hostBaseClass::memLogDelimit ( void ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "-------------------------------------------------------------\n"); + mem_log (str); +} + +void hostBaseClass::mem_log_host ( struct hostBaseClass::host * host_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s - %s - %s - %s\n", + host_ptr->hostname.c_str(), + host_ptr->ip.c_str(), + host_ptr->mac.c_str(), + host_ptr->uuid.c_str(), + host_ptr->type.c_str()); + mem_log (str); +} + +void hostBaseClass::memDumpNodeState ( string hostname ) +{ + hostBaseClass::host* host_ptr ; + host_ptr = hostBaseClass::getHost ( hostname ); + if ( host_ptr == NULL ) + { + mem_log ( hostname, ": ", "Not Found hostBaseClass\n" ); + return ; + } + else + { + mem_log_host ( host_ptr ); + // memLogDelimit (); + } +} + diff --git a/mtce-common/cgts-mtce-common-1.0/common/hostClass.h b/mtce-common/cgts-mtce-common-1.0/common/hostClass.h new file mode 100644 index 00000000..36d615b7 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/hostClass.h @@ -0,0 +1,221 @@ +#ifndef __INCLUDE_HOSTCLASS_H__ +#define __INCLUDE_HOSTCLASS_H__ +/* + * Copyright (c) 2015 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +/** + * @file + * Wind River CGTS Platform Host Maintenance "Host Manager" + * class, support structs and enums. + */ + +#include +#include +#include +#include +#include +#include + +//using namespace std; + +#include "nodeTimers.h" /* for ... mtcTimer */ + +/** + * @addtogroup hostBaseClass + * @{ + * This class is used to maintain a linked list of hosts for a given application. + */ + +class hostBaseClass +{ + private: + + /** + * A single host entity within the hostBaseClass. + * Used to build a linked list of added/provisioned hosts. + */ + struct host { + + /** The name of the host */ + std::string hostname ; + + /** The name of the host */ + std::string uuid ; + + /** The IP address of the host */ + std::string ip ; + + /** The Mac address of the host node */ + std::string mac ; + + /** A string indicating the host type as 'compute' , 'storage' or 'controller' */ + std::string type ; + + /** The Type ; host specific service refinement */ + int nodetype ; + + /** general retry counter */ + int retries ; + + /** Generic toggle switch */ + bool toggle ; + + /** Pointer to the previous host in the list */ + struct host * prev; + + /** Pointer to the next host in the list */ + struct host * next; + } ; + + struct host * head ; /**< Host Linked List Head pointer */ + struct host * tail ; /**< Host Linked List Tail pointer */ + + /** Allocate memory for a new host. + * + * Preserves the host address in the host_ptr list and increments + * the memory_allocs counter used by the inservice test audit. + * + * @return + * a pointer to the memory of the newly allocated host */ + struct hostBaseClass::host * newHost ( void ); + + /** Start heartbeating a new host. + * + * host is added to the end of the host linked list. + * + * @param host_info_ptr + * is a pointer containing pertinent info about the physical host + * @return + * a pointer to the newly added host + */ + struct hostBaseClass::host* addHost ( string hostname ); + + /** Get pointer to "hostname" host. + * + * Host list lookup by pointer from hostname. + * + * @param host_info_ptr + * is a pointer containing info required to find the host in the host list + * @return + * a pointer to the hostname's host + */ + struct hostBaseClass::host* getHost ( string hostname ); + + /** Free the memory of a previously allocated host. + * + * The memory to be removed is found in the host_ptr list, cleared and + * the memory_allocs counter is decremented. + * If the memory cannot be found then an error is returned. + * + * @param host_ptr + * is a pointer to the host to be freed + * @return + * a signed integer of PASS or -EINVAL + */ + int delHost ( struct hostBaseClass::host * host_ptr ); + + + /** Remove a host from the linked list. + * + * Node is spliced out of the host linked list. + * + * @param node_info_ptr + * is a pointer containing info required to find the host in the host list + * @return + * an integer of PASS or -EINVAL */ + int remHost ( string hostname ); + + /** List of allocated host memory. + * + * An array of host pointers. + */ + hostBaseClass::host * host_ptrs[MAX_HOSTS] ; + + /** A memory allocation counter. + * + * Should represent the number of hosts in the linked list. + */ + int memory_allocs ; + + /** A memory used counter + * + * A variable storing the accumulated host memory + */ + int memory_used ; + + void mem_log_host ( struct hostBaseClass::host * host_ptr ); + +/** Public Interfaces that allow hosts to be + * added or removed from maintenance. + */ +public: + + hostBaseClass(); /**< constructor */ + ~hostBaseClass(); /**< destructor */ + + /**< The service this list is associated with */ + int service ; + + int hosts ; + + string my_hostname ; /**< My hostname */ + string my_local_ip ; /**< Primary IP address */ + string my_float_ip ; /**< Secondary (floating) IP address */ + + + bool bm_provisioned ; + + /** Add a host to the linked list using public API */ + int add_host ( node_inv_type & inv ); + + /** Mod a host to the linked list using public API */ + int mod_host ( node_inv_type & inv ); + + /** Remove a host from the linked list using public API */ + int rem_host ( string hostname ); + + /** Free the memory of an already allocated host link using public API */ + int del_host ( string hostname ); + + string get_ip ( string hostname ); + string get_uuid ( string hostname ); + string get_hostaddr ( string hostname ); + string get_hostname ( string uuid ); + + + + void memLogDelimit ( void ); /**< Debug log delimiter */ + void memDumpNodeState ( string hostname ); + void memDumpAllState ( void ); + void print_node_info ( void ); /**< Print node info banner */ + + /** This is a list of host names. */ + std::list hostlist ; + std::list::iterator hostlist_iter_ptr ; + + + +} ; + +/** + * @addtogroup hostBaseClass_base + * @{ + */ + +hostBaseClass * get_hostBaseClass_ptr ( void ); + +/* allocates hostBaseClass obj_ptr and host_ptr */ +#define GET_HOST_PTR(hostname) \ + hostBaseClass * obj_ptr = get_hostBaseClass_ptr () ; \ + hostBaseClass::host * host_ptr = obj_ptr->getHost ( hostname ) ; \ + if ( host_ptr == NULL ) \ + { \ + elog ("%s hostname unknown\n", hostname.c_str()); \ + return (FAIL_HOSTNAME_LOOKUP); \ + } + +#endif // __INCLUDE_HOSTCLASS_H__ diff --git a/mtce-common/cgts-mtce-common-1.0/common/hostUtil.cpp b/mtce-common/cgts-mtce-common-1.0/common/hostUtil.cpp new file mode 100644 index 00000000..ed079ea1 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/hostUtil.cpp @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGCS Platform - Host Server Utility Module + */ + +#include "hostUtil.h" + +string hostUtil_getServiceIp ( mtc_service_enum service ) +{ + string ip = "0.0.0.0" ; + + daemon_config_type * cfg_ptr = daemon_get_cfg_ptr(); + + switch (service) + { + case SERVICE_SYSINV: + { + ip = cfg_ptr->sysinv_api_bind_ip ; + break ; + } + case SERVICE_TOKEN: + { + if ( cfg_ptr->keystone_auth_host) + { + ip = cfg_ptr->keystone_auth_host; + } + else + { + ip = "localhost"; + } + break ; + } + case SERVICE_SMGR: + case SERVICE_VIM: + { + ip = "localhost" ; + break ; + } + default: + { + slog ("Unsupported service (%d)\n", service ); + break ; + } + } + return (ip); +} + +string hostUtil_getPrefixPath ( ) +{ + string prefix_path = ""; + + daemon_config_type * cfg_ptr = daemon_get_cfg_ptr(); + + if ( cfg_ptr->keystone_prefix_path) + { + prefix_path = cfg_ptr->keystone_prefix_path; + } + + return (prefix_path); +} + +int hostUtil_getServicePort ( mtc_service_enum service ) +{ + daemon_config_type * cfg_ptr = daemon_get_cfg_ptr(); + + switch (service) + { + case SERVICE_SYSINV: + return(cfg_ptr->sysinv_api_port); + + case SERVICE_SMGR: + return(cfg_ptr->ha_port); + + case SERVICE_VIM: + return(cfg_ptr->vim_cmd_port); + + case SERVICE_TOKEN: + return(cfg_ptr->keystone_port); + + default: + { + slog ("Unsupported service (%d)\n", service ); + break ; + } + } + return (0); +} + +bool hostUtil_is_valid_ip_addr ( string ip ) +{ + if ( !ip.empty() ) + if ( ip.compare(NONE) ) + return (true); + return (false); +} + +bool hostUtil_is_valid_mac_addr ( string mac ) +{ + if ( !mac.empty() ) + if ( mac.length() == COL_CHARS_IN_MAC_ADDR ) + return (true); + return (false); +} + +bool hostUtil_is_valid_bm_type ( string bm_type ) +{ + dlog3 ("BM_Type:%s\n", bm_type.c_str()); + if ( !bm_type.empty() ) + { + if (( bm_type == "bmc" ) || + ( bm_type == "ilo" ) || + ( bm_type == "ilo3" ) || + ( bm_type == "ilo4" ) || + ( bm_type == "quanta" )) + { + return (true); + } + } + return ( false ); +} + +bool hostUtil_is_valid_uuid ( string uuid ) +{ + if (( !uuid.empty() ) && ( uuid.length() == UUID_LEN ) ) + return (true); + return (false); +} + +/***************************************************************************** + * + * Name : hostUtil_tmpfile + * + * Description : Create a temporary file with a randomized suffix. + * Write the specified 'data' to it and return its + * open file descriptor. + * + * The file is unlinked so that it is automatically deleted by the kernel + * when the file descriptor is closed or the program exits. + * + * TODO: fix or figure out why the unlink removes the file right away even + * with the file open. + * + *****************************************************************************/ + +int hostUtil_mktmpfile ( string hostname, string basename, string & filename, string data ) +{ + // buffer to hold the temporary file name + char tempBuff[MAX_FILENAME_LEN]; + + int fd = -1; + + memset(tempBuff,0,sizeof(tempBuff)); + + if ( basename.empty() || data.empty() ) + { + slog ("%s called with one or more bad parameters (%d:%d)\n", + hostname.c_str(), basename.empty(), data.empty()); + return (0); + } + + /* add what mkstemp will make unique */ + basename.append("XXXXXX"); + + // Copy the relevant information in the buffers + snprintf ( &tempBuff[0], MAX_FILENAME_LEN, "%s", basename.data()); + + // Create the temporary file, this function will + // replace the 'X's with random letters + fd = mkstemp(tempBuff); + + // Call unlink so that whenever the file is closed or the program exits + // the temporary file is deleted. + // + // Note: Unlinking removes the file immediately. + // Commenting out. Caller must remove file. + // + // unlink(tempBuff); + + if(fd<1) + { + elog ("%s failed to create temp file (%d:%m)\n", hostname.c_str(), errno ); + return 0 ; + } + else + { + filename = tempBuff ; + dlog2 ("%s temporary file [%s] created\n", hostname.c_str(), tempBuff ); + } + + // Write the data to the temporary file + if ( write ( fd, data.data(), data.size()) < 0 ) + { + elog ("%s failed to write data to '%s' (%d:%m)\n", + hostname.c_str(), filename.c_str(), errno ); + return 0 ; + } + else + { + dlog2 ("%s wrote %s to %s\n", hostname.c_str(), data.c_str(), filename.c_str()); + } + return (fd); +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/hostUtil.h b/mtce-common/cgts-mtce-common-1.0/common/hostUtil.h new file mode 100644 index 00000000..d207f4da --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/hostUtil.h @@ -0,0 +1,85 @@ +#ifndef __INCLUDE_HOSTUTIL_H__ +#define __INCLUDE_HOSTUTIL_H__ + +/* +* Copyright (c) 2013-2014, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* +*/ + +#include +#include +#include +#include +#include +#include /* for ... HTTP_ status definitions */ + +using namespace std; + +#include "nodeBase.h" + +/* Supported Server Names */ +//#define SERVER__UNKNOWN ((const char*)"Undetermined Server") +//#define SERVER__NOKIA_QUANTA_1234_GEN1 ((const char*)"Quanta Computer") +//#define SERVER__HP_PROLIANT_DL380_GEN9 ((const char*)"ProLiant DL380 Gen9") +//#define SERVER__HP_PROLIANT_DL360_GEN9 ((const char*)"ProLiant DL360 Gen9") + +/* Supported Board Management Controller Names */ +//#define SERVER_BMC__UNKNOWN ((const char*)"Unknown BMC") +//#define SERVER_BMC__STANDARD_ILO_V3 ((const char*)"iLO 3 Standard") +//#define SERVER_BMC__STANDARD_ILO_V4 ((const char*)"iLO 4 Standard") + + +/* A list of supported servers */ +//typedef enum +//{ +// SERVER_IS_UNKNOWN = 0, +// SERVER_IS_NOKIA__QUANTA_1234____GEN1__ILO_V4 = 1, +// SERVER_IS_HP_____PROLIANT_DL380_GEN9__ILO_V4 = 2, +// SERVER_IS_HP_____PROLIANT_DL360_GEN9__ILO_V4 = 3, +// SERVER_IS_LAST = 4 +//} server_enum ; + +/* Server Table Entry Type */ +//typedef struct +//{ +// server_enum server_code ; +// protocol_enum protocol ; +// const char * server_name ; +// const char * server_bmc ; +// const char * profile ; +// +//} server_table_entry_type ; +//server_table_entry_type * hostUtil_get_server_info ( server_enum server_code ); + +typedef enum +{ + CLIENT_NONE = 0, + CLIENT_SYSINV = 1, + CLIENT_VIM_HOSTS = 2, + CLIENT_VIM_SYSTEMS = 3, + CLIENT_SENSORS = 4, + CLIENT_SENSORGROUPS = 5, + CLIENT_SM = 6, +} mtc_client_enum ; + +typedef enum +{ + SERVICE_SYSINV = 0, + SERVICE_TOKEN = 1, + SERVICE_SMGR = 2, + SERVICE_VIM = 3, +} mtc_service_enum ; + +string hostUtil_getServiceIp ( mtc_service_enum service ); +int hostUtil_getServicePort ( mtc_service_enum service ); +string hostUtil_getPrefixPath ( void ); + +bool hostUtil_is_valid_uuid ( string uuid ); +bool hostUtil_is_valid_ip_addr ( string ip ); +bool hostUtil_is_valid_bm_type ( string bm_type ); + +int hostUtil_mktmpfile ( string hostname, string basename, string & filename, string data ); + +#endif diff --git a/mtce-common/cgts-mtce-common-1.0/common/httpUtil.cpp b/mtce-common/cgts-mtce-common-1.0/common/httpUtil.cpp new file mode 100644 index 00000000..e626961e --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/httpUtil.cpp @@ -0,0 +1,1065 @@ +/* + * Copyright (c) 2015-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +/** + * @file + * Wind River CGTS Platform Common HTTP utility Module + * + */ + +#include + +using namespace std; + +#include "httpUtil.h" +#include "jsonUtil.h" +#include "tokenUtil.h" /* for ... tokenUtil_handler */ +#include "nodeUtil.h" /* for ... string_contains */ +#include "nodeClass.h" +#include "timeUtil.h" /* for ... time_debug_type */ +#include "keyClass.h" /* for ... add_key, del_key */ + +static keyClass keyValObject ; +static char rest_api_filename[MAX_FILENAME_LEN]; +static char rest_api_log_str [MAX_API_LOG_LEN]; +static libEvent nullEvent ; + +/* *********************************************************************** + * + * Name : httpUtil_event_init + * + * Description: Initialize the supplied libevent structure to default + * start values including with the supplied hostname, + * service , ip and port values. + * + * Note: No memory allication is performed. + * + * ************************************************************************/ + +int httpUtil_event_init ( libEvent * ptr , + string hostname, + string service, + string ip, + int port ) +{ + /* Default Starting States */ + ptr->sequence = 0 ; + ptr->request = SERVICE_NONE ; + ptr->state = HTTP__TRANSMIT ; + ptr->log_prefix = hostname ; + ptr->log_prefix.append(" ") ; + ptr->log_prefix.append(service) ; + + /* Execution Controls */ + ptr->stuck = 0 ; + ptr->count = 0 ; + ptr->timeout = 0 ; + ptr->retries = 0 ; + ptr->cur_retries = 0 ; + ptr->max_retries = 0 ; + ptr->active = false ; + ptr->mutex = false ; + ptr->found = false ; + ptr->blocking = false ; + ptr->noncritical = false ; + ptr->rx_retry_cnt= 0 ; + ptr->rx_retry_max= 1000 ; + + ptr->uuid.clear(); + ptr->new_uuid.clear() ; + + /* Service Specific Request Info */ + ptr->ip = ip ; + ptr->port = port ; + ptr->hostname = hostname ; + ptr->service = service ; + + /* Copy the mtce token into the libEvent struct for this command */ + ptr->token.url.clear(); + ptr->token.token.clear(); + ptr->token.issued.clear(); + ptr->token.expiry.clear(); + ptr->token.delay = false ; + ptr->token.refreshed = false ; + + /* Instance Specific Request Data Data */ + ptr->entity_path.clear() ; + ptr->entity_path_next.clear() ; + ptr->address.clear(); + ptr->payload.clear(); + ptr->response.clear(); + + ptr->operation.clear(); + ptr->information.clear(); + ptr->result.clear(); + ptr->label.clear(); + + /** Default the user agent to mtce ; other users and commands can override */ + ptr->user_agent = "mtce/1.0" ; + + ptr->admin_url.clear(); + ptr->internal_url.clear(); + ptr->public_url.clear(); + + /* HTTP Specific Info */ + ptr->type = EVHTTP_REQ_GET ; /* request type GET/PUT/PATCH etc */ + + /* Result Info */ + ptr->status = FAIL; + ptr->http_status = 0 ; + ptr->low_wm = ptr->med_wm = ptr->high_wm = false ; + node_inv_init ( ptr->inv_info ) ; + + ptr->this_time = 0 ; + ptr->prev_time = 0 ; + + memset (&ptr->req_str[0], 0, MAX_API_LOG_LEN); + + return (PASS); +} + + +/* initialize this module */ +void httpUtil_init ( void ) +{ + httpUtil_event_init ( &nullEvent, "null", "null" , "0.0.0.0", 0); + nullEvent.request = SERVICE_NONE ; + + snprintf (&rest_api_filename[0], MAX_FILENAME_LEN, "/var/log/%s_api.log", + program_invocation_short_name ); +} + +/* *********************************************************************** + * + * Name : httpUtil_free_conn + * + * Description: Free an event's connection memory if it exists. + * + * ************************************************************************/ + +void httpUtil_free_conn ( libEvent & event ) +{ + if ( event.conn ) + { + hlog3 ("%s Free Connection (%p)\n", event.log_prefix.c_str(), event.conn ); + evhttp_connection_free ( event.conn ); + event.conn = NULL ; + } + else + { + hlog1 ("%s Already Freed Connection\n", event.log_prefix.c_str()); + } +} + +/* *********************************************************************** + * + * Name : httpUtil_free_base + * + * Description: Free an event's base memory if it exists. + * + * ************************************************************************/ + +void httpUtil_free_base ( libEvent & event ) +{ + /* Free the base */ + if ( event.base ) + { + hlog3 ("%s Free Base (%p)\n", event.log_prefix.c_str(), event.base ); + + event_base_free(event.base); + event.base = NULL ; + if ( event.conn ) + { + hlog ("%s Free Connection (%p) --------- along with base\n", + event.log_prefix.c_str(), event.conn ); + + evhttp_connection_free ( event.conn ); + event.conn = NULL ; + } + } + else + { + hlog1 ("%s Already Freed Event Base\n", event.log_prefix.c_str()); + } +} + +/* *********************************************************************** + * + * Name : httpUtil_connect + * + * Description: Allocate memory for a new connection off the supplied + * base with respect to an ip and port. + * + * ************************************************************************/ + +int httpUtil_connect ( libEvent & event ) +{ + if ( event.base ) + { + hlog ("%s target:%s:%d\n", event.log_prefix.c_str(), event.ip.c_str(), event.port); + + /* Open an http connection to specified IP and port */ + event.conn = evhttp_connection_base_new ( event.base, NULL, + event.ip.c_str(), + event.port ); + /* bind to the correctly-versioned local address */ + if ( event.conn ) + { + return(PASS) ; + } + else + { + elog ("%s create connection failed (evhttp_connection_base_new)\n", event.log_prefix.c_str()); + return (FAIL_CONNECT); + } + } + else + { + slog ("%s Null Event base\n", event.log_prefix.c_str()); + return (FAIL_EVENT_BASE); + } +} + +/* *********************************************************************** + * + * Name : httpUtil_request + * + * Description: Allocate memory for a new request off the supplied base. + * + * ************************************************************************/ + +int httpUtil_request ( libEvent & event, + void(*hdlr)(struct evhttp_request *, void *)) +{ + int rc = PASS ; + + /* make a new request and bind the event handler to it */ + event.req = evhttp_request_new( hdlr , event.base ); + if ( ! event.req ) + { + elog ("%s evhttp_request_new returned NULL\n", event.log_prefix.c_str() ); + rc = FAIL ; + } + return (rc); +} + +/* *********************************************************************** + * + * Name : httpUtil_payload_add + * + * Description: Add the payload to the output buffer. + * + * @returns 0 for success or -1 in error case + * + * ************************************************************************/ + +int httpUtil_payload_add ( libEvent & event ) +{ + int rc = PASS ; + + /* Returns the output buffer. */ + event.buf = evhttp_request_get_output_buffer ( event.req ); + + /* Check for no buffer */ + if ( ! event.buf ) + { + elog ("%s evhttp_request_get_output_buffer returned null (%p)\n", + event.log_prefix.c_str(), event.req ); + + rc = FAIL ; + } + else + { + /* write the body into the buffer */ + rc = evbuffer_add_printf ( event.buf, "%s", event.payload.c_str()); + if ( rc == -1 ) + { + elog ("%s evbuffer_add_printf returned error (-1)\n", + event.log_prefix.c_str()); + + rc = FAIL ; + } + else if ( rc == 0 ) + { + elog ("%s no data added to output buffer (len=0)\n", + event.log_prefix.c_str()); + + rc = FAIL ; + } + else + { + rc = PASS ; + } + } + return (rc); +} + +/* *********************************************************************** + * + * Name : httpUtil_payload_len + * + * Description: Calculate payload length from the output buffer + * and return a string representing that length value. + * + * ************************************************************************/ + +string httpUtil_payload_len ( libEvent * ptr ) +{ + string body_len ; + char len_str[10] ; + int len = evbuffer_get_length ( ptr->req->output_buffer ) ; + if (( len == -1 ) || ( len == 0 )) + { + body_len = "" ; + } + else + { + memset ( &len_str[0], 0 , 10 ); + sprintf ( &len_str[0], "%d", len ); + body_len = len_str ; + hlog2 ("%s Payload Length: %s\n", ptr->log_prefix.c_str(), body_len.c_str() ); + } + return ( body_len ); +} + +/* *********************************************************************** + * + * Name : httpUtil_header_add + * + * Description: Add the supplied list of headers to the http request + * headers section. + * + * ************************************************************************/ + +int httpUtil_header_add ( libEvent * ptr, http_headers_type * hdrs_ptr ) +{ + int rc = PASS ; + + if ( hdrs_ptr->entries > MAX_HEADERS ) + { + elog ("%s Too many headers (%d:%d)\n", + ptr->log_prefix.c_str(), MAX_HEADERS, hdrs_ptr->entries ); + return FAIL ; + } + for ( int i = 0 ; i < hdrs_ptr->entries ; i++ ) + { + /* Add the header */ + rc = evhttp_add_header( ptr->req->output_headers, + hdrs_ptr->entry[i].key.c_str() , + hdrs_ptr->entry[i].value.c_str()); + if ( rc ) + { + elog ("%s evhttp_add_header returned failure (%d:%s:%s)\n", + ptr->log_prefix.c_str(), rc, + hdrs_ptr->entry[i].key.c_str(), + hdrs_ptr->entry[i].value.c_str()); + rc = FAIL ; + break ; + } + } + return (rc); +} + + + +/* *********************************************************************** + * + * Name : httpUtil_get_length + * + * Description: Loads libEvent.response_len with the length of the + * input buffer so we can allocate enough memory to + * copy it into. + * + * Get the length of the json response. + * Deal with oversized messages. + * + * @param event is a reference to the callers libEvent struct + * where it inds the input buffer pointer + * + * @return integer value representing the length of the input buffer + * + * ************************************************************************/ + +int httpUtil_get_length ( libEvent & event ) +{ + event.response_len = evbuffer_get_length (event.req->input_buffer); + if ( event.response_len == 0 ) + { + hlog ("%s Request - Response has not content\n", + event.log_prefix.c_str()); + event.status = FAIL_JSON_ZERO_LEN ; + } + return ( event.response_len ); +} + +/* Load the response string into the event struct */ +int httpUtil_get_response ( libEvent & event ) +{ + if ( httpUtil_get_length ( event ) ) + { + size_t real_len ; + + /* Get a stack buffer, zero it, copy to it and terminate it */ + char * stack_buf_ptr = (char*)malloc (event.response_len+1); + memset ( stack_buf_ptr, 0, event.response_len+1 ); + real_len = evbuffer_remove( event.req->input_buffer, stack_buf_ptr, + event.response_len); + + if ( real_len != event.response_len ) + { + wlog ("%s Length differs from removed length (%ld:%ld)\n", + event.log_prefix.c_str(), + event.response_len, + real_len ); + } + + if ( real_len == 0 ) + { + hlog1 ("%s has no response data\n", event.log_prefix.c_str() ); + } + /* Terminate the buffer , this is where the +1 above is required. + * Without it there is memory corruption reported by Linux */ + *(stack_buf_ptr+event.response_len) = '\0'; + + /* Store the response */ + event.response = stack_buf_ptr ; + + free (stack_buf_ptr); + } + return ( event.status ); +} + +/* *********************************************************************** + * + * Name : mtcHttpUtil_status + * + * Description: Extracts and returns the HTTP execution status + * + * ************************************************************************/ + +int httpUtil_status ( libEvent & event ) +{ + int rc = PASS ; + + if ( !event.req ) + { + elog ("%s Invalid request\n", event.hostname.length() ? event.hostname.c_str() : "unknown" ); + return (FAIL_UNKNOWN_HOSTNAME); + } + event.status = event.http_status = evhttp_request_get_response_code (event.req); + switch (event.status) + { + case HTTP_OK: + case 201: + case 202: + case 203: + case 204: + { + hlog ("%s HTTP_OK (%d)\n", event.hostname.c_str(), event.status ); + event.status = PASS ; + break; + } + /* Authentication error - refresh the token */ + case 401: + { + keyToken_type * token_ptr = tokenUtil_get_ptr() ; + rc = FAIL_AUTHENTICATION ; + token_ptr->delay = true ; /* force delayed token renewal on authentication error */ + break ; + } + case 0: + { + wlog ("%s failed to maintain connection to '%s:%d' for '%s'\n", + event.hostname.c_str(), event.ip.c_str(), event.port, event.log_prefix.c_str() ); + event.status = FAIL_HTTP_ZERO_STATUS ; + rc = FAIL_HTTP_ZERO_STATUS ; + break ; + } + default: + { + hlog2 ("%s Status: %d\n", event.hostname.c_str(), event.status ); + rc = event.status ; + break; + } + } + return (rc); +} + + + +void httpUtil_handler ( struct evhttp_request *req, void *arg ) +{ + unsigned long temp ; + int rc = PASS ; + + UNUSED(req); + libEvent * event_ptr ; + + if ( arg == NULL ) + { + elog ("null base pointer\n"); + return ; + } + + /* find the event for this base */ + if ( keyValObject.get_key ((unsigned long)arg, temp ) != PASS ) + { + wlog ("get_key value 'event' lookup from base (%p) key failed\n", arg ); + return ; + } + + event_ptr = (libEvent*)temp; + if (( event_ptr->request >= SERVICE_LAST ) || ( event_ptr->request == SERVICE_NONE )) + { + slog ("HTTP Event Lookup Failed for http base (%p) <------\n", arg); + return ; + } + + /* Check the HTTP Status Code */ + event_ptr->status = httpUtil_status ( (*event_ptr) ) ; + if ( event_ptr->status == HTTP_NOTFOUND ) + { + elog ("%s returned (Not-Found) (%d)\n", + event_ptr->log_prefix.c_str(), + event_ptr->status); + if ( event_ptr->type != EVHTTP_REQ_POST ) + event_ptr->status = PASS ; + + goto httpUtil_handler_done ; + } + + else if (( event_ptr->status != PASS ) && ( ! req )) + { + elog ("%s Request Timeout (%d)\n", + event_ptr->log_prefix.c_str(), + event_ptr->timeout); + + event_ptr->status = FAIL_TIMEOUT ; + goto httpUtil_handler_done ; + } + + else if ( event_ptr->status != PASS ) + { + goto httpUtil_handler_done ; + } + + /* Delete commands don't have a response unless there is an error. + * Deal with this as a special case - + * Currently only Neutron uses the delete */ + if ( event_ptr->type == EVHTTP_REQ_DELETE ) + { + if ( httpUtil_get_length ( (*event_ptr) ) != 0 ) + { + /* Preserve the incoming status over the get response */ + rc = event_ptr->status ; + httpUtil_get_response ( (*event_ptr) ) ; + event_ptr->status = rc ; + } + if (event_ptr->status == FAIL_JSON_ZERO_LEN ) + event_ptr->status = PASS ; + } + else if ( httpUtil_get_response ( (*event_ptr) ) != PASS ) + { + elog ("%s failed to get response\n", event_ptr->log_prefix.c_str()); + goto httpUtil_handler_done ; + } + + if ( event_ptr->handler ) + { + // ilog ("%s calling event specific handler\n", event_ptr->log_prefix.c_str() ); + rc = event_ptr->handler ( (*event_ptr) ) ; + } + else + { + slog ("%s no event handler bound in\n", event_ptr->log_prefix.c_str() ); + rc = event_ptr->status = FAIL_NULL_POINTER ; + } + +httpUtil_handler_done: + + // hlog2 ("%s Base:%p:%p Event:%p\n", event_ptr->log_prefix.c_str(), event_ptr->base, arg, event_ptr ); + + keyValObject.del_key ((unsigned long)arg ); + event_ptr->active = false ; + + gettime ( event_ptr->done_time ); + timedelta ( event_ptr->send_time, event_ptr->done_time, event_ptr->diff_time ); + + if ( event_ptr->status ) + { + elog ( "%s Failed (rc:%d)\n", + event_ptr->log_prefix.c_str(), + event_ptr->status ); + } + httpUtil_log_event ( event_ptr ); +} + + +/* *********************************************************************** + * + * Name : httpUtil_api_request + * + * Description: Makes an HTTP request based on all the info + * in the supplied libEvent. + * + * This is the primary external interface in this module. + * + * Both blocking and non-blocking request type are supported. + * + * ************************************************************************/ + +/*************************************************************************** + * + * Name : httpUtil_latency_log + * + * Description: Measures command handling time and creates a Latency log + * if that time exceeds the specified threshold (msecs). + * + * Parms: + * event - the event in context + * + * label_ptr - "start" to init the prev_timer or + * - "some label" to identify the point in the code and to + * measure time against the previous call. + * + * msecs - the latency log threshold + * + * Usage: + * + * httpUtil_latency_log ( event, HTTPUTIL_SCHED_MON_START, 0 ); + * + * [ timed code ] + * + * httpUtil_latency_log ( event, "label 1" , msecs ); + * + * [ timed code ] + * + * httpUtil_latency_log ( event, "label 2", msecs ); + * + * ... + * + *****************************************************************************/ + +#define HTTPUTIL_SCHED_MON_START ((const char *)"start") +#define MAX_DELAY_B4_LATENCY_LOG (1700) +void httpUtil_latency_log ( libEvent & event, const char * label_ptr, int line , int msecs ) +{ + event.this_time = gettime_monotonic_nsec () ; + + /* If label_ptr is != NULL and != start then take the measurement */ + if ( label_ptr && strncmp ( label_ptr, HTTPUTIL_SCHED_MON_START, strlen(HTTPUTIL_SCHED_MON_START))) + { + if ( event.this_time > (event.prev_time + (NSEC_TO_MSEC*(msecs)))) + { + llog ("%s ... %4llu.%-4llu msec - %s (%d)\n", event.hostname.c_str(), + ((event.this_time-event.prev_time) > NSEC_TO_MSEC) ? ((event.this_time-event.prev_time)/NSEC_TO_MSEC) : 0, + ((event.this_time-event.prev_time) > NSEC_TO_MSEC) ? ((event.this_time-event.prev_time)%NSEC_TO_MSEC) : 0, + label_ptr, line ); + } + } + /* reset to be equal for next round */ + event.prev_time = event.this_time ; +} + +bool token_recursion = false ; + +int httpUtil_api_request ( libEvent & event ) + +{ + http_headers_type hdrs ; + int hdr_entry = 0 ; + string path = "" ; + bool free_key = true ; + event.status = PASS ; + + event.log_prefix = event.hostname ; + event.log_prefix.append (" "); + event.log_prefix.append (event.service) ; + event.log_prefix.append (" '"); + event.log_prefix.append (event.operation) ; + event.log_prefix.append ("'"); + + hlog ("%s '%s' request\n", event.log_prefix.c_str(), getHttpCmdType_str(event.type)); + + if (( event.request == SERVICE_NONE ) || + ( event.request >= SERVICE_LAST )) + { + slog ("%s Invalid request %d\n", event.log_prefix.c_str(), event.request); + event.status = FAIL_BAD_PARM ; + return (event.status); + } + /* Check for memory leaks */ + if ( event.base ) + { + slog ("%s http base memory leak avoidance (%p)\n", + event.log_prefix.c_str(), event.base ); + + // Be sure to free the key + keyValObject.del_key ((unsigned long)event.base ); + // event_base_free(event.base); + } + + /* Allocate the base */ + event.base = event_base_new(); + if ( event.base == NULL ) + { + elog ("%s No Memory for Request\n", event.log_prefix.c_str()); + event.status = FAIL_EVENT_BASE ; + return (event.status) ; + } + else + { + if ( keyValObject.add_key ((unsigned long)event.base, (unsigned long)&event) != PASS ) + { + slog ("%s failed to store base:event as key (%p) value pair\n", + event.log_prefix.c_str(), event.base ); + + /* lets try and recover from this */ + keyValObject.del_key ((unsigned long)event.base); + if ( keyValObject.add_key ((unsigned long)event.base, (unsigned long)&event) != PASS ) + { + slog ("%s still cannot store base:event after key_del\n", event.log_prefix.c_str()); + + event.status = FAIL_LOCATE_KEY_VALUE ; + goto httpUtil_api_request_done ; + } + } + } + + if ( event.request == KEYSTONE_GET_TOKEN ) + { + event.payload = "" ; + + /* create the json string that can request an authority + * token and write that string to 'payload' */ + event.status = jsonApi_auth_request ( event.hostname, event.payload ); + if ( event.status != PASS ) + { + elog ("%s unable to perform get token request (rc:%d)\n", event.hostname.c_str(), event.status ); + goto httpUtil_api_request_done ; + } + } + else if (( event.request == KEYSTONE_GET_ENDPOINT_LIST ) || + ( event.request == KEYSTONE_GET_SERVICE_LIST )) + { + ; + } + + else if (( event.request == SYSINV_SENSOR_ADD ) || + ( event.request == SYSINV_SENSOR_DEL ) || + ( event.request == SYSINV_SENSOR_LOAD ) || + ( event.request == SYSINV_SENSOR_MOD ) || + ( event.request == SYSINV_SENSOR_MOD_GROUP ) || + ( event.request == SYSINV_SENSOR_ADD_GROUP ) || + ( event.request == SYSINV_SENSOR_DEL_GROUP ) || + ( event.request == SYSINV_SENSOR_LOAD_GROUPS ) || + ( event.request == SYSINV_SENSOR_LOAD_GROUP ) || + ( event.request == SYSINV_SENSOR_GROUP_SENSORS )) + { + ; + } + + else if ( TEST_WITH_NO_TOKEN ) + { + ; + } + else + { + slog ("%s Unsupported Request (%d)\n", event.hostname.c_str(), event.request); + event.status = FAIL_BAD_CASE ; + goto httpUtil_api_request_done ; + } + + /* Establish connection */ + if ( httpUtil_connect ( event )) + { + event.status = FAIL_CONNECT ; + goto httpUtil_api_request_done ; + } + + if ( httpUtil_request ( event, &httpUtil_handler )) + { + event.status = FAIL_REQUEST_NEW ; + goto httpUtil_api_request_done ; + } + + if ( event.request != KEYSTONE_GET_TOKEN ) + { + jlog ("%s Address : %s\n", event.hostname.c_str(), event.address.c_str()); + } + + if (( event.type != EVHTTP_REQ_GET ) && + ( event.type != EVHTTP_REQ_DELETE )) + { + /* Add payload to the output buffer but only for PUT, POST and PATCH requests */ + if ( httpUtil_payload_add ( event )) + { + event.status = FAIL_PAYLOAD_ADD ; + goto httpUtil_api_request_done ; + } + if ( daemon_get_cfg_ptr()->debug_json ) + { + if ((!string_contains(event.payload,"token")) && + (!string_contains(event.payload,"assword"))) + { + jlog ("%s Payload : %s\n", event.hostname.c_str(), + event.payload.c_str() ); + } + else + { + jlog ("%s Payload : ... contains private content ...\n", + event.hostname.c_str()); + + } + } + } + + /* Build the HTTP Header */ + hdrs.entry[hdr_entry].key = "Host" ; + hdrs.entry[hdr_entry].value = event.ip ; + hdr_entry++; + + hdrs.entry[hdr_entry].key = "X-Auth-Project-Id" ; + hdrs.entry[hdr_entry].value = "admin"; + hdr_entry++; + + if (( event.type != EVHTTP_REQ_GET ) && + ( event.type != EVHTTP_REQ_DELETE )) + { + hdrs.entry[hdr_entry].key = "Content-Length" ; + hdrs.entry[hdr_entry].value = httpUtil_payload_len ( &event ); + hdr_entry++; + } + + hdrs.entry[hdr_entry].key = "User-Agent" ; + hdrs.entry[hdr_entry].value = event.user_agent ; + hdr_entry++; + + hdrs.entry[hdr_entry].key = "Content-Type" ; + hdrs.entry[hdr_entry].value = "application/json" ; + hdr_entry++; + + hdrs.entry[hdr_entry].key = "Accept" ; + hdrs.entry[hdr_entry].value = "application/json" ; + hdr_entry++; + + if ( event.request != KEYSTONE_GET_TOKEN ) + { + hdrs.entry[hdr_entry].key = "X-Auth-Token" ; + hdrs.entry[hdr_entry].value = tokenUtil_get_ptr()->token ; + hdr_entry++; + } + + hdrs.entry[hdr_entry].key = "Connection" ; + hdrs.entry[hdr_entry].value = "close" ; + hdr_entry++; + hdrs.entries = hdr_entry ; + + /* Add the headers */ + if ( httpUtil_header_add ( &event, &hdrs )) + { + event.status = FAIL_HEADER_ADD ; + goto httpUtil_api_request_done ; + } + + /* get some timestamps and log the request */ + snprintf (&event.req_str[0], MAX_API_LOG_LEN-1, + "\n%s [%5d] %s %s '%s' seq:%d -> Address : %s:%d %s %s ... %s", + pt(), getpid(), + event.hostname.c_str(), + event.service.c_str(), + event.operation.c_str(), + event.sequence, event.ip.c_str(), event.port, + getHttpCmdType_str( event.type ), + event.address.c_str(), + event.information.c_str()); + + gettime ( event.send_time ); + gettime ( event.done_time ); /* create a valid done value */ + + if ( event.request == KEYSTONE_GET_TOKEN ) + { + path = MTC_POST_KEY_LABEL ; + event.address = path ; + event.prefix_path += path; + hlog ("%s Keystone Internal Address : %s\n", event.hostname.c_str(), event.prefix_path.c_str()); + event.status = evhttp_make_request ( event.conn, event.req, event.type, event.prefix_path.data()); + } + else + { + event.status = evhttp_make_request ( event.conn, event.req, event.type, event.address.data()); + } + daemon_signal_hdlr (); + if ( event.status == PASS ) + { + string label = event.log_prefix ; + label.append (" - "); + label.append (event.operation); + + /* O.K we are commited to making the request */ + free_key = false ; + + evhttp_connection_set_timeout(event.conn, event.timeout); + + httpUtil_latency_log ( event, HTTPUTIL_SCHED_MON_START,__LINE__, 0 ); + + /* Default to retry for both blocking and non-blocking command */ + event.status = RETRY ; + if ( event.blocking == true ) + { + hlog ("%s Requested (blocking) (to:%d)\n", event.log_prefix.c_str(), event.timeout); + + /* Send the message with timeout */ + event_base_dispatch(event.base); + httpUtil_latency_log ( event, label.c_str(), __LINE__, MAX_DELAY_B4_LATENCY_LOG ); + goto httpUtil_api_request_done ; + } + else if ( event.request == KEYSTONE_GET_TOKEN ) + { + httpUtil_event_info (event); + event.active = true ; + event.status = event_base_loop(event.base, EVLOOP_NONBLOCK); + httpUtil_latency_log ( event, label.c_str(), __LINE__, MAX_DELAY_B4_LATENCY_LOG ); /* Should be immediate ; non blocking */ + return (event.status); + // goto httpUtil_api_request_done ; + } + else + { + hlog ("%s Requested (blocking) (to:%d)\n", event.log_prefix.c_str(), event.timeout ); + event_base_dispatch(event.base); + httpUtil_latency_log ( event, label.c_str(), __LINE__, MAX_DELAY_B4_LATENCY_LOG ) ; + goto httpUtil_api_request_done ; + } + } + else + { + elog ("%s Call to 'evhttp_make_request' failed (rc:%d)\n", + event.hostname.c_str(), event.status); + } + +httpUtil_api_request_done: + + httpUtil_free_conn ( event ); + httpUtil_free_base ( event ); + + /* If the request fails then delete the key here */ + if ( free_key ) + { + keyValObject.del_key ((unsigned long)event.base) ; + } + + return (event.status); +} + + +void httpUtil_event_info ( libEvent & event ) +{ + ilog ("%s request to %s.%d Status:%d \n", + event.log_prefix.c_str(), + event.ip.c_str(), + event.port, + event.status); + if ( event.request == KEYSTONE_GET_TOKEN ) + { + ilog ("--- Address : %s\n", event.prefix_path.c_str()); + } + else + { + ilog ("--- Address : %s\n", event.address.c_str()); + } + ilog ("--- Payload : %s\n", event.payload.c_str()); + ilog ("--- Response: %s\n", event.response.c_str()); + ilog ("--- TokenUrl: %s\n", event.token.url.c_str()); +} + +void httpUtil_log_event ( libEvent * event_ptr ) +{ + string event_sig = daemon_get_cfg_ptr()->debug_event ; + msgSock_type * mtclogd_ptr = get_mtclogd_sockPtr (); + + send_log_message ( get_mtclogd_sockPtr(), event_ptr->hostname.data(), &rest_api_filename[0], &event_ptr->req_str[0] ); + + if ( event_ptr->request == KEYSTONE_GET_TOKEN ) + { + jlog1 ("%s seq:%d -> %s:%d %s %s http status: %d ... %s\n", + event_ptr->log_prefix.c_str(), + event_ptr->sequence, + event_ptr->ip.c_str(), + event_ptr->port, + getHttpCmdType_str( event_ptr->type ), + event_ptr->prefix_path.c_str(), + event_ptr->http_status, + event_ptr->information.c_str()); + } + else + { + jlog1 ("%s seq:%d -> %s:%d %s %s http status: %d ... %s\n", + event_ptr->log_prefix.c_str(), + event_ptr->sequence, + event_ptr->ip.c_str(), + event_ptr->port, + getHttpCmdType_str( event_ptr->type ), + event_ptr->address.c_str(), + event_ptr->http_status, + event_ptr->information.c_str()); + } + + if (!event_ptr->payload.empty()) + { + if ((!string_contains(event_ptr->payload,"token")) && + (!string_contains(event_ptr->payload,"assword"))) + { + snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1, + "%s [%5d] %s seq:%d -> Payload : %s", + pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence, event_ptr->payload.c_str() ); + } + else + { + snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1, + "%s [%5d] %s seq:%d -> Payload : ... contains private content ...", + pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence ); + } + send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), &rest_api_filename[0], &rest_api_log_str[0] ); + } + + if ( !event_ptr->response.empty() ) + { + if ((!string_contains(event_ptr->response,"token")) && + (!string_contains(event_ptr->response,"assword"))) + { + snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1, + "%s [%5d] %s seq:%d -> Response: %s", + pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence, event_ptr->response.c_str() ); + } + else + { + snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1, + "%s [%5d] %s seq:%d -> Response: ... contains private content ...", + pt(), getpid(), event_ptr->log_prefix.c_str(), event_ptr->sequence ); + } + send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), rest_api_filename, &rest_api_log_str[0] ); + } + + snprintf (&rest_api_log_str[0], MAX_API_LOG_LEN-1, + "%s [%5d] %s %s '%s' seq:%d -> Status : %d {execution time %ld.%06ld secs}\n", + pt(), getpid(), + event_ptr->hostname.c_str(), + event_ptr->service.c_str(), + event_ptr->operation.c_str(), + event_ptr->sequence, + event_ptr->http_status, + event_ptr->diff_time.secs, + event_ptr->diff_time.msecs ); + + if (( event_ptr->diff_time.secs > 2 ) || (event_ptr->http_status != HTTP_OK ) ) + { + int len = strlen (rest_api_log_str) ; + snprintf (&rest_api_log_str[len-1], 20, " <---------"); + } + + send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), &rest_api_filename[0], &rest_api_log_str[0] ); +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/httpUtil.h b/mtce-common/cgts-mtce-common-1.0/common/httpUtil.h new file mode 100644 index 00000000..294f2a51 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/httpUtil.h @@ -0,0 +1,346 @@ +#ifndef __INCLUDE_HTTPUTIL_H__ +#define __INCLUDE_HTTPUTIL_H__ + +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +#include /* for ... string */ +#include /* for ... http libevent client */ +#include +#include + +using namespace std; + +#include "nodeBase.h" +#include "timeUtil.h" /* for ... time_delta_type */ + +/* HTTP Error Codes with no specific existing define MACRO */ +#define MTC_HTTP_BAD_REQUEST 400 +#define MTC_HTTP_UNAUTHORIZED 401 +#define MTC_HTTP_FORBIDDEN 403 +#define MTC_HTTP_CONFLICT 409 +#define MTC_HTTP_LENGTH_REQUIRED 411 +#define MTC_HTTP_NORESPONSE 444 +#define MTC_HTTP_UNPROCESSABLE_ENTITY 422 + +#define MTC_HTTP_ACCEPTED 202 + +#define EVENT_METHODS (EVHTTP_REQ_PATCH | \ + EVHTTP_REQ_POST | \ + EVHTTP_REQ_GET | \ + EVHTTP_REQ_PUT | \ + EVHTTP_REQ_DELETE) + +/** Maximum libevent response message size in bytes. */ +// #define MAX_EVENT_LEN (163840) +#define MAX_URL_LEN (200) + +#define HTTP_VIM_TIMEOUT (20) + +#define HTTP_MAX_RETRIES (3) + +#define HTTP_SYSINV_CRIT_TIMEOUT (20) +#define HTTP_SYSINV_NONC_TIMEOUT (10) + +#define HTTP_TOKEN_TIMEOUT (15) +#define HTTP_KEYSTONE_GET_TIMEOUT (10) +#define HTTP_SMGR_TIMEOUT (20) +#define HTTP_VIM_TIMEOUT (20) + +#define SMGR_MAX_RETRIES (3) + +#define CLIENT_HEADER "User-Agent" +#define CLIENT_SYSINV_1_0 "sysinv/1.0" +#define EVENT_SERVER "HTTP Event Server" + +#define SMGR_EVENT_SIG "smgrEvent" +#define SYSINV_EVENT_SIG "sysinvEvent" + +#define KEYSTONE_SIG "token" +#define SENSOR_SIG "sensor" +#define SYSINV_SIG "sysinv" +#define SMGR_SIG "smgr" +#define VIM_SIG "vim" + +#define SYSINV_OPER__LOAD_HOST "load host" +#define SYSINV_OPER__UPDATE_TASK "update task" +#define SYSINV_OPER__FORCE_TASK "force task" +#define SYSINV_OPER__UPDATE_UPTIME "update uptime" +#define SYSINV_OPER__UPDATE_VALUE "update value" +#define SYSINV_OPER__UPDATE_STATE "update state" +#define SYSINV_OPER__UPDATE_STATES "update states" +#define SYSINV_OPER__FORCE_STATES "force states" +#define SYSINV_OPER__CONFIG_SHOW "config show" +#define SYSINV_OPER__CONFIG_MODIFY "config modify" + +#define VIM_HOST__DISABLED "disabled" +#define VIM_HOST__ENABLED "enabled" +#define VIM_HOST__OFFLINE "offline" +#define VIM_HOST__FAILED "failed" + +/** The workQueue_process FSM states */ +typedef enum { + HTTP__TRANSMIT = 0, + HTTP__RECEIVE_WAIT = 1, + HTTP__RECEIVE = 2, + HTTP__FAILURE = 3, + HTTP__DONE_FAIL = 4, + HTTP__DONE_PASS = 5, + HTTP__STAGES = 6 +} httpStages_enum ; + +#define HTTP_RECEIVE_WAIT_MSEC (10) + +typedef struct +{ + string url ; /**< Keystone server URL string */ + string issued ; /**< Timestamp token was issued */ + string expiry ; /**< Timestamp when token is expired */ + string token ; /**< The huge 3kb token */ + bool refreshed; /**< set true when refreshed */ + bool delay ; /**< trigger renew with small delay + error renewal - flood avoidance */ +} keyToken_type ; + +/** All supported Request Type Enums */ +typedef enum { + SERVICE_NONE, + + SYSINV_ADD, + SYSINV_GET, + SYSINV_HOST_QUERY, + SYSINV_UPDATE, + + SYSINV_CONFIG_SHOW, + SYSINV_CONFIG_MODIFY, + + SYSINV_SENSOR_LOAD, + SYSINV_SENSOR_LOAD_GROUPS, + SYSINV_SENSOR_LOAD_GROUP, + SYSINV_SENSOR_ADD, + SYSINV_SENSOR_ADD_GROUP, + SYSINV_SENSOR_DEL, + SYSINV_SENSOR_DEL_GROUP, + SYSINV_SENSOR_MOD, + SYSINV_SENSOR_MOD_GROUP, + SYSINV_SENSOR_GROUP_SENSORS, + + VIM_UPDATE, + VIM_HOST_DISABLED, + VIM_HOST_ENABLED, + VIM_HOST_OFFLINE, + VIM_HOST_FAILED, + VIM_DPORT_FAILED, + VIM_DPORT_CLEARED, + VIM_DPORT_DEGRADED, + VIM_DPORT_OFFLINE, + VIM_HOST_QUERY, + + VIM_HOST_STATE_QUERY, + VIM_HOST_INSTANCE_QUERY, + VIM_HOST_INSTANCE_FAILED, + VIM_HOST_INSTANCE_STATUS, + VIM_HOST_INSTANCE_NOTIFY, + + SMGR_START_SWACT, + SMGR_QUERY_SWACT, + SMGR_HOST_UNLOCKED, + SMGR_HOST_LOCKED, + SMGR_HOST_ENABLED, + SMGR_HOST_DISABLED, + + KEYSTONE_TOKEN, + KEYSTONE_GET_TOKEN, + KEYSTONE_GET_SERVICE_LIST, + KEYSTONE_GET_ENDPOINT_LIST, + + TEST_WITH_NO_TOKEN, + TEST_WITH_TOKEN, + + SERVICE_LAST +} libEvent_enum ; + + +/** Local event control structure for REST API services + * + * Nova, Neutron, Keystone and Inventory + * + */ +struct libEvent +{ + /** Execution Controls */ + httpStages_enum state ; /**< This http request FSM state */ + int sequence ; /**< Event sequence number */ + bool mutex ; /**< single operation at a time */ + bool active ; /**< true if waiting on response */ + int stuck ; /**< Count mutex active stuck state */ + bool blocking ; /**< true if command is blocking */ + bool found ; /**< true if query was found */ + int timeout ; /**< Request timeout */ + int count ; /**< retry recover counter */ + int fails ; /**< fail counter */ + int retries ; /**< number of retries on failure*/ + int cur_retries ; + int max_retries ; + bool noncritical ; /**< true: event is non-ctitical */ + int rx_retry_cnt ; /**< help avoid infinite rx retry*/ + int rx_retry_max ; /**< each cmd can have a max */ + /* HTTP request Info */ + enum evhttp_cmd_type type; /**< HTTP Request Type ; PUT/GET */ + struct event_base *base; /**< libEvent API service base */ + struct evhttp_connection *conn; /**< HTTP connection ptr */ + struct evhttp_request *req ; /**< HTTP request ptr */ + struct evbuffer *buf ; /**< HTTP output buffer ptr */ + struct evbuffer_ptr evp ; /**< HTTP output buffer ptr */ + + string log_prefix ; /**< log prefix for this event */ + + /** Service Specific Request Info */ + libEvent_enum request ; /**< Specify the request command */ + keyToken_type token ; /**< Copy of the active token */ + string service ; /**< Service being executed */ + string hostname ; /**< Target hostname */ + string uuid ; /**< The UUID for this request */ + string new_uuid ; /**< The UUID created & returned */ + string ip ; /**< Server IP address */ + int port ; /**< Server port number */ + string operation ; /**< Specify the operation */ + string information ; + string key ; + string value ; + string prefix_path ; + string label ; /**< typically a response label */ + string entity_path ; /**< HTTP entity request string */ + string entity_path_next ; /**< next entity request string */ + string address ; /**< http url address */ + string payload ; /**< the request's payload */ + string user_agent ; /**< set the User-Agent header */ + + /** Result Info */ + int status ; /**< Execution Status */ + int http_status ; /**< raw http returned status */ + int exec_time_msec ; /**< execution time in msec */ + node_inv_type inv_info ; + size_t response_len ; /**< the json response length */ + string response ; /**< the json response string */ + string result ; /**< Command specific result str */ + + /* Endpoint strings */ + string admin_url ; + string internal_url ; + string public_url ; + + time_debug_type send_time ; /**< Request Dispatch Timestamp */ + time_debug_type done_time ; /**< Response Handler Timestamp */ + time_delta_type diff_time ; /**< how long the command handling took */ + + bool low_wm ; + bool med_wm ; + bool high_wm ; + + int (*handler) (struct libEvent &) ; + + char req_str[MAX_API_LOG_LEN] ; + + unsigned long long prev_time ; /* latency log candidate start (prev) time */ + unsigned long long this_time ; /* ... end (now or this) time */ + +} ; + + +typedef struct +{ + struct event_base * base_ptr ; + struct libEvent * event_ptr ; +} event_base_pair_type ; + +typedef struct +{ + int elements ; + list pair_list ; +} event_base_list_type ; + + + +/** Maximum number of headers that can be added to an HTTP message. */ +#define MAX_HEADERS (10) + +/** A header entry type. */ +typedef struct +{ + string key ; /**< the header label. */ + string value ; /**< the header value. */ +} http_header_entry_type; + +/** The header entry table. */ +typedef struct +{ + int entries ; /**< Number of entries in the header table. */ + http_header_entry_type entry[MAX_HEADERS]; /**< entry array. */ +} http_headers_type ; + +void httpUtil_init ( void ); + +int httpUtil_event_init ( libEvent * ptr , + string hostname, + string service, + string ip, + int port ); + +/** Add payload to the HTTP message body. */ +int httpUtil_payload_add ( libEvent & event ); + +/** Add all headers in header table to the HTTP connection message. */ +int httpUtil_header_add ( libEvent * ptr, http_headers_type * hdrs_ptr ); + +/** Create an HTTP request. */ +int httpUtil_request_make ( libEvent * ptr, enum evhttp_cmd_type type, string path ); + +/** Open a connection to an HTTP server. */ +int httpUtil_connect ( libEvent & event ); + +/** Get a new HTTP request pointer. */ +int httpUtil_request ( libEvent & event, + void(*hdlr)(struct evhttp_request *, void *)); + +/** Common REST API Request Utility */ +int httpUtil_api_request ( libEvent & event ); + +/** Common REST API Request Utility */ +int httpUtil_request ( libEvent & event , bool block, + void(*hdlr)(struct evhttp_request *, void *)); + +/** Common REST API Receive Utility for non-blocking requests */ +int httpUtil_receive ( libEvent & event ); + +/** HTTP response status checker */ +int httpUtil_status ( libEvent & event ); + +/** Free the libEvent */ +void httpUtil_free_base ( libEvent & event ); + +/** Free the event lib connection */ +void httpUtil_free_conn ( libEvent & event ); + +/** TODO: FIXME: Get the payload string length. */ +string httpUtil_payload_len ( libEvent * ptr ); + +/** Get the length of the json response */ +int httpUtil_get_length ( libEvent & event ); + +/** Load the json response into the event struct */ +int httpUtil_get_response ( libEvent & event ); + +/** print event filtered event */ +void httpUtil_log_event ( libEvent * event ); + +void httpUtil_event_info ( libEvent & event ); + +const char * getHttpCmdType_str ( evhttp_cmd_type type ); + + +#endif /* __INCLUDE_HTTPUTIL_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/ipmiUtil.cpp b/mtce-common/cgts-mtce-common-1.0/common/ipmiUtil.cpp new file mode 100644 index 00000000..7cc0e05b --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/ipmiUtil.cpp @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + * + * + * @file + * Wind River Titanium Cloud Common IPMI Utilities + */ +#include +#include +#include + +using namespace std; + +#include "nodeBase.h" /* for ... mtce node common definitions */ +#include "hostUtil.h" /* for ... mtce host common definitions */ +#include "ipmiUtil.h" /* for ... this module header */ +#include "nodeClass.h" /* for ... */ + +/* Create a randomly named password filename */ +void ipmiUtil_create_pw_fn ( thread_info_type * info_ptr, string pw ) +{ + info_ptr->password_file.clear (); + string password_tempfile = IPMITOOL_OUTPUT_DIR ; + password_tempfile.append(".") ; + password_tempfile.append(program_invocation_short_name); + password_tempfile.append("-"); + password_tempfile.append(info_ptr->hostname); + password_tempfile.append("-"); + + info_ptr->pw_file_fd = hostUtil_mktmpfile (info_ptr->hostname, + password_tempfile, + info_ptr->password_file, + pw ); + if ( info_ptr->pw_file_fd <= 0 ) + { + info_ptr->status_string = "failed to get an open temporary password filedesc" ; + info_ptr->status = FAIL_FILE_CREATE ; + info_ptr->password_file.clear(); + } + else + { + /* clean-up */ + if ( info_ptr->pw_file_fd > 0 ) + close(info_ptr->pw_file_fd); + info_ptr->pw_file_fd = 0 ; + } +} + +/* Create the ipmitool output_filename */ +string ipmiUtil_create_data_fn ( string & hostname, string file_suffix ) +{ + /* create the output filename */ + string ipmitool_datafile = IPMITOOL_OUTPUT_DIR ; + ipmitool_datafile.append(program_invocation_short_name); + ipmitool_datafile.append("_"); + ipmitool_datafile.append(hostname); + + /* add the sensor list command */ + ipmitool_datafile.append(file_suffix); + + return ( ipmitool_datafile ); +} + +/* Create the ipmi request */ +string ipmiUtil_create_request ( string cmd, string & ip, string & un, string & pw, string & out ) +{ + /* ipmitool -I lanplus -H $uut_ip -U $uut_un -E */ + /* build the ipmitool command */ + string ipmitool_request = IPMITOOL_PATH_AND_FILENAME ; + + /* Specify lanplus network mode for centralized power control, 1 retry + * followed by the bm ip address and password file */ + ipmitool_request.append(" -I lanplus -R 1 -H "); + ipmitool_request.append(ip); + + /* then specify the bmc username */ + ipmitool_request.append(" -U "); + ipmitool_request.append(un); + + if ( daemon_is_file_present ( MTC_CMD_FIT__LOUD_BM_PW ) == true ) + { + /* get the password from the file and put it on the command line */ + ipmitool_request.append(" -P "); + ipmitool_request.append(daemon_get_file_str(pw.data())); + } + else + { + /* add the password file option and file */ + ipmitool_request.append(" -f "); + ipmitool_request.append(pw); + } + + /* add the command */ + ipmitool_request.append(" "); + ipmitool_request.append(cmd); + + /* output filename */ + ipmitool_request.append (" > "); + ipmitool_request.append (out); + + return (ipmitool_request); +} + +/* init the mc info struct */ +void ipmiUtil_mc_info_init ( mc_info_type & mc_info ) +{ + mc_info.device_id.clear(); + mc_info.manufacturer_name.clear(); + mc_info.manufacturer_id.clear(); + mc_info.product_name.clear(); + mc_info.product_id.clear(); + mc_info.fw_version.clear(); + mc_info.hw_version.clear(); +} + +/* print a log of the mc info data */ +void mc_info_log ( string hostname, mc_info_type & mc_info, int rc ) +{ + if ( rc ) + { + elog ("%s mc info load failed (rc:%d)\n", hostname.c_str(), rc ); + } + else + { + ilog ("%s Manufacturer: %s [id:%s] [ Device: %s ver %s ]\n", + hostname.c_str(), + mc_info.manufacturer_name.c_str(), + mc_info.manufacturer_id.c_str(), + mc_info.device_id.c_str(), + mc_info.hw_version.c_str()); + + ilog ("%s Product Name: %s [id:%s] [ BMC FW: ver %s ]\n", + hostname.c_str(), + mc_info.product_name.c_str(), + mc_info.product_id.c_str(), + mc_info.fw_version.c_str()); + } +} + +/* load the specified key value in buffer line into 'value' */ +bool _got_delimited_value ( char * buf_ptr, const char * key, const char * delimiter, string & value ) +{ + if ( strstr ( buf_ptr, key )) + { + string _str = buf_ptr ; + if ( _str.find(key) != std::string::npos ) + { + if ( _str.find( delimiter ) != std::string::npos ) + { + int y = _str.find( delimiter ) ; + value = _str.substr ( y+strlen(delimiter), std::string::npos) ; + value.erase ( value.size()-1, std::string::npos ) ; + return (true); + } + } + } + return (false); +} + +/***************************************************************************** + * + * Name : ipmiUtil_mc_info_load + * + * Description: Load the contents of a file containing an ipmitool formatted + * output from an mc info request into the passed in mc_info + * struct. Loaded info includes + * + * Manufacturer (id/name) + * Product (id/name) + * Device (id/version) + * Firmware (version) + * + * A log like the following is generated. + * + * controller-0 mc info: Nokia:7244 - Quanta:12866 (0x3242) [bmc fw:3.29] [device:32 ver:1] + * + * Example MC Info output from ipmitool + * + * Device ID : 32 + * Device Revision : 1 + * Firmware Revision : 3.29 + * IPMI Version : 2.0 + * Manufacturer ID : 7244 + * Manufacturer Name : Nokia + * Product ID : 12866 (0x3242) + * Product Name : Quanta + * Device Available : yes + * Provides Device SDRs : no + * Additional Device Support : + * Sensor Device + * SDR Repository Device + * SEL Device + * FRU Inventory Device + * Chassis Device + * + **************************************************************************/ + +#define BUFFER (80) +int ipmiUtil_mc_info_load ( string hostname, const char * filename, mc_info_type & mc_info ) +{ + int rc = FAIL ; + ipmiUtil_mc_info_init ( mc_info ); + if ( daemon_is_file_present ( filename ) ) + { + FILE * _stream = fopen ( filename, "r" ); + if ( _stream ) + { + char buffer [BUFFER]; + MEMSET_ZERO(buffer); + while ( fgets (buffer, BUFFER, _stream) ) + { + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_FW_VERSION, MC_INFO_LABEL_DELIMITER, mc_info.fw_version )) + { + rc = PASS ; + continue; + } + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_HW_VERSION, MC_INFO_LABEL_DELIMITER, mc_info.hw_version )) + continue; + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_DEVICE_ID, MC_INFO_LABEL_DELIMITER, mc_info.device_id )) + continue; + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_PRODUCT_ID, MC_INFO_LABEL_DELIMITER, mc_info.product_id )) + continue; + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_PRODUCT_NAME, MC_INFO_LABEL_DELIMITER, mc_info.product_name )) + continue; + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_MANUFACTURE_ID, MC_INFO_LABEL_DELIMITER, mc_info.manufacturer_id )) + continue; + if ( _got_delimited_value ( buffer, MC_INFO_LABEL_MANUFACTURE_NAME, MC_INFO_LABEL_DELIMITER, mc_info.manufacturer_name )) + continue; + else + blog3 ("buffer: %s\n", buffer ); + MEMSET_ZERO(buffer); + } + fclose(_stream); + } + } + else + { + elog ("%s failed to open mc info file '%s'\n", hostname.c_str(), filename); + rc = FAIL_FILE_ACCESS ; + } + + mc_info_log ( hostname, mc_info, rc ); + return (rc); +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/ipmiUtil.h b/mtce-common/cgts-mtce-common-1.0/common/ipmiUtil.h new file mode 100644 index 00000000..3a4c650f --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/ipmiUtil.h @@ -0,0 +1,102 @@ +#ifndef __INCLUDE_IPMIUTIL_H__ +#define __INCLUDE_IPMIUTIL_H__ + +/* + * Copyright (c) 2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River Titanium Cloud's Maintenance Common IPMI Utilities Header + */ + +#include "nodeBase.h" /* for ... */ +#include "threadUtil.h" /* for ... thread utilities */ + +#define MC_INFO_LABEL_DELIMITER ((const char *)(": ")) +#define MC_INFO_LABEL_FW_VERSION ((const char *)("Firmware Revision")) +#define MC_INFO_LABEL_HW_VERSION ((const char *)("Device Revision")) +#define MC_INFO_LABEL_DEVICE_ID ((const char *)("Device ID")) +#define MC_INFO_LABEL_PRODUCT_ID ((const char *)("Product ID")) +#define MC_INFO_LABEL_PRODUCT_NAME ((const char *)("Product Name")) +#define MC_INFO_LABEL_MANUFACTURE_ID ((const char *)("Manufacturer ID")) +#define MC_INFO_LABEL_MANUFACTURE_NAME ((const char *)("Manufacturer Name")) + +#define IPMITOOL_POWER_RESET_CMD ((const char *)("chassis power reset")) +#define IPMITOOL_POWER_RESET_RESP ((const char *)("Chassis Power Control: Reset")) + +#define IPMITOOL_POWER_OFF_CMD ((const char *)("chassis power off")) +#define IPMITOOL_POWER_OFF_RESP ((const char *)("Chassis Power Control: Down/Off")) + +#define IPMITOOL_POWER_ON_CMD ((const char *)("chassis power on")) +#define IPMITOOL_POWER_ON_RESP ((const char *)("Chassis Power Control: Up/On")) + +#define IPMITOOL_POWER_CYCLE_CMD ((const char *)("chassis power cycle")) +#define IPMITOOL_POWER_CYCLE_RESP ((const char *)("Chassis Power Control: Cycle")) + +#define IPMITOOL_POWER_STATUS_CMD ((const char *)("chassis power status")) +#define IPMITOOL_POWER_ON_STATUS ((const char *)("Chassis Power is on")) +#define IPMITOOL_POWER_OFF_STATUS ((const char *)("Chassis Power is off")) + +#define IPMITOOL_RESTART_CAUSE_CMD ((const char *)("chassis restart_cause")) + +#define IPMITOOL_MC_INFO_CMD ((const char *)("mc info")) + +#define IPMITOOL_CMD_FILE_SUFFIX ((const char *)("_power_cmd_result")) +#define IPMITOOL_MC_INFO_FILE_SUFFIX ((const char *)("_mc_info")) +#define IPMITOOL_RESTART_CAUSE_FILE_SUFFIX ((const char *)("_restart_cause")) +#define IPMITOOL_POWER_STATUS_FILE_SUFFIX ((const char *)("_power_status")) + +#define IPMITOOL_MAX_RECV_RETRIES (10) + +/* Warning : Changes here require 'mtc_ipmiRequest_str' string array to be updated */ +typedef enum +{ + IPMITOOL_THREAD_CMD__NULL = 0, + IPMITOOL_THREAD_CMD__POWER_RESET, + + IPMITOOL_THREAD_CMD__POWER_ON, + IPMITOOL_THREAD_CMD__POWER_OFF, + IPMITOOL_THREAD_CMD__POWER_CYCLE, + + IPMITOOL_THREAD_CMD__MC_INFO, + IPMITOOL_THREAD_CMD__POWER_STATUS, + IPMITOOL_THREAD_CMD__RESTART_CAUSE, + + IPMITOOL_THREAD_CMD__READ_SENSORS, + + IPMITOOL_THREAD_CMD__LAST + +} ipmitool_cmd_enum ; + +const char * getIpmiCmd_str ( int command ); +const char * getIpmiAction_str ( int command ); + + +typedef struct +{ + std::string product_name ; + std::string product_id ; + std::string manufacturer_name ; + std::string manufacturer_id ; + std::string device_id ; + std::string fw_version ; + std::string hw_version ; +} mc_info_type ; + +int ipmiUtil_mc_info_load ( string hostname, const char * filename, mc_info_type & mc_info ); +void ipmiUtil_mc_info_init ( mc_info_type & mc_info ); + +/* Create a randomly named password filename */ +void ipmiUtil_create_pw_fn ( thread_info_type * info_ptr, string pw ); + +/* Create the ipmitool output_filename in info_ptr->password_file */ +string ipmiUtil_create_data_fn ( string & hostname, string file_suffix ); + +/* Create the ipmi request */ +string ipmiUtil_create_request ( string cmd, string & ip, string & un, string & pw, string & out ); + +#endif diff --git a/mtce-common/cgts-mtce-common-1.0/common/jsonUtil.cpp b/mtce-common/cgts-mtce-common-1.0/common/jsonUtil.cpp new file mode 100644 index 00000000..ee84ce7c --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/jsonUtil.cpp @@ -0,0 +1,1260 @@ +/* + * Copyright (c) 2013-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform Controller Maintenance JSON Utilities + */ + +#include +#include +#include +#include +#include /* for ... json-c json string parsing */ +#include + +using namespace std; + +#ifdef __AREA__ +#undef __AREA__ +#endif +#define __AREA__ "jsn" + +#include "nodeClass.h" +#include "nodeUtil.h" +#include "jsonUtil.h" /* JSON Utilities */ + +/* Internal Private Interfaces */ +static struct json_object * _json_verify_object ( struct json_object * obj, + const char * label); +static struct json_object * _json_get_host_next ( struct json_object * obj ); +static struct json_object * _json_object_array_get_idx ( struct json_object * obj, + int index ); +static int _json_get_object_number ( struct json_object * obj ); +static string _json_get_key_value_string ( struct json_object * obj, + const char * key ); + +/* init one element of the struct */ +void jsonUtil_init ( jsonUtil_info_type & info , int index ) +{ + node_inv_init ( info.host[index] ) ; +} + +/* init the entire struct */ +void jsonUtil_init ( jsonUtil_info_type & info ) +{ + info.elements = 0 ; + for ( int i = 0 ; i < MAX_JSON_INV_GET_HOST_NUM ; i++ ) + { + jsonUtil_init ( info , i ) ; + } + info.next = "" ; +} + +/* Validate the supplied label is in the specified object */ +static struct json_object * _json_verify_object ( struct json_object * obj, + const char * label ) +{ + struct json_object * req_obj = (struct json_object *)(NULL); + + json_bool status = json_object_object_get_ex (obj, label, &req_obj); + if (( status == TRUE ) && ( req_obj )) + { + return (req_obj); + } + wlog ("Specified label '%s' not found in response\n", label ); + status = json_object_object_get_ex (obj, "error", &req_obj ); + if (( status == TRUE ) && ( req_obj )) + { + elog ("Found 'error' label instead\n"); + } + else + { + elog ("Neither specified nor error label found in object\n"); + } + return ((struct json_object *)(NULL)) ; +} + +static struct +json_object * _json_get_host_next ( struct json_object * obj ) +{ + /* Get the next host entity path */ + struct json_object * next_obj = (struct json_object *)(NULL); + json_bool status = json_object_object_get_ex(obj, MTC_JSON_INV_NEXT, &next_obj ); + if (( status == TRUE ) && ( next_obj )) + { + return (next_obj); + } + else + { + return ((struct json_object *)(NULL)) ; + } +} + + +/* Get the json host info object */ +static struct +json_object * _json_object_array_get_idx ( struct json_object * obj, int index ) +{ + /* Get the json host array list ; there should be one since + * we read inventory one host at a time */ + struct array_list *array_list_obj = json_object_get_array(obj); + if ( array_list_obj ) + { + int len = array_list_length (array_list_obj); + if ( len == 0 ) + { + ilog ( "No provisioned hosts\n"); + } + else if ( index < len ) + { + struct json_object *node_obj ; + node_obj = json_object_array_get_idx (obj, index ); + if ( node_obj ) + { + return ( node_obj ); + } + else + { + elog ("No json host info object\n"); + } + } + else + { + elog ("No json host for requested index\n"); + } + } + else + { + elog ("No json host array list\n"); + } + + return ((struct json_object *)(NULL)) ; +} + +/* return the number of array objects in the specified object */ +static int _json_get_object_number ( struct json_object * obj ) +{ + /* Get number of elements in the json host array list */ + struct array_list *array_list_obj = json_object_get_array(obj); + if ( array_list_obj ) + { + return ( array_list_length (array_list_obj)); + } + return (0); +} + +string _json_get_key_value_string ( struct json_object * obj, const char * key ) +{ + std::string value = "" ; + + /* Get the node uuid */ + struct json_object * key_obj = (struct json_object *)(NULL); + json_bool status = json_object_object_get_ex(obj, key, &key_obj ); + if ( ( status == TRUE ) && ( key_obj )) + { + value.append(json_object_get_string(key_obj)); + } + else + { + value.append("none"); + } + return ( value ); +} + +string jsonUtil_get_key_value_string ( struct json_object * obj, const char * key ) +{ + return (_json_get_key_value_string ( obj, key )); +} + +int jsonUtil_get_key_value_int ( struct json_object * obj, const char * key ) +{ + int value = 0 ; + + /* Get the node uuid */ + struct json_object * key_obj = (struct json_object *)(NULL); + json_bool status = json_object_object_get_ex(obj, key, &key_obj); + if ( (status == TRUE ) && ( key_obj )) + { + value = json_object_get_int(key_obj); + } + return ( value ); +} + +bool jsonUtil_get_key_value_bool ( struct json_object * obj, const char * key ) +{ + bool value = false ; + + /* Get the node uuid */ + struct json_object * key_obj = (struct json_object *)(NULL); + json_bool status = json_object_object_get_ex(obj, key, &key_obj ); + if (( status == TRUE ) && ( key_obj )) + { + value = json_object_get_boolean(key_obj); + } + else + { + wlog ("failed to get key object\n"); + } + return ( value ); +} + +int jsonUtil_get_key_val ( char * json_str_ptr, + string key, + string & value ) +{ + value = "" ; + + /* init to null to avoid trap on early cleanup call with + * bad non-null default pointer value */ + struct json_object *raw_obj = (struct json_object *)(NULL); + + if ((json_str_ptr == NULL) || ( *json_str_ptr == '\0' ) || ( ! strncmp ( json_str_ptr, "(null)" , 6 ))) + { + elog ("Cannot tokenize a null json string\n"); + elog ("... json string: %s\n", json_str_ptr ); + return (FAIL); + } + + size_t len_before = strlen (json_str_ptr); + + jlog2 ("String: %s\n", json_str_ptr ); + + raw_obj = json_tokener_parse( json_str_ptr ); + if ( raw_obj ) + { + value = _json_get_key_value_string ( raw_obj, key.data() ) ; + jlog1 ("%s:%s\n", key.c_str(), value.c_str()); + } + else + { + size_t len_after = strlen (json_str_ptr); + + elog ("Unable to tokenize string (before:%ld after:%ld);\n", len_before, len_after); + elog ("... json string: %s\n", json_str_ptr ); + } + + if (raw_obj) + json_object_put(raw_obj); + +/* Sometimes gettibng an empty key is acceptable */ +// if ( value.empty() || !value.compare("none") ) +// { +// return (FAIL); +// } + + return (PASS); +} + + +/** This utility freads the passed in inventory GET request + * response json character string and performes the following + * operations with failure detection for each step. + * + * 1. tokenizes the passed in string + * 2. confirms string as valid inventory GET response + * 3. + * 4. + * + * @returns + * PASS if no inventory, + * RETRY if there is a next element + * FAIL if there was a error + * + * Parse and load the data from the json inv request */ +int jsonUtil_inv_load ( char * json_str_ptr, + jsonUtil_info_type & info ) +{ + int rc = PASS ; + + /* init to null to avoid trap on early cleanup call with + * bad non-null default pointer value */ + struct json_object *req_obj = (struct json_object *)(NULL); + struct json_object *raw_obj = (struct json_object *)(NULL); + struct json_object *node_obj = (struct json_object *)(NULL); + struct json_object *next_obj = (struct json_object *)(NULL); + + // printf ("String: <%s>\n", json_str_ptr ); + if (( json_str_ptr == NULL ) || ( *json_str_ptr == '\0' ) || + ( ! strncmp ( json_str_ptr, "(null)" , 6 ))) + { + elog ("Cannot tokenize a null json string\n"); + return (FAIL); + } + raw_obj = json_tokener_parse( json_str_ptr ); + if ( !raw_obj ) + { + elog ("No or invalid inventory GET response\n"); + rc = FAIL ; + goto cleanup ; + } + else + { + jlog1 ("%s\n", json_object_get_string(raw_obj)); + } + + /* Check response sanity */ + req_obj = _json_verify_object ( raw_obj, MTC_JSON_INV_LABEL ); + if ( !req_obj ) + { + elog ("Missing or Invalid JSON Inventory Object\n"); + rc = FAIL ; + goto cleanup ; + } + + /* Get the label used to request the next inventory element */ + next_obj = _json_get_host_next ( raw_obj ); + if ( !next_obj ) + { + info.next.clear(); + } + else + { + info.next.clear(); + info.next.append(json_object_get_string(next_obj)); + } + + /* Limit the amount of batched inventory that can be read at once */ + info.elements = _json_get_object_number ( req_obj ) ; + if ( info.elements > MAX_JSON_INV_GET_HOST_NUM ) + info.elements = MAX_JSON_INV_GET_HOST_NUM ; + + for ( int i = 0 ; i < info.elements ; i++ ) + { + node_obj = _json_object_array_get_idx ( req_obj, i ); + if ( !node_obj ) + { + wlog ("Host object index %d is not present.\n", i ); + rc = RETRY ; + goto cleanup ; + } + + /* Get all required fields */ + info.host[i].uuid = _json_get_key_value_string ( node_obj, MTC_JSON_INV_UUID ); + info.host[i].name = _json_get_key_value_string ( node_obj, MTC_JSON_INV_NAME ); + info.host[i].avail = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL ); + info.host[i].admin = _json_get_key_value_string ( node_obj, MTC_JSON_INV_ADMIN ); + info.host[i].oper = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER ); + info.host[i].mac = _json_get_key_value_string ( node_obj, MTC_JSON_INV_HOSTMAC ); + info.host[i].ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_HOSTIP ); + info.host[i].type = _json_get_key_value_string ( node_obj, MTC_JSON_INV_TYPE ); + info.host[i].func = _json_get_key_value_string ( node_obj, MTC_JSON_INV_FUNC ); + info.host[i].task = _json_get_key_value_string ( node_obj, MTC_JSON_INV_TASK ); + info.host[i].bm_ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_BMIP ); + info.host[i].bm_un = _json_get_key_value_string ( node_obj, MTC_JSON_INV_BMUN ); + info.host[i].bm_type = _json_get_key_value_string( node_obj, MTC_JSON_INV_BMTYPE ); + info.host[i].action = _json_get_key_value_string ( node_obj, MTC_JSON_INV_ACTION ); + info.host[i].uptime = _json_get_key_value_string ( node_obj, MTC_JSON_INV_UPTIME ); + info.host[i].oper_subf = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER_SUBF ); + info.host[i].avail_subf = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL_SUBF); + info.host[i].infra_ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_INFRAIP ); + + if ( info.host[i].uuid.length() != UUID_LEN ) + { + elog ("Failed to get json host uuid string\n"); + rc = FAIL; + } + if ( info.host[i].name.length() == 0 ) + { + elog ("Failed to get json host name string\n"); + rc = FAIL ; + } + // jsonUtil_print ( info, i ); + } + +cleanup: + + if (raw_obj) json_object_put(raw_obj); + if (req_obj) json_object_put(req_obj); + if (next_obj) json_object_put(next_obj); + if (node_obj) json_object_put(node_obj); + + return (rc); +} + +/* This handler does nothing but verify the + tokenization of the response */ +int jsonUtil_patch_load ( char * json_str_ptr, + node_inv_type & info ) +{ + /* init to null to avoid trap on early + * cleanup call with bad non null + * default pointer value */ + struct json_object *node_obj = (struct json_object *)(NULL); + + node_obj = json_tokener_parse( json_str_ptr ); + if ( !node_obj ) + { + elog ("No or invalid inventory PATCH response\n"); + return (FAIL); + } + + /* Get all required fields */ + info.uuid = _json_get_key_value_string ( node_obj, MTC_JSON_INV_UUID ); + info.name = _json_get_key_value_string ( node_obj, MTC_JSON_INV_NAME ); + info.avail = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL ); + info.admin = _json_get_key_value_string ( node_obj, MTC_JSON_INV_ADMIN ); + info.oper = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER ); + info.mac = _json_get_key_value_string ( node_obj, MTC_JSON_INV_HOSTMAC ); + info.ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_HOSTIP ); + info.type = _json_get_key_value_string ( node_obj, MTC_JSON_INV_TYPE ); + info.func = _json_get_key_value_string ( node_obj, MTC_JSON_INV_FUNC ); + info.task = _json_get_key_value_string ( node_obj, MTC_JSON_INV_TASK ); + info.bm_ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_BMIP ); + info.bm_un = _json_get_key_value_string ( node_obj, MTC_JSON_INV_BMUN ); + info.bm_type = _json_get_key_value_string( node_obj, MTC_JSON_INV_BMTYPE ); + info.action= _json_get_key_value_string ( node_obj, MTC_JSON_INV_ACTION ); + info.uptime= _json_get_key_value_string ( node_obj, MTC_JSON_INV_UPTIME ); + info.oper_subf = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER_SUBF ); + info.avail_subf = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL_SUBF); + info.infra_ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_INFRAIP ); + + if (node_obj) json_object_put(node_obj); + + return (PASS); +} + + + +/* Load up json_info with the contents of the json_str */ +int jsonUtil_load_host ( char * json_str_ptr, node_inv_type & info ) +{ + int rc = PASS ; + string error = "" ; + + /* init to null to avoid trap on early cleanup call with + * bad non-null default pointer value */ + struct json_object *node_obj = (struct json_object *)(NULL); + struct json_object *err_obj = (struct json_object *)(NULL); + + if (( json_str_ptr == NULL ) || ( *json_str_ptr == '\0' ) || + ( ! strncmp ( json_str_ptr, "(null)" , 6 ))) + { + elog ("Cannot tokenize a null json string\n"); + return (FAIL); + } + node_obj = json_tokener_parse( json_str_ptr ); + if ( !node_obj ) + { + elog ("No or invalid inventory response\n"); + rc = FAIL ; + goto load_host_cleanup ; + } + + /* Check for error */ + error = _json_get_key_value_string ( node_obj, "error_message" ); + if ( error == "none" ) + { + node_inv_init ( info ); + + /* Get all required fields */ + info.mac = _json_get_key_value_string ( node_obj, MTC_JSON_INV_HOSTMAC); + info.ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_HOSTIP ); + info.uuid = _json_get_key_value_string ( node_obj, MTC_JSON_INV_UUID ); + info.name = _json_get_key_value_string ( node_obj, MTC_JSON_INV_NAME ); + info.avail = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL ); + info.admin = _json_get_key_value_string ( node_obj, MTC_JSON_INV_ADMIN ); + info.oper = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER ); + info.type = _json_get_key_value_string ( node_obj, MTC_JSON_INV_TYPE ); + info.func = _json_get_key_value_string ( node_obj, MTC_JSON_INV_FUNC ); + info.task = _json_get_key_value_string ( node_obj, MTC_JSON_INV_TASK ); + info.bm_ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_BMIP ); + info.bm_un = _json_get_key_value_string ( node_obj, MTC_JSON_INV_BMUN ); + info.bm_type = _json_get_key_value_string( node_obj, MTC_JSON_INV_BMTYPE); + info.action= _json_get_key_value_string ( node_obj, MTC_JSON_INV_ACTION ); + info.uptime= _json_get_key_value_string ( node_obj, MTC_JSON_INV_UPTIME ); + info.id = _json_get_key_value_string ( node_obj, "id" ); + info.oper_subf = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER_SUBF ); + info.avail_subf = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL_SUBF); + info.infra_ip = _json_get_key_value_string ( node_obj, MTC_JSON_INV_INFRAIP ); + + if ( info.uuid.length() != UUID_LEN ) + { + elog ("Failed to get json host uuid string\n"); + rc = FAIL; + } + if ( info.name.length() == 0 ) + { + elog ("Failed to get json host name string\n"); + rc = FAIL ; + } + + } + else + { + std::size_t found ; + /* { "error_message": + "{ "debuginfo": null, + "faultcode": "Server", + "faultstring": "Server controller-0 could not be found." + }" + } + */ + /* get the error */ + found=error.find ( "could not be found" ); + if ( found!=std::string::npos) + { + elog ("%s\n", error.c_str()); + elog ("Requested host not found\n"); + rc = PASS ; + goto load_host_cleanup ; + } + else + { + elog ("Unknown error (%s)\n", error.c_str()); + rc = PASS ; + } + } + +load_host_cleanup: + + if (node_obj) json_object_put(node_obj); + if (err_obj) json_object_put(err_obj); + + return (rc); +} + + +/* Load up json_info with the contents of the json_str */ +int jsonUtil_load_host_state ( char * json_str_ptr, node_inv_type & info ) +{ + int rc = PASS ; + string error = "" ; + + /* init to null to avoid trap on early cleanup call with + * bad non-null default pointer value */ + struct json_object *node_obj = (struct json_object *)(NULL); + struct json_object *err_obj = (struct json_object *)(NULL); + + if (( json_str_ptr == NULL ) || ( *json_str_ptr == '\0' ) || + ( ! strncmp ( json_str_ptr, "(null)" , 6 ))) + { + elog ("Cannot tokenize a null json string\n"); + return (FAIL); + } + node_obj = json_tokener_parse( json_str_ptr ); + if ( !node_obj ) + { + elog ("No or invalid inventory response\n"); + rc = FAIL ; + goto load_host_cleanup ; + } + + /* Check for error */ + error = _json_get_key_value_string ( node_obj, "error_message" ); + if ( error == "none" ) + { + node_inv_init ( info ); + + /* Get all required fields */ + info.uuid = _json_get_key_value_string ( node_obj, MTC_JSON_INV_UUID ); + info.name = _json_get_key_value_string ( node_obj, MTC_JSON_INV_NAME ); + info.avail = _json_get_key_value_string ( node_obj, MTC_JSON_INV_AVAIL ); + info.admin = _json_get_key_value_string ( node_obj, MTC_JSON_INV_ADMIN ); + info.oper = _json_get_key_value_string ( node_obj, MTC_JSON_INV_OPER ); + } + else + { + std::size_t found ; + + /* get the error */ + found=error.find ( "could not be found" ); + if ( found!=std::string::npos) + { + elog ("%s\n", error.c_str()); + elog ("Requested host not found\n"); + rc = PASS ; + goto load_host_cleanup ; + } + else + { + elog ("Unknown error (%s)\n", error.c_str()); + rc = PASS ; + } + } + +load_host_cleanup: + + if (node_obj) json_object_put(node_obj); + if (err_obj) json_object_put(err_obj); + + return (rc); +} + +void jsonUtil_print ( jsonUtil_info_type & info, int index ) +{ + if ( info.elements == 0 ) + return ; + + if ( info.elements < index ) + return ; + + print_inv ( info.host[index] ) ; +} + +// {"auth": {"tenantName": "admin", "passwordCredentials": {"username": "admin", "password": "password"}}} + + +/* TODO: remove "assumed" case in favor of failing utility */ +int jsonApi_auth_request ( string & hostname, string & payload ) +{ + int rc = PASS ; + char * getenv_ptr = NULL ; + string projectname = "" ; + string username = "" ; + string password = "" ; + string userdomain = "" ; + string projectdomain = "" ; + + /* Get local username an password credentials */ + getenv_ptr = daemon_get_cfg_ptr()->keystone_auth_project; + if ( getenv_ptr == NULL ) + { + wlog ("%s Null Project Name\n", hostname.c_str()); + return ( FAIL_AUTHENTICATION ); + } + projectname = getenv_ptr ; + + getenv_ptr = daemon_get_cfg_ptr()->keystone_user_domain; + if ( getenv_ptr == NULL ) + { + wlog ("%s Null User Domain Name\n", hostname.c_str()); + return ( FAIL_AUTHENTICATION ); + } + userdomain = getenv_ptr ; + + getenv_ptr = daemon_get_cfg_ptr()->keystone_project_domain; + if ( getenv_ptr == NULL ) + { + wlog ("%s Null Project Domain Name\n", hostname.c_str()); + return ( FAIL_AUTHENTICATION ); + } + projectdomain = getenv_ptr ; + + getenv_ptr = daemon_get_cfg_ptr()->keystone_auth_username; + if ( getenv_ptr == NULL ) + { + wlog ("%s Null Username\n", hostname.c_str()); + return ( FAIL_AUTHENTICATION ); + } + username = getenv_ptr ; + + getenv_ptr = daemon_get_cfg_ptr()->keystone_auth_pw; + if ( getenv_ptr == NULL ) + { + wlog ("%s Null Password for '%s'\n", hostname.c_str(), username.c_str()); + return ( FAIL_AUTHENTICATION ); + } + password = getenv_ptr ; + + /* + * { + * "auth": + * { + * "identity": + * { + * "methods": ["password"], + * "password": + * { + * "user": + * { + * "name": "user name", + * "domain": { "name": "user domain name" }, + * "password": "password" + * } + * } + * }, + * "scope": + * { + * "project": + * { + * "name": "project name", + * "domain": { "name": "project domain name" } + * } + * } + * } + * } + * + */ + + /***** Create the payload *****/ + payload.append ("{\"auth\": "); + payload.append ("{\"identity\": "); + payload.append ("{\"methods\": [\"password\"],"); + payload.append ("\"password\": "); + payload.append ("{\"user\": {\"name\": \""); + payload.append (username.data()); + payload.append ("\",\"domain\": {\"name\": \""); + payload.append (userdomain.data()); + payload.append ("\"},\"password\": \""); + payload.append (password.data()); + payload.append ("\"}}},"); + payload.append ("\"scope\": "); + payload.append ("{\"project\": {\"name\": \""); + payload.append (projectname.data()); + payload.append ("\", \"domain\": { \"name\": \""); + payload.append (projectdomain.data()); + payload.append ("\"}}}}}"); + + return (rc); +} + +/* Tokenizes the json string and loads info with + * the received token and adminURL. + * The search algorithm below + * + * An authentication response returns the token ID in X-Subject-Token header + * rather than in the response body. + * + * + "token": { <--- 1 + "audit_ids": [ + "LdAVJLRPQwiVN2OkJnuewg" + ], + "expires_at": "2016-06-08T21:16:04.408053Z", <--- 2 + "extras": {}, + "issued_at": "2016-06-08T20:16:04.408082Z", <--- 3 + "methods": [ + "password" + ], + "catalog": [ <--- 4 + { + "endpoints": [ + { + "id": "24177b65a50548519ae5182a5fd44533", + "interface": "public", + "region": "RegionOne", + "region_id": "RegionOne", + "url": "http://10.10.10.2:9696" + }, + { + "id": "52cd1c1b83d9449babfe85b69797c952", + "interface": "internal", + "region": "RegionOne", + "region_id": "RegionOne", + "url": "http://192.168.204.2:9696" + }, + { + "id": "ea7b94d6a9fb4b86acd29985babb61b3", + "interface": "admin", <--- 5 + "region": "RegionOne", + "region_id": "RegionOne", + "url": "http://192.168.204.2:9696" <--- 6 + } + ], + "id": "367ab50ca63e468f8abbf8fe348efe12", + "name": "neutron", + "type": "network" + }, + { ... }]} +*/ +int jsonApi_auth_load ( string & hostname, + char * json_str_ptr, + jsonUtil_auth_type & info ) +{ + json_bool status ; + int rc = FAIL ; + + info.tokenid = "" ; + info.issued = "" ; + info.expiry = "" ; + info.adminURL= "" ; + + /* init to null to avoid trap on early cleanup call */ + struct array_list * array_list_obj = (struct array_list *)(NULL) ; + struct json_object *raw_obj = (struct json_object *)(NULL); + struct json_object *token_obj = (struct json_object *)(NULL); + struct json_object *svccat_obj = (struct json_object *)(NULL); + struct json_object *tuple_obj = (struct json_object *)(NULL); + struct json_object *type_obj = (struct json_object *)(NULL); + struct json_object *url_obj = (struct json_object *)(NULL); + struct json_object *end_obj = (struct json_object *)(NULL); + + bool found_type = false ; + + raw_obj = json_tokener_parse( json_str_ptr ); + if ( !raw_obj ) + { + elog ("%s No or invalid inventory GET response\n", hostname.c_str()); + goto auth_load_cleanup ; + } + + /* Get the token object */ + status = json_object_object_get_ex(raw_obj, MTC_JSON_AUTH_TOKEN, &token_obj); + if (( status == TRUE ) && ( token_obj )) + { + info.issued.append (_json_get_key_value_string(token_obj, MTC_JSON_AUTH_ISSUE )); + info.expiry.append (_json_get_key_value_string(token_obj, MTC_JSON_AUTH_EXPIRE)); + } + else + { + elog ("%s Failed to read %s object label\n", hostname.c_str(), MTC_JSON_AUTH_TOKEN ); + goto auth_load_cleanup ; + } + /* Now look for the compute admin URL */ + /* Get the token object */ + status = json_object_object_get_ex(token_obj, MTC_JSON_AUTH_SVCCAT, &svccat_obj ); + if (( status == TRUE ) && ( svccat_obj )) + { + array_list_obj = json_object_get_array(svccat_obj); + if ( array_list_obj ) + { + string entity ; + int len = array_list_length (array_list_obj); + if ( len == 0 ) + { + ilog ( "%s No reply %s elements\n", hostname.c_str(), MTC_JSON_AUTH_SVCCAT ); + goto auth_load_cleanup; + } + for ( int i = 0 ; i < len ; i++ ) + { + tuple_obj = _json_object_array_get_idx (svccat_obj, i); + entity = _json_get_key_value_string ( tuple_obj, MTC_JSON_AUTH_TYPE ); + if ( entity == MTC_JSON_AUTH_COMP ) + { + found_type = true ; + break ; + } + } + } + } + + if ( found_type == true ) + { + json_bool status = json_object_object_get_ex(tuple_obj, MTC_JSON_AUTH_ENDPOINTS, &end_obj); + if ( ( status == TRUE ) && ( end_obj )) + { + array_list_obj = json_object_get_array(end_obj); + if ( array_list_obj ) + { + + + int len = array_list_length (array_list_obj); + if ( len == 0 ) + { + ilog ( "No reply %s elements in array\n", MTC_JSON_AUTH_ENDPOINTS); + goto auth_load_cleanup; + } + for ( int i = 0 ; i < len ; i++ ) + { + url_obj = _json_object_array_get_idx (end_obj, i); + if ( url_obj ) + { + string inf = _json_get_key_value_string ( url_obj, MTC_JSON_AUTH_INTERFACE ); + if (( inf.length() > 0 ) && (inf == MTC_JSON_AUTH_ADMIN)) + { + info.adminURL = _json_get_key_value_string ( url_obj, MTC_JSON_AUTH_URL); + jlog ( "Found adminURL %s\n", info.adminURL.c_str()); + rc = PASS ; + break ; + } + } + } + } + else + { + elog ("%s Failed to find %s object array\n", + hostname.c_str(), MTC_JSON_AUTH_ENDPOINTS ); + } + } + else + { + elog ("%s Failed to find %s object\n", + hostname.c_str(), MTC_JSON_AUTH_ENDPOINTS ); + } + } + else + { + elog ("%s Failed to find %s object label\n", + hostname.c_str(), MTC_JSON_AUTH_SVCCAT); + } + +auth_load_cleanup: + + if (raw_obj) + { + if ( rc ) + { + wlog ("%s JSON String:%s\n", hostname.c_str(), json_object_get_string(raw_obj)); + } + json_object_put(raw_obj); + } + if (token_obj) json_object_put(token_obj); + if (svccat_obj) json_object_put(svccat_obj); + if (tuple_obj) json_object_put(tuple_obj); + if (end_obj) json_object_put(end_obj); + if (url_obj) json_object_put(type_obj); + if (type_obj) json_object_put(type_obj); + + return (rc); +} + +/*********************************************************************** + * This utility updates the reference key_list with all the + * values for the specified label. + ***********************************************************************/ +int jsonUtil_get_list ( char * json_str_ptr, string label, list & key_list ) +{ + int rc = PASS ; + struct array_list * list_obj = (struct array_list *)(NULL); + struct json_object * label_obj = (struct json_object *)(NULL); + struct json_object * raw_obj = (struct json_object *)(NULL); + struct json_object * item_obj = (struct json_object *)(NULL); + + raw_obj = json_tokener_parse( json_str_ptr ); + if ( !raw_obj ) + { + elog ("unable to parse raw object (%s)\n", json_str_ptr); + rc = FAIL_JSON_OBJECT ; + goto get_list_cleanup ; + } + + label_obj = _json_verify_object (raw_obj, label.data()); + if ( !label_obj ) + { + elog ("unable to find label '%s'\n", label.c_str()); + rc = FAIL_JSON_OBJECT ; + goto get_list_cleanup ; + } + list_obj = json_object_get_array(label_obj); + if ( list_obj ) + { + int len = array_list_length (list_obj); + jlog ( "'%s' array has %d elements\n", label.c_str(), len ); + for ( int i = 0 ; i < len ; i++ ) + { + item_obj = _json_object_array_get_idx (label_obj, i); + jlog1 ("%s %d:%s\n", label.c_str(), i, json_object_get_string(item_obj)); + key_list.push_back (json_object_get_string(item_obj)); + } + } + +get_list_cleanup: + + if (raw_obj) json_object_put(raw_obj); + if (label_obj) json_object_put(label_obj); + if (item_obj) json_object_put(item_obj); + + return (rc); +} + +/*************************************************************************** + * This utility searches for an 'array_label' and then loops over the array + * looking at each element for the specified 'search_key' and 'search_value' + * Once found it searches that same element for the specified 'element_key' + * and loads its value content into 'element_value' - what we're looking for + ***************************************************************************/ +int jsonApi_array_value ( char * json_str_ptr, + string array_label, + string search_key, + string search_value, + string element_key, + string & element_value) +{ + json_bool status ; + int rc = FAIL ; + + /* init to null to avoid trap on early cleanup call */ + struct array_list * array_list_obj = (struct array_list *)(NULL) ; + struct json_object *raw_obj = (struct json_object *)(NULL); + struct json_object *array_obj = (struct json_object *)(NULL); + struct json_object *tuple_obj = (struct json_object *)(NULL); + struct json_object *type_obj = (struct json_object *)(NULL); + + if ( strlen(json_str_ptr) < 3 ) + { + elog ("Null json string\n" ); + rc = FAIL_NULL_POINTER; + goto array_value_cleanup ; + } + raw_obj = json_tokener_parse( json_str_ptr ); + if ( !raw_obj ) + { + elog ("No or invalid json string (%s)\n", json_str_ptr ); + rc = FAIL_JSON_PARSE ; + goto array_value_cleanup ; + } + + /* Now look in each array element for the 'search_key' */ + status = json_object_object_get_ex(raw_obj, array_label.data(), &array_obj ); + if (( status == TRUE ) && ( array_obj )) + { + /* Leaking array_list_obj ???? */ + array_list_obj = json_object_get_array(array_obj); + if ( array_list_obj ) + { + int len = array_list_length (array_list_obj); + if ( len == 0 ) + { + wlog ( "%s has zero array elements\n", array_label.c_str() ); + goto array_value_cleanup; + } + for ( int i = 0 ; i < len ; i++ ) + { + tuple_obj = _json_object_array_get_idx (array_obj, i); + if ( tuple_obj ) + { + string element = _json_get_key_value_string ( tuple_obj, search_key.data() ); + if ( !search_value.compare(element)) + { + /* ok we found "secname : cUSERS" now get the uuid */ + element_value = _json_get_key_value_string ( tuple_obj, element_key.data() ); + if ( !element_value.empty() ) + { + jlog1 ("%s with %s element has %s:%s\n", array_label.c_str(), + search_value.c_str(), + element_key.c_str(), + element_value.c_str()); + rc = PASS ; + } + } + } + } + if ( rc ) + { + elog ("Failed to find %s : %s\n", search_key.c_str(), element_key.c_str()); + rc = FAIL_JSON_OBJECT ; + } + } + } + else + { + elog ("Failed to locate array label (%s)\n", array_label.c_str()); + rc = FAIL_JSON_OBJECT ; + } + +array_value_cleanup: + + if (raw_obj) json_object_put(raw_obj); + if (array_obj) json_object_put(array_obj); + if (tuple_obj) json_object_put(tuple_obj); + if (type_obj) json_object_put(type_obj); + + return (rc); +} + +/*********************************************************************** + * This utility updates the reference string 'element' with the + * contents of the specified labeled array element index. + ***********************************************************************/ +int jsonUtil_get_array_idx ( char * json_str_ptr, + string label, + int idx, + string & element ) +{ + json_bool status ; + int rc = PASS ; + + /* init to null to avoid trap on early cleanup call */ + struct array_list * array_list_obj = (struct array_list *)(NULL) ; + struct json_object *raw_obj = (struct json_object *)(NULL); + struct json_object *array_obj = (struct json_object *)(NULL); + struct json_object *tuple_obj = (struct json_object *)(NULL); + + if ( strlen(json_str_ptr) < 3 ) + { + elog ("Null json string\n" ); + rc = FAIL_NULL_POINTER; + goto get_array_idx_cleanup ; + } + raw_obj = json_tokener_parse( json_str_ptr ); + if ( !raw_obj ) + { + elog ("No or invalid json string (%s)\n", json_str_ptr ); + rc = FAIL_JSON_PARSE ; + goto get_array_idx_cleanup ; + } + + /* Now look in each array element for the 'search_key' */ + status = json_object_object_get_ex(raw_obj, label.data(), &array_obj ); + if (( status == TRUE ) && ( array_obj )) + { + element.clear(); + + array_list_obj = json_object_get_array(array_obj); + if ( array_list_obj ) + { + int len = array_list_length (array_list_obj); + if ( idx < len ) + { + tuple_obj = _json_object_array_get_idx (array_obj, idx); + if ( tuple_obj ) + { + jlog1 ("%s %d:%s\n", label.c_str(), idx, json_object_get_string(tuple_obj)); + element = json_object_get_string(tuple_obj); + } + if ( rc ) + { + elog ("Failed to get '%s' array index %d\n", label.c_str(), idx); + rc = FAIL_JSON_OBJECT ; + } + } + else if ( len == 0 ) + { + dlog ( "%s array has zero elements\n", label.c_str() ); + } + else + { + dlog ( "%s array has fewer elements than the specified index (%d)\n", label.c_str(), idx ); + } + } + } + else + { + elog ("Failed to locate array label (%s)\n", label.c_str()); + rc = FAIL_JSON_OBJECT ; + } + +get_array_idx_cleanup: + + if (raw_obj) json_object_put(raw_obj); + if (array_obj) json_object_put(array_obj); + if (tuple_obj) json_object_put(tuple_obj); + return (rc); +} + + +/*********************************************************************** + * This utility updates the reference element with the number of array + * elements for the specified label in the provided string + ***********************************************************************/ +int jsonUtil_array_elements ( char * json_str_ptr, string label, int & elements ) +{ + json_bool status ; + int rc = FAIL ; + + /* init to null to avoid trap on early cleanup call */ + struct array_list * array_list_obj = (struct array_list *)(NULL) ; + struct json_object *raw_obj = (struct json_object *)(NULL); + struct json_object *array_obj = (struct json_object *)(NULL); + + if ( strlen(json_str_ptr) < 3 ) + { + elog ("Null json string\n" ); + rc = FAIL_NULL_POINTER; + goto array_elements_cleanup ; + } + raw_obj = json_tokener_parse( json_str_ptr ); + if ( !raw_obj ) + { + elog ("No or invalid json string (%s)\n", json_str_ptr ); + rc = FAIL_JSON_PARSE ; + goto array_elements_cleanup ; + } + + /* Now look in each array element for the 'search_key' */ + status = json_object_object_get_ex(raw_obj, label.data(), &array_obj ); + if (( status == TRUE ) && ( array_obj )) + { + array_list_obj = json_object_get_array(array_obj); + if ( array_list_obj ) + { + elements = array_list_length (array_list_obj); + rc = PASS ; + } + } + else + { + elog ("Failed to locate array label (%s)\n", label.c_str()); + rc = FAIL_JSON_OBJECT ; + } + +array_elements_cleanup: + + if (raw_obj) json_object_put(raw_obj); + if (array_obj) json_object_put(array_obj); + + return (rc); +} + +/************************************************************************************* + * + * Name : escapeJsonString + * + * Description: escape special characters in JSON string + * + **************************************************************************************/ +string jsonUtil_escapeSpecialChar(const string& input) +{ + ostringstream ss; + for (string::const_iterator iter = input.begin(); iter != input.end(); iter++) + { + switch (*iter) + { + case '\\': ss << "\\\\"; break; + case '"': ss << "\\\""; break; + case '/': ss << "\\/"; break; + case '\b': ss << "\\b"; break; + case '\f': ss << "\\f"; break; + case '\n': ss << "\\n"; break; + case '\r': ss << "\\r"; break; + case '\t': ss << "\\t"; break; + default: ss << *iter; break; + } + } + return ss.str(); +} + +/*********************************************************************** + * Get JSON Integer Value from Key + * return PASS if success, FAIL if fail. + ***********************************************************************/ +int jsonUtil_get_int( struct json_object *jobj, + const char *key, void *value ) +{ + struct json_object *jobj_value; + if (!json_object_object_get_ex(jobj, key, &jobj_value)) + { + return FAIL; + } + enum json_type type = json_object_get_type(jobj_value); + switch(type) + { + case json_type_boolean: + *(unsigned int *)value = json_object_get_boolean(jobj_value); + break; + case json_type_int: + *(unsigned int *)value = json_object_get_int(jobj_value); + break; + case json_type_double: + *(double *)value = json_object_get_double(jobj_value); + break; + default: + elog("type %d is not supported\n", type); + return FAIL; + break; + } + return PASS; +} + +/*********************************************************************** + * Get JSON String Value from Key + * return PASS if success, FAIL if fail. + ***********************************************************************/ +int jsonUtil_get_string( struct json_object* jobj, + const char* key, string * value ) +{ + struct json_object *jobj_value; + if (!json_object_object_get_ex(jobj, key, &jobj_value)) + { + return FAIL; + } + enum json_type type = json_object_get_type(jobj_value); + const char *str; + switch(type) + { + case json_type_string: + str = json_object_get_string(jobj_value); + break; + default: + elog("type %d is not supported\n", type); + return FAIL; + break; + } + *value = str; + return PASS; +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/jsonUtil.h b/mtce-common/cgts-mtce-common-1.0/common/jsonUtil.h new file mode 100644 index 00000000..780a519b --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/jsonUtil.h @@ -0,0 +1,160 @@ +#ifndef __INCLUDE_JSONUTIL_H__ +#define __INCLUDE_JSONUTIL_H__ +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform Controller Maintenance + * + * JSON Utility Header + */ + +#include +#include +#include "json-c/json.h" + +using namespace std; + +/** Inventory json GET request load struct. + * + * Used to hold/load the parsed contents of the response + * json string returned from an inventory HTTP GET request. */ +typedef struct +{ + int elements ; /**< converted elements */ + /** An array of inventory information, one for each host */ + node_inv_type host[MAX_JSON_INV_GET_HOST_NUM]; + string next ; /**< pointer to the next inventory element */ +} jsonUtil_info_type ; + +#define MTC_JSON_AUTH_TOKEN "token" +#define MTC_JSON_AUTH_SVCCAT "catalog" +#define MTC_JSON_AUTH_TYPE "type" /**< looking for "compute" */ +#define MTC_JSON_AUTH_ENDPOINTS "endpoints" +#define MTC_JSON_AUTH_URL "url" +#define MTC_JSON_AUTH_ISSUE "issued_at" +#define MTC_JSON_AUTH_EXPIRE "expires_at" +#define MTC_JSON_AUTH_ID "X-Subject-Token" +#define MTC_JSON_AUTH_COMP "compute" +#define MTC_JSON_AUTH_INTERFACE "interface" /** looking for admin */ +#define MTC_JSON_AUTH_ADMIN "admin" + + +/** Authroization info loaded from the authorization server */ +typedef struct +{ + bool updated ; /**< true if struct has been updated. */ + int status ; /**< PASS or error code. token is only valid if PASS.*/ + string tokenid ; /**< The long encrypted toke.n */ + string issued ; /**< The "issued_at": "". */ + string expiry ; /**< The "expires": "". */ + string adminURL; /**< path to the nova server. */ +} jsonUtil_auth_type ; + +/** Module initialization interface. + */ +void jsonUtil_init ( jsonUtil_info_type & info ); + +/** Print the authroization struct to stdio. + */ +void jsonUtil_print ( jsonUtil_info_type & info , int index ); +void jsonUtil_print_inv ( node_inv_type & info ); + +int jsonUtil_get_key_val ( char * json_str_ptr, + string key, + string & value ); + +/** Submit a request to get an authorization token and nova URL */ +int jsonApi_auth_request ( string & hostname, string & payload ); + +/** Parse through the authorization request's response json string + * and load the relavent information into the passed in structure */ + int jsonUtil_inv_load ( char * json_str_ptr, + jsonUtil_info_type & info ); + +int jsonUtil_load_host ( char * json_str_ptr, node_inv_type & info ); +int jsonUtil_load_host_state ( char * json_str_ptr, node_inv_type & info ); + +int jsonUtil_hwmon_info ( char * json_str_ptr, node_inv_type & info ); + +/** Handle the patch request response and verify execution status */ +int jsonUtil_patch_load ( char * json_str_ptr, node_inv_type & info ); + +/** Tokenizes the json string and loads 'info' with the received token + * + * @param json_str_ptr + * to a json string + * @param info + * is the updated jsonUtil_auth_type bucket containing the token + * + * @return execution status (PASS or FAIL) + * + *- PASS indicates tokenization ok and info is updated. + *- FAIL indicates bad or error reply in json string. + * + */ +int jsonApi_auth_load ( string & hostname, char * json_str_ptr, + jsonUtil_auth_type & info ); + + +/*************************************************************************** + * This utility searches for an 'array_label' and then loops over the array + * looking at each element for the specified 'search_key' and 'search_value' + * Once found it searches that same element for the specified 'element_key' + * and loads its value content into 'element_value' - what we're looking for + ***************************************************************************/ +int jsonApi_array_value ( char * json_str_ptr, + string array_label, + string search_key, + string search_value, + string element_key, + string & element_value); + +/*********************************************************************** + * This utility updates the reference key_list with all the + * values for the specified label. + ***********************************************************************/ +int jsonUtil_get_list ( char * json_str_ptr, + string label, list & key_list ); + +/*********************************************************************** + * This utility updates the reference element with the number of array + * elements for the specified label in the provided string + ***********************************************************************/ +int jsonUtil_array_elements ( char * json_str_ptr, string label, int & elements ); + +/*********************************************************************** + * This utility updates the reference string 'element' with the + * contents of the specified labeled array element index. + ***********************************************************************/ +int jsonUtil_get_array_idx ( char * json_str_ptr, string label, int idx, string & element ); + +/*********************************************************************** +* Escape special characters in JSON string +************************************************************************/ +string jsonUtil_escapeSpecialChar(const string& input); + +int jsonUtil_get_key_value_int ( struct json_object * obj, const char * key ); +bool jsonUtil_get_key_value_bool ( struct json_object * obj, const char * key ); +string jsonUtil_get_key_value_string ( struct json_object * obj, const char * key ); + +/*********************************************************************** + * Get JSON Integer Value from Key + * return 0 if success, -1 if fail. + ***********************************************************************/ +int jsonUtil_get_int( struct json_object *jobj, + const char *key, void *value ); + +/*********************************************************************** + * Get JSON String Value from Key + * return 0 if success, -1 if fail. + ***********************************************************************/ +int jsonUtil_get_string( struct json_object* jobj, + const char* key, string * value ); + +#endif /* __INCLUDE_JSONUTIL_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/keyClass.cpp b/mtce-common/cgts-mtce-common-1.0/common/keyClass.cpp new file mode 100644 index 00000000..51ed2655 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/keyClass.cpp @@ -0,0 +1,558 @@ +/* + * Copyright (c) 2015 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +/* This module implements a linked list for unsigned long key:value pairs. + * + * Was first introduced to provide to associate a libEvent address with a + * eventLib base pointer so that the event handler could lookup the event + * from the base, Key is base and value is the libEvent address. + * + */ + +#ifdef __AREA__ +#undef __AREA__ +#define __AREA__ "kvp" +#endif + +#include "nodeBase.h" +#include "keyClass.h" +//#include "nodeUtil.h" + + +/* keyClass Constructor */ +keyClass::keyClass() +{ + head = tail = NULL; + memory_allocs = 0 ; + memory_used = 0 ; + keys = 0 ; + + for ( int i = 0 ; i < MAX_KEYS ; i++ ) + { + key_ptrs[i] = NULL ; + } +} + +/* keyClass Destructor */ +keyClass::~keyClass() +{ + for ( int i = 0 ; i < MAX_KEYS ; i++ ) + { + if ( key_ptrs[i] ) + { + delete key_ptrs[i] ; + } + } +} + +/****************************************************************************************** + ********** C O M M O N P R I V A T E I N T E R F A C E S *************** + *****************************************************************************************/ + +/****************************************************************** + * + * Name : newKey (private) + * + * Description: Allocates memory for a new key value pair and + * stores its the address in key_ptrs + * + * @param void + * @return pointer to the newly allocted Key memory + * + *******************************************************************/ +struct keyClass::keyValue * keyClass::newKey ( void ) +{ + struct keyClass::keyValue * key_ptr = NULL ; + + // find an empty spot + for ( int i = 0 ; i < MAX_KEYS ; i++ ) + { + if ( key_ptrs[i] == NULL ) + { + key_ptrs[i] = key_ptr = new keyValue ; + memory_allocs++ ; + memory_used += sizeof (struct keyClass::keyValue); + keys++ ; + return key_ptr ; + } + } + elog ( "Failed to save new key pointer address\n" ); + return key_ptr ; +} + + +/************************************************************************** + * + * Name : delKey (private) + * + * Description: Frees the memory of a pre-allocated key and removes + * it from the key_ptrs list. + * + * @param key * pointer to the key memory address to be freed + * @return int return code { PASS or -EINVAL } + * + **************************************************************************/ +int keyClass::delKey ( struct keyClass::keyValue * key_ptr ) +{ + if ( memory_allocs > 0 ) + { + for ( int i = 0 ; i < MAX_KEYS ; i++ ) + { + if ( key_ptrs[i] == key_ptr ) + { + delete key_ptr ; + key_ptrs[i] = NULL ; + memory_used -= sizeof (struct keyClass::keyValue); + if ( memory_allocs ) memory_allocs-- ; + if ( keys ) keys-- ; + return PASS ; + } + } + elog ( "Unable to validate memory address being freed\n" ); + } + else + elog ( "Free memory called when there is no memory to free\n" ); + + return -EINVAL ; +} + +/***************************************************************** + * + * Name : remKey + * + * Description: Remove a specified key from the linked list + * + *@param unsigned long key signature + *@return PASS or failure codes ENODEV, ENXIO, EFAULT + * + *****************************************************************/ +int keyClass::remKey( struct keyValue * ptr ) +{ + if ( head == NULL ) + return -ENXIO ; + + if ( ptr == NULL ) + return -EFAULT ; + + /* If the key is the head key */ + if ( ptr == head ) + { + /* only one key in the list case */ + if ( head == tail ) + { + dlog3 ("Single Key -> Head Case\n"); + head = NULL ; + tail = NULL ; + } + else + { + dlog3 ("Multiple Keys -> Head Case\n"); + head = head->next ; + head->prev = NULL ; + } + } + /* if not head but tail then there must be more than one + * key in the list so go ahead and chop the tail. + */ + else if ( ptr == tail ) + { + dlog3 ("Multiple Key -> Tail Case\n"); + tail = tail->prev ; + tail->next = NULL ; + } + else + { + dlog3 ("Multiple Key -> Full Splice Out\n"); + ptr->prev->next = ptr->next ; + ptr->next->prev = ptr->prev ; + } + delKey ( ptr ); + + return (PASS) ; +} + + + +/****************************************************************************************** + ********** K E Y T Y P E P R I V A T E I N T E R F A C E S ************* + *****************************************************************************************/ + +/****************************************************************** + * + * Name : addKey (private) + * + * Description: Reprovisions the key:value if it already exists + * Calls newkey to allocates memory for a new key + * and then tacks the new key value onto the end + * of the linked list. + * + * @param unsigned long key and value + * @return pointer to the newly allocted Key memory + * + *******************************************************************/ +struct keyClass::keyValue* keyClass::addKey( unsigned long key__int, unsigned long val__int ) +{ + /* verify key is not already provisioned */ + struct keyValue * ptr = getKey ( key__int ); + if ( ptr ) + { + if ( delKey ( ptr ) ) + { + /* Should never get here but if we do then */ + /* something is seriously wrong */ + elog ("Unable to remove key during reprovision\n"); + return static_cast(NULL); + } + } + + /* allocate memory for new key */ + ptr = newKey (); + if( ptr == NULL ) + { + elog ( "Failed to allocate memory for new key\n" ); + return static_cast(NULL); + } + + /* push the calling data into new key */ + ptr->key__int = key__int ; + ptr->val__int = val__int ; + + dlog3 ("add key:%lx val:%lx\n", ptr->key__int, ptr->val__int ); + + /* If the key list is empty add it to the head */ + if( head == NULL ) + { + head = ptr ; + tail = ptr ; + ptr->prev = NULL ; + ptr->next = NULL ; + } + else + { + /* link the new_key to the tail of the key_list + * then mark the next field as the end of the key_list + * adjust tail to point to the last key + */ + tail->next = ptr ; + ptr->prev = tail ; + ptr->next = NULL ; + tail = ptr ; + } + return ptr ; +} + +/****************************************************************** + * + * Name : getKey (private) + * + * Description: Looks for a key in the linked list. + * + * @param unsigned long key + * @return pointer to the matching key in the linked list + * + *******************************************************************/ +struct keyClass::keyValue * keyClass::getKey ( unsigned long key__int ) +{ + /* check for empty list condition */ + if ( head == NULL ) + return NULL ; + + for ( struct keyValue * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->key__int == key__int ) + { + dlog3 ("get key:%lx val:%lx\n", ptr->key__int, ptr->val__int ); + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return static_cast(NULL); +} + +/*****************************************************************/ +/* String key version */ +/****************************************************************** + * + * Name : addKey (private) + * + * Description: Reprovisions the key:value if it already exists + * Calls newkey to allocates memory for a new key + * and then tacks the new key value onto the end + * of the linked list. + * + * @param unsigned long key and value + * @return pointer to the newly allocted Key memory + * + *******************************************************************/ +struct keyClass::keyValue* keyClass::addKey( string key__str, unsigned long * val__ptr ) +{ + /* verify key is not already provisioned */ + struct keyValue * ptr = getKey ( key__str ); + if ( ptr ) + { + if ( delKey ( ptr ) ) + { + /* Should never get here but if we do then */ + /* something is seriously wrong */ + elog ("Unable to remove key during reprovision\n"); + return static_cast(NULL); + } + } + + /* allocate memory for new key */ + ptr = newKey (); + if( ptr == NULL ) + { + elog ( "Failed to allocate memory for new key\n" ); + return static_cast(NULL); + } + + /* push the calling data into new key */ + ptr->key__str = key__str ; + ptr->val__ptr = val__ptr ; + + dlog3 ("add key:%s val:%p\n", ptr->key__str.c_str(), ptr->val__ptr ); + + /* If the key list is empty add it to the head */ + if( head == NULL ) + { + head = ptr ; + tail = ptr ; + ptr->prev = NULL ; + ptr->next = NULL ; + } + else + { + /* link the new_key to the tail of the key_list + * then mark the next field as the end of the key_list + * adjust tail to point to the last key + */ + tail->next = ptr ; + ptr->prev = tail ; + ptr->next = NULL ; + tail = ptr ; + } + return ptr ; +} + + +/****************************************************************** + * + * Name : getKey (private) + * + * Description: Looks for a key in the linked list. + * + * @param unsigned long key + * @return pointer to the matching key in the linked list + * + *******************************************************************/ +struct keyClass::keyValue * keyClass::getKey ( string key__str ) +{ + /* check for empty list condition */ + if ( head == NULL ) + return NULL ; + + for ( struct keyValue * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->key__str == key__str ) + { + dlog3 ("get key:%s val:%p\n", ptr->key__str.c_str(), ptr->val__ptr ); + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return static_cast(NULL); +} + +/****************************************************************************************** + **************** P U B L I C I N T E R F A C E S **************************** + *****************************************************************************************/ + +/****************************************************************************************** + * + * Name : get_key + * + * Purpose : look up the alue based on a key + * + ******************************************************************************************/ + +/* + * Unsigned Long K E Y + * Unsigned Long V A L u e + */ +int keyClass::get_key ( unsigned long key__int, unsigned long & val__int ) +{ + /* verify key is not already provisioned */ + struct keyValue * keyValue_ptr = getKey ( key__int ); + if ( keyValue_ptr ) + { + val__int = keyValue_ptr->val__int ; + return (PASS); + } + return(FAIL_NOT_FOUND); +} + +/* + * String K E Y + * Unsigned Long Pointer V A L u e + */ +int keyClass::get_key ( string key__str, unsigned long *& val__ptr ) +{ + /* verify key is not already provisioned */ + struct keyValue * keyValue_ptr = getKey ( key__str ); + if ( keyValue_ptr ) + { + val__ptr = keyValue_ptr->val__ptr ; + return (PASS); + } + return(FAIL_NOT_FOUND); +} + + +/****************************************************************************************** + * + * Name : add_key + * + * Purpose : add a key value to the object + * + ******************************************************************************************/ + +/* + * Unsigned Long K E Y + * Unsigned Long V A L u e + */ + +int keyClass::add_key ( unsigned long key__int, unsigned long val__int ) +{ + int rc = FAIL ; + struct keyClass::keyValue * keyValue_ptr = static_cast(NULL); + + keyValue_ptr = keyClass::getKey(key__int); + if ( keyValue_ptr ) + { + wlog ("add key:%lx failed - in use (value:%lx)\n", keyValue_ptr->key__int, keyValue_ptr->val__int ); + + /* Send back a retry in case the add needs to be converted to a modify */ + return (RETRY); + } + /* Otherwise add it as a new key */ + else + { + keyValue_ptr = keyClass::addKey( key__int , val__int); + if ( keyValue_ptr ) + { + dlog3 ("add key:%lx\n", key__int ); + rc = PASS ; + } + else + { + rc = FAIL_NULL_POINTER ; + } + } + return (rc); +} + +/* + * String K E Y + * Unsigned Long Pointer V A L u e + */ +int keyClass::add_key ( string key__str, unsigned long * val__ptr ) +{ + int rc = FAIL ; + struct keyClass::keyValue * keyValue_ptr = static_cast(NULL); + + keyValue_ptr = keyClass::getKey(key__str); + if ( keyValue_ptr ) + { + wlog ("add key:%s failed - in use (value:%p)\n", keyValue_ptr->key__str.c_str(), keyValue_ptr->val__ptr ); + + return (RETRY); + } + /* Otherwise add it as a new key */ + else + { + keyValue_ptr = keyClass::addKey( key__str, val__ptr); + if ( keyValue_ptr ) + { + dlog3 ("add key:%s\n", key__str.c_str()); + + rc = PASS ; + } + else + { + rc = FAIL_NULL_POINTER ; + } + } + return (rc); +} + + +/****************************************************************************************** + * + * Name : del_key + * + * Purpose : del a key value from the object + * + ******************************************************************************************/ + +/* + * Unsigned Long K E Y + * Unsigned Long V A L u e + */ + + +int keyClass::del_key ( unsigned long key__int ) +{ + int rc = FAIL_DEL_UNKNOWN ; + keyClass::keyValue * keyValue_ptr = keyClass::getKey( key__int ); + if ( keyValue_ptr ) + { + rc = remKey ( keyValue_ptr ); + if ( rc != PASS ) + { + elog ("del key:%lx failed - rc:%d\n", key__int , rc ); + } + else + { + dlog3 ("del key:%lx\n", key__int ); + } + } + else + { + wlog ("del key:%lx failed - not found\n", key__int ); + } + return (rc); +} + +/* + * String K E Y + * Unsigned Long Pointer V A L u e + */ +int keyClass::del_key ( string key__str ) +{ + int rc = FAIL_DEL_UNKNOWN ; + keyClass::keyValue * keyValue_ptr = keyClass::getKey( key__str ); + if ( keyValue_ptr ) + { + rc = remKey ( keyValue_ptr ); + if ( rc != PASS ) + { + elog ("del key:%s failed - rc:%d\n", key__str.c_str(), rc ); + } + else + { + dlog3 ("del key:%s\n", key__str.c_str()); + } + } + else + { + wlog ("del key:%s failed - not found\n", key__str.c_str()); + } + return (rc); +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/keyClass.h b/mtce-common/cgts-mtce-common-1.0/common/keyClass.h new file mode 100644 index 00000000..3d29a7ef --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/keyClass.h @@ -0,0 +1,89 @@ +#ifndef __INCLUDE_KEYCLASS_H__ +#define __INCLUDE_KEYCLASS_H__ +/* + * Copyright (c) 2015 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +#include +#include +#include +#include +#include + + +using namespace std; + +// #include "nodeBase.h" + +#define MAX_KEYS 100 + +class keyClass +{ + private: + + /** + * A single key:value pair within the keyClass. + * Used to build a linked list of key value pairs. + */ + struct keyValue { + + string key__str ; + unsigned long * val__ptr ; /* The value for the string key is a unsigned long pointer */ + + unsigned long key__int ; + unsigned long val__int ; + + struct keyValue * prev; + struct keyValue * next; + } ; + + struct keyValue * head ; + struct keyValue * tail ; + + /** Allocate memory for a new key. */ + struct keyClass::keyValue * newKey ( void ); + + struct keyClass::keyValue * addKey ( string key__str, unsigned long * val__ptr ); + struct keyClass::keyValue * addKey ( unsigned long key__int, unsigned long val__int ); + + struct keyClass::keyValue * getKey ( string key__str ); + struct keyClass::keyValue * getKey ( unsigned long key__int ); + + int remKey ( struct keyClass::keyValue * keyValue_ptr ); + int delKey ( struct keyClass::keyValue * keyValue_ptr ); + + keyClass::keyValue * key_ptrs[MAX_KEYS] ; + + int memory_allocs ; + int memory_used ; + +public: + + keyClass(); /**< constructor */ + ~keyClass(); /**< destructor */ + + int keys ; + + int get_key ( unsigned long key__int , unsigned long & val__int ); + int get_key ( string key__str , unsigned long *& val__ptr ); + int add_key ( unsigned long key__int , unsigned long val__int ); + int add_key ( string key__str , unsigned long * val__ptr ); + int del_key ( unsigned long key__int ); + int del_key ( string key__str ); +} ; + +keyClass * get_keyClass_ptr ( void ); + +#define GET_KEYVALUE_PTR(key) \ + keyClass * keyClass_ptr = get_keyClass_ptr () ; \ + keyClass::keyValue * keyValue_ptr = keyClass_ptr->getKey ( key ) ; \ + if ( keyValue_ptr == NULL ) \ + { \ + elog ("key %ld not fault\n", hostname.c_str()); \ + return (FAIL_HOSTNAME_LOOKUP); \ + } + +#endif // __INCLUDE_KEYCLASS_H__ diff --git a/mtce-common/cgts-mtce-common-1.0/common/logMacros.h b/mtce-common/cgts-mtce-common-1.0/common/logMacros.h new file mode 100644 index 00000000..267eaa41 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/logMacros.h @@ -0,0 +1,421 @@ +#ifndef __INCLUDE_NODELOG_HH__ +#define __INCLUDE_NODELOG_HH__ +/* + * Copyright (c) 2013-2017 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform "Node Log" Header + */ + +#include + +#define DEBUG_LEVEL1 0x00000001 +#define DEBUG_LEVEL2 0x00000002 +#define DEBUG_LEVEL3 0x00000004 +#define DEBUG_LEVEL4 0x00000008 +#define DEBUG_MEM_LOG 0x00000010 +#ifndef __AREA__ +#define __AREA__ "---" +#endif + +// #include "daemon_common.h" + +/* including for getpid */ +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** configuration options */ +typedef struct +{ + int scheduling_priority ; /**< Scheduling priority of this daemon */ + bool active ; /**< Maintenance activity state true|false */ + int hbs_pulse_period ; /**< time (msec) between heartbeat requests */ + int token_refresh_rate ; /**< token refresh rate in seconds */ + int hbs_minor_threshold ; /**< heartbeat miss minor threshold */ + int hbs_degrade_threshold ; /**< heartbeat miss degrade threshold */ + int hbs_failure_threshold ; /**< heartbeat miss failure threshold */ + + int hbs_calibrate_threshold ; /**< number of hosts where threshold calibration begins to take effect */ + int hbs_calibrate_period_factor ; /**< hbs_pulse_period = hbs_pulse_period * hosts */ + int hbs_calibrate_minor_factor ; /**< hbs_minor_threshold = threshold factor * hosts */ + int hbs_calibrate_degrade_factor; /**< hbs_degrade_threshold = threshold factor * hosts */ + int hbs_calibrate_fail_factor ; /**< hbs_failure_threshold = threshold factor * hosts */ + + char* mgmnt_iface ; /**< management interface name pointer */ + char* infra_iface ; /**< infrastructure interface name pointer */ + char* multicast ; /**< Multicast address */ + int ha_port ; /**< HA REST API Port Number */ + int vim_cmd_port ; /**< Mtce -> VIM Command REST API Port */ + int vim_event_port ; /**< VIM -> Mtce Event REST API Port */ + int mtc_agent_port ; /**< mtcAgent receive port (from Client) */ + int mtc_client_port ; /**< mtcClient receive port (from Agent) */ + + int keystone_port ; /**< Keystone REST API port number */ + char* keystone_prefix_path ; /**< Keystone REST API prefix path */ + char* keystone_auth_host ; /**< =auth_host=192.168.204.2 */ + char* keystone_identity_uri ; /**< =http://192.168.204.2:5000/ */ + char* keystone_auth_uri ; /**< =http://192.168.204.2:5000/ */ + char* keystone_auth_username ; /**< =mtce */ + char* keystone_auth_pw ; /**< =abc123 */ + char* keystone_region_name ; /**< =RegionOne */ + char* keystone_auth_project ; /**< =services */ + char* keystone_user_domain; /**< = Default */ + char* keystone_project_domain; /**< = Default */ + char* keyring_directory ; /**< =/opt/platform/.keyring/ */ + + char* sysinv_mtc_inv_label ; /**< =/v1/hosts/ */ + int sysinv_api_port ; /**< =6385 */ + char* sysinv_api_bind_ip ; /**< = */ + + char* ceilometer_url ; /**< ceilometer sensor sample database url */ + int ceilometer_port ; /**< ceilometer REST API port number */ + + int mtc_rx_mgmnt_port ; /**< mtcClient listens mgmnt nwk cmd reqs */ + int mtc_rx_infra_port ; /**< mtcClient listens infra nwk cmd reqs */ + int mtc_tx_mgmnt_port ; /**< mtcClient sends mgmnt nwk cmds/resp's */ + int mtc_tx_infra_port ; /**< mtcClient sends infra nwk cmds/resp's */ + + int hbs_agent_mgmnt_port ; /**< hbsAgent mgmnt network pulse resp port */ + int hbs_client_mgmnt_port ; /**< hbsClient mgmnt network pulse req port */ + int hbs_agent_infra_port ; /**< hbsAgent infra network pulse resp port */ + int hbs_client_infra_port ; /**< hbsClient infra network pulse req port */ + int daemon_log_port ; /**< daemon log port */ + + int mtcalarm_req_port ; /**< port daemons send alarm requests to */ + + int agent_rx_port ; + int client_rx_port ; + + bool infra_degrade_only ; /**< Only degrade on infra heartbeat failure */ + int mtc_to_hbs_cmd_port ; /**< mtcAgent to hbsAgent command port */ + int mtc_to_guest_cmd_port ; /**< mtcAgent to guestAgent command port */ + int hwmon_cmd_port ; /**< mtcAgent to hwmon command port */ + int hbs_to_mtc_event_port ; /**< hbsAgent tm mtcAgent event port */ + int inv_event_port ; /**< Port inventory sends change events on */ + int per_node ; /**< Memory usage per node or per resource */ + int audit_period ; /**< daemon specific audit period */ + int pm_period ; /**< Resmon specific pm period */ + int ntp_audit_period ; /**< Resmon specific ntp audit period */ + int ntpq_cmd_timeout ; /**< Resmon specific ntpq command timeout */ + int pmon_amon_port ; /**< active process monitor pulse rx port */ + int pmon_event_port ; /**< process monitor tx event port */ + int pmon_pulse_port ; /**< process Monitor I'm Alive pulse port */ + int pmon_cmd_port ; /**< process Monitor command receive port */ + int rmon_api_tx_port ; /**< resource monitor api tx port */ + int rmon_event_port ; /**< resource monitor api event port */ + int rmon_critical_thr ; /**< resmon critical threshold in use */ + int rmon_tx_port ; /**< resource monitor tx event port */ + int log_step ; /**< used to throttle logging at step rate */ + int event_port ; /**< daemon specific event tx port */ + int cmd_port ; /**< daemon specific command rx port */ + int sensor_port ; /**< sensor read value port */ + int start_delay ; /**< startup delay, added for pmon */ + int api_retries ; /**< api retries before failure */ + int hostwd_failure_threshold ; /**< allowed # of missed pmon/hostwd messages */ + bool hostwd_reboot_on_err ; /**< should hostwd reboot on fault detected */ + bool hostwd_use_kern_wd ; /**< use the kernel watchdog for extra safety */ + bool need_infra_poll_audit ; /**< true if we need to poll for infra */ + char *hostwd_console_path ; /**< console on which to log extreme events */ + char *mode ; /**< Test Mode String */ + int testmode ; /**< Test Head Test Mode */ + int testmask ; /**< bit mask of stress tests */ + unsigned int mask ; /**< Config init mask */ + + + /* Debug of compute hang issue */ + unsigned int stall_pmon_thld; + int stall_mon_period ; + int stall_poll_period ; + int stall_rec_thld ; + char* mon_process_1 ; + char* mon_process_2 ; + char* mon_process_3 ; + char* mon_process_4 ; + char* mon_process_5 ; + char* mon_process_6 ; + char* mon_process_7 ; + + int latency_thld ; /**< scheduling latency threshold in msec b4 log */ + + /** Multi Node Failure Avoidance Controls */ + char * mnfa_threshold_type ; /**< value used in multi node failure + avoidance calculation ; + 'number' / 'percent'age of hosts */ + int mnfa_threshold_percent ; /**< number of hosts simultaneously + failing heartbeat */ + int mnfa_threshold_number ; /**< percentage of pool + simultanepously failing heartbeat*/ + int mnfa_recovery_threshold ; /**< Multi-Node-Failure Avoidance Recovery Threshold + Similar to the LOC above for graceful recovery + hosts that have LOC for longer than this time in + seconds are failed and sent into the enable_handler + FSM while those that recover before this period are + sent into the graceful recovery_handler FSM. */ + + /** Configurable Timeouts ; unit is 'seconds' */ + int controller_mtcalive_timeout ; /**< mtcAlive wait timeout */ + int compute_mtcalive_timeout ; /**< mtcAlive wait timeout */ + int goenabled_timeout ; /**< goenabled wait timeout */ + int host_services_timeout ; /**< host services start/stop timeout*/ + int swact_timeout ; /**< swact wait timeout */ + int sysinv_timeout ; /**< sysinv reset api timeout secs */ + int sysinv_noncrit_timeout ; /**< sysinv nonc request timeout */ + int work_queue_timeout ; /**< end of action workq complete TO */ + int loc_recovery_timeout ; /**< loss of comms recovery timeout */ + int mnfa_recovery_timeout ; /**< mnfa recovery timeout */ + int node_reinstall_timeout ; /**< node reinstall timeout */ + int dor_mode_timeout ; /**< dead office recovery timeout */ + int dor_recovery_timeout_ext ; /**< dor recovery timeout extension */ + int uptime_period ; /**< Uptime refresh timer period */ + int online_period ; /**< locked availability refresh */ + int insv_test_period ; /**< insv test period in secs */ + int oos_test_period ; /**< oos test period in secs */ + int failsafe_shutdown_delay ; /**< seconds before failsafe reboot */ + int hostwd_update_period ; /**< expect hostwd to be updated */ + int kernwd_update_period ; /**< expect kernel watchdog to be updated */ + int autorecovery_threshold ; /**< AIO stop autorecovery threshold */ + + int debug_all ; + int debug_json ; /**< Enable jlog (json string ) output if not false */ + int debug_timer ; /**< Enable tlog (timer logs ) output if not false */ + int debug_fsm ; /**< Enable flog (fsm debug ) output if not false */ + int debug_http ; /**< Enable hlog (http logs ) output if not false */ + int debug_msg ; /**< Enable mlog (msg logs ) output if not false */ + int debug_work ; /**< Enable qlog (work Q logs ) output if not false */ + int debug_state ; /**< Enable clog (state changes) output if not false */ + int debug_alive ; /**< Enable alog (mtcAlive logs) output if not false */ + int debug_bmgmt ; /**< Enable alog (brd mgmt logs) output if not false */ + int debug_level ; /**< Enable dlog (debug levels ) output if not 0 */ + char* debug_filter ; + char* debug_event ; /**< Event signature to trace */ + bool flush ; /**< Force log flush in main loop */ + int flush_thld ; /**< Flush threshold */ + + int fit_code ; /**< fault insertion code ; nodeBase.h fit_code_enum */ + char* fit_host ; /**< the host to apply the fault insertion code to */ +} daemon_config_type ; + +daemon_config_type * daemon_get_cfg_ptr (void); +int daemon_set_cfg_option ( const char * option , int value ); + +bool ltc ( void ); + +/* returns the current log count */ +int lc (void); + +char * pt ( void ) ; /* returns pointer to the current time */ +char * _hn ( void ) ; /* returns pointer to the current host name */ +void set_hn ( char * hn ); /* set the current host name */ + +/* copy time (not date) into callers buffer */ +void gettime ( char * now_time_ptr ) ; + +extern char *program_invocation_name; +extern char *program_invocation_short_name; +#define _pn program_invocation_short_name + +#define SYSLOG_OPTION LOG_NDELAY +#define SYSLOG_FACILITY LOG_LOCAL5 + +/** Open syslog */ +#define open_syslog() \ +{ \ + openlog(program_invocation_short_name, SYSLOG_OPTION, SYSLOG_FACILITY ) ; \ +} + +/** Open syslog using filename identifier */ +#define open_syslog_args(filename) \ +{ \ + openlog(filename, SYSLOG_OPTION, SYSLOG_FACILITY ) ; \ +} + +/** Close syslog */ +#define close_syslog() \ +{ \ + closelog(); \ +} + +/* ltc represents '-f' option for running in forground and means 'log to console' */ + +/** Scheduling Latency */ +#define NSEC_TO_MSEC (1000000) +#define llog(format, args...) \ + { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Latncy: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + +/** Swerr logger macro*/ +#define slog(format, args...) { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Swerr : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Swerr : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +/** Error log macro */ +#define elog(format, args...) { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Error : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Error : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +/** Warning logger macro */ +#define wlog(format, args...) { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Warn : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Warn : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +/** Warning logger macro with throttling */ +#define wlog_throttled(cnt,max,format,args...) { \ + if ( ++cnt == 1 ) \ + { \ + if (ltc()) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Warn : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Warn : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ + if ( cnt >= max ) \ + { \ + cnt = 0 ; \ + } \ +} + +/** Info logger macro with throttling */ +#define ilog_throttled(cnt,max,format,args...) { \ + if ( ++cnt == 1 ) \ + { \ + if (ltc()) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Info : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Info : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ + if ( cnt >= max ) \ + { \ + cnt = 0 ; \ + } \ +} + +/** Work Queue logger macro with throttling */ +#define qlog_throttled(cnt,max,format,args...) { \ + if ( daemon_get_cfg_ptr()->debug_work ) \ + { \ + if ( ++cnt == 1 ) \ + { \ + if (ltc()) { printf ("%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Work : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Work : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ + if ( cnt >= max ) \ + { \ + cnt = 0 ; \ + } \ + } \ +} + +/** Info logger macro*/ +#define ilog(format, args...) { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Info : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Info : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +/** Info logger macro*/ +#define dlog(format, args...) { \ + if(daemon_get_cfg_ptr()->debug_level&1) \ + { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ +} + +/** Debug print macro used to record a "debug log" with file, line and function. */ + +/** Info logger macro*/ +#define dlog1(format, args...) { \ + if(daemon_get_cfg_ptr()->debug_level&2) \ + { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug2: " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug2: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ +} + +/** Info logger macro*/ +#define dlog2(format, args...) { \ + if(daemon_get_cfg_ptr()->debug_level&4) \ + { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug4: " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug4: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ +} + +/** Info logger macro*/ +#define dlog3(format, args...) { \ + if(daemon_get_cfg_ptr()->debug_level&8) \ + { \ + if ( ltc() ) { printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug8: " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Debug8: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + } \ +} + +#define blog(format, args...) { \ + if ( ltc() ) { if(daemon_get_cfg_ptr()->debug_bmgmt) printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt : " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { if(daemon_get_cfg_ptr()->debug_bmgmt) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +#define blog1(format, args...) { \ + if ( ltc() ) { if(daemon_get_cfg_ptr()->debug_bmgmt&2) printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt2: " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { if(daemon_get_cfg_ptr()->debug_bmgmt&2) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt2: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +#define blog2(format, args...) { \ + if ( ltc() ) { if(daemon_get_cfg_ptr()->debug_bmgmt&4) printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt4: " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { if(daemon_get_cfg_ptr()->debug_bmgmt&4) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt4: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + +#define blog3(format, args...) { \ + if ( ltc() ) { if(daemon_get_cfg_ptr()->debug_bmgmt&8) printf ( "%s [%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt8: " format, pt(), getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ + else { if(daemon_get_cfg_ptr()->debug_bmgmt&8) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: BMgt8: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } \ +} + + +/* This is a progress log with a unique symbol that can be searched on |-| */ +/* This log can be used for automated log analysis */ +#define plog(format, args...) { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Info : " format, getpid(), lc(), _hn(), _pn, "|-|", __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define mlog(format, args...) { if(daemon_get_cfg_ptr()->debug_msg&1 ) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Msg : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define mlog1(format, args...) { if(daemon_get_cfg_ptr()->debug_msg&2 ) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Msg2 : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define mlog2(format, args...) { if(daemon_get_cfg_ptr()->debug_msg&4 ) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Msg4 : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define mlog3(format, args...) { if(daemon_get_cfg_ptr()->debug_msg&8 ) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Msg8 : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define jlog(format, args...) { if(daemon_get_cfg_ptr()->debug_json ) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Json : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define jlog1(format, args...) { if(daemon_get_cfg_ptr()->debug_json&2) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Json2: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define jlog2(format, args...) { if(daemon_get_cfg_ptr()->debug_json&4) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Json4: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define jlog3(format, args...) { if(daemon_get_cfg_ptr()->debug_json&8) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Json8: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define hlog(format, args...) { if(daemon_get_cfg_ptr()->debug_http) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Http : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define hlog1(format, args...) { if(daemon_get_cfg_ptr()->debug_http&2) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Http2: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define hlog2(format, args...) { if(daemon_get_cfg_ptr()->debug_http&4) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Http4: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define hlog3(format, args...) { if(daemon_get_cfg_ptr()->debug_http&8) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Http8: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define alog(format, args...) { if(daemon_get_cfg_ptr()->debug_alive ) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Alive : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define alog1(format, args...) { if(daemon_get_cfg_ptr()->debug_alive&2) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Alive2: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define alog2(format, args...) { if(daemon_get_cfg_ptr()->debug_alive&4) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Alive4: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define alog3(format, args...) { if(daemon_get_cfg_ptr()->debug_alive&8) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Alive8: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define qlog(format, args...) { if(daemon_get_cfg_ptr()->debug_work) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Work : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define qlog1(format, args...) { if(daemon_get_cfg_ptr()->debug_work&2) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Work2: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define qlog2(format, args...) { if(daemon_get_cfg_ptr()->debug_work&4) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Work4: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define qlog3(format, args...) { if(daemon_get_cfg_ptr()->debug_work&8) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Work8: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define flog(format, args...) { if(daemon_get_cfg_ptr()->debug_fsm) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: FSM : " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define tlog(format, args...) { if(daemon_get_cfg_ptr()->debug_timer) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Timer: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define clog(format, args...) { if(daemon_get_cfg_ptr()->debug_state) syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Change: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + +#define log_event(format, args...) { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s: Event: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } +#define log_stress(format, args...) { syslog(LOG_INFO, "[%d.%05d] %s %s %-3s %-18s(%4d) %-24s:Stress: " format, getpid(), lc(), _hn(), _pn, __AREA__, __FILE__, __LINE__, __FUNCTION__, ##args) ; } + + +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_NODELOG_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/msgClass.cpp b/mtce-common/cgts-mtce-common-1.0/common/msgClass.cpp new file mode 100644 index 00000000..9f785fa1 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/msgClass.cpp @@ -0,0 +1,1094 @@ +/* + * Copyright (c) 2015-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ +#include "msgClass.h" +#include "daemon_common.h" + +/** + * Creating a msgClassAddr address without port and protocol is + * to allow an easy way to check the version of an address. It can + * not be used to create a socket. + * + * @param IP address or hostname + */ +msgClassAddr::msgClassAddr(const char* address) +{ + initAddr(address, 0, 0); + this->return_status = FAIL_BAD_PARM; +} + + +/** + * @param IP address or hostname + * @param host-byte order port + * @param IP protocol + */ +msgClassAddr::msgClassAddr(const char* address, int port, int proto) +{ + this->return_status = initAddr(address, port, proto); +} + + +/* copy constructor */ +msgClassAddr::msgClassAddr(const msgClassAddr& addr) +{ + this->return_status = initAddr(addr.address_str, addr.port, addr.proto); +} + + +/** + * To be used by constructors to initialize the instance. Uses + * getaddrinfo to allocate the sockaddr and determine the IP + * version, then builds based on the IP version. Also sets + * the sockaddr's port to the network-byte order version of the + * host-byte order port value passed in. + * + * + * @param IP address or hostname + * @param host-byte order port + * @param IP protocol + * + * @return PASS if successful, failure code otherwise + */ +int msgClassAddr::initAddr(const char* address, int port, int proto) +{ + int rc; + struct addrinfo *res = NULL; + struct addrinfo hints; + this->proto = proto; + this->port = port; + this->address_str = new char[strlen(address)+1]; + this->address_numeric_string = new char[INET6_ADDRSTRLEN]; + snprintf(this->address_str, strlen(address)+1, "%s", address); + this->addr_any = false; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET6; + rc = getaddrinfo(this->address_str, NULL, &hints, &res); + if(rc) + { + dlog("IPv6 address resolution failed, rc=%d", rc); + if(res) + { + freeaddrinfo(res); + } + hints.ai_family = AF_INET; + rc = getaddrinfo(this->address_str, NULL, &hints, &res); + if(rc) + { + dlog("IPv4 address resolution failed, rc=%d", rc); + this->address_info = NULL; + delete[] this->address_numeric_string; + this->address_numeric_string = NULL; + return FAIL_HOSTADDR_LOOKUP; + } + } + this->address_info = res; + switch(this->getIPVersion()) + { + case AF_INET: + inet_ntop(AF_INET, &((sockaddr_in*)this->address_info->ai_addr)->sin_addr, this->address_numeric_string, INET_ADDRSTRLEN); + ((sockaddr_in*)this->address_info->ai_addr)->sin_port = htons(port); + return PASS; + break; + case AF_INET6: + inet_ntop(AF_INET6, &((sockaddr_in6*)this->address_info->ai_addr)->sin6_addr, this->address_numeric_string, INET6_ADDRSTRLEN); + ((sockaddr_in6*)this->address_info->ai_addr)->sin6_port = htons(port); + return PASS; + break; + default: + delete[] this->address_numeric_string; + this->address_numeric_string = NULL; + wlog("IP version %d not supported", this->getIPVersion()); + return FAIL_NO_IP_SUPPORT; + break; + } +} + + +/* destructor */ +msgClassAddr::~msgClassAddr() +{ + if(this->address_str) + { + delete[] this->address_str; + } + + if(this->address_numeric_string) + { + delete[] this->address_numeric_string; + } + + if(this->address_info) + { + freeaddrinfo(this->address_info); + } +} + + +/** + * @return IP address or unresolved hostname this instance was created with + */ +const char* msgClassAddr::toString() const +{ + if(this->address_info == NULL) + { + return NULL; + } + return this->address_str; +} + + +/** + * @return IP address or resolved hostname this instance was created with + */ +const char* msgClassAddr::toNumericString() const +{ + if(this->address_info == NULL) + { + return NULL; + } + if(this->address_numeric_string == NULL) + { + return NULL; + } + switch(this->getIPVersion()) + { + case AF_INET: + inet_ntop(AF_INET, &((sockaddr_in*)this->address_info->ai_addr)->sin_addr, this->address_numeric_string, INET6_ADDRSTRLEN); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((sockaddr_in6*)this->address_info->ai_addr)->sin6_addr, this->address_numeric_string, INET6_ADDRSTRLEN); + break; + } + return this->address_numeric_string; +} + + +/** + * @return IP version of address + */ +int msgClassAddr::getIPVersion() const +{ + if(this->address_info == NULL) + { + return AF_UNSPEC; + } + return this->address_info->ai_family; +} + + +/** + * @return IP protocol instance was created with + */ +int msgClassAddr::getIPProtocol() const +{ + return this->proto; +} + + +/** + * @return port in host-byte order + */ +int msgClassAddr::getPort() const +{ + return this->port; +} + + +/** + * Constant accessor for sockaddr + * Intended to be used external to msgClassSock + */ +const struct sockaddr* msgClassAddr::getSockAddr() const +{ + if(this->address_info == NULL) + { + return NULL; + } + return this->address_info->ai_addr; +} + + +/** + * Non-constant accessor for sockaddr. + * Intended to be used internally by msgClassSock + */ +struct sockaddr* msgClassAddr::getSockAddr() +{ + if(this->address_info == NULL) + { + return NULL; + } + return this->address_info->ai_addr; +} + + +/* + * if(this->getIPVersion==AF_INET) + * return sizeof(sockaddr_in); + * if(this->getIPVersion==AF_INET) + * return sizeof(sockaddr_in6); + * + * @return size of the sockaddr + */ +socklen_t msgClassAddr::getSockLen() const +{ + if(this->address_info == NULL) + { + return 0; + } + return this->address_info->ai_addrlen; +} + + +/** + * Given an interface, find the hostname that resolves on this interface + * and use that to get the IP address of this interface. Will only resolve + * hostnames on the Management or Infra interfaces + * + * @param Name of the interface to get address for + * @param Character pointer to pass back address of interface + * @param Length of character array. + * @return Returns PASS if (mgmnt or infra) interface has address, FAIL otherwise + */ +int msgClassAddr::getAddressFromInterface(const char* interface, char* address, int len) +{ + int rc = FAIL; + + // before proceeding further, confirm if the interface + // is either the management interface or the infra interface. + // Mtce doesn't care about others besides these. + iface_enum interface_type = iface_enum(0); + char *infra_iface_name = NULL; + + get_infra_iface(&infra_iface_name); + if (infra_iface_name && strlen(infra_iface_name)) { + if (!strcmp(interface, infra_iface_name)) { + // requesting address for the infra interface + interface_type = INFRA_IFACE; + } + free (infra_iface_name); + } + + if (interface_type != INFRA_IFACE) { + // check if this is the mgmt interface + // otherwise return error + if (!strcmp(interface, daemon_mgmnt_iface().data())) { + interface_type = MGMNT_IFACE; + dlog ("Resolving %s as Management interface", interface); + } else { + return rc; + } + } + char hostname[MAX_HOST_NAME_SIZE+1] = {0}; + if (gethostname(hostname, + MAX_HOST_NAME_SIZE) < 0) { + elog("Failed to get system host name (err: %d)", errno); + return rc; + } + + // if hostname is localhost then resolution will give us + // the interface loopback address. Detect this case and + // return. + if (!strncmp(hostname, "localhost", 9)) { + wlog ("Detected localhost as system hostname." + " Cannot resolve IP address"); + return rc; + } + + // if it is infra then we need to determine the interface + // host name. For management interface, the system hostname + // is the intf hostname + char iface_hostname[MAX_HOST_NAME_SIZE+1] = {0}; + snprintf(iface_hostname, MAX_HOST_NAME_SIZE, + "%s%s", hostname, + (((interface_type == INFRA_IFACE)) ? "-infra" : "")); + + struct addrinfo *res = NULL; + int ret = getaddrinfo(iface_hostname, NULL, NULL, &res); + if(ret) + { + elog("IP address resolution failed for %s (err: %s)", + iface_hostname, gai_strerror(ret)); + return rc; + } + + struct addrinfo *if_address; + void *src = NULL; + for(if_address=res; ((if_address!=NULL)&&(rc!=PASS)); if_address=if_address->ai_next) + { + switch(if_address->ai_family) + { + case AF_INET: + src = (void *) &((sockaddr_in*)if_address->ai_addr)->sin_addr; + if (inet_ntop(AF_INET, src, address, len)) + rc = PASS; + + break; + case AF_INET6: + src = (void *) &((sockaddr_in6*)if_address->ai_addr)->sin6_addr; + // skip if this is a link-local address + if (IN6_IS_ADDR_LINKLOCAL(src)) + continue; + + if (inet_ntop(AF_INET6, src, address, INET6_ADDRSTRLEN)) + rc = PASS; + + break; + } + } + + freeaddrinfo(res); + return rc; +} + + + +/** + * Loop through all addresses on an interface until the first one is found that + * is either AF_INET or AF_INET6. This should get the address family of the + * first address on the interface. This is only intended to be used if there is + * only one family of addresses on the interface; otherwise, the value of address + * is undefined. Ignores the default IPv6 link-local address. + * + * @param name of interface + * @return IP version of interface + */ +int msgClassAddr::getVersionFromInterface(const char* interface) +{ + struct ifaddrs *if_address_list = NULL; + struct ifaddrs *if_address; + char ip_address[INET6_ADDRSTRLEN]; + + if(getifaddrs(&if_address_list)) + { + if(if_address_list) + { + freeifaddrs(if_address_list); + } + return FAIL; + } + + for(if_address=if_address_list; if_address!=NULL; if_address=if_address->ifa_next) + { + if((strlen(interface)==strlen(if_address->ifa_name)) && (!strncmp(interface, if_address->ifa_name, strlen(if_address->ifa_name))) && if_address->ifa_addr) + { + switch(if_address->ifa_addr->sa_family) + { + case AF_INET: + freeifaddrs(if_address_list); + return AF_INET; + case AF_INET6: + inet_ntop(AF_INET6, &((sockaddr_in6*)if_address->ifa_addr)->sin6_addr, ip_address, INET6_ADDRSTRLEN); + if(strncmp(ip_address,"fe80", 4)) + { + freeifaddrs(if_address_list); + return AF_INET6; + } + } + } + } + if(if_address_list) + { + freeifaddrs(if_address_list); + } + return AF_UNSPEC; +} + + + + + +/** + * @return source msgClassAddr + */ +const msgClassAddr* msgClassSock::get_src_addr() +{ + return this->src_addr; +} + + +/** + * @return source msgClassAddr + */ +const msgClassAddr* msgClassSock::get_dst_addr() +{ + return this->dst_addr; +} + + +/** + * @return character array representation of source IP address + */ +const char* msgClassSock::get_src_str() const +{ + return this->src_addr->toNumericString(); +} + + +/** + * @return character array representation of destination IP address + */ +const char* msgClassSock::get_dst_str() const +{ + return this->dst_addr->toNumericString(); +} + + +/** + * Calls a specialized method to create a socket, based on the given + * IP version and protocol. + * + * @param IP version to be used to created socket. Either AF_INET or AF_INET6. + * @param Protocol of socket. Supports IPPROTO_UDP and IPPROTO_RAW for now. + * @return true if created successfully, false otherwise + */ +bool msgClassSock::createSocket(int ip_version, int proto) +{ + if(proto==IPPROTO_UDP) + { + switch(ip_version) + { + case AF_INET: + return createSocketUDP4(); + case AF_INET6: + return createSocketUDP6(); + default: + elog("Failed to create UDP socket: address family %d is invalid", ip_version); + errno = EAFNOSUPPORT; + return false; + }; + } + else if(proto==IPPROTO_RAW) + { + switch(ip_version) + { + case AF_INET: + return createSocketRaw4(); + case AF_INET6: + return createSocketRaw6(); + default: + elog("Failed to create Raw socket: address family %d is invalid", ip_version); + errno = EAFNOSUPPORT; + return false; + }; + } + else + { + elog("Failed to create socket: protocol %d not supported", proto); + errno = EPFNOSUPPORT; + return false; + } +} + +/* get the current socket status, + * ok = true if the socket is initialized and seemingly working or + * ok = false if the socket has failed and needs reinitialization + **/ +bool msgClassSock::sock_ok ( void ) +{ + return (this->ok); +} + +void msgClassSock::sock_ok ( bool status ) +{ + this->ok = status ; +} + +/** + * Creates an IPv4 UDP socket + * + * @return true if created successfully, false otherwise + */ +bool msgClassSock::createSocketUDP4() +{ + int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(sock < 0) + { + elog("Failed to create IPv4 UDP socket"); + return false; + } + else + { + this->sock = sock; + return true; + } +} + +/** + * Creates an IPv4 Raw (ping) socket + * + * @return true if created successfully, false otherwise + */ +bool msgClassSock::createSocketRaw4() +{ + int sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if(sock < 0) + { + elog("Failed to create IPv4 Raw socket"); + return false; + } + else + { + this->sock = sock; + return true; + } +} + +/** + * Creates an IPv6 UDP socket + * + * @return true if created successfully, false otherwise + */ +bool msgClassSock::createSocketUDP6() +{ + int sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); + if(sock < 0) + { + elog("Failed to create IPv6 UDP socket"); + return false; + } + else + { + this->sock = sock; + return true; + } +} + +/** + * Creates an IPv6 Raw (ping) socket + * + * @return true if created successfully, false otherwise + */ +bool msgClassSock::createSocketRaw6() +{ + int sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + if(sock < 0) + { + elog("Failed to create IPv6 Raw socket"); + return false; + } + else + { + this->sock = sock; + return true; + } +} + + +/* destructor */ +msgClassSock::~msgClassSock() +{ + delete this->src_addr; + delete this->dst_addr; + if(sock >= 0) + { + close(sock); + } + if(this->interface) + { + delete[] this->interface; + } +} + + +/* default constructor */ +msgClassSock::msgClassSock() +{ + this->dst_addr = NULL; + this->interface= NULL; + this->src_addr = NULL; + this->sock = 0; + this->return_status = RETRY; + this->ok = false ; +} + + +/** + * Reads data from socket into buffer. Data is to be destined + * to the instance's dst_addr, or any address if allow_any is true, + * and once read, the src_addr flag will be set to the address that + * the data came originated from. + * + * @param Buffer to read data to + * @param maximum size of buffer + * @return number of bytes read + */ +int msgClassSock::read(char* data, int len) +{ + socklen_t socklen = this->src_addr->getSockLen(); + return recvfrom(this->sock, data, len, 0, this->src_addr->getSockAddr(), &socklen); +} + +/** + * Reads a reply from the specified socket into buffer ignoring the address + * of where it came from. + * + * @param Buffer to read data to + * @param maximum size of buffer + * @return number of bytes read + */ +int msgClassSock::readReply(char* data, int len) +{ + return recv(this->sock, data, len, 0 ); +} + +/** + * If it is sending to the "correct" port and address, then it can use + * the existing sockaddr. While that would ideally always be the case, + * in order to preserve the existing structure, there are some cases + * where the port and/or address are only specified when the data is + * being sent. In these cases, a new sockaddr is allocated to be + * used for the call to sendto. If src_addr is set, then the source + * address will be that address. + * + * @param data to be sent + * @param size of data + * @param destination IP address. If none is specified, uses instance's dst_addr + * @param destination port. If none is specified, uses instance's stored port + * @return number of bytes sent + */ +int msgClassSock::write(const char* data, int len, const char* dst, int port) +{ + int ret = 0 ; + sockaddr* dst_sock_addr = this->dst_addr->getSockAddr(); + + sockaddr_in dst_addr_in; + sockaddr_in6 dst_addr_in6; + + if((port!=0) || (dst!=NULL)) + { + ret = 1 ; + switch(this->dst_addr->getIPVersion()) + { + case AF_INET: + dst_sock_addr = (sockaddr*) &dst_addr_in; + memcpy(dst_sock_addr, this->dst_addr->getSockAddr(), sizeof(sockaddr_in)); + if(port!=0) + { + ((sockaddr_in*)dst_sock_addr)->sin_port = htons(port); + } + if(dst!=NULL) + { + ret = inet_pton(AF_INET, dst, &(((sockaddr_in*)dst_sock_addr)->sin_addr)); + } + break; + case AF_INET6: + dst_sock_addr = (sockaddr*) &dst_addr_in6; + memcpy(dst_sock_addr, this->dst_addr->getSockAddr(), sizeof(sockaddr_in6)); + if(port!=0) + { + ((sockaddr_in6*)dst_sock_addr)->sin6_port = htons(port); + } + if(dst!=NULL) + { + ret = inet_pton(AF_INET6, dst, &(((sockaddr_in6*)dst_sock_addr)->sin6_addr)); + } + break; + default: + slog ("invalid AF network family (%d)\n", this->dst_addr->getIPVersion()); + return (-1); + } + if ( ret != 1 ) + { + wlog ("write requires address resolution; inet_pton returned %d for ip '%s'\n", ret, dst ); + return (-1); + } + } + + ret = sendto(this->sock, data, len, 0, dst_sock_addr, this->dst_addr->getSockLen()); + if(ret<0) + { + elog("Failed to send with errno=%d", errno); + } + return ret; +} + +/** + * Given an Rx socket, send a message to the last address that a messaged has received from. + * + * @param data to be sent + * @param size of data + * @param destination IP address. If none is specified, uses instance's dst_addr + * @param destination port. If none is specified, uses instance's stored port + * @return number of bytes sent + */ +int msgClassSock::reply(const msgClassSock* source, const char* data, int len) +{ + return write(data, len, source->get_src_str()); +} + + +/* + * This is to be used when code needs to know the actual file descriptor + * of socket, for example to poll for received data. + * + * @return the file descriptor as an int + */ +int msgClassSock::getFD() +{ + return this->sock; +} + + +/** + * Forces packets to be sent from interface of Tx socket + * + * @return PASS if successful, failure code otherwise + */ +int msgClassSock::interfaceBind() +{ + struct ifreq ifr; + if(this->interface) + { + memset(&ifr, 0, sizeof(ifreq)); + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", this->interface); + if(setsockopt(this->sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr))) + { + elog("Failed to bind socket to interface (%d:%m)\n", errno); + return FAIL_SOCKET_BIND; + } + return PASS; + } + return FAIL_BAD_CASE; +} + + +int msgClassSock::setPriortyMessaging( const char * iface ) +{ + int flags = 0 ; + int result = 0 ; + + switch( this->dst_addr->getIPVersion()) + { + case AF_INET: + + ilog ("Setting %s with IPv4 priority messaging\n", iface ); + flags = IPTOS_CLASS_CS6; + result = setsockopt( this->sock, IPPROTO_IP, IP_TOS, + &flags, sizeof(flags) ); + if( 0 > result ) + { + elog ( "Failed to set socket send priority for interface (%s) (%d:%m)\n", iface, errno ); + return( FAIL_SOCKET_OPTION ); + } + break ; + + case AF_INET6: + + ilog ("Setting %s with IPv6 priority messaging\n", iface ); + flags = IPTOS_CLASS_CS6; + result = setsockopt( this->sock, IPPROTO_IPV6, IPV6_TCLASS, &flags, sizeof(flags) ); + if( 0 > result ) + { + elog ( "Failed to set socket send priority for interface (%s) (%d:%m)\n", iface, errno ); + return( FAIL_SOCKET_OPTION ); + } + break ; + } + + flags = 6; + result = setsockopt( this->sock, SOL_SOCKET, SO_PRIORITY, &flags, sizeof(flags) ); + if( 0 > result ) + { + elog ( "Failed to set socket send priority for interface (%s) (%d:%m)\n", iface, errno ); + return( FAIL_SOCKET_OPTION ); + } + return(PASS); +} + + +/* Set socket memory size */ +int msgClassSock::setSocketMemory( const char * iface, const char * name, int size ) +{ + /* don't use whats on the stack ; create a local var */ + int _size = size ; + int rx_buff_memory = 0 ; + int len = sizeof(rx_buff_memory); + int result = setsockopt( this->sock, SOL_SOCKET, SO_RCVBUF, &_size, sizeof(_size) ); + if( 0 > result ) + { + elog ( "failed to set socket memory size for '%s' (%d:%m)\n", iface, errno ); + return( FAIL_SOCKET_OPTION ); + } + else + { + getsockopt(this->sock , SOL_SOCKET, SO_RCVBUF, &rx_buff_memory, (socklen_t*)&len); + } + /*********************************************************************************** + * From setsockopt SO_RCVBUF man page. + * + * Sets or gets the maximum socket receive buffer in bytes. The + * kernel doubles this value (to allow space for bookkeeping + * overhead) when it is set using setsockopt(2), and this doubled + * value is returned by getsockopt(2). The default value is set + * by the /proc/sys/net/core/rmem_default file, and the maximum + * allowed value is set by the /proc/sys/net/core/rmem_max file. + * The minimum (doubled) value for this option is 256. + ************************************************************************************ + * Note: Value is divided by 2 because when you set the SO_RCVBUF the + * kernel doubles the value for book keeping. + ************************************************************************************/ + ilog ("Setting %s %s to %d bytes\n", iface, name, (rx_buff_memory/2) ); + return(PASS); +} + +/* Set the socket as non-blocking */ +int msgClassSock::setSocketNonBlocking ( void ) +{ + int on = 1; + + if ( 0 > ioctl(this->sock, FIONBIO, (char *)&on)) + { + elog ("unable to set socket to non-blocking [%d:%m]\n", errno ); + return FAIL_SOCKET_NOBLOCK; + } + return PASS; +} + +/** + * Creates a socket to be used to receive data on a given address/port. + * First, it creates the destination msgClassAddr, which is the address + * that is is listening on, then it stores the interface if it is to be + * used, and then calls the Rx socket initialization function, which + * does the majority of the socket initialization. The return_status is set to PASS if it succeeds, or the failure code elsewise. + * + * @param IP address or hostname + * @param host-byte order port + * @param IP protocol + * @param name of interface to bind to, or null otherwise + * @param Whether to listen on all addresses instead + * @param Whether the address is multicast + */ +msgClassRx::msgClassRx(const char* address, int port, int proto, const char* interface, bool allow_any, bool is_multicast) +{ + this->dst_addr = new msgClassAddr(address, port, proto); + this->src_addr = new msgClassAddr(address, port, proto); + if(interface) + { + ilog ("Creating %s socket on port %d with address: %s\n", interface, port, address); + this->interface = new char[strlen(interface)+1]; + snprintf(this->interface, strlen(interface)+1, "%s", interface); + } + else + { + ilog ("Creating localhost socket on port %d with address: %s\n", port, address); + this->interface = NULL; + } + this->return_status = initSocket(allow_any, is_multicast); +} + + +/** + * Creates a socket to be used to receive data on a given address/port. + * First, it copies the destination msgClassAddr, which is the address + * that is is listening on, then it stores the interface if it is to be + * used, and then calls the Rx socket initialization function, which + * does the majority of the socket initialization. The return_status + * is set to PASS if it succeeds, or the failure code elsewise. + * + * @param destination address + * @param name of interface to bind to, or null otherwise + * @param Whether to listen on all addresses instead + * @param Whether the address is multicast + */ +msgClassRx::msgClassRx(const msgClassAddr& addr, const char* interface, bool allow_any, bool is_multicast) +{ + this->dst_addr = new msgClassAddr(addr); + this->src_addr = new msgClassAddr(addr.toString()); + if(interface) + { + this->interface = new char[strlen(interface)+1]; + snprintf(this->interface, strlen(interface)+1, "%s", interface); + } + else + { + this->interface = NULL; + } + this->return_status = initSocket(allow_any, is_multicast); +} + + +/** + * Creates socket, sets necessary socket options for Rx socket, + * and binds to the correct address and interface if applicable + * + * @param whether to bind to all sockets of that family. + * @param Whether the address is multicast + * @return PASS if successful, failure code otherwise + */ +int msgClassRx::initSocket(bool allow_any, bool is_multicast) +{ + int on = 1; + char address[INET6_ADDRSTRLEN]; + if(createSocket(this->dst_addr->getIPVersion(), this->dst_addr->getIPProtocol()) == false) + { + return FAIL_SOCKET_CREATE; + } + if(setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) + { + return FAIL; + } + + if(is_multicast) + { + switch(this->dst_addr->getIPVersion()) + { + case AF_INET: + { + struct ip_mreqn mreq; + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr.s_addr = ((sockaddr_in*)this->dst_addr->getSockAddr())->sin_addr.s_addr; + mreq.imr_ifindex = if_nametoindex(this->interface); + if(setsockopt(this->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) + { + elog("Failed to set multicast address (%d:%m)\n", errno); + return FAIL_SOCKET_OPTION; + } + break; + } + case AF_INET6: + { + struct ipv6_mreq mreq; + memset(&mreq, 0, sizeof(mreq)); + mreq.ipv6mr_multiaddr = ((sockaddr_in6*)this->dst_addr->getSockAddr())->sin6_addr; + mreq.ipv6mr_interface = if_nametoindex(this->interface); + if(setsockopt(this->sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) + { + elog("Failed to set multicast address (%d:%m)\n", errno); + return FAIL_SOCKET_OPTION; + } + break; + } + } + } + else if(allow_any) + { + switch(this->dst_addr->getIPVersion()) + { + case AF_INET: + ((sockaddr_in*)this->dst_addr->getSockAddr())->sin_addr.s_addr = htonl(INADDR_ANY); + break; + case AF_INET6: + ((sockaddr_in6*)this->dst_addr->getSockAddr())->sin6_addr = in6addr_any; + break; + } + } + else if(this->interface) + { + msgClassAddr::getAddressFromInterface(this->interface, address, INET6_ADDRSTRLEN); + switch(this->dst_addr->getIPVersion()) + { + case AF_INET: + inet_pton(AF_INET, address, &((sockaddr_in*)this->dst_addr->getSockAddr())->sin_addr); + break; + case AF_INET6: + inet_pton(AF_INET6, address, &((sockaddr_in6*)this->dst_addr->getSockAddr())->sin6_addr); + break; + } + } + + if(bind(this->sock, this->dst_addr->getSockAddr(), this->dst_addr->getSockLen())) + { + elog("Failed to bind socket to address (%d:%m)\n", errno); + return FAIL_SOCKET_BIND; + } + + return (this->setSocketNonBlocking ()); +} + + + + +/** + * Creates a socket to be used to transmit data to a given address/port. + * First, it creates the destination msgClassAddr, then stores the interface + * if it is to be used, and then calls the Tx socket initialization function, + * which does the majority of the socket initialization. The return_status is set to PASS if it succeeds, or the failure code elsewise. + * + * @param IP address or hostname + * @param host-byte order port + * @param IP protocol + * @param name of interface to bind to, or null otherwise + */ +msgClassTx::msgClassTx(const char* address, int port, int proto, const char* interface) +{ + this->dst_addr = new msgClassAddr(address, port, proto); + this->src_addr = new msgClassAddr(address, port, proto); + if(interface) + { + ilog ("Creating %s socket on port %d with address: %s\n", interface, port, address); + this->interface = new char[strlen(interface)+1]; + snprintf(this->interface, strlen(interface)+1, "%s", interface); + } + else + { + ilog ("Creating socket on port %d with address: %s\n", port, address); + this->interface = NULL; + } + this->return_status = initSocket(); +} + + +/** + * Creates a socket to be used to transmit data to a given address/port. + * First, it copies the destination msgClassAddr, then stores the interface + * if it is to be used, and then calls the Tx socket initialization function, + * which does the majority of the socket initialization. The return_status is set to PASS if it succeeds, or the failure code elsewise. + * + * @param destination address + * @param name of interface to bind to, or null otherwise + */ +msgClassTx::msgClassTx(const msgClassAddr& addr, const char* interface) +{ + this->dst_addr = new msgClassAddr(addr); + this->src_addr = new msgClassAddr(addr); + if(interface) + { + this->interface = new char[strlen(interface)+1]; + snprintf(this->interface, strlen(interface)+1, "%s", interface); + } + else + { + this->interface = NULL; + } + this->return_status = initSocket(); +} + + +/** + * Creates socket, sets necessary socket options for Tx socket, + * and binds to the correct address and interface if applicable + * + * @return PASS if successful, failure code otherwise + */ +int msgClassTx::initSocket() +{ + int on = 1; + char address[INET6_ADDRSTRLEN]; + if(createSocket(this->dst_addr->getIPVersion(), this->dst_addr->getIPProtocol()) == false) + { + return FAIL_SOCKET_CREATE; + } + if(setsockopt(this->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) + { + return FAIL; + } + if(this->interface) + { + msgClassAddr::getAddressFromInterface(this->interface, address, INET6_ADDRSTRLEN); + dlog("Address of interface %s is %s", this->interface, address); + delete this->src_addr; + this->src_addr = new msgClassAddr(address); + if(bind(this->sock, this->src_addr->getSockAddr(), this->src_addr->getSockLen())) + { + elog("Failed to bind socket to address (%d:%m)\n", errno); + return FAIL_SOCKET_BIND; + } + } + return PASS; +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/msgClass.h b/mtce-common/cgts-mtce-common-1.0/common/msgClass.h new file mode 100644 index 00000000..cbeee29f --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/msgClass.h @@ -0,0 +1,216 @@ +#ifndef __INCLUDE_MSGCLASS_H__ +#define __INCLUDE_MSGCLASS_H__ + +/* + * Copyright (c) 2015-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nodeBase.h" +#include "returnCodes.h" +#include "nodeUtil.h" + + +/* + * The msgClassAddr class is a version-independent representation + * of an IP address with TLP and port specified. Note that only UDP sockets + * are supported at this point. + */ +class msgClassAddr +{ +public: + msgClassAddr(const char* address, int port, int proto); + msgClassAddr(const msgClassAddr& addr); + msgClassAddr(const char* address); + ~msgClassAddr(); + int getAddress(char* address, int addr_len, int* port, int* proto) const; + int setAddress(char* address, int port, int proto); + const char* toString() const; + const char* toNumericString() const; + int getIPVersion() const; + int getIPProtocol() const; + int getPort() const; + const struct sockaddr* getSockAddr() const; + struct sockaddr* getSockAddr(); + socklen_t getSockLen() const; + msgClassAddr& operator= ( const msgClassAddr &rhs ) + { + this->return_status = initAddr(rhs.address_str, rhs.port, rhs.proto); + return *this; + } + /** + * Is to be set to allow the status of the last operation to be checked. + * Useful in checking if an instance was initialized correctly. + */ + int return_status; + + /** + * Intended to mark the address as being all, equivalent to either + * "0.0.0.0" or "::" depending on the address family. Is to allow + * a normal address to be passed in to determine the IP family, but + * uses that value instead of the passed in value. + **/ + bool addr_any; + static int getAddressFromInterface(const char* interface, char* address, int len); + static int getVersionFromInterface(const char* interface); + +protected: + /** + * Stores the protocol of the address. + */ + int proto; + + /** + * Stores the port in host-byte order. + */ + int port; + + /** + * Stores the address string used to create this msgClassAddr instance. + * If it is resolved to an IP address, this can be used to access the + * original unresolved value. + */ + char* address_str; + + /** + * Stores a numeric representation of the IP address of the address. + * This differs from address_str if address_str was a hostname that + * was resolved. + */ + char* address_numeric_string; + + /** + * Stores the addrinfo struct created by getaddrinfo. This contains + * both the IP version and the sockaddr. + */ + struct addrinfo* address_info; + +private: + int initAddr(const char* address, int port, int proto); + +}; + +/* + * The msgClassSock class is an abstraction of the inet sockets used + * by maintenance,which are not dependent on the socket protocol. This is needed + * to allow both IPv4 and IPv6 addresses to be used on the management network. + */ +class msgClassSock +{ +public: + ~msgClassSock(); + int read(char* data, int len); + int write(const char* data, int len, const char* dest=NULL, int port=0); + int reply(const msgClassSock* source, const char* data, int len); + int readReply(char* data, int len); + int getFD(); + int interfaceBind(); + int setPriortyMessaging( const char * iface ); + int setSocketMemory ( const char * iface, const char * name, int rmem ); + int setSocketNonBlocking ( void ); + + const msgClassAddr* get_src_addr(); + const msgClassAddr* get_dst_addr(); + const char* get_src_str() const; + const char* get_dst_str() const; + + /* get the current socket status, + * ok = true if the socket is initialized and seemingly working or + * ok = false if the socket has failed and needs reinitialization + **/ + bool sock_ok ( void ); + void sock_ok ( bool status ); + + /** + * Is to be set to allow the status of the last operation to be checked. + * Useful in checking if an instance was initialized correctly. + */ + int return_status; + const char* toString(); + +protected: + msgClassSock(); + + /** + * Stores the file descriptor of the allocated socket. Should + * only be accessed via the getFD() accessor. + */ + int sock; + + bool createSocket(int ip_version, int proto); + + /** + * Source address of outgoing packets. May be specified for Tx sockets, + * and is set by Rx sockets when receiving packets. + */ + msgClassAddr* src_addr; + + /** + * Address that this socket is to be either transmitting to or receiving + * on, depending if it is Rx or Tx. + */ + msgClassAddr* dst_addr; + + /** + * If the socket is to be bound to a specific interface, that the + * interface name is stores here; otherwise, this is NULL. + */ + char* interface; + + /** + * Set true when interface is initialized and working + * or false if it is not initialized or failed. + * This boolean can be used in a main loop to decide + * if a socket needs to be re initialized or not. + */ + bool ok ; + +private: + bool createSocketUDP4(); + bool createSocketUDP6(); + bool createSocketRaw4(); + bool createSocketRaw6(); +}; + +/* + * A socket for receiving data, this replaces the Rx sockets + * that are tied to inet. The dst_addr is set to the address to + * be receiving packets on when reading. + */ +class msgClassRx : public msgClassSock +{ +public: + msgClassRx(const char* address, int port, int proto, const char* interface=NULL, bool allow_any=false, bool is_multicast=false); + msgClassRx(const msgClassAddr& addr, const char* interface=NULL, bool allow_any=false, bool is_multicast=false); +private: + int initSocket(bool allow_any, bool is_multicast=false); +}; + +/* + * A socket for receiving data, this replaces the Tx sockets + * that are tied to inet. The dst_addr is set to the address to + * be sending packets to when writing. + */ +class msgClassTx : public msgClassSock +{ +public: + msgClassTx(const char* address, int port, int proto, const char* interface=NULL); + msgClassTx(const msgClassAddr& addr, const char* interface=NULL); +private: + int initSocket(); +}; + +#endif /* __INCLUDE_MSGCLASS_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/nlEvent.cpp b/mtce-common/cgts-mtce-common-1.0/common/nlEvent.cpp new file mode 100644 index 00000000..fafb00f9 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/nlEvent.cpp @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2013, 2015 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGCS Platform netlink listener event support for maintenance + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#include "nodeBase.h" +#include "nodeUtil.h" + +int get_netlink_events_throttle = 0 ; +int get_netlink_events ( int nl_socket , std::list & links_gone_down, + std::list & links_gone_up ) +{ + char buf[4096]; + char name[IF_NAMESIZE]; + + int len ; + int ret = 0; + + struct sockaddr_nl sa; + struct iovec iov = { buf, sizeof (buf) }; + struct msghdr msg = { &sa, sizeof (sa), &iov, 1, NULL, 0, 0 }; + struct nlmsghdr *h; + struct ifinfomsg *ifi; + /* struct ifaddrmsg * ifa ; used for addr change events */ + + links_gone_up.clear(); + links_gone_down.clear(); + + len = recvmsg (nl_socket, &msg, 0); + if (len < 0) + { + /* Socket non-blocking so bail out once we have read everything */ + if ( (errno == EWOULDBLOCK) || (errno == EAGAIN)) + { + return ret ; + } + + /* Anything else is an error */ + elog ("failed netlink recvmsg (%d:%d) (%d:%s)\n", nl_socket, len, errno, strerror(errno)); + return len; + } + + if (len == 0) + { + wlog ("No netlink data read_netlink: EOF\n"); + } + + /* Handle all the messages from 'recvmsg' */ + h = (struct nlmsghdr *) &buf[0] ; + for ( ; NLMSG_OK (h,(unsigned int)len); h=NLMSG_NEXT (h,len)) + { + /* ignore address change events */ + if (h->nlmsg_type == RTM_NEWADDR ) + { + +#ifdef RTM_NEWADDR_SUPPORTED + ifa = (struct ifaddrmsg *) NLMSG_DATA (nlh); + + struct rtattr * rth = IFA_RTA (ifa); + int rtl = IFA_PAYLOAD (nlh); + for (;rtl && RTA_OK (rth, rtl); rth = RTA_NEXT (rth,rtl)) + { + char name[IFNAMSIZ]; + uint32_t ipaddr; + + if (rth->rta_type != IFA_LOCAL) continue; + + ipaddr = * ((uint32_t *)RTA_DATA(rth)); + ipaddr = htonl(ipaddr); + + fprintf (stdout,"%s is now %X\n",if_indextoname(ifa->ifa_index,name),ipaddr); + } +#else + dlog ("unsupported netlink event: RTM_NEWADDR\n"); + continue ; +#endif + } + + /* Finish reading */ + if (h->nlmsg_type == NLMSG_NOOP ) + { + ilog ("netlink message: Nothing to read\n"); + return ret; + } + + /* Finish reading */ + if (h->nlmsg_type == NLMSG_DONE) + { + ilog ("netlink message: No more messages\n"); + return ret; + } + + /* Message is some kind of error */ + if (h->nlmsg_type == NLMSG_ERROR) + { + wlog ("netlink message: indicates error\n"); + return -1; + } + + ifi = (ifinfomsg*) NLMSG_DATA (h); + memset ( name, 0 , IF_NAMESIZE ); + if ( ifi->ifi_index ) + { + if_indextoname(ifi->ifi_index, name); + if (ifi->ifi_flags & IFF_RUNNING) + { + /* if 'up' then remove interface from 'down' list and add it to the 'up' list */ + links_gone_down.remove(name); + links_gone_up.push_front(name); + dlog ( "%s is up and running \n", name ); + } + else + { + if ( ifi->ifi_flags & IFF_UP ) + { + dlog ("%s is admin:up but oper:down\n", name ); + } + else + { + dlog ("%s is admin:down and oper:down\n", name ); + } + + /* if 'down' then remove interface from 'up' list and add it to the 'down' list */ + links_gone_up.remove(name); + links_gone_down.push_front(name); + } + get_netlink_events_throttle = 0 ; + } + else + { + wlog_throttled (get_netlink_events_throttle, 100, "got netlink event for unknown interface index\n"); + } + ret++ ; + } + links_gone_up.unique(); + links_gone_down.unique(); + + return ret; +} + + +void log_link_events ( int netlink_sock, + int ioctl_sock, + const char * mgmnt_iface_ptr, + const char * infra_iface_ptr, + bool & mgmnt_link_up_and_running, + bool & infra_link_up_and_running) +{ + std::list links_gone_down ; + std::list links_gone_up ; + std::list::iterator iter_curr_ptr ; + dlog3 ("logging for interfaces %s and %s\n", mgmnt_iface_ptr, infra_iface_ptr); + if ( get_netlink_events ( netlink_sock, links_gone_down, links_gone_up )) + { + bool running = false ; + if ( !links_gone_down.empty() ) + { + dlog3 ("%ld links have dropped\n", links_gone_down.size() ); + + /* Look at the down list */ + for ( iter_curr_ptr = links_gone_down.begin(); + iter_curr_ptr != links_gone_down.end() ; + iter_curr_ptr++ ) + { + dlog3 ( "downed link: %s (running:%d:%d)\n", + iter_curr_ptr->c_str(), + mgmnt_link_up_and_running, + infra_link_up_and_running ); + + if ( !strcmp (mgmnt_iface_ptr, iter_curr_ptr->data())) + { + if ( mgmnt_link_up_and_running == true ) + { + mgmnt_link_up_and_running = false ; + wlog ("Mgmnt link %s is down\n", mgmnt_iface_ptr ); + } + } + if ( !strcmp (infra_iface_ptr, iter_curr_ptr->data())) + { + if ( infra_link_up_and_running == true ) + { + infra_link_up_and_running = false ; + wlog ("Infra link %s is down\n", infra_iface_ptr ); + } + } + + if ( get_link_state ( ioctl_sock, iter_curr_ptr->data(), &running ) == PASS ) + { + dlog ("%s is down (oper:%s)\n", iter_curr_ptr->c_str(), running ? "up" : "down" ); + } + else + { + wlog ("%s is down (driver query failed)\n", iter_curr_ptr->c_str() ); + } + } + } + if ( !links_gone_up.empty() ) + { + dlog3 ("%ld links have recovered\n", links_gone_up.size()); + + /* Look at the up list */ + for ( iter_curr_ptr = links_gone_up.begin(); + iter_curr_ptr != links_gone_up.end() ; + iter_curr_ptr++ ) + { + dlog3 ( "recovered link: %s (running:%d:%d)\n", + iter_curr_ptr->c_str(), + mgmnt_link_up_and_running, + infra_link_up_and_running ); + + if ( !strcmp (mgmnt_iface_ptr, iter_curr_ptr->data())) + { + mgmnt_link_up_and_running = true ; + wlog ("Mgmnt link %s is up\n", mgmnt_iface_ptr ); + } + if ( !strcmp (infra_iface_ptr, iter_curr_ptr->data())) + { + infra_link_up_and_running = true ; + wlog ("Infra link %s is up\n", infra_iface_ptr ); + } + + if ( get_link_state ( ioctl_sock, iter_curr_ptr->data(), &running ) == PASS ) + { + dlog ("%s is up (oper:%s)\n", + iter_curr_ptr->c_str(), + running ? "up" : "down" ); + } + else + { + wlog ("%s is up (driver query failed)\n", iter_curr_ptr->c_str() ); + } + } + } + } +} + + + + +/* Open a netlink listener socket and return that socket id. + * Return 0 on create or bind failure */ +int open_netlink_socket ( int groups ) +{ + struct sockaddr_nl addr; + int on = 1 ; + ilog ( "NLMon Groups: %d\n", groups ) ; + + int nl_socket = socket (AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (nl_socket < 0) + { + elog ("Failed to open netlink socket (%d:%s)\n", errno, strerror(errno)); + return (0); + } + + else if ( 0 > ioctl( nl_socket, FIONBIO, (char *)&on)) + { + elog ("failed to set 'netlink monitor' socket non-blocking (%d:%m)\n", errno ); + close (nl_socket); + nl_socket = 0 ; + } + else + { + memset ((void *) &addr, 0, sizeof (addr)); + + addr.nl_family = AF_NETLINK; + addr.nl_pid = getpid (); + /* addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR; */ + addr.nl_groups = groups ; /* allow the caller to specify the groups */ + + if (bind (nl_socket, (struct sockaddr *) &addr, sizeof (addr)) < 0) + { + elog ( "Failed to bind netlink socket (%d:%s)\n", errno, strerror(errno)); + close (nl_socket); + nl_socket = 0 ; + } + } + return (nl_socket); +} + +void close_netlink_socket ( int socket ) +{ + if ( socket ) + { + close (socket); + } +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/nlEvent.h b/mtce-common/cgts-mtce-common-1.0/common/nlEvent.h new file mode 100644 index 00000000..a1d4e872 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/nlEvent.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013, 2015 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGCS Platform netlink listener event support for maintenance + */ + +void close_netlink_socket ( int socket ); +int open_netlink_socket ( int groups ); +int get_netlink_events ( int nl_socket , + std::list & links_gone_down, + std::list & links_gone_up ); +void log_link_events ( int netlink_sock, + int ioctl_sock, + const char * mgmnt_iface_ptr, + const char * infra_iface_ptr, + bool & mgmnt_link_up_and_running, + bool & infra_link_up_and_running); + diff --git a/mtce-common/cgts-mtce-common-1.0/common/nodeBase.cpp b/mtce-common/cgts-mtce-common-1.0/common/nodeBase.cpp new file mode 100755 index 00000000..3f70200a --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/nodeBase.cpp @@ -0,0 +1,707 @@ +/* + * Copyright (c) 2013, 2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform "Node Base" Utility + */ + +#include +#include +#include + +using namespace std; + +#include "nodeBase.h" + +/** Maintenance command request to heartbeat servcie message header */ +const char mtc_hbs_cmd_req_header [MSG_HEADER_SIZE] = {"cgts mtc hbs cmd:"}; + +/** Maintenance Request Message header content */ +const char mtc_cmd_req_msg_header [MSG_HEADER_SIZE] = {"cgts mtc cmd req:"}; + +/** Maintenance Response Message header content */ +const char mtc_cmd_rsp_msg_header [MSG_HEADER_SIZE] = {"cgts mtc cmd rsp:"}; + +/** Maintenance Reply Message header content */ +const char mtc_msg_rep_msg_header [MSG_HEADER_SIZE] = {"cgts mtc rep msg:"}; + +/** Maintenance Log message header */ +const char mtc_log_msg_hdr [MSG_HEADER_SIZE] = {"cgts mtc log msg:"}; + +/** Maintenance Message header content */ +const char mtc_compute_msg_header [MSG_HEADER_SIZE] = {"cgts mtc message:"}; + +const char mtc_event_hdr [MSG_HEADER_SIZE] = {"mtce event msg :"}; + +const char mtc_pmond_pulse_header[MSG_HEADER_SIZE] = {"pmond alive pulse"}; + +const char mtc_heartbeat_event_hdr[MSG_HEADER_SIZE] = {"heart beat event:"}; + +const char mtc_heartbeat_loss_hdr [MSG_HEADER_SIZE] = {"heart beat loss :"}; +const char mtc_heartbeat_ready_hdr[MSG_HEADER_SIZE] = {"heart beat ready:"}; +const char mtc_loopback_hdr [MSG_HEADER_SIZE] = {"mtc loopback msg:"}; + +const char * get_loopback_header (void) { return mtc_loopback_hdr;} +const char * get_hbs_cmd_req_header (void) { return mtc_hbs_cmd_req_header ;} +const char * get_cmd_req_msg_header (void) { return mtc_cmd_req_msg_header ;} +const char * get_cmd_rsp_msg_header (void) { return mtc_cmd_rsp_msg_header ;} +const char * get_compute_msg_header (void) { return mtc_compute_msg_header ;} +const char * get_pmond_pulse_header (void) { return mtc_pmond_pulse_header ;} +const char * get_mtc_log_msg_hdr (void) { return mtc_log_msg_hdr ;} +const char * get_mtce_event_header (void) { return mtc_event_hdr ;} +const char * get_heartbeat_ready_header(void) { return mtc_heartbeat_ready_hdr;} +const char * get_heartbeat_loss_header (void) { return mtc_heartbeat_loss_hdr ;} +const char * get_heartbeat_event_header(void) { return mtc_heartbeat_event_hdr;} +const char * get_msg_rep_msg_header (void) { return mtc_msg_rep_msg_header ;} + +int print_mtc_message ( mtc_message_type * msg_ptr ) +{ + if ( msg_ptr->buf[0] ) + { + mlog1 ("Message: %d.%d.%d %x:%x:%x.%x.%x.%x [%s][%s]\n", + msg_ptr->ver, + msg_ptr->rev, + msg_ptr->res, + msg_ptr->cmd, + msg_ptr->num, + msg_ptr->parm[0], + msg_ptr->parm[1], + msg_ptr->parm[2], + msg_ptr->parm[3], + msg_ptr->hdr, + &msg_ptr->buf[0]); + } + else + { + mlog1 ("Message: %d.%d.%d %x:%x:%x.%x.%x.%x [%s]\n", + msg_ptr->ver, + msg_ptr->rev, + msg_ptr->res, + msg_ptr->cmd, + msg_ptr->num, + msg_ptr->parm[0], + msg_ptr->parm[1], + msg_ptr->parm[2], + msg_ptr->parm[3], + msg_ptr->hdr); + } + return (PASS); +} + +int print_mtc_message ( mtc_message_type * msg_ptr , bool force ) +{ + if ( force == true ) + { + if ( msg_ptr->buf[0] ) + { + ilog ("Message: %d.%d.%u %x:%x:%x.%x.%x.%x [%s][%s]\n", + msg_ptr->ver, + msg_ptr->rev, + msg_ptr->res, + msg_ptr->cmd, + msg_ptr->num, + msg_ptr->parm[0], + msg_ptr->parm[1], + msg_ptr->parm[2], + msg_ptr->parm[3], + msg_ptr->hdr, + &msg_ptr->buf[0]); + } + else + { + mlog1("Message: %d.%d.%d %x:%x:%x.%x.%x.%x [%s]\n", + msg_ptr->ver, + msg_ptr->rev, + msg_ptr->res, + msg_ptr->cmd, + msg_ptr->num, + msg_ptr->parm[0], + msg_ptr->parm[1], + msg_ptr->parm[2], + msg_ptr->parm[3], + msg_ptr->hdr); + } + } + else + { + print_mtc_message ( msg_ptr ); + } + return (PASS); +} + +const char * get_mtcNodeCommand_str ( int cmd ) +{ + switch ( cmd ) + { + case MTC_CMD_NONE: return ("none" ); + + /* general action command */ + case MTC_CMD_LOOPBACK: return ("loopback"); + case MTC_CMD_REBOOT: return ("reboot"); + case MTC_CMD_WIPEDISK: return ("wipedisk"); + case MTC_CMD_RESET: return ("reset"); + case MTC_MSG_MTCALIVE: return ("mtcAlive msg"); + case MTC_REQ_MTCALIVE: return ("mtcAlive req"); + case MTC_MSG_LOCKED: return ("locked msg"); + case MTC_CMD_LAZY_REBOOT: return ("lazy reboot"); + + /* goenabled commands and messages */ + case MTC_MSG_MAIN_GOENABLED: return ("goEnabled main msg"); + case MTC_MSG_SUBF_GOENABLED: return ("goEnabled subf msg"); + case MTC_REQ_MAIN_GOENABLED: return ("goEnabled main req"); + case MTC_REQ_SUBF_GOENABLED: return ("goEnabled subf req"); + case MTC_MSG_MAIN_GOENABLED_FAILED: return ("goEnabled main failed"); + case MTC_MSG_SUBF_GOENABLED_FAILED: return ("goEnabled subf failed"); + + /* start and stop services commands and messages */ + case MTC_CMD_STOP_CONTROL_SVCS: return ("stop controller host services"); + case MTC_CMD_STOP_COMPUTE_SVCS: return ("stop compute host services"); + case MTC_CMD_STOP_STORAGE_SVCS: return ("stop storage host services"); + case MTC_CMD_START_CONTROL_SVCS: return ("start controller host services"); + case MTC_CMD_START_COMPUTE_SVCS: return ("start compute host services"); + case MTC_CMD_START_STORAGE_SVCS: return ("start storage host services"); + case MTC_CMD_HOST_SVCS_RESULT: return ("host services result"); + + /* Heartbeat Control Commands */ + case MTC_RESTART_HBS: return("heartbeat restart"); + case MTC_BACKOFF_HBS: return("heartbeat backoff"); + case MTC_RECOVER_HBS: return("heartbeat recover"); + + /* heartbeat service messages */ + case MTC_EVENT_HEARTBEAT_READY: return("heartbeat ready event"); + case MTC_EVENT_HEARTBEAT_LOSS: return("heartbeat loss"); + case MTC_EVENT_HEARTBEAT_RUNNING: return("heartbeat running"); + case MTC_EVENT_HEARTBEAT_ILLHEALTH: return("heartbeat illhealth"); + case MTC_EVENT_HEARTBEAT_STOPPED: return("heartbeat stopped"); + case MTC_EVENT_HEARTBEAT_DEGRADE_SET:return("heartbeat degrade set"); + case MTC_EVENT_HEARTBEAT_MINOR_CLR: return("heartbeat minor clear"); + case MTC_EVENT_HEARTBEAT_DEGRADE_CLR:return("heartbeat degrade clear"); + case MTC_EVENT_HEARTBEAT_MINOR_SET: return("heartbeat minor set"); + + /* degrade events */ + case MTC_DEGRADE_RAISE: return ("degrade raise"); + case MTC_DEGRADE_CLEAR: return ("degrade clear"); + + /* general events */ + case MTC_EVENT_LOOPBACK: return ("loopback"); + case MTC_EVENT_MONITOR_READY: return ("monitor ready event"); + case MTC_EVENT_GOENABLE_FAIL: return ("goenable fail"); + case MTC_EVENT_HOST_STALLED: return("host stalled event"); + + /* pmon events */ + case MTC_EVENT_PMON_CLEAR: return("pmon clear"); + case MTC_EVENT_PMON_CRIT: return("pmon critical event"); + case MTC_EVENT_PMON_MAJOR: return("pmon major event"); + case MTC_EVENT_PMON_MINOR: return("pmon minor event"); + case MTC_EVENT_PMON_LOG: return("pmon log"); + case MTC_EVENT_PMOND_RAISE: return("pmon raise"); + + /* rmon events */ + case MTC_EVENT_RMON_READY: return("rmon ready event"); + case MTC_EVENT_RMON_CLEAR: return("rmon clear"); + case MTC_EVENT_RMON_CRIT: return("rmon critical event"); + case MTC_EVENT_RMON_MAJOR: return("rmon major event"); + case MTC_EVENT_RMON_MINOR: return("rmon minor event"); + case MTC_EVENT_RMON_LOG: return("rmon log"); + + /* data port events */ + case MTC_EVENT_AVS_CLEAR: return("AVS clear"); + case MTC_EVENT_AVS_MAJOR: return("AVS major"); + case MTC_EVENT_AVS_CRITICAL: return("AVS critical"); + case MTC_EVENT_AVS_OFFLINE: return("AVS offline"); + + /* hardware Monitor events */ + case MTC_EVENT_HWMON_CONFIG: return("hwmon config event"); /* OBS */ + case MTC_EVENT_HWMON_CLEAR: return("hwmon clear"); + case MTC_EVENT_HWMON_MINOR: return("hwmon minor event"); + case MTC_EVENT_HWMON_MAJOR: return("hwmon major event"); + case MTC_EVENT_HWMON_CRIT: return("hwmon critical event"); + case MTC_EVENT_HWMON_RESET: return("hwmon reset event"); + case MTC_EVENT_HWMON_LOG: return("hwmon log"); + case MTC_EVENT_HWMON_POWERDOWN: return("hwmon powerdown event"); /* OBS */ + case MTC_EVENT_HWMON_POWERCYCLE:return("hwmon powercycle event"); + + /* Host Commands */ + case MTC_CMD_ADD_HOST: return("add host"); + case MTC_CMD_DEL_HOST: return("del host"); + case MTC_CMD_MOD_HOST: return("modify host"); + case MTC_CMD_QRY_HOST: return("query host"); + case MTC_CMD_START_HOST: return("start host service"); + case MTC_CMD_STOP_HOST: return("stop host service"); + + /* VM Instance Commands */ + case MTC_CMD_ADD_INST: return("add instance"); + case MTC_CMD_DEL_INST: return("delete instance"); + case MTC_CMD_MOD_INST: return("modify instance"); + case MTC_CMD_QRY_INST: return("query instance"); + case MTC_CMD_VOTE_INST: return ("vote instance"); + case MTC_CMD_NOTIFY_INST: return ("notify instance"); + case MTC_EVENT_VOTE_NOTIFY: return ("notify instance event"); + + /* service events */ + case MTC_SERVICE_PMOND: return ("pmond service"); + case MTC_SERVICE_RMOND: return ("rmond service"); + case MTC_SERVICE_HWMOND: return ("hwmond service"); + case MTC_SERVICE_HEARTBEAT: return ("heartbeat service"); + default: + break ; + } + return ( "unknown"); +} + + +void print_mtc_message ( string hostname, int direction, mtc_message_type & msg , const char * iface, bool force ) +{ + string str = "-" ; + if ( msg.buf[0] ) + str = msg.buf ; + + if ( force ) + { + ilog ("%s %s %s (%s network) %d.%d %x:%x:%x.%x.%x.%x [%s] %s\n", + hostname.c_str(), + direction ? "rx <-" : "tx ->" , + get_mtcNodeCommand_str (msg.cmd), + iface, + msg.ver, + msg.rev, + msg.cmd, + msg.num, + msg.parm[0], + msg.parm[1], + msg.parm[2], + msg.parm[3], + msg.hdr, + str.c_str()); + } + else + { + mlog1 ("%s %s %s (%s network) %d.%d %x:%x:%x.%x.%x.%x [%s] %s\n", + hostname.c_str(), + direction ? "rx <-" : "tx ->" , + get_mtcNodeCommand_str (msg.cmd), + iface, + msg.ver, + msg.rev, + msg.cmd, + msg.num, + msg.parm[0], + msg.parm[1], + msg.parm[2], + msg.parm[3], + msg.hdr, + str.c_str()); + } +} + +/* Graceful recovery stages strings and string get'er */ +static std::string recoveryStages_str [MTC_RECOVERY__STAGES +1] ; +static std::string disableStages_str [MTC_DISABLE__STAGES +1] ; +static std::string enableStages_str [MTC_ENABLE__STAGES +1] ; +static std::string sensorStages_str [MTC_SENSOR__STAGES +1] ; +static std::string powerStages_str [MTC_POWER__STAGES +1] ; +static std::string powercycleStages_str [MTC_POWERCYCLE__STAGES +1] ; +static std::string resetStages_str [MTC_RESET__STAGES +1] ; +static std::string reinstallStages_str [MTC_RESET__STAGES +1] ; +static std::string oosTestStages_str [MTC_OOS_TEST__STAGES +1] ; +static std::string insvTestStages_str [MTC_INSV_TEST__STAGES +1] ; +static std::string configStages_str [MTC_CONFIG__STAGES +1] ; +static std::string addStages_str [MTC_ADD__STAGES +1] ; +static std::string delStages_str [MTC_DEL__STAGES +1] ; +static std::string subStages_str [MTC_SUBSTAGE__STAGES +1] ; + +void mtc_stages_init ( void ) +{ + enableStages_str [MTC_ENABLE__START ] = "Handler-Start"; + enableStages_str [MTC_ENABLE__RESERVED_1 ] = "reserved 1"; + enableStages_str [MTC_ENABLE__HEARTBEAT_CHECK ] = "Heartbeat-Check"; + enableStages_str [MTC_ENABLE__HEARTBEAT_STOP_CMD ] = "Heartbeat-Stop"; + enableStages_str [MTC_ENABLE__RECOVERY_TIMER ] = "Recovery-Start"; + enableStages_str [MTC_ENABLE__RECOVERY_WAIT ] = "Recovery-Wait"; + enableStages_str [MTC_ENABLE__RESET_PROGRESSION ] = "Reset-Prog"; + enableStages_str [MTC_ENABLE__RESET_WAIT ] = "Reset-Prog-Wait"; + enableStages_str [MTC_ENABLE__INTEST_START ] = "Intest-Start"; + enableStages_str [MTC_ENABLE__MTCALIVE_PURGE ] = "MtcAlive-Purge"; + enableStages_str [MTC_ENABLE__MTCALIVE_WAIT ] = "MtcAlive-Wait"; + enableStages_str [MTC_ENABLE__CONFIG_COMPLETE_WAIT ] = "Config-Complete-Wait"; + enableStages_str [MTC_ENABLE__GOENABLED_TIMER ] = "GoEnable-Start"; + enableStages_str [MTC_ENABLE__GOENABLED_WAIT ] = "GoEnable-Wait"; + enableStages_str [MTC_ENABLE__PMOND_READY_WAIT ] = "PmondReady-Wait"; + enableStages_str [MTC_ENABLE__HOST_SERVICES_START ] = "HostServices-Start"; + enableStages_str [MTC_ENABLE__HOST_SERVICES_WAIT ] = "HostServices-Wait"; + enableStages_str [MTC_ENABLE__SERVICES_START_WAIT ] = "Services-Start"; + enableStages_str [MTC_ENABLE__HEARTBEAT_WAIT ] = "Heartbeat-Wait"; + enableStages_str [MTC_ENABLE__HEARTBEAT_SOAK ] = "Heartbeat-Soak"; + enableStages_str [MTC_ENABLE__STATE_CHANGE ] = "State-Change"; + enableStages_str [MTC_ENABLE__WORKQUEUE_WAIT ] = "WorkQueue-Wait"; + enableStages_str [MTC_ENABLE__WAIT ] = "Enable-Wait"; + enableStages_str [MTC_ENABLE__DONE ] = "Enable-Done"; + enableStages_str [MTC_ENABLE__ENABLED ] = "Host-Enabled"; + enableStages_str [MTC_ENABLE__SUBF_FAILED ] = "Host-Degraded-Subf-Failed"; + enableStages_str [MTC_ENABLE__DEGRADED ] = "Host-Degraded"; + enableStages_str [MTC_ENABLE__FAILURE ] = "Failure"; + enableStages_str [MTC_ENABLE__FAILURE_WAIT ] = "Failure-Wait"; + enableStages_str [MTC_ENABLE__FAILURE_SWACT_WAIT ] = "Failure-Swact-Wait"; + enableStages_str [MTC_ENABLE__STAGES ] = "unknown" ; + + recoveryStages_str[MTC_RECOVERY__START ] = "Handler-Start"; + recoveryStages_str[MTC_RECOVERY__REQ_MTCALIVE ] = "Req-MtcAlive"; + recoveryStages_str[MTC_RECOVERY__REQ_MTCALIVE_WAIT ] = "Req-MtcAlive-Wait"; + recoveryStages_str[MTC_RECOVERY__RESET_RECV_WAIT ] = "Reset-Recv-Wait"; + recoveryStages_str[MTC_RECOVERY__MTCALIVE_TIMER ] = "MtcAlive-Timer"; + recoveryStages_str[MTC_RECOVERY__MTCALIVE_WAIT ] = "MtcAlive-Wait"; + recoveryStages_str[MTC_RECOVERY__GOENABLED_TIMER ] = "GoEnable-Timer"; + recoveryStages_str[MTC_RECOVERY__GOENABLED_WAIT ] = "GoEnable-Wait"; + recoveryStages_str[MTC_RECOVERY__HOST_SERVICES_START] = "HostServices-Start"; + recoveryStages_str[MTC_RECOVERY__HOST_SERVICES_WAIT ] = "HostServices-Wait"; + recoveryStages_str[MTC_RECOVERY__CONFIG_COMPLETE_WAIT]= "Compute-Config-Wait"; + recoveryStages_str[MTC_RECOVERY__SUBF_GOENABLED_TIMER]= "Subf-GoEnable-Timer"; + recoveryStages_str[MTC_RECOVERY__SUBF_GOENABLED_WAIT] = "Subf-GoEnable-Wait"; + recoveryStages_str[MTC_RECOVERY__SUBF_SERVICES_START] = "Subf-Services-Start"; + recoveryStages_str[MTC_RECOVERY__SUBF_SERVICES_WAIT ] = "Subf-Services-Wait"; + recoveryStages_str[MTC_RECOVERY__HEARTBEAT_START ] = "Heartbeat-Start"; + recoveryStages_str[MTC_RECOVERY__HEARTBEAT_SOAK ] = "Heartbeat-Soak"; + recoveryStages_str[MTC_RECOVERY__STATE_CHANGE ] = "State Change"; + recoveryStages_str[MTC_RECOVERY__ENABLE_START ] = "Enable-Start"; + recoveryStages_str[MTC_RECOVERY__FAILURE ] = "Failure"; + recoveryStages_str[MTC_RECOVERY__WORKQUEUE_WAIT ] = "WorkQ-Wait"; + recoveryStages_str[MTC_RECOVERY__ENABLE_WAIT ] = "Enable-Wait"; + recoveryStages_str[MTC_RECOVERY__STAGES ] = "unknown"; + + disableStages_str [MTC_DISABLE__START ] = "Disable-Start"; + disableStages_str [MTC_DISABLE__HANDLE_POWERON_SEND ] = "Disable-PowerOn-Send"; + disableStages_str [MTC_DISABLE__HANDLE_POWERON_RECV ] = "Disable-PowerOn-Recv"; + disableStages_str [MTC_DISABLE__HANDLE_FORCE_LOCK ] = "Disable-Force-Lock"; + disableStages_str [MTC_DISABLE__RESET_HOST_WAIT ] = "Disable-Reset-Wait"; + disableStages_str [MTC_DISABLE__DISABLE_SERVICES ] = "Disable-Services-Start"; + disableStages_str [MTC_DISABLE__DIS_SERVICES_WAIT ] = "Disable-Services-Wait"; + disableStages_str [MTC_DISABLE__HANDLE_CEPH_LOCK ] = "Disable-Ceph-Lock-Wait"; + disableStages_str [MTC_DISABLE__RESERVED ] = "Disable-reserved"; + disableStages_str [MTC_DISABLE__TASK_STATE_UPDATE ] = "Disable-States-Update"; + disableStages_str [MTC_DISABLE__WORKQUEUE_WAIT ] = "Disable-WorkQ-Wait"; + disableStages_str [MTC_DISABLE__DISABLED ] = "Host-Disabled"; + disableStages_str [MTC_DISABLE__STAGES ] = "Unknown"; + + powerStages_str [MTC_POWERON__START ] = "Power-On-Start"; + powerStages_str [MTC_POWERON__POWER_STATUS_WAIT ] = "Power-On-Status"; + powerStages_str [MTC_POWERON__POWER_STATUS_WAIT ] = "Power-On-Status-Wait"; + powerStages_str [MTC_POWERON__REQ_SEND ] = "Power-On-Req-Send"; + powerStages_str [MTC_POWERON__RESP_WAIT ] = "Power-On-Resp-Wait"; + powerStages_str [MTC_POWERON__DONE ] = "Power-On-Done"; + powerStages_str [MTC_POWERON__FAIL ] = "Power-On-Fail"; + powerStages_str [MTC_POWERON__FAIL_WAIT ] = "Power-On-Fail-Wait"; + powerStages_str [MTC_POWEROFF__START ] = "Power-Off-Start"; + powerStages_str [MTC_POWEROFF__REQ_SEND ] = "Power-Off-Req-Send"; + powerStages_str [MTC_POWEROFF__RESP_WAIT ] = "Power-Off-Resp-Wait"; + powerStages_str [MTC_POWEROFF__DONE ] = "Power-Off-Done"; + powerStages_str [MTC_POWEROFF__FAIL ] = "Power-Off-Fail"; + powerStages_str [MTC_POWEROFF__FAIL_WAIT ] = "Power-Off-Fail-Wait"; + powerStages_str [MTC_POWER__DONE ] = "Power-Done"; + powerStages_str [MTC_POWER__STAGES ] = "Power-Unknown"; + + + powercycleStages_str [MTC_POWERCYCLE__START ] = "Power-Cycle-Start"; + powercycleStages_str [MTC_POWERCYCLE__POWEROFF ] = "Power-Cycle-Off"; + powercycleStages_str [MTC_POWERCYCLE__POWEROFF_WAIT ] = "Power-Cycle-Off-Wait"; + powercycleStages_str [MTC_POWERCYCLE__POWERON ] = "Power-Cycle-On"; + powercycleStages_str [MTC_POWERCYCLE__POWERON_REQWAIT] = "Power-Cycle-On-Req-Wait"; + powercycleStages_str [MTC_POWERCYCLE__POWERON_VERIFY] = "Power-Cycle-On-Verify"; + powercycleStages_str [MTC_POWERCYCLE__POWERON_WAIT ] = "Power-Cycle-On-Wait"; + powercycleStages_str [MTC_POWERCYCLE__DONE ] = "Power-Cycle-Done"; + powercycleStages_str [MTC_POWERCYCLE__FAIL ] = "Power-Cycle-Fail"; + powercycleStages_str [MTC_POWERCYCLE__HOLDOFF ] = "Power-Cycle-Hold-Off"; + powercycleStages_str [MTC_POWERCYCLE__COOLOFF ] = "Power-Cycle-Cool-Off"; + + powercycleStages_str [MTC_POWERCYCLE__POWEROFF_CMND_WAIT] = "Power-Cycle-Off-Cmnd-Wait"; + powercycleStages_str [MTC_POWERCYCLE__POWERON_CMND_WAIT] = "Power-Cycle-On-Cmnd-Wait"; + powercycleStages_str [MTC_POWERCYCLE__POWERON_VERIFY_WAIT]= "Power-Cycle-On-Verify-Wait"; + + + resetStages_str [MTC_RESET__START ] = "Reset-Start"; + resetStages_str [MTC_RESET__REQ_SEND ] = "Reset-Req-Send"; + resetStages_str [MTC_RESET__RESP_WAIT ] = "Reset-Resp-Wait"; + resetStages_str [MTC_RESET__QUEUE ] = "Reset-Queue"; + resetStages_str [MTC_RESET__OFFLINE_WAIT ] = "Reset-Offline-Wait"; + resetStages_str [MTC_RESET__DONE ] = "Reset-Done"; + resetStages_str [MTC_RESET__FAIL ] = "Reset-Fail"; + resetStages_str [MTC_RESET__FAIL_WAIT ] = "Reset-Fail-Wait"; + resetStages_str [MTC_RESET__STAGES ] = "Reset-Unknown"; + + reinstallStages_str [MTC_REINSTALL__START ] = "Reinstall-Start"; + reinstallStages_str [MTC_REINSTALL__RESP_WAIT ] = "Reinstall-Response-Wait"; + reinstallStages_str [MTC_REINSTALL__OFFLINE_WAIT ] = "Reinstall-Offline-Wait"; + reinstallStages_str [MTC_REINSTALL__ONLINE_WAIT ] = "Reinstall-Online-Wait"; + reinstallStages_str [MTC_REINSTALL__FAIL ] = "Reinstall-Failure"; + reinstallStages_str [MTC_REINSTALL__MSG_DISPLAY ] = "Reinstall-Message-Display"; + reinstallStages_str [MTC_REINSTALL__DONE ] = "Reinstall-Done"; + reinstallStages_str [MTC_REINSTALL__STAGES ] = "Reinstall-Unknown"; + + oosTestStages_str [MTC_OOS_TEST__LOAD_NEXT_TEST ] = "Test-Load-Next"; + oosTestStages_str [MTC_OOS_TEST__BMC_ACCESS_TEST ] = "Test-BMC-Access-Test"; + oosTestStages_str [MTC_OOS_TEST__BMC_ACCESS_RESULT ] = "Test-BMC-Access-Result"; + oosTestStages_str [MTC_OOS_TEST__START_WAIT ] = "Test-Start-Wait"; + oosTestStages_str [MTC_OOS_TEST__WAIT ] = "Test-Wait"; + oosTestStages_str [MTC_OOS_TEST__DONE ] = "Test-Done"; + oosTestStages_str [MTC_OOS_TEST__STAGES ] = "Test-Unknown"; + + insvTestStages_str[MTC_INSV_TEST__START ] = "Test-Start"; + insvTestStages_str[MTC_INSV_TEST__WAIT ] = "Test-Wait"; + insvTestStages_str[MTC_INSV_TEST__RUN ] = "Test-Run"; + insvTestStages_str[MTC_INSV_TEST__STAGES ] = "Test-Unknown"; + + sensorStages_str [MTC_SENSOR__START ] = "Sensor-Read-Start"; + sensorStages_str [MTC_SENSOR__READ_FAN ] = "Sensor-Read-Fans"; + sensorStages_str [MTC_SENSOR__READ_TEMP ] = "Sensor-Read-Temp"; + sensorStages_str [MTC_SENSOR__STAGES ] = "Sensor-Unknown"; + + configStages_str [MTC_CONFIG__START ] = "Config-Start"; + configStages_str [MTC_CONFIG__SHOW ] = "Config-Show"; + configStages_str [MTC_CONFIG__MODIFY ] = "Config-Modify"; + configStages_str [MTC_CONFIG__VERIFY ] = "Config-Verify"; + configStages_str [MTC_CONFIG__FAILURE ] = "Config-Fail"; + configStages_str [MTC_CONFIG__TIMEOUT ] = "Config-Timeout"; + configStages_str [MTC_CONFIG__DONE ] = "Config-Done"; + configStages_str [MTC_CONFIG__STAGES ] = "Config-Unknown"; + + addStages_str [MTC_ADD__START ] = "Add-Start"; + addStages_str [MTC_ADD__START_DELAY ] = "Add-Start-Delay"; + addStages_str [MTC_ADD__START_SERVICES ] = "Add-Start-Services"; + addStages_str [MTC_ADD__START_SERVICES_WAIT ] = "Add-Start-Services-Wait"; +// addStages_str [MTC_ADD__CLEAR_ALARMS ] = "Add-Clear-Alarms"; + addStages_str [MTC_ADD__MTC_SERVICES ] = "Add-Mtc-Services"; + addStages_str [MTC_ADD__CLEAR_TASK ] = "Add-Clear-Task"; + addStages_str [MTC_ADD__WORKQUEUE_WAIT ] = "Add-WorkQ-Wait"; + addStages_str [MTC_ADD__DONE ] = "Add-Done"; + addStages_str [MTC_ADD__STAGES ] = "Add-Unknown"; + + delStages_str [MTC_DEL__START ] = "Del-Start"; + delStages_str [MTC_DEL__WAIT ] = "Del-Wait"; + delStages_str [MTC_DEL__DONE ] = "Del-Done"; + + subStages_str [MTC_SUBSTAGE__START ] = "subStage-Start"; + subStages_str [MTC_SUBSTAGE__SEND ] = "subStage-Send"; + subStages_str [MTC_SUBSTAGE__RECV ] = "subStage-Recv"; + subStages_str [MTC_SUBSTAGE__WAIT ] = "subStage-Wait"; + subStages_str [MTC_SUBSTAGE__DONE ] = "subStage-Done"; + subStages_str [MTC_SUBSTAGE__FAIL ] = "subStage-Fail"; +} + +string get_delStages_str ( mtc_delStages_enum stage ) +{ + if ( stage >= MTC_DEL__STAGES ) + { + return (delStages_str[MTC_DEL__STAGES]); + } + return (delStages_str[stage]); +} + +/* Get the specified 'enable' stage string */ +string get_enableStages_str ( mtc_enableStages_enum stage ) +{ + if ( stage >= MTC_ENABLE__STAGES ) + { + return (enableStages_str[MTC_ENABLE__STAGES]); + } + return (enableStages_str[stage]); +} + +/* Get the specified 'recovery' stage string */ +string get_recoveryStages_str ( mtc_recoveryStages_enum stage ) +{ + if ( stage >= MTC_RECOVERY__STAGES ) + { + return (recoveryStages_str[MTC_RECOVERY__STAGES]); + } + return (recoveryStages_str[stage]); +} + +/* Get the specified 'config' stage string */ +string get_configStages_str ( mtc_configStages_enum stage ) +{ + if ( stage >= MTC_CONFIG__STAGES ) + { + return (configStages_str[MTC_CONFIG__STAGES]); + } + return (configStages_str[stage]); +} + +/* Get the specified 'disable' stage string */ +string get_disableStages_str ( mtc_disableStages_enum stage ) +{ + if ( stage >= MTC_DISABLE__STAGES ) + { + return (disableStages_str[MTC_DISABLE__STAGES]); + } + return (disableStages_str[stage]); +} + +/* Get the specified 'power' stage string */ +string get_powerStages_str ( mtc_powerStages_enum stage ) +{ + if ( stage >= MTC_POWER__STAGES ) + { + return (powerStages_str[MTC_POWER__STAGES]); + } + return (powerStages_str[stage]); +} + +/* Get the specified 'powercycle' stage string */ +string get_powercycleStages_str ( mtc_powercycleStages_enum stage ) +{ + if ( stage >= MTC_POWERCYCLE__STAGES ) + { + return (powercycleStages_str[MTC_POWERCYCLE__STAGES]); + } + return (powercycleStages_str[stage]); +} + +/* Get the specified 'reset' stage string */ +string get_resetStages_str ( mtc_resetStages_enum stage ) +{ + if ( stage >= MTC_RESET__STAGES ) + { + return (resetStages_str[MTC_RESET__STAGES]); + } + return (resetStages_str[stage]); +} + +/* Get the specified 'reinstall' stage string */ +string get_reinstallStages_str ( mtc_reinstallStages_enum stage ) +{ + if ( stage >= MTC_REINSTALL__STAGES ) + { + return (reinstallStages_str[MTC_REINSTALL__STAGES]); + } + return (reinstallStages_str[stage]); +} + +/* Get the specified 'out-of-service test' stage string */ +string get_oosTestStages_str ( mtc_oosTestStages_enum stage ) +{ + if ( stage >= MTC_OOS_TEST__STAGES ) + { + return (oosTestStages_str[MTC_OOS_TEST__STAGES]); + } + return (oosTestStages_str[stage]); +} + +/* Get the specified 'in-service test' stage string */ +string get_insvTestStages_str ( mtc_insvTestStages_enum stage ) +{ + if ( stage >= MTC_INSV_TEST__STAGES ) + { + return (insvTestStages_str[MTC_INSV_TEST__STAGES]); + } + return (insvTestStages_str[stage]); +} + +string get_sensorStages_str ( mtc_sensorStages_enum stage ) +{ + if ( stage >= MTC_SENSOR__STAGES ) + { + return (sensorStages_str[MTC_SENSOR__STAGES]); + } + return (sensorStages_str[stage]); +} + +/** Return the string representing the specified 'sub' stage */ +string get_subStages_str ( mtc_subStages_enum stage ) +{ + if ( stage >= MTC_SUBSTAGE__STAGES ) + { + return (subStages_str[MTC_SUBSTAGE__STAGES]); + } + return (subStages_str[stage]); +} + +void log_adminAction ( string hostname, + mtc_nodeAdminAction_enum currAction, + mtc_nodeAdminAction_enum newAction ) +{ + if (( currAction != MTC_ADMIN_ACTION__LOCK ) && + ( newAction == MTC_ADMIN_ACTION__LOCK )) + { + ilog ("%s Lock Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__FORCE_LOCK ) && + ( newAction == MTC_ADMIN_ACTION__FORCE_LOCK )) + { + ilog ("%s Lock Action (Force)\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__UNLOCK ) && + ( newAction == MTC_ADMIN_ACTION__UNLOCK )) + { + ilog ("%s Unlock Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__SWACT ) && + ( newAction == MTC_ADMIN_ACTION__SWACT )) + { + ilog ("%s Swact Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__FORCE_SWACT ) && + ( newAction == MTC_ADMIN_ACTION__FORCE_SWACT )) + { + ilog ("%s Swact Action (Force)\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__ADD ) && + ( newAction == MTC_ADMIN_ACTION__ADD )) + { + ilog ("%s Add Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__RESET ) && + ( newAction == MTC_ADMIN_ACTION__RESET )) + { + ilog ("%s Reset Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__REBOOT ) && + ( newAction == MTC_ADMIN_ACTION__REBOOT )) + { + ilog ("%s Reboot Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__REINSTALL ) && + ( newAction == MTC_ADMIN_ACTION__REINSTALL )) + { + ilog ("%s Reinstall Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__POWEROFF ) && + ( newAction == MTC_ADMIN_ACTION__POWEROFF )) + { + ilog ("%s Power-Off Action\n", hostname.c_str()); + } + else if (( currAction != MTC_ADMIN_ACTION__POWERON ) && + ( newAction == MTC_ADMIN_ACTION__POWERON )) + { + ilog ("%s Power-On Action\n", hostname.c_str()); + } +} + +/* Init recovery control structure */ +void recovery_ctrl_init ( recovery_ctrl_type & recovery_ctrl ) +{ + recovery_ctrl.state = RECOVERY_STATE__INIT ; + recovery_ctrl.attempts = 0 ; + recovery_ctrl.holdoff = 0 ; + recovery_ctrl.queries = 0 ; + recovery_ctrl.retries = 0 ; +} + +/* returns 'true' if the specified command is a host services command */ +bool is_host_services_cmd ( unsigned int cmd ) +{ + if (( cmd == MTC_CMD_START_CONTROL_SVCS ) || + ( cmd == MTC_CMD_START_COMPUTE_SVCS ) || + ( cmd == MTC_CMD_START_STORAGE_SVCS ) || + ( cmd == MTC_CMD_STOP_CONTROL_SVCS ) || + ( cmd == MTC_CMD_STOP_COMPUTE_SVCS ) || + ( cmd == MTC_CMD_STOP_STORAGE_SVCS ) || + ( cmd == MTC_CMD_HOST_SVCS_RESULT )) + { + return (true); + } + return (false); +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/nodeBase.h b/mtce-common/cgts-mtce-common-1.0/common/nodeBase.h new file mode 100755 index 00000000..cf42f347 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/nodeBase.h @@ -0,0 +1,1255 @@ +#ifndef __INCLUDE_NODEBASE_HH__ +#define __INCLUDE_NODEBASE_HH__ +/* + * Copyright (c) 2013-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform "Node Base" Header + */ + +#include +#include +#include + +using namespace std; + +#include "fitCodes.h" +#include "logMacros.h" +#include "returnCodes.h" +#include "nodeTimers.h" + +#define ALIGN_PACK(x) __attribute__((packed)) x + +/* Out-Of-Service Stress tests */ +#define WANT_SYSINV_API_STRESS 0x00000001 +#define WANT_SERVICE_UPDOWN_API_STRESS 0x00000002 +#define WANT_SMGR_API_STRESS 0x00000004 +#define WANT_FM_API_STRESS 0x00000008 +#define WANT_TOKEN_REFRESH_STRESS 0x00000010 + +void daemon_exit ( void ); + +#define MAX_EVENT_BUF (2048) +#define MAX_RECV_FAILS_B4_RECONNECT (4) +#define MAX_INFLIGHT_HTTP_REQUESTS (7) +#define MAX_FILE_SIZE (128) +#define MAX_FSM_SSH2_RETRIES (20) +#define MAX_POWERCYCLE_STAGE_RETRIES (3) +#define MAX_POWERCYCLE_ATTEMPT_RETRIES (3) +#define MAX_POWERCYCLE_QUERY_RETRIES (10) +#define MAX_BMC_POWER_CTRL_RETRIES (5) + +/* Added for failure handling offline feature */ +#define MIN_OFFLINE_PERIOD_MSECS (10) +#define MIN_OFFLINE_THRESHOLD (1) + +/* Board management Expect Script return Codes: 1xx range + * These codes are also defined in /usr/local/sbin/bmvars.exp */ +#define FAIL_BM_UNSUPPORTED (100*256) +#define FAIL_BM_INV_QUERY (101*256) +#define FAIL_BM_NO_IP (102*256) + +#define FAIL_BM_PING_TEST (112*256) +#define FAIL_BM_PING_SPAWN (113*256) +#define FAIL_BM_PING_TIMEOUT (114*256) +#define FAIL_BM_PING_ZERO_PERCENT (115*256) +#define FAIL_BM_PING_FIFTY_PERCENT (116*256) + +#define FAIL_BM_USERNAME (120*256) +#define FAIL_BM_IPADDR (121*256) +#define FAIL_BM_PASSWORD (122*256) + + +#define MTC_PARM_UPTIME_IDX (0) +#define MTC_PARM_HEALTH_IDX (1) +#define MTC_PARM_FLAGS_IDX (2) +#define MTC_PARM_MAX_IDX (3) + +/** 'I Am ' flags for maintenance. + * + * These flags are shipped in the parm[2] if the + * mtcAlive message from each host. */ +#define MTC_FLAG__I_AM_CONFIGURED (0x00000001) +#define MTC_FLAG__I_AM_NOT_HEALTHY (0x00000002) +#define MTC_FLAG__I_AM_HEALTHY (0x00000004) +#define MTC_FLAG__I_AM_LOCKED (0x00000008) +#define MTC_FLAG__SUBF_CONFIGURED (0x00000010) +#define MTC_FLAG__MAIN_GOENABLED (0x00000020) +#define MTC_FLAG__SUBF_GOENABLED (0x00000040) +#define MTC_FLAG__SM_DEGRADED (0x00000080) +#define MTC_FLAG__PATCHING (0x00000100) /* Patching in progress */ +#define MTC_FLAG__PATCHED (0x00000200) /* Patched but not reset */ + +#define MTC_UNHEALTHY_THRESHOLD (3) + +/* Node Health States */ +#define NODE_HEALTH_UNKNOWN (0) +#define NODE_HEALTHY (1) +#define NODE_UNHEALTHY (2) + +#define HOST_IS_VIRTUAL ((const char *)"/var/run/virtual.host") + +/** Configuration Pass/Fail Flag File */ +#define CONFIG_PASS_FILE ((const char *)"/var/run/.config_pass") +#define CONFIG_FAIL_FILE ((const char *)"/var/run/.config_fail") +#define NODE_LOCKED_FILE ((const char *)"/var/run/.node_locked") +#define NODE_RESET_FILE ((const char *)"/var/run/.node_reset") +#define SMGMT_DEGRADED_FILE ((const char *)"/var/run/.sm_degraded") +#define SMGMT_UNHEALTHY_FILE ((const char *)"/var/run/.sm_node_unhealthy") + +/** path to and module init file name */ +#define MTCE_CONF_FILE ((const char *)"/etc/mtc.conf") +#define MTCE_INI_FILE ((const char *)"/etc/mtc.ini") +#define NFVI_PLUGIN_CFG_FILE ((const char *)"/etc/nfv/nfv_plugins/nfvi_plugins/config.ini") +#define SYSINV_CFG_FILE ((const char *)"/etc/sysinv/sysinv.conf") +#define HWMON_CONF_FILE ((const char *)"/etc/mtc/hwmond.conf") + + +#define GOENABLED_DIR ((const char *)"/etc/goenabled.d") /* generic */ +#define GOENABLED_COMPUTE_DIR ((const char *)"/etc/goenabled.d/compute") +#define GOENABLED_STORAGE_DIR ((const char *)"/etc/goenabled.d/storage") +#define GOENABLED_CONTROL_DIR ((const char *)"/etc/goenabled.d/control") + +#define GOENABLED_MAIN_READY ((const char *)"/var/run/.goenabled") +#define GOENABLED_SUBF_READY ((const char *)"/var/run/.goenabled_subf") + +#define GOENABLED_MAIN_PASS ((const char *)"/var/run/goenabled") +#define GOENABLED_SUBF_PASS ((const char *)"/var/run/goenabled_subf") +#define GOENABLED_MAIN_FAIL ((const char *)"/var/run/goenabled_failed") +#define GOENABLED_SUBF_FAIL ((const char *)"/var/run/goenabled_subf_failed") + +#define CONFIG_COMPLETE_CONTROL ((const char *)"/var/run/.controller_config_complete") +#define CONFIG_COMPLETE_COMPUTE ((const char *)"/var/run/.compute_config_complete") +#define CONFIG_COMPLETE_STORAGE ((const char *)"/var/run/.storage_config_complete") +#define CONFIG_COMPLETE_FILE ((const char *)"/etc/platform/.initial_config_complete") + +#define DISABLE_COMPUTE_SERVICES ((const char *)"/var/run/.disable_compute_services") + +#define PATCHING_IN_PROG_FILE ((const char *)"/var/run/patch_installing") +#define NODE_IS_PATCHED_FILE ((const char *)"/var/run/node_is_patched") + +#define PLATFORM_CONF_FILE ((const char *)"/etc/platform/platform.conf") +#define PLATFORM_CONF_DIR ((const char *)"/etc/platform") +#define PLATFORM_SIMPLEX_MODE ((const char *)"/etc/platform/simplex") +#define SERVICES_DIR ((const char *)"/etc/services.d") +#define SERVER_PROFILE_DIR ((const char *)"/etc/bmc/server_profiles.d") +#define PASSWORD_FILE ((const char *)"/etc/passwd") +#define SHADOW_FILE ((const char *)"/etc/shadow") +#define USERNAME_ROOT ("wrsroot") + +#define PMON_CONF_FILE_DIR ((const char *)"/etc/pmon.d") + +#define BM_DNSMASQ_FILENAME ((const char *)"dnsmasq.bmc_hosts") + +/* Added for Centos */ +#define CENTOS_RELEASE_FILE ((const char *)"/etc/centos-release") +#define SYSTEMD_SERVICE_FILE_DIR ((const char *)"/usr/lib/systemd/system") + +#define THREAD_NAME__IPMITOOL ((const char *)("ipmitool")) + +#define IPMITOOL_PATH_AND_FILENAME ((const char *)("/usr/bin/ipmitool")) +#define IPMITOOL_OUTPUT_DIR ((const char *)("/var/run/ipmitool/")) + +/** 'lo' interface IP address - TODO: get it from the interface */ +#define LOOPBACK_IP "127.0.0.1" +#define LOOPBACK_IPV6 "::1" +#define LOCALHOST "localhost" + +#define NONE (const char *)"none" + +/** Largest heartbeat pulse (req/resp) message size */ +#define MAX_API_LOG_LEN (0x1000) +#define MAX_FILENAME_LEN (100) +#define MAX_SYSTEM_CMD_LEN (200) + +#define MAX_START_SERVICES_RETRY (20) + +#define DEFAULT_MTCALIVE_TIMEOUT (1200) +#define DEFAULT_GOENABLE_TIMEOUT (300) +#define DEFAULT_DOR_MODE_TIMEOUT (20) +#define DEFAULT_DOR_MODE_CPE_TIMEOUT (600) + +/** TODO: Convert names to omit JSON part */ +#define MTC_JSON_INV_LABEL "ihosts" +#define MTC_JSON_INV_NEXT "next" +#define MTC_JSON_INV_UUID "uuid" +#define MTC_JSON_INV_NAME "hostname" +#define MTC_JSON_INV_HOSTIP "mgmt_ip" +#define MTC_JSON_INV_HOSTMAC "mgmt_mac" +#define MTC_JSON_INV_INFRAIP "infra_ip" +#define MTC_JSON_INV_AVAIL "availability" +#define MTC_JSON_INV_OPER "operational" +#define MTC_JSON_INV_ADMIN "administrative" +#define MTC_JSON_INV_OPER_SUBF "subfunction_oper" +#define MTC_JSON_INV_AVAIL_SUBF "subfunction_avail" +#define MTC_JSON_INV_TYPE "personality" +#define MTC_JSON_INV_FUNC "subfunctions" // personality" +#define MTC_JSON_INV_TASK "task" +#define MTC_JSON_INV_ACTION "action" +#define MTC_JSON_INV_UPTIME "uptime" +#define MTC_JSON_INV_BMIP "bm_ip" +#define MTC_JSON_INV_BMTYPE "bm_type" +#define MTC_JSON_INV_BMUN "bm_username" + +#define MTC_JSON_SEVERITY "severity" + +/* These Task strings should not be changed without + * the corresponding change in Horizon. + * + * Task strings must be limited to less than 64 bytes. + * + **/ +#define MAX_TASK_STR_LEN (63) /* leave room for null termination */ +#define MTC_TASK_DISABLE_CONTROL "Disabling Controller" +#define MTC_TASK_DISABLE_SERVICES "Disabling Services" +#define MTC_TASK_UNLOCK_FAILED "Unlock Operation Failed" +#define MTC_TASK_REBOOT_REQUEST "Reboot Request" +#define MTC_TASK_RESET_REQUEST "Reset Request" +#define MTC_TASK_REBOOTING "Rebooting" +#define MTC_TASK_RESETTING "Resetting" +#define MTC_TASK_REBOOT_FAIL "Reboot Failed" +#define MTC_TASK_REBOOT_TIMEOUT "Reboot/Reset Timeout" +#define MTC_TASK_REBOOT_FAIL_RETRY "Reboot Failed, retrying (%d of %d)" +#define MTC_TASK_REBOOT_ABORT "Reboot Failed, try again when host is 'online'" +#define MTC_TASK_RESET_PROG "Rebooting/Resetting Host" +#define MTC_TASK_REINSTALL "Reinstalling Host" +#define MTC_TASK_REINSTALL_FAIL "Reinstall Failed" +#define MTC_TASK_REINSTALL_SUCCESS "Reinstall Succeeded" +#define MTC_TASK_BOOTING "Booting" +#define MTC_TASK_BOOT_FAIL "Boot Failed, rebooting" +#define MTC_TASK_TESTING "Testing" +#define MTC_TASK_INITIALIZING "Initializing" +#define MTC_TASK_INIT_FAIL "Initialization Failed, recovering" +#define MTC_TASK_START_SERVICE_FAIL "Start Services Failed" +#define MTC_TASK_START_SERVICE_TO "Start Services Timeout" +#define MTC_TASK_ENABLING "Enabling" +#define MTC_TASK_ENABLING_SUBF "Enabling Compute Service" +#define MTC_TASK_ENABLING_SUBF_FAIL "Enabling Compute Service Failed" +#define MTC_TASK_ENABLING_SUBF_TO "Enabling Compute Service Timeout" +#define MTC_TASK_ENABLE_WORK_FAIL "Enable Action Failed, re-enabling" +#define MTC_TASK_ENABLE_WORK_FAIL_ "Enable Action Failed" +#define MTC_TASK_ENABLE_WORK_TO "Enable Action Timeout, re-enabling" +#define MTC_TASK_ENABLE_WORK_TO_ "Enable Action Timeout" +#define MTC_TASK_ENABLE_FAIL_HB "Enable Heartbeat Failure, re-enabling" +#define MTC_TASK_RECOVERY_FAIL "Graceful Recovery Failed, re-enabling" +#define MTC_TASK_RECOVERY_WAIT "Graceful Recovery Wait" +#define MTC_TASK_RECOVERED "Gracefully Recovered" +#define MTC_TASK_MAIN_CONFIG_FAIL "Configuration Failed, re-enabling" +#define MTC_TASK_SUBF_CONFIG_FAIL "Compute Configuration Failed, re-enabling" +#define MTC_TASK_SUBF_CONFIG_FAIL_ "Compute Configuration Failed" +#define MTC_TASK_MAIN_CONFIG_TO "Configuration Timeout, re-enabling" +#define MTC_TASK_SUBF_CONFIG_TO "Compute Configuration Timeout, re-enabling" +#define MTC_TASK_SUBF_CONFIG_TO_ "Compute Configuration Timeout" +#define MTC_TASK_INTEST_FAIL "In-Test Failed, re-enabling" +#define MTC_TASK_INTEST_FAIL_ "In-Test Failed" +#define MTC_TASK_INTEST_FAIL_TO "In-Test Timeout, re-enabling" +#define MTC_TASK_INTEST_FAIL_TO_ "In-Test Timeout" +#define MTC_TASK_RESET_FAIL "Reset Failed" +#define MTC_TASK_RESET_QUEUE "Reset Failed, retrying (%d of %d)" +#define MTC_TASK_POWERON_FAIL "Power-On Failed" +#define MTC_TASK_POWERON_QUEUE "Power-On Failed, retrying (%d of %d)" +#define MTC_TASK_POWEROFF_FAIL "Power-Off Failed" +#define MTC_TASK_POWEROFF_QUEUE "Power-Off Failed, retrying (%d of %d)" + +#define MTC_TASK_BMC_NOT_PROV "Request Failed, Management Controller Not Provisioned" +#define MTC_TASK_BMC_NOT_CONNECTED "Request Failed, Management Controlle Not Accessible" + +#define MTC_TASK_DISABLE_REQ "Requesting Disable" +#define MTC_TASK_MIGRATE_INSTANCES "Migrating Instances" +#define MTC_TASK_DISABLE_SERVICES "Disabling Services" +#define MTC_TASK_POWERCYCLE_HOST "Critical Event Power-Cycle %d; due to critical sensor" +#define MTC_TASK_POWERCYCLE_HOLD "Critical Event Power-Cycle %d; recovery in %d minute(s)" +#define MTC_TASK_POWERCYCLE_COOL "Critical Event Power-Cycle %d; power-on in %d minute(s)" +#define MTC_TASK_POWERCYCLE_ON "Critical Event Power-Cycle %d; power-on host" +#define MTC_TASK_POWERCYCLE_RETRY "Critical Event Power-Cycle %d; power-on host (retry)" +#define MTC_TASK_POWERCYCLE_BOOT "Critical Event Power-Cycle %d; host is booting" +#define MTC_TASK_POWERCYCLE_FAIL "Critical Event Power-Cycle %d; failed" +#define MTC_TASK_POWERCYCLE_DOWN "Critical Event Power-Down ; due to persistent critical sensor" +#define MTC_TASK_RESETTING_HOST "Resetting Host, critical sensor" +#define MTC_TASK_CPE_SX_UNLOCK_MSG "Unlocking, please stand-by while the system gracefully reboots" +#define MTC_TASK_SELF_UNLOCK_MSG "Unlocking active controller, please stand-by while it reboots" +#define MTC_TASK_AUTO_RECOVERY "Critical failure. Auto-recovery enabled, re-enabling" +#define MTC_TASK_AUTO_RECOVERY_DISABLED "Critical failure. Auto-recovery disabled, threshold reached" +#define MTC_TASK_FAILED_SWACT_REQ "Critical failure.Requesting SWACT to enabled standby controller" +#define MTC_TASK_FAILED_NO_BACKUP "Critical failure.Please provision/enable standby controller" + +#define COMMAND_RETRY_DELAY (8) /* from sshUtil.h */ +#define COMMAND_DELAY (2) /* from sshUtil.h */ + +#define MTC_POWER_ACTION_RETRY_DELAY (20) +#define MTC_POWER_ACTION_RETRY_COUNT (10) +#define MTC_RESET_ACTION_RETRY_COUNT (5) + +/* number of calls to the bm_handler while bm_access is not confirmed */ +#define MTC_MAX_B2B_BM_ACCESS_FAIL_COUNT_B4_ALARM (5) + /* string too long for inv */ +#define MTC_TASK_DISABLE_REJ "Lock Rejected: Incomplete Migration" /* Please Enable More Compute Resources" */ +#define MTC_TASK_DISABLE_NOHOST "Lock Rejected: Please Enable More Compute Resources" +#define MTC_TASK_MIGRATE_FAIL "Lock Failed: Undetermined Reason" +#define MTC_TASK_DISABLE_NOHOSTS "Insufficient Enabled Resources for Live Migration" +#define MTC_TASK_DISABLE_FORCE "Force Lock Reset in Progress" +#define MAX_JSON_INV_GET_HOST_NUM (10) + +#define MTC_TASK_SWACT_COMPLETE "Swact: Complete" +#define MTC_TASK_SWACT_NO_COMPLETE "Swact: Did Not Complete" +#define MTC_TASK_SWACT_REQUEST "Swact: Request" +#define MTC_TASK_SWACT_INPROGRESS "Swact: In-Progress" +#define MTC_TASK_SWACT_FAILED "Swact: Failed" +#define MTC_TASK_SWACT_TIMEOUT "Swact: Timeout" +#define MTC_TASK_SWACT_NOSERVICE "Swact: No active services" +#define MTC_TASK_SWACT_FAIL_QUERY "Swact: Query Services Failed" + +/** The character length of a UUID */ +#ifndef UUID_LEN +#define UUID_LEN (36) +#endif + +/** Range of characters in an IP address */ +#define COL_CHARS_IN_MAC_ADDR (17) /**< Colin del'ed xx:xx:xx:xx:xx:xx */ +#define MIN_CHARS_IN_IP_ADDR (3) /**< Min chars in ipv4 or ipv6 address */ +#define MAX_CHARS_IN_IP_ADDR (INET6_ADDRSTRLEN) /**< Max chars in the longer of IPV4 or IPV6 address */ + +/* root@controller-0:~# getconf HOST_NAME_MAX + * 64 + */ +#define MAX_CHARS_HOSTNAME (32) /**< The largest hostname length */ +// #define MAX_CHARS_HOSTNAME (64) /**< The largest hostname length */ +#define MAX_CHARS_FILENAME (256) /**< The largest hostname length */ + +#define MAX_CHARS_ON_LINE (256) /**> max number of chars on a single line */ +#define MAX_CHARS_IN_INT (65) /**> max number of chars in an integer */ + +/** Maximum number of nodes supported by this module */ +#define MAX_NODES (int)(500) + +/** Maximum number of nodes supported by CGTS platform */ +#define MAX_HOSTS (MAX_NODES) + +/** Longest hostname size */ +#define MAX_HOST_NAME_SIZE (int) (MAX_CHARS_HOSTNAME) + +/** maximum number f queued actions supported */ +#define MTC_MAX_QUEUED_ACTIONS (2) + +/* 50 milliseconds */ +#define SOCKET_WAIT 50000 + +/* 5 milliseconds */ +#define MTCAGENT_SELECT_TIMEOUT (5000) + +/* dedicate more idle time in CPE ; there is less maintenance to do */ +#define MTCAGENT_CPE_SELECT_TIMEOUT (10000) + +/** Number of retries maintenance will do when it experiences + * a REST API call failure ; any failure */ +#define REST_API_RETRY_COUNT (3) + +/** Number of mtcAlive misses before transitioning a locked-disabled + * host from 'online' to 'offline'. + * See mtcTimers.h for the mtcAlive and offline timer periods */ +#define MTC_OFFLINE_MISSES (1) + +/** Number of back to back mtcAlive messages before we allow + * a power-off to online transition */ +#define MTC_MTCALIVE_HITS_TO_GO_ONLINE (5) + +#define CONTROLLER_0 ((const char *)"controller-0") +#define CONTROLLER_1 ((const char *)"controller-1") +#define CONTROLLER ((const char *)"controller") + +/* The infrastructure networking floating IP + * + * Note: If there is no infra then this label will resolve + * to another floating IP on the management network. + * + * If there is no Infra network then this label is not and should not be used */ +#define CONTROLLER_NFS ((const char *)"controller-nfs") + +#define CGTS_NODE_TYPES 4 +#define CGTS_NODE_TYPE_SIZE 12 +#define CGTS_NODE_NULL (0x00) +#define CONTROLLER_TYPE (0x01) +#define COMPUTE_TYPE (0x02) +#define STORAGE_TYPE (0x04) +#define CGCS_STORAGE_NFS 0 +#define CGCS_STORAGE_CEPH 1 + +#define MAX_SENSOR_NAME_LEN 64 +#define MAX_PROCESS_NAME_LEN 64 +#define MAX_MTCE_EVENT_NAME_LEN 64 +#define MAX_RESOURCE_NAME_LEN 64 + +/** RMON message codes **/ +#define RMON_CRITICAL (3) +#define RMON_MAJOR (2) +#define RMON_MINOR (1) +#define RMON_CLEAR (0) + +/** Interface Codes **/ +#define MGMNT_INTERFACE (0) +#define INFRA_INTERFACE (1) + + +/** Maintenance Inventory struct */ +typedef struct +{ + unsigned int nodetype ; + std::string type ; + std::string uuid ; + std::string name ; + std::string ip ; + std::string mac ; + std::string infra_ip ; + std::string admin ; + std::string oper ; + std::string avail ; + std::string task ; + std::string action ; + std::string uptime ; + std::string bm_ip ; + std::string bm_un ; + std::string bm_type ; + std::string id ; + + /* Added to support sub-function state and status */ + std::string func ; + std::string oper_subf ; + std::string avail_subf ; + +} node_inv_type ; +void node_inv_init (node_inv_type & inv); + +#define RECOVERY_STATE__INIT (0) +#define RECOVERY_STATE__ACTION (1) +#define RECOVERY_STATE__COOLOFF (2) +#define RECOVERY_STATE__HOLDOFF (3) +#define RECOVERY_STATE__MONITOR (4) +#define RECOVERY_STATE__BLOCKED (5) +typedef struct +{ + int state ; /* recovery state */ + int holdoff ; /* holdoff minute count */ + int queries ; /* query retries */ + int retries ; /* general retries */ + int attempts ; /* unrecovered attempts */ + struct mtc_timer control_timer ; + struct mtc_timer recovery_timer ; +} recovery_ctrl_type ; +void recovery_ctrl_init ( recovery_ctrl_type & recovery_ctrl ); + + +const char * get_loopback_header ( void ) ; +const char * get_hbs_cmd_req_header ( void ) ; +const char * get_cmd_req_msg_header ( void ) ; +const char * get_cmd_rsp_msg_header ( void ) ; +const char * get_msg_rep_msg_header ( void ) ; +const char * get_compute_msg_header ( void ) ; +const char * get_mtc_log_msg_hdr ( void ) ; +const char * get_pmond_pulse_header ( void ) ; +const char * get_mtce_event_header ( void ) ; +const char * get_heartbeat_loss_header ( void ) ; +const char * get_heartbeat_event_header( void ) ; +const char * get_heartbeat_ready_header( void ) ; + +#define MSG_HEADER_SIZE (18) /* this is the length of the first bytes + of every message as a string. Its the message + signature or label */ + +#define MAX_MSG (1024) + +/************************************************ + * Common Maintenace Message Structure Layout * + ************************************************ + +--------------------------------------------+ + | Message Signature | 18 bytes - MSG_HEADER_SIZE - string return from the above procs + +--------------------------------------------+ + | Free Format Header Buffer | 74 bytes - for 64 byte hostname and a bit extra - 128 bytes - 18 - 36 = 74 bytes + +--------------------------------------------+ + | Message Version and Cmd Parms | 36 bytes - ver/rev, res, cmd, num, parm[5] + +--------------------------------------------+ + above is 128 bytes + +--------------------------------------------+ + | Message Buffer | BUF_SIZE + +--------------------------------------------+ + full message is 1024 bytes max + + ** Maintenance Message header byte size minus the ver/rev,res,cmd.num,parm[5] */ +#define HDR_SIZE ((128)-(sizeof(unsigned int)*8)-(sizeof(unsigned short)*2)-28) +#define BUF_SIZE ((MAX_MSG)-(HDR_SIZE)) + +#define MTC_CMD_VERSION (1) +#define MTC_CMD_REVISION (0) + +#define MTC_CMD_FEATURE_VER__MACADDR_IN_CMD (1) + +typedef struct +{ + char hdr[HDR_SIZE] ; + unsigned short ver ; /* major version number */ + unsigned short rev ; /* minor revision number */ + unsigned int res ; /* a reserved field */ + unsigned int cmd ; + unsigned int num ; + unsigned int parm[5] ; + char buf[BUF_SIZE] ; +} ALIGN_PACK(mtc_message_type); + +#define MTC_CMD_TX (0) +#define MTC_CMD_RX (1) + +int print_mtc_message ( mtc_message_type * msg_ptr ); +int print_mtc_message ( mtc_message_type * msg_ptr , bool force ); +void print_mtc_message ( string hostname, int direction, mtc_message_type & msg, const char * iface, bool force ); + +#define MAX_LOG_MSG (6000-HDR_SIZE-MAX_HOST_NAME_SIZE-MAX_FILENAME_LEN) +typedef struct +{ + char header [HDR_SIZE] ; + char filename [MAX_FILENAME_LEN+1] ; + char hostname [MAX_HOST_NAME_SIZE+1] ; + char logbuffer[MAX_LOG_MSG] ; +} log_message_type; + +/** Generic Maintenance Commands */ +#define MTC_CMD_ADD_HOST (0x11110010) /* Add Host */ +#define MTC_CMD_DEL_HOST (0x11110011) /* Delete Host */ +#define MTC_CMD_MOD_HOST (0x11110012) /* Query Host */ +#define MTC_CMD_QRY_HOST (0x11110013) /* Modify Host */ +#define MTC_CMD_START_HOST (0x11110014) /* Start Monitoring Host */ +#define MTC_CMD_STOP_HOST (0x11110015) /* Stop Moniroting Host */ + +#define MTC_CMD_ADD_INST (0x11110020) /* Add Inst */ +#define MTC_CMD_DEL_INST (0x11110021) /* Delete Inst */ +#define MTC_CMD_MOD_INST (0x11110022) /* Query Inst */ +#define MTC_CMD_QRY_INST (0x11110023) /* Modify Inst */ + +#define MTC_CMD_VOTE_INST (0x11110024) /* Vote Inst */ +#define MTC_CMD_NOTIFY_INST (0x11110025) /* Notify Inst */ + +#define MTC_SERVICE_PMOND (0xB00BF00D) +#define MTC_SERVICE_RMOND (0xFAABF00D) +#define MTC_SERVICE_HWMOND (0xF00BF00D) +#define MTC_SERVICE_HEARTBEAT (0xBABEF00D) + +/** process to process loopback command */ +#define MTC_EVENT_LOOPBACK (0x01010101) + +#define MTC_EVENT_GOENABLE_FAIL (0x7AB00BAE) + +#define MTC_ENHANCED_HOST_SERVICES (0x1B0000B1) + +/******************************************************** + * The following 4 definitions are Events signatures + * the process monitor service sends to maintenance. + ********************************************************/ + +/* Generic Monitor Service ready event */ +#define MTC_EVENT_MONITOR_READY (0xf0f0f0f0) + +/* TODO: Obsolete code */ +#define MTC_EVENT_RMON_READY (0x0f0f0f0f) + +/** Process Monitor Event codes */ +#define MTC_EVENT_PMON_CLEAR (0x02020202) /**< Clear Action */ +#define MTC_EVENT_PMON_CRIT (0x04040404) /**< Crit Failed Action */ +#define MTC_EVENT_PMON_MAJOR (0x05050505) /**< Major Degrade Action */ +#define MTC_EVENT_PMON_MINOR (0x08080808) /**< Minor Log action */ +#define MTC_EVENT_PMON_LOG (0x03030303) /**< Minor Log action */ + +/** Process Monitor Event codes */ +#define MTC_EVENT_RMON_CLEAR (0x10101010) /**< Clear Action */ +#define MTC_EVENT_RMON_CRIT (0x20202020) /**< Crit Failed Action */ +#define MTC_EVENT_RMON_MAJOR (0x30303030) /**< Major Degrade Action */ +#define MTC_EVENT_RMON_MINOR (0x40404040) /**< Minor Log action */ +#define MTC_EVENT_RMON_LOG (0x50505050) /**< Minor Log action */ + +/** Process Monitor Daemon Running - Event Raise / Clear Codes */ +#define MTC_EVENT_PMOND_CLEAR (0x06060606) +#define MTC_EVENT_PMOND_RAISE (0x07070707) + +/** Host Appears to be Stalled */ +#define MTC_EVENT_HOST_STALLED (0x66600999) + +/** Accelerated Virtual Switch Event Codes - Clear, Major and Critical */ +#define MTC_EVENT_AVS_CLEAR (0x12340000) +#define MTC_EVENT_AVS_MAJOR (0x12340001) +#define MTC_EVENT_AVS_CRITICAL (0x12340002) +#define MTC_EVENT_AVS_OFFLINE (0x12340003) + +/** Hardware Monitor (hwmond) Action Request Codes + * Action based event messages that hwmond sends to maintenance */ +#define MTC_EVENT_HWMON_CONFIG (0x11110000) /* Sensor Config Log */ +#define MTC_EVENT_HWMON_CLEAR (0x11110001) /* Clear Event */ +#define MTC_EVENT_HWMON_MINOR (0x11110002) /* Raise Minor Alarm */ +#define MTC_EVENT_HWMON_MAJOR (0x11110003) /* ... Major */ +#define MTC_EVENT_HWMON_CRIT (0x11110004) /* ... Critical */ +#define MTC_EVENT_HWMON_RESET (0x11110005) /* Reset the Host */ +#define MTC_EVENT_HWMON_LOG (0x11110006) /* Create a log */ +#define MTC_EVENT_HWMON_reserved (0x11110007) /* Reinstall the Host */ +#define MTC_EVENT_HWMON_POWERDOWN (0x11110008) /* Power Down the Host */ +#define MTC_EVENT_HWMON_POWERCYCLE (0x11110009) /* Power Cycle the Host */ + +/* Specialized Heartbeat Commands */ +#define MTC_RESTART_HBS (0x0000f11f) /**< Restart monitoring specified host */ +#define MTC_BACKOFF_HBS (0x0000f00f) /**< Cmd Hbs to reduce heartbeat period */ +#define MTC_RECOVER_HBS (0x00000ff0) /**< Recover to default heartbeat period */ + +#define MTC_DEGRADE_RAISE (0x77770001) /**< command to trigger host degrade */ +#define MTC_DEGRADE_CLEAR (0x77770000) /**< command to clear host degrade */ + +/******************************************************* + * The following 4 definitions are Events signatures + * the heartbeat service sends to maintenance + *******************************************************/ + +/** Inform maintenance that the heartbeat service is runing + * and ready to accept control commands */ +#define MTC_EVENT_HEARTBEAT_READY (0x5a5a5a5a) + +/** Specified Host has exceeded the heartbeat-miss FAILURE threshold */ +#define MTC_EVENT_HEARTBEAT_LOSS (0x0000fead) +#define MTC_EVENT_HEARTBEAT_RUNNING (0x0110fead) +#define MTC_EVENT_HEARTBEAT_ILLHEALTH (0x0001fead) +#define MTC_EVENT_HEARTBEAT_STOPPED (0x0100fead) + +/** Specified Host has exceeded the heartbeat-miss DEGRADE threshold */ +#define MTC_EVENT_HEARTBEAT_DEGRADE_SET (0xbeefbeef) + +/** Specified Host has exceeded the heartbeat-miss MINOR threshold */ +#define MTC_EVENT_HEARTBEAT_MINOR_SET (0xdadeedad) + +/** Specified Host has recovered from MINOR assertion */ +#define MTC_EVENT_HEARTBEAT_MINOR_CLR (0xdad00dad) + +/** A degraded but not failed host host has responsed to a heartbeat + * So we can clear its degrade condition */ +#define MTC_EVENT_HEARTBEAT_DEGRADE_CLR (0xf00df00d) + +/** Response received for voting and notification */ +#define MTC_EVENT_VOTE_NOTIFY (0xfeedfeed) + +#define PMOND_MISSING_THRESHOLD (100) /**< Count before degrade */ +#define NULL_PULSE_FLAGS (0xffffffff) /**< Unknown flags value */ +#define PMOND_FLAG (0x00000001) /**< Process Monitor O.K. Flag */ +#define INFRA_FLAG (0x00000002) /**< Infrastructure iface provisioned Flag */ + +#define STALL_MON_FLAG (0x00010000) /**< Flag indicating hang monitor running */ +#define STALL_REC_FLAG (0x00020000) /**< Flag indicating hbsClient took action */ +#define STALL_ERR1_FLAG (0x00100000) /**< Error 1 Flag */ +#define STALL_ERR2_FLAG (0x00200000) /**< Error 2 Flag */ +#define STALL_ERR3_FLAG (0x00400000) /**< Error 3 Flag */ +#define STALL_ERR4_FLAG (0x00800000) /**< Error 4 Flag */ +#define STALL_PID1_FLAG (0x01000000) /**< Monitored process 1 is stalled */ +#define STALL_PID2_FLAG (0x02000000) /**< Monitored process 2 is stalled */ +#define STALL_PID3_FLAG (0x04000000) /**< Monitored process 3 is stalled */ +#define STALL_PID4_FLAG (0x08000000) /**< Monitored process 4 is stalled */ +#define STALL_PID5_FLAG (0x10000000) /**< Monitored process 5 is stalled */ +#define STALL_PID6_FLAG (0x20000000) /**< Monitored process 6 is stalled */ +#define STALL_PID7_FLAG (0x40000000) /**< Monitored process 7 is stalled */ +#define STALL_REC_FAIL_FLAG (0x80000000) /**< Auto recover failed, still running */ + +#define STALL_ERROR_FLAGS (STALL_ERR1_FLAG | \ + STALL_ERR2_FLAG | \ + STALL_ERR3_FLAG | \ + STALL_ERR4_FLAG | \ + STALL_PID1_FLAG | \ + STALL_PID2_FLAG | \ + STALL_PID3_FLAG | \ + STALL_PID4_FLAG | \ + STALL_PID5_FLAG | \ + STALL_PID6_FLAG | \ + STALL_PID7_FLAG | \ + STALL_REC_FAIL_FLAG) + +#define STALL_MSG_THLD (20) + +#define STALL_SYSREQ_CMD (0x66006600) /**< Stall SYSREQ Recovery Command */ +#define STALL_REBOOT_CMD (0x00990099) /**< Stall REBOOT Recovery Command */ + +/* MD5_DIGEST_LENGTH is 16 and need space for *2 plus cr */ +#define MD5_STRING_LENGTH ((MD5_DIGEST_LENGTH*2)+1) + + +#define MTC_CMD_NONE 0 +#define MTC_CMD_LOOPBACK 1 /* to host */ +#define MTC_CMD_REBOOT 2 /* to host */ +#define MTC_CMD_WIPEDISK 3 /* to host */ +#define MTC_CMD_RESET 4 /* to host */ +#define MTC_MSG_MTCALIVE 5 /* from host */ +#define MTC_REQ_MTCALIVE 6 /* to host */ +#define MTC_MSG_MAIN_GOENABLED 7 /* from host */ +#define MTC_MSG_SUBF_GOENABLED 8 /* from host */ +#define MTC_REQ_MAIN_GOENABLED 9 /* to host */ +#define MTC_REQ_SUBF_GOENABLED 10 /* to host */ +#define MTC_MSG_MAIN_GOENABLED_FAILED 11 /* from host */ +#define MTC_MSG_SUBF_GOENABLED_FAILED 12 /* from host */ +#define MTC_MSG_LOCKED 13 /* to host */ +#define MTC_CMD_STOP_CONTROL_SVCS 14 /* to host */ +#define MTC_CMD_STOP_COMPUTE_SVCS 15 /* to host */ +#define MTC_CMD_STOP_STORAGE_SVCS 16 /* to host */ +#define MTC_CMD_START_CONTROL_SVCS 17 /* to host */ +#define MTC_CMD_START_COMPUTE_SVCS 18 /* to host */ +#define MTC_CMD_START_STORAGE_SVCS 19 /* to host */ +#define MTC_CMD_LAZY_REBOOT 20 /* to host */ +#define MTC_CMD_HOST_SVCS_RESULT 21 /* to host */ +#define MTC_CMD_LAST 22 + +#define RESET_PROG_MAX_REBOOTS_B4_RESET (5) +#define RESET_PROG_MAX_REBOOTS_B4_RETRY (RESET_PROG_MAX_REBOOTS_B4_RESET+2) + +const char * get_mtcNodeCommand_str ( int cmd ); + +typedef enum +{ + PROTOCOL__NONE = 0, + PROTOCOL__SMASH = 1, + PROTOCOL__IPMI = 2, + PROTOCOL__MAX = 3 +} protocol_enum ; + + +/** Maintenance Commands used to specify HTTP REST API Command operations */ +typedef enum +{ + MTC_CMD_NOT_SET, + MTC_CMD_DISABLE, + MTC_CMD_ENABLE, + MTC_CMD_VOTE, + MTC_CMD_NOTIFY, + + /** HA Service Manager Commands - Command Descriptions */ + CONTROLLER_LOCKED, /**< specified controller is locked */ + CONTROLLER_UNLOCKED, /**< specified controller is unlocked */ + CONTROLLER_DISABLED, /**< specified controller is unlocked-disabled */ + CONTROLLER_ENABLED, /**< specified controller is unlocked-enabled */ + CONTROLLER_SWACT, /**< swact services away from specified controller */ + CONTROLLER_QUERY, /**< query active services on specified controller */ +} mtc_cmd_enum ; + +typedef enum +{ + MTC_SWACT__START = 0, + MTC_SWACT__QUERY, + MTC_SWACT__QUERY_FAIL, + MTC_SWACT__QUERY_RECV, + MTC_SWACT__SWACT, + MTC_SWACT__SWACT_FAIL, + MTC_SWACT__SWACT_RECV, + MTC_SWACT__SWACT_POLL, + MTC_SWACT__DONE, + MTC_SWACT__STAGES, +} mtc_swactStages_enum ; + +/** Maintenance Administrative actions */ +typedef enum +{ + MTC_ADMIN_ACTION__NONE = 0, + MTC_ADMIN_ACTION__LOCK = 1, + MTC_ADMIN_ACTION__UNLOCK = 2, + MTC_ADMIN_ACTION__RESET = 3, + MTC_ADMIN_ACTION__REBOOT = 4, + MTC_ADMIN_ACTION__REINSTALL = 5, + MTC_ADMIN_ACTION__POWEROFF = 6, + MTC_ADMIN_ACTION__POWERON = 7, + MTC_ADMIN_ACTION__RECOVER = 8, + MTC_ADMIN_ACTION__DELETE = 9, + MTC_ADMIN_ACTION__POWERCYCLE =10, + MTC_ADMIN_ACTION__ADD =11, + MTC_ADMIN_ACTION__SWACT =12, + MTC_ADMIN_ACTION__FORCE_LOCK =13, + MTC_ADMIN_ACTION__FORCE_SWACT =14, + + /* FSM Actions */ + MTC_ADMIN_ACTION__ENABLE =15, + MTC_ADMIN_ACTION__ENABLE_SUBF =16, + MTC_ADMIN_ACTIONS =17 +} mtc_nodeAdminAction_enum ; + +typedef enum +{ + MTC_CONFIG_ACTION__NONE = 0, + MTC_CONFIG_ACTION__INSTALL_PASSWD = 1, + MTC_CONFIG_ACTION__CHANGE_PASSWD = 2, + MTC_CONFIG_ACTION__CHANGE_PASSWD_AGAIN = 3, + MTC_CONFIG_ACTIONS = 4, +} mtc_nodeConfigAction_enum ; + + +/** Maintenance Administrative states */ +typedef enum +{ + MTC_ADMIN_STATE__LOCKED = 0, + MTC_ADMIN_STATE__UNLOCKED = 1, + MTC_ADMIN_STATES = 2 +} mtc_nodeAdminState_enum ; + +/** Maintenance Operational states */ +typedef enum +{ + MTC_OPER_STATE__DISABLED = 0, + MTC_OPER_STATE__ENABLED = 1, + MTC_OPER_STATES = 2 +} mtc_nodeOperState_enum ; + +/** Maintenance Availablity status */ +typedef enum +{ + MTC_AVAIL_STATUS__NOT_INSTALLED = 0, + MTC_AVAIL_STATUS__AVAILABLE = 1, + MTC_AVAIL_STATUS__DEGRADED = 2, + MTC_AVAIL_STATUS__FAILED = 3, + MTC_AVAIL_STATUS__INTEST = 4, + MTC_AVAIL_STATUS__POWERED_OFF = 5, + MTC_AVAIL_STATUS__OFFLINE = 6, + MTC_AVAIL_STATUS__ONLINE = 7, + MTC_AVAIL_STATUS__OFFDUTY = 8, + MTC_AVAIL_STATUS = 9 +} mtc_nodeAvailStatus_enum ; + + +void mtc_stages_init ( void ); + +typedef enum +{ + MTC_ENABLE__START = 0, + MTC_ENABLE__RESERVED_1 = 1, + MTC_ENABLE__HEARTBEAT_CHECK = 2, + MTC_ENABLE__HEARTBEAT_STOP_CMD = 3, + MTC_ENABLE__RECOVERY_TIMER = 4, + MTC_ENABLE__RECOVERY_WAIT = 5, + MTC_ENABLE__RESET_PROGRESSION = 6, + MTC_ENABLE__RESET_WAIT = 7, + MTC_ENABLE__INTEST_START = 8, + MTC_ENABLE__MTCALIVE_PURGE = 9, + MTC_ENABLE__MTCALIVE_WAIT = 10, + MTC_ENABLE__CONFIG_COMPLETE_WAIT = 11, + MTC_ENABLE__GOENABLED_TIMER = 12, + MTC_ENABLE__GOENABLED_WAIT = 13, + MTC_ENABLE__PMOND_READY_WAIT = 14, + MTC_ENABLE__HOST_SERVICES_START = 15, + MTC_ENABLE__HOST_SERVICES_WAIT = 16, + MTC_ENABLE__SERVICES_START_WAIT = 17, + MTC_ENABLE__HEARTBEAT_WAIT = 18, + MTC_ENABLE__HEARTBEAT_SOAK = 19, + MTC_ENABLE__STATE_CHANGE = 20, + MTC_ENABLE__WORKQUEUE_WAIT = 21, + MTC_ENABLE__WAIT = 22, + MTC_ENABLE__ENABLED = 23, + MTC_ENABLE__SUBF_FAILED = 24, + MTC_ENABLE__DEGRADED = 25, + MTC_ENABLE__DONE = 26, + MTC_ENABLE__FAILURE = 27, + MTC_ENABLE__FAILURE_WAIT = 28, + MTC_ENABLE__FAILURE_SWACT_WAIT = 29, + MTC_ENABLE__STAGES = 30, +} mtc_enableStages_enum ; + +/** Return the string representing the specified 'enable' stage */ +string get_enableStages_str ( mtc_enableStages_enum stage ); + +typedef enum +{ + MTC_DISABLE__START = 0, + MTC_DISABLE__HANDLE_FORCE_LOCK = 1, + MTC_DISABLE__RESET_HOST_WAIT = 2, + MTC_DISABLE__DISABLE_SERVICES = 3, + MTC_DISABLE__DIS_SERVICES_WAIT = 4, + MTC_DISABLE__HANDLE_CEPH_LOCK = 5, + MTC_DISABLE__RESERVED = 6, + MTC_DISABLE__TASK_STATE_UPDATE = 7, + MTC_DISABLE__WORKQUEUE_WAIT = 8, + MTC_DISABLE__DISABLED = 9, + MTC_DISABLE__HANDLE_POWERON_SEND =10, + MTC_DISABLE__HANDLE_POWERON_RECV =11, + MTC_DISABLE__STAGES =12, +} mtc_disableStages_enum ; + +/** Return the string representing the specified 'disable' stage */ +string get_disableStages_str ( mtc_disableStages_enum stage ); + +typedef enum +{ + MTC_ADD__START = 0, + MTC_ADD__START_DELAY, + MTC_ADD__START_SERVICES, + MTC_ADD__START_SERVICES_WAIT, + MTC_ADD__MTC_SERVICES, + MTC_ADD__CLEAR_TASK, + MTC_ADD__WORKQUEUE_WAIT, + MTC_ADD__DONE, + MTC_ADD__STAGES +} mtc_addStages_enum ; + + +/** Return the string representing the specified 'add' stage */ +string get_addStages_str ( mtc_addStages_enum stage ); + + +typedef enum +{ + MTC_DEL__START = 0, + MTC_DEL__WAIT, + MTC_DEL__DONE, + MTC_DEL__STAGES +} mtc_delStages_enum ; + +string get_delStages_str ( mtc_delStages_enum stage ); + + +#define MTC_MAX_FAST_ENABLES (2) +typedef enum +{ + MTC_RECOVERY__START = 0, + MTC_RECOVERY__REQ_MTCALIVE, + MTC_RECOVERY__REQ_MTCALIVE_WAIT, + MTC_RECOVERY__RESET_RECV_WAIT, + MTC_RECOVERY__RESET_WAIT, + MTC_RECOVERY__MTCALIVE_TIMER, + MTC_RECOVERY__MTCALIVE_WAIT, + MTC_RECOVERY__GOENABLED_TIMER, + MTC_RECOVERY__GOENABLED_WAIT, + MTC_RECOVERY__HOST_SERVICES_START, + MTC_RECOVERY__HOST_SERVICES_WAIT, + + /* Subfunction stages */ + MTC_RECOVERY__CONFIG_COMPLETE_WAIT, + MTC_RECOVERY__SUBF_GOENABLED_TIMER, + MTC_RECOVERY__SUBF_GOENABLED_WAIT, + MTC_RECOVERY__SUBF_SERVICES_START, + MTC_RECOVERY__SUBF_SERVICES_WAIT, + + MTC_RECOVERY__HEARTBEAT_START, + MTC_RECOVERY__HEARTBEAT_SOAK, + MTC_RECOVERY__STATE_CHANGE, + MTC_RECOVERY__ENABLE_START, + MTC_RECOVERY__FAILURE, + MTC_RECOVERY__WORKQUEUE_WAIT, + MTC_RECOVERY__ENABLE_WAIT, + MTC_RECOVERY__STAGES, +} mtc_recoveryStages_enum ; + +/** Return the string representing the specified 'recovery' stage */ +string get_recoveryStages_str ( mtc_recoveryStages_enum stage ); + +/* mtce support for sysinv driven configuration changes */ +typedef enum { + MTC_CONFIG__START, + MTC_CONFIG__SHOW, + MTC_CONFIG__MODIFY, + MTC_CONFIG__VERIFY, + MTC_CONFIG__FAILURE, + MTC_CONFIG__TIMEOUT, + MTC_CONFIG__DONE, + MTC_CONFIG__STAGES +} mtc_configStages_enum ; + +/** Return the string representing the specified 'add' stage */ +string get_configStages_str ( mtc_configStages_enum stage ); + + +/** Service Degrade Mask + * + * Hosts can become degraded for more than one reason. + * The following are bit field definitions that represent + * various degrade reasons ; heartbeat, process error, + * inservice test, etc. */ +#define DEGRADE_MASK_NONE 0x00000000 +#define DEGRADE_MASK_HEARTBEAT_MGMNT 0x00000001 +#define DEGRADE_MASK_HEARTBEAT_INFRA 0x00000002 +#define DEGRADE_MASK_PMON 0x00000004 +#define DEGRADE_MASK_INSV_TEST 0x00000008 +#define DEGRADE_MASK_AVS_MAJOR 0x00000010 +#define DEGRADE_MASK_AVS_CRITICAL 0x00000020 +#define DEGRADE_MASK_RESMON 0x00000040 +#define DEGRADE_MASK_HWMON 0x00000080 +#define DEGRADE_MASK_SUBF 0x00000100 +#define DEGRADE_MASK_SM 0x00000200 +#define DEGRADE_MASK_CONFIG 0x00000400 +#define DEGRADE_MASK_RES2 0x00000800 +#define DEGRADE_MASK_ENABLE 0x00001000 +#define DEGRADE_MASK_RES4 0x00002000 +#define DEGRADE_MASK_RES5 0x00004000 +#define DEGRADE_MASK_RES6 0x00008000 + +/* future masks up to 0x80000000 */ + +/* FSM Stages for handling host 'reset' through + * board management controller interface */ +typedef enum +{ + MTC_RESET__START = 0, + MTC_RESET__REQ_SEND, + MTC_RESET__RESP_WAIT, + MTC_RESET__QUEUE, + MTC_RESET__OFFLINE_WAIT, + MTC_RESET__DONE, + MTC_RESET__FAIL, + MTC_RESET__FAIL_WAIT, + MTC_RESET__STAGES +} mtc_resetStages_enum ; + + +/* FSM Stages for handling host 'reset' through + * board management controller interface */ +typedef enum +{ + MTC_RESETPROG__START = 0, + MTC_RESETPROG__REBOOT, + MTC_RESETPROG__WAIT, + MTC_RESETPROG__FAIL, + MTC_RESETPROG__STAGES +} mtc_resetProgStages_enum ; + +/** Return the string representing the specified 'reset' stage */ +string get_resetStages_str ( mtc_resetStages_enum stage ); + +/* FSM Stages for handling host 'reinstall' */ +typedef enum +{ + MTC_REINSTALL__START = 0, + MTC_REINSTALL__RESP_WAIT, + MTC_REINSTALL__OFFLINE_WAIT, + MTC_REINSTALL__ONLINE_WAIT, + MTC_REINSTALL__FAIL, + MTC_REINSTALL__MSG_DISPLAY, + MTC_REINSTALL__DONE, + MTC_REINSTALL__STAGES +} mtc_reinstallStages_enum ; + +/** Return the string representing the specified 'reinstall' stage */ +string get_reinstallStages_str ( mtc_reinstallStages_enum stage ); + +typedef enum +{ + MTC_POWERON__START = 0, + MTC_POWERON__POWER_STATUS, + MTC_POWERON__POWER_STATUS_WAIT, + MTC_POWERON__REQ_SEND, + MTC_POWERON__RETRY_WAIT, + MTC_POWERON__RESP_WAIT, + MTC_POWERON__DONE, + MTC_POWERON__FAIL, + MTC_POWERON__FAIL_WAIT, + MTC_POWERON__QUEUE, + + MTC_POWEROFF__START, + MTC_POWEROFF__REQ_SEND, + MTC_POWEROFF__RESP_WAIT, + MTC_POWEROFF__DONE, + MTC_POWEROFF__FAIL, + MTC_POWEROFF__FAIL_WAIT, + MTC_POWEROFF__QUEUE, + + MTC_POWER__DONE, /* clear power action */ + MTC_POWER__STAGES +} mtc_powerStages_enum ; + +/** Return the string representing the specified 'power' stage */ +string get_powerStages_str ( mtc_powerStages_enum stage ); + +/* FSM Stages for handling host 'powercycle' through + * board management controller interface */ +typedef enum +{ + MTC_POWERCYCLE__START = 0, + MTC_POWERCYCLE__POWEROFF, + MTC_POWERCYCLE__POWEROFF_CMND_WAIT, + MTC_POWERCYCLE__POWEROFF_WAIT, + MTC_POWERCYCLE__POWERON, + MTC_POWERCYCLE__POWERON_REQWAIT, + MTC_POWERCYCLE__POWERON_VERIFY, + MTC_POWERCYCLE__POWERON_VERIFY_WAIT, + MTC_POWERCYCLE__POWERON_CMND_WAIT, + MTC_POWERCYCLE__POWERON_WAIT, + MTC_POWERCYCLE__DONE, + MTC_POWERCYCLE__FAIL, + MTC_POWERCYCLE__HOLDOFF, + MTC_POWERCYCLE__COOLOFF, + MTC_POWERCYCLE__STAGES, +} mtc_powercycleStages_enum ; + +/** Return the string representing the specified 'powercycle' stage */ +string get_powercycleStages_str ( mtc_powercycleStages_enum stage ); + +typedef enum +{ + MTC_SUBSTAGE__START = 0, + MTC_SUBSTAGE__SEND = 1, + MTC_SUBSTAGE__RECV = 2, + MTC_SUBSTAGE__WAIT = 3, + MTC_SUBSTAGE__DONE = 4, + MTC_SUBSTAGE__FAIL = 5, + MTC_SUBSTAGE__STAGES = 6 +} mtc_subStages_enum ; + +/** Return the string representing the specified 'sub' stage */ +string get_subStages_str ( mtc_subStages_enum stage ); + +typedef enum +{ + MTC_OOS_TEST__LOAD_NEXT_TEST = 0, + MTC_OOS_TEST__BMC_ACCESS_TEST = 1, + MTC_OOS_TEST__BMC_ACCESS_RESULT = 2, + MTC_OOS_TEST__START_WAIT = 3, + MTC_OOS_TEST__WAIT = 4, + MTC_OOS_TEST__DONE = 5, + MTC_OOS_TEST__STAGES = 6, +} mtc_oosTestStages_enum ; + +/** Return the string representing the specified 'test' stage */ +string get_oosTestStages_str ( mtc_oosTestStages_enum stage ); + +typedef enum +{ + MTC_INSV_TEST__START = 0, + MTC_INSV_TEST__WAIT = 1, + MTC_INSV_TEST__RUN = 2, + MTC_INSV_TEST__STAGES = 3, +} mtc_insvTestStages_enum ; + +/** Return the string representing the specified 'test' stage */ +string get_insvTestStages_str ( mtc_insvTestStages_enum stage ); + +#define MTC_NO_TEST 0 +#define MTC_OOS_TEST 1 +#define MTC_INSV_TEST 2 + +typedef enum +{ + MTC_SENSOR__START = 0, + MTC_SENSOR__READ_FAN = 1, + MTC_SENSOR__READ_TEMP= 2, + MTC_SENSOR__STAGES = 3, +} mtc_sensorStages_enum ; + +/** Return the string representing the specified 'sensor' stage */ +string get_sensorStages_str ( mtc_sensorStages_enum stage ); + +typedef enum +{ + MTC_OFFLINE__IDLE = 0, + MTC_OFFLINE__START, + MTC_OFFLINE__SEND_MTCALIVE, + MTC_OFFLINE__WAIT, + MTC_OFFLINE__STAGES +} mtc_offlineStages_enum ; + +typedef enum +{ + MTC_ONLINE__START = 0, + MTC_ONLINE__WAITING, + MTC_ONLINE__RETRYING, + MTC_ONLINE__STAGES +} mtc_onlineStages_enum ; + +#define MTC_ENABLE 0x12345678 +#define MTC_DEGRADE 0x87654321 +#define MTC_DISABLE 0xdeadbeef +#define MTC_RESET 0xdeadb00b +#define MTC_WIPEDISK 0xdeadfeed + + +typedef enum +{ + MTC_STRESS_TEST__START = 0, + MTC_STRESS_TEST__DO = 1, + MTC_STRESS_TEST__WAIT = 2, + MTC_STRESS_TEST__VERIFY = 3, + MTC_STRESS_TEST__NEXT = 4, + MTC_STRESS_TEST__DONE = 5, + MTC_STRESS_TEST__STAGES = 6, +} mtc_stressStages_enum ; + +typedef union +{ + mtc_enableStages_enum enable ; + mtc_disableStages_enum disable ; + int raw ; +} mtc_stages_union ; + +typedef struct +{ + mtc_nodeAdminAction_enum adminAction ; + mtc_nodeAdminState_enum adminState ; + mtc_nodeOperState_enum operState ; + mtc_nodeAvailStatus_enum availStatus ; +} fsm_states_type ; + +/** Maintenance FSM test case codes */ +typedef enum +{ + FSM_TC_ENABLED_NOACTION, + FSM_TC_ENABLED_TO_DISABLED_FAILED, + FSM_TC_ENABLED_TO_ENABLED_DEGRADED, + FSM_TC_ENABLED_DEGRADED_TO_ENABLED_DEGRADED, + FSM_TC_ENABLED_DEGRADED_TO_ENABLED, + FSM_TC_LAST, +} mtcNodeFsm_tc_enum ; + +/* The list of heartbeat interfaces / networks */ +typedef enum +{ + MGMNT_IFACE = 0, + INFRA_IFACE = 1, + MAX_IFACES = 2 +} iface_enum ; + +/** Returns true if the specified admin state string is valid */ +bool adminStateOk ( string admin ); + +/** Returns true if the specified oper state string is valid */ +bool operStateOk ( string oper ); + +/** Returns true if the specified avail status string is valid */ +bool availStatusOk ( string avail ); + +string get_availStatus_str ( mtc_nodeAvailStatus_enum availStatus ); +string get_operState_str ( mtc_nodeOperState_enum operState ); +string get_adminState_str ( mtc_nodeAdminState_enum adminState ); + +void log_adminAction ( string hostname, + mtc_nodeAdminAction_enum currAction, + mtc_nodeAdminAction_enum newAction ); + +int send_hbs_command ( string hostname, int command ); +int send_hwmon_command ( string hostname, int command ); +int send_guest_command ( string hostname, int command ); + +int daemon_log_message ( const char * hostname, + const char * filename, + const char * log_str ); + +bool is_host_services_cmd ( unsigned int cmd ); + +/** Runtime Trace Log Utilities */ +void daemon_dump_membuf ( void ); +void daemon_dump_membuf_banner ( void ); + +void mem_log ( char * log ); +void mem_log ( string log ); +void mem_log ( char log ); +void mem_log ( string one, string two ); +void mem_log ( string one, string two, string three ); +void mem_log ( string label, int value, string data ); + +string get_hostname ( void ); + +#define MTC_FSM_ENABLE_TEST 0x12345678 + +#define MAX_MEM_LIST_SIZE (2000) +#define MAX_MEM_LOG_LEN (1000) +#define MAX_MEM_LOG_DATA (MAX_MEM_LOG_LEN-100) + +#define TESTHEAD_BAR "+--------------------------------------------------------------------+\n" +#define NODEBUG printf ( "\tDebug: Not implemented\n" ) +#define FAILED printf ( "Failed |\n" ); +#define PASSED printf ( "Passed |\n" ); +#define PENDING printf ( "To-Do |\n" ); +#define FAILED_STR printf ( "Failed |\n" ); + +#endif /* __INCLUDE_NODEBASE_H__ */ diff --git a/mtce-common/cgts-mtce-common-1.0/common/nodeClass.cpp b/mtce-common/cgts-mtce-common-1.0/common/nodeClass.cpp new file mode 100755 index 00000000..4b8e7ca9 --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/nodeClass.cpp @@ -0,0 +1,8607 @@ +/* + * Copyright (c) 2013-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + + /** + * @file + * Wind River CGTS Platform Nodal Health Check Service Node Implementation + */ + +#include +#include +#include +#include +#include /* for ENODEV, EFAULT and ENXIO */ +#include /* for close and usleep */ + +using namespace std; + +#ifdef __AREA__ +#undef __AREA__ +#define __AREA__ "---" +#endif + +#include "nodeBase.h" +#include "threadUtil.h" +#include "nodeClass.h" +#include "nodeUtil.h" +#include "mtcNodeMsg.h" /* for ... send_mtc_cmd */ +#include "nlEvent.h" /* for ... get_netlink_events */ +#include "daemon_common.h" + +#include "alarmUtil.h" +#include "mtcAlarm.h" +#include "alarm.h" +#include "hbsAlarm.h" + +extern void mtcTimer_handler ( int sig, siginfo_t *si, void *uc); + +const char mtc_nodeAdminAction_str[MTC_ADMIN_ACTIONS][20] = +{ + "none", + "lock", + "unlock", + "reset", + "reboot", + "reinstall", + "power-off", + "power-on", + "recovery", + "delete", + "powercycle", + "add", + "swact", + "force-lock", + "force-swact", + "enable", + "enable-subf", +}; + +const char * get_adminAction_str ( mtc_nodeAdminAction_enum action ) +{ + if ( action > MTC_ADMIN_ACTIONS ) + { + slog ("Invalid admin action (%d)\n", action); + action = MTC_ADMIN_ACTION__NONE ; + } + + return ( &mtc_nodeAdminAction_str[action][0] ); +} + +const char mtc_nodeAdminState_str[MTC_ADMIN_STATES][15] = +{ + "locked", + "unlocked", +}; + +string get_adminState_str ( mtc_nodeAdminState_enum adminState ) +{ + if ( adminState > MTC_ADMIN_STATES ) + { + slog ("Invalid admin state (%d)\n", adminState ); + adminState = MTC_ADMIN_STATE__LOCKED ; + } + return ( mtc_nodeAdminState_str[adminState] ); +} + +bool adminStateOk ( string admin ) +{ + if (( admin.compare(mtc_nodeAdminState_str[0])) && + ( admin.compare(mtc_nodeAdminState_str[1]))) + { + wlog ("Invalid 'admin' state (%s)\n", admin.c_str()); + return ( false ); + } + return (true); +} +const char mtc_nodeOperState_str[MTC_OPER_STATES][15] = +{ + "disabled", + "enabled" +}; + +string get_operState_str ( mtc_nodeOperState_enum operState ) +{ + if ( operState > MTC_OPER_STATES ) + { + slog ("Invalid oper state (%d)\n", operState ); + operState = MTC_OPER_STATE__DISABLED ; + } + return ( mtc_nodeOperState_str[operState] ); +} + +bool operStateOk ( string oper ) +{ + if (( oper.compare(mtc_nodeOperState_str[0])) && + ( oper.compare(mtc_nodeOperState_str[1]))) + { + wlog ("Invalid 'oper' state (%s)\n", oper.c_str()); + return ( false ); + } + return (true); +} + +const char mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS][15] = +{ + "not-installed", + "available", + "degraded", + "failed", + "intest", + "power-off", + "offline", + "online", + "offduty" +}; + +bool availStatusOk ( string avail ) +{ + if (( avail.compare(mtc_nodeAvailStatus_str[0])) && + ( avail.compare(mtc_nodeAvailStatus_str[1])) && + ( avail.compare(mtc_nodeAvailStatus_str[2])) && + ( avail.compare(mtc_nodeAvailStatus_str[3])) && + ( avail.compare(mtc_nodeAvailStatus_str[4])) && + ( avail.compare(mtc_nodeAvailStatus_str[5])) && + ( avail.compare(mtc_nodeAvailStatus_str[6])) && + ( avail.compare(mtc_nodeAvailStatus_str[7])) && + ( avail.compare(mtc_nodeAvailStatus_str[8]))) + { + wlog ("Invalid 'avail' status (%s)\n", avail.c_str()); + return ( false ); + } + return (true); +} + +string get_availStatus_str ( mtc_nodeAvailStatus_enum availStatus ) +{ + if ( availStatus > MTC_AVAIL_STATUS ) + { + slog ("Invalid avail status (%d)\n", availStatus ); + availStatus = MTC_AVAIL_STATUS__FAILED ; + } + return ( mtc_nodeAvailStatus_str[availStatus] ); +} + +#ifdef WANT_nodeClass_latency_log /* Needs to be tied to a node */ +#define NODECLASS_LATENCY_MON_START ((const char *)"start") +#define MAX_DELAY_B4_LATENCY_LOG (1700) +void nodeClass_latency_log ( const char * label_ptr, int msecs ) +{ + static unsigned long long prev__time = 0 ; + static unsigned long long this__time = 0 ; + + this__time = gettime_monotonic_nsec () ; + + /* If label_ptr is != NULL and != start then take the measurement */ + if ( label_ptr && strncmp ( label_ptr, NODECLASS_LATENCY_MON_START, strlen(NODECLASS_LATENCY_MON_START))) + { + if ( this__time > (prev__time + (NSEC_TO_MSEC*(msecs)))) + { + llog ("%4llu.%-4llu msec - %s\n", + ((this__time-prev__time) > NSEC_TO_MSEC) ? ((this__time-prev__time)/NSEC_TO_MSEC) : 0, + ((this__time-prev__time) > NSEC_TO_MSEC) ? ((this__time-prev__time)%NSEC_TO_MSEC) : 0, + label_ptr); + } + } + /* reset to be equal for next round */ + prev__time = this__time ; +} +#endif + +/* nodeLinkClass constructor */ +nodeLinkClass::nodeLinkClass() +{ + this->is_poweron_handler = NULL; + for(unsigned int i=0; inode_ptrs[i] = NULL; + } + + this->offline_threshold = 0; + this->offline_period = 0; + /* this->mtcTimer = mtc_timer(); + * this->mtcTimer_mnfa = mtc_timer(); + * this->mtcTimer_token = mtc_timer(); + * this->mtcTimer_uptime = mtc_timer(); + */ + this->api_retries = 0; + for(unsigned int i =0; ipulse_requests[i] = 0; + this->hbs_expected_pulses[i] = 0; + this->hbs_detected_pulses[i] = 0; + } + this->compute_mtcalive_timeout = 0; + this->controller_mtcalive_timeout = 0; + this->goenabled_timeout = 0; + this->loc_recovery_timeout = 0; + this->mnfa_recovery_timeout = 0; + this->node_reinstall_timeout = 0; + this->token_refresh_rate = 0; + this->autorecovery_enabled = false ; + this->autorecovery_disabled = false ; + + + head = tail = NULL; + memory_allocs = 0 ; + memory_used = 0 ; + hosts = 0 ; + host_deleted = false ; + + /* Init the base level pulse info and pointers for all interfaces */ + pulse_ptr = NULL ; + for ( int i = 0 ; i < MAX_IFACES ; i++ ) + { + pulse_list[i].head_ptr = NULL ; + pulse_list[i].tail_ptr = NULL ; + pulse_list[i].last_ptr = NULL ; + pulses[i] = 0 ; + } + /* init the resource reference index to null */ + rrri = 0 ; + + /* Entry of RRA is reserved (not used) and set to NULL */ + hbs_rra[0] = static_cast(NULL) ; + + /* Make no assumption on the service */ + maintenance = false ; + heartbeat = false ; + active = false ; + + /* Set some defaults for the hearbeat service */ + hbs_ready = false ; + hbs_state_change = false ; + hbs_disabled = true ; + hbs_pulse_period = hbs_pulse_period_save = 200 ; + hbs_minor_threshold = HBS_MINOR_THRESHOLD ; + hbs_degrade_threshold = HBS_DEGRADE_THRESHOLD ; + hbs_failure_threshold = HBS_FAILURE_THRESHOLD ; + + hbs_silent_fault_detector = 0 ; + hbs_silent_fault_logged = false ; + + /* Start with null identity */ + my_hostname.clear() ; + my_local_ip.clear() ; + my_float_ip.clear() ; + active_controller_hostname.clear() ; + inactive_controller_hostname.clear() ; + + /* Start with no failures */ + mnfa_awol_list.clear(); + mnfa_host_count[MGMNT_IFACE] = 0 ; + mnfa_host_count[INFRA_IFACE] = 0 ; + mnfa_occurances = 0 ; + mnfa_active = false ; + mnfa_threshold_type = MNFA_NUMBER ; + mnfa_threshold_percent = 5 ; + mnfa_threshold_number = 3 ; + mnfa_threshold = mnfa_threshold_number ; + + mgmnt_link_up_and_running = false ; + infra_link_up_and_running = false ; + infra_network_provisioned = false ; + infra_degrade_only = false ; + + dor_mode_active = false ; + dor_start_time = 0 ; + dor_mode_active_log_throttle = 0 ; + + swact_timeout = MTC_MINS_2 ; + uptime_period = MTC_UPTIME_REFRESH_TIMER ; + online_period = MTC_OFFLINE_TIMER ; + sysinv_timeout = HTTP_SYSINV_CRIT_TIMEOUT ; + sysinv_noncrit_timeout = HTTP_SYSINV_NONC_TIMEOUT ; + work_queue_timeout = MTC_WORKQUEUE_TIMEOUT ; + + /* Inservice test periods in seconds - 0 = disabled */ + insv_test_period = 0 ; + oos_test_period = 0 ; + + /* Init the inotify shadow password file descriptors to zero */ + inotify_shadow_file_fd = 0 ; + inotify_shadow_file_wd = 0 ; + + /* Ensure that HA Swact gate is open on init. + * This true gates maintenance commands */ + smgrEvent.mutex = false ; + + /* Init the event bases to null as they have not been allocated yet */ + sysinvEvent.base = NULL ; + smgrEvent.base = NULL ; + tokenEvent.base = NULL ; + sysinvEvent.conn = NULL ; + smgrEvent.conn = NULL ; + tokenEvent.conn = NULL ; + sysinvEvent.req = NULL ; + smgrEvent.req = NULL ; + tokenEvent.req = NULL ; + sysinvEvent.buf = NULL ; + smgrEvent.buf = NULL ; + tokenEvent.buf = NULL ; + + unknown_host_throttle = 0 ; + invalid_arg_throttle = 0 ; + + testmode = 0 ; + module_init( ); +} + +/* nodeLinkClass destructor */ +nodeLinkClass::~nodeLinkClass() +{ + /* Free any allocated host memory */ + for ( int i = 0 ; i < MAX_HOSTS ; i++ ) + { + if ( node_ptrs[i] ) + { + delete node_ptrs[i] ; + } + } +} + +/* Clear start host service controls */ +void nodeLinkClass::clear_hostservices_ctls ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr ) + { + node_ptr->start_services_needed = false ; + node_ptr->start_services_needed_subf = false ; + node_ptr->start_services_running_main = false ; + node_ptr->start_services_running_subf = false ; + node_ptr->start_services_retries = 0 ; + } +} + +/* Clear all the main function enable failure bools */ +void nodeLinkClass::clear_main_failed_bools ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr ) + { + node_ptr->config_failed = false ; + node_ptr->goEnabled_failed = false ; + node_ptr->inservice_failed = false ; + node_ptr->hostservices_failed = false ; + return; + } + slog ("null pointer\n"); +} + +/* Clear all the sub function enable failure bools */ +void nodeLinkClass::clear_subf_failed_bools ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr ) + { + node_ptr->config_failed_subf = false ; + node_ptr->goEnabled_failed_subf = false ; + node_ptr->inservice_failed_subf = false ; + node_ptr->hostservices_failed_subf = false ; + return; + } + slog ("null pointer\n"); +} + +/* + * Allocates memory for a new node and stores its the address in node_ptrs + * @param void + * @return node pointer to the newly allocted node + */ +struct nodeLinkClass::node * nodeLinkClass::newNode ( void ) +{ + struct nodeLinkClass::node * temp_node_ptr = NULL ; + + if ( memory_allocs == 0 ) + { + memset ( node_ptrs, 0 , sizeof(struct node *)*MAX_NODES); + } + + // find an empty spot + for ( int i = 0 ; i < MAX_NODES ; i++ ) + { + if ( node_ptrs[i] == NULL ) + { + node_ptrs[i] = temp_node_ptr = new node ; + memory_allocs++ ; + memory_used += sizeof (struct nodeLinkClass::node); + + return temp_node_ptr ; + } + } + elog ( "Failed to save new node pointer address\n" ); + return temp_node_ptr ; +} + +/* Frees the memory of a pre-allocated node and removes + * it from the node_ptrs list + * @param node * pointer to the node memory address to be freed + * @return int return code { PASS or -EINVAL } + */ +int nodeLinkClass::delNode ( struct nodeLinkClass::node * node_ptr ) +{ + if ( memory_allocs > 0 ) + { + for ( int i = 0 ; i < MAX_NODES ; i++ ) + { + if ( node_ptrs[i] == node_ptr ) + { + delete node_ptr ; + node_ptrs[i] = NULL ; + memory_allocs-- ; + memory_used -= sizeof (struct nodeLinkClass::node); + return PASS ; + } + } + elog ( "Error: Unable to validate memory address being freed\n" ); + } + else + elog ( "Error: Free memory called when there is no memory to free\n" ); + + return -EINVAL ; +} + + /* + * Allocate new node and tack it on the end of the node_list + */ +struct +nodeLinkClass::node* nodeLinkClass::addNode( string hostname ) +{ + /* verify node is not already provisioned */ + struct node * ptr = getNode ( hostname ); + if ( ptr ) + { + /* if it is then clean it up and fall through */ + if ( !testmode ) + { + wlog ("Warning: Node already provisioned\n"); + } + if ( remNode ( hostname ) ) + { + /* Should never get here but if we do then */ + /* something is seriously wrong */ + elog ("Error: Unable to remove node during reprovision\n"); + return static_cast(NULL); + } + } + + /* allocate memory for new node */ + ptr = newNode (); + if( ptr == NULL ) + { + elog ( "Error: Failed to allocate memory for new node\n" ); + return static_cast(NULL); + } + + /* init the new node */ + ptr->hostname = hostname ; + + ptr->ip = "" ; + ptr->mac = "" ; + ptr->infra_ip = "" ; + ptr->infra_mac = "" ; + + ptr->patching = false ; + ptr->patched = false ; + + /* the goenabled state bool */ + ptr->goEnabled = false ; + ptr->goEnabled_subf = false ; + + clear_hostservices_ctls ( ptr ); + + /* clear all the enable failure bools */ + clear_main_failed_bools ( ptr ); + clear_subf_failed_bools ( ptr ); + + /* Set the subfunction to disabled */ + ptr->operState_subf = MTC_OPER_STATE__DISABLED ; + ptr->availStatus_subf = MTC_AVAIL_STATUS__NOT_INSTALLED ; + + ptr->operState_dport = MTC_OPER_STATE__DISABLED ; + ptr->availStatus_dport= MTC_AVAIL_STATUS__OFFDUTY ; + + ptr->enabled_count = 0 ; + + ptr->cmdName = ""; + ptr->cmdReq = 0 ; + ptr->cmdRsp = 0 ; + ptr->cmdRsp_status= 0 ; + ptr->cmdRsp_status_string = "" ; + + ptr->add_completed = false ; + + /* init the hwmon reset and powercycle recovery control structures */ + recovery_ctrl_init ( ptr->hwmon_reset ); + recovery_ctrl_init ( ptr->hwmon_powercycle ); + + /* Default timeout values */ + ptr->mtcalive_timeout = HOST_MTCALIVE_TIMEOUT ; + + /* no ned to send a reboot response back to any client */ + ptr->activeClient = CLIENT_NONE ; + + ptr->task = "none" ; + ptr->action = "none" ; + ptr->clear_task = false ; + + ptr->mtcAlive_gate = true ; + ptr->mtcAlive_online = false ; + ptr->mtcAlive_offline = true ; + ptr->mtcAlive_misses = 0 ; + ptr->mtcAlive_hits = 0 ; + ptr->mtcAlive_count = 0 ; + ptr->mtcAlive_purge = 0 ; + + ptr->offline_search_count = 0 ; + ptr->mtcAlive_mgmnt = false ; + ptr->mtcAlive_infra = false ; + ptr->reboot_cmd_ack_mgmnt = false ; + ptr->reboot_cmd_ack_infra = false ; + + ptr->offline_log_reported = true ; + ptr->online_log_reported = false ; + + ptr->dor_recovery_mode = false ; + ptr->was_dor_recovery_mode= false ; + ptr->dor_recovery_time = 0 ; + + mtcTimer_init ( ptr->mtcTimer, hostname, "mtc timer"); /* Init node's general mtc timer */ + mtcTimer_init ( ptr->insvTestTimer, hostname, "insv test timer"); + mtcTimer_init ( ptr->oosTestTimer, hostname, "oos test timer"); /* Init node's oos test timer */ + mtcTimer_init ( ptr->mtcSwact_timer, hostname, "mtcSwact timer"); /* Init node's mtcSwact timer */ + mtcTimer_init ( ptr->mtcCmd_timer, hostname, "mtcCmd timer"); /* Init node's mtcCmd timer */ + mtcTimer_init ( ptr->mtcConfig_timer, hostname, "mtcConfig timer"); /* Init node's mtcConfig timer */ + mtcTimer_init ( ptr->mtcAlive_timer , hostname, "mtcAlive timer"); /* Init node's mtcAlive timer */ + mtcTimer_init ( ptr->offline_timer, hostname, "offline timer"); /* Init node's FH offline timer */ + mtcTimer_init ( ptr->http_timer, hostname, "http timer" ); /* Init node's http timer */ + mtcTimer_init ( ptr->bm_timer, hostname, "bm timer" ); /* Init node's bm timer */ + mtcTimer_init ( ptr->bm_ping_info.timer,hostname,"ping timer" ); /* Init node's ping timer */ + mtcTimer_init ( ptr->bmc_access_timer, hostname, "bmc acc timer" ); /* Init node's bm access timer */ + mtcTimer_init ( ptr->host_services_timer, hostname, "host services timer" ); /* host services timer */ + + mtcTimer_init ( ptr->hwmon_powercycle.control_timer, hostname, "powercycle control timer"); + mtcTimer_init ( ptr->hwmon_powercycle.recovery_timer, hostname, "powercycle recovery timer"); + mtcTimer_init ( ptr->hwmon_reset.control_timer, hostname, "reset control timer"); + mtcTimer_init ( ptr->hwmon_reset.recovery_timer, hostname, "reset recovery timer"); + + mtcCmd_init ( ptr->host_services_req ); + mtcCmd_init ( ptr->mtcAlive_req ); + mtcCmd_init ( ptr->reboot_req ); + mtcCmd_init ( ptr->general_req ); + + ptr->configStage = MTC_CONFIG__START ; + ptr->swactStage = MTC_SWACT__START ; + ptr->offlineStage = MTC_OFFLINE__IDLE ; + ptr->onlineStage = MTC_ONLINE__START ; + ptr->addStage = MTC_ADD__START ; + ptr->delStage = MTC_DEL__START ; + ptr->recoveryStage = MTC_RECOVERY__START ; + ptr->insvTestStage = MTC_INSV_TEST__RUN ; /* Start wo initial delay */ + ptr->oosTestStage = MTC_OOS_TEST__LOAD_NEXT_TEST ; + ptr->resetProgStage = MTC_RESETPROG__START; + ptr->powerStage = MTC_POWER__DONE ; + ptr->powercycleStage = MTC_POWERCYCLE__DONE; + ptr->subStage = MTC_SUBSTAGE__DONE ; + ptr->reinstallStage = MTC_REINSTALL__DONE ; + ptr->resetStage = MTC_RESET__START ; + ptr->handlerStage.enable = MTC_ENABLE__START ; /* Enable and Disable */ + + ptr->oos_test_count = 0 ; + ptr->insv_test_count = 0 ; + ptr->insv_recovery_counter = 0 ; + + ptr->uptime = 0 ; + ptr->uptime_refresh_counter = 0 ; + ptr->node_unlocked_counter = 0 ; + + /* Default to a healthy config until mtcAlive messages prove otherwise */ + ptr->mtce_flags = ( MTC_FLAG__I_AM_CONFIGURED | + MTC_FLAG__I_AM_HEALTHY ) ; + + ptr->graceful_recovery_counter = 0 ; + ptr->health_threshold_counter = 0 ; + ptr->unknown_health_reported = false ; + ptr->mnfa_graceful_recovery = false ; + + /* initialize all board management variables for this host */ + ptr->bm_ip = NONE ; + ptr->bm_type = NONE ; + ptr->bm_un = NONE ; + ptr->bm_pw = NONE ; + + ptr->bm_provisioned = false ; /* assume not provisioned until learned */ + ptr->power_on = false ; /* learned on first BMC connection */ + bmc_access_data_init ( ptr ); /* init all the BMC access vars all modes */ + + /* init the alarm array only to have it updated later + * with current alarm severities */ + for ( int id = 0 ; id < MAX_ALARMS ; id++ ) + { + ptr->alarms[id] = FM_ALARM_SEVERITY_CLEAR ; + } + ptr->alarms_loaded = false ; + + ptr->cfgEvent.base = NULL ; + ptr->sysinvEvent.base= NULL ; + ptr->vimEvent.base = NULL ; + + ptr->httpReq.base = NULL ; + ptr->libEvent_done_fifo.clear(); + ptr->libEvent_work_fifo.clear(); + + ptr->oper_sequence = 0 ; + ptr->oper_failures = 0 ; + + ptr->mtcCmd_work_fifo.clear(); + ptr->mtcCmd_done_fifo.clear(); + + ptr->cfgEvent.conn = NULL ; + ptr->sysinvEvent.conn= NULL ; + ptr->vimEvent.conn = NULL ; + ptr->httpReq.conn = NULL ; + + ptr->cfgEvent.req = NULL ; + ptr->sysinvEvent.req = NULL ; + ptr->vimEvent.req = NULL ; + ptr->httpReq.req = NULL ; + + + ptr->cfgEvent.buf = NULL ; + ptr->sysinvEvent.buf = NULL ; + ptr->vimEvent.buf = NULL ; + ptr->httpReq.buf = NULL ; + + + ptr->stall_recovery_log_throttle = 0 ; + ptr->stall_monitor_log_throttle = 0 ; + ptr->unexpected_pulse_log_throttle = 0 ; + ptr->lookup_mismatch_log_throttle = 0 ; + + ptr->log_throttle = 0 ; + ptr->no_work_log_throttle = 0 ; + + /* Clear the degrade control structs */ + ptr->degrade_mask = DEGRADE_MASK_NONE ; + ptr->degraded_resources_list.clear () ; + ptr->pmond_ready = false ; + ptr->rmond_ready = false ; + ptr->hwmond_ready = false ; + ptr->hbsClient_ready = false ; + + ptr->toggle = false ; + + ptr->retries = 0 ; + ptr->http_retries_cur = 0 ; + ptr->cmd_retries = 0 ; + ptr->power_action_retries = 0 ; + + ptr->subf_enabled = false ; + + for ( int i = 0 ; i < MAX_IFACES ; i++ ) + { + ptr->pulse_link[i].next_ptr = NULL ; + ptr->pulse_link[i].prev_ptr = NULL ; + ptr->monitor[i] = false ; + ptr->hbs_minor[i] = false ; + ptr->hbs_degrade[i] = false ; + ptr->hbs_failure[i] = false ; + ptr->max_count[i] = 0 ; + ptr->hbs_count[i] = 0 ; + ptr->hbs_minor_count[i] = 0 ; + ptr->b2b_misses_count[i] = 0 ; + ptr->hbs_degrade_count[i] = 0 ; + ptr->hbs_failure_count[i] = 0 ; + ptr->heartbeat_failed[i] = false; + } + + ptr->health = NODE_HEALTH_UNKNOWN ; + + ptr->pmon_missing_count = 0; + ptr->pmon_degraded = false ; + + /* now add it to the node list ; dealing with all conditions */ + + /* if the node list is empty add it to the head */ + if( head == NULL ) + { + head = ptr ; + tail = ptr ; + ptr->prev = NULL ; + ptr->next = NULL ; + } + else + { + /* link in the new_node to the tail of the node_list + * then mark the next field as the end of the node_list + * adjust tail to point to the last node + */ + tail->next = ptr ; + ptr->prev = tail ; + ptr->next = NULL ; + tail = ptr ; + } + + /* start with no action and an empty todo list */ + ptr->adminAction = MTC_ADMIN_ACTION__NONE ; + ptr->adminAction_todo_list.clear(); + + ptr->handlerStage.enable = MTC_ENABLE__START; + + hosts++ ; + + /* (re)build the Resource Reference Array */ + if ( heartbeat ) + build_rra (); + + return ptr ; +} + +struct nodeLinkClass::node* nodeLinkClass::getNode ( string hostname ) +{ + /* check for empty list condition */ + if ( head == NULL ) + return NULL ; + + if ( hostname.empty() ) + return static_cast(NULL); + + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( !hostname.compare ( ptr->hostname )) + { + return ptr ; + } + /* Node can be looked up by ip addr too */ + if ( !hostname.compare ( ptr->ip )) + { + return ptr ; + } + /* Node can be looked up by infra_ip addr too */ + if ( !hostname.compare ( ptr->infra_ip )) + { + return ptr ; + } + /* Node can be looked up by uuid too */ + if ( !hostname.compare ( ptr->uuid )) + { + return ptr ; + } + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return static_cast(NULL); +} + + +struct nodeLinkClass::node* nodeLinkClass::getEventBaseNode ( libEvent_enum request, + struct event_base * base_ptr) +{ + struct node * ptr = static_cast(NULL) ; + + /* check for empty list condition */ + if ( head == NULL ) + return NULL ; + + if ( base_ptr == NULL ) + return NULL ; + + for ( ptr = head ; ; ptr = ptr->next ) + { + switch ( request ) + { + case SYSINV_HOST_QUERY: + { + if ( ptr->sysinvEvent.base == base_ptr ) + { + hlog1 ("%s Found Sysinv Event Base Pointer (%p)\n", + ptr->hostname.c_str(), ptr->sysinvEvent.base); + + return ptr ; + } + } + case VIM_HOST_DISABLED: + case VIM_HOST_ENABLED: + case VIM_HOST_OFFLINE: + case VIM_HOST_FAILED: + { + if ( ptr->vimEvent.base == base_ptr ) + { + hlog1 ("%s Found vimEvent Base Pointer (%p) \n", + ptr->hostname.c_str(), ptr->vimEvent.base); + + return ptr ; + } + } + default: + ; + } /* End Switch */ + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + + wlog ("%s Event Base Pointer (%p) - Not Found\n", + ptr->hostname.c_str(), base_ptr); + + return static_cast(NULL); + +} + +/* Find the node in the list of nodes being heartbeated and splice it out */ +int nodeLinkClass::remNode( string hostname ) +{ + int rc = -ENODEV ; + if ( hostname.c_str() == NULL ) + return -EFAULT ; + + if ( head == NULL ) + return -ENXIO ; + + struct node * ptr = getNode ( hostname ); + + if ( ptr == NULL ) + return -EFAULT ; + + mtcTimer_fini ( ptr->mtcTimer ); + mtcTimer_fini ( ptr->mtcSwact_timer ); + mtcTimer_fini ( ptr->mtcAlive_timer ); + mtcTimer_fini ( ptr->offline_timer ); + mtcTimer_fini ( ptr->mtcCmd_timer ); + mtcTimer_fini ( ptr->http_timer ); + + mtcTimer_fini ( ptr->insvTestTimer ); + mtcTimer_fini ( ptr->oosTestTimer ); + mtcTimer_fini ( ptr->mtcConfig_timer ); + mtcTimer_fini ( ptr->host_services_timer ); + mtcTimer_fini ( ptr->hwmon_powercycle.control_timer ); + mtcTimer_fini ( ptr->hwmon_powercycle.recovery_timer ); + mtcTimer_fini ( ptr->hwmon_reset.control_timer ); + mtcTimer_fini ( ptr->hwmon_reset.recovery_timer ); + + mtcTimer_fini ( ptr->bm_timer ); + mtcTimer_fini ( ptr->bmc_access_timer ); + mtcTimer_fini ( ptr->bm_ping_info.timer ); + +#ifdef WANT_PULSE_LIST_SEARCH_ON_DELETE + + /* Splice the node out of the pulse monitor list */ + + for ( int i = 0 ; i < MAX_IFACES ; i++ ) + { + /* Does the pulse monitor list exist ? */ + if ( pulse_list[i].head_ptr != NULL ) + { + pulse_ptr = ptr ; + if ( pulse_list[i].head_ptr == pulse_ptr ) + { + if ( pulse_list[i].head_ptr == pulse_list[i].tail_ptr ) + { + pulse_list[i].head_ptr = NULL ; + pulse_list[i].tail_ptr = NULL ; + dlog ("Pulse: Single Node -> Head Case\n"); + } + else + { + dlog ("Pulse: Multiple Nodes -> Head Case\n"); + pulse_list[i].head_ptr = pulse_list[i].head_ptr->pulse_link[i].next_ptr ; + pulse_list[i].head_ptr->pulse_link[i].prev_ptr = NULL ; + } + } + else if ( pulse_list[i].tail_ptr == pulse_ptr ) + { + dlog ("Pulse: Multiple Node -> Tail Case\n"); + pulse_list[i].tail_ptr = pulse_list[i].tail_ptr->pulse_link[i].prev_ptr ; + pulse_list[i].tail_ptr->pulse_link[i].next_ptr = NULL ; + } + else + { + dlog ("Pulse: Multiple Node -> Full Splice Out\n"); + pulse_ptr->pulse_link[i].prev_ptr->pulse_link[i].next_ptr = pulse_ptr->pulse_link[i].next_ptr ; + pulse_ptr->pulse_link[i].next_ptr->pulse_link[i].prev_ptr = pulse_ptr->pulse_link[i].prev_ptr ; + } + } + } + +#endif + + /* If the node is the head node */ + if ( ptr == head ) + { + /* only one node in the list case */ + if ( head == tail ) + { + dlog ("Single Node -> Head Case\n"); + head = NULL ; + tail = NULL ; + delNode ( ptr ); + rc = PASS ; + } + else + { + dlog ("Multiple Nodes -> Head Case\n"); + head = head->next ; + head->prev = NULL ; + delNode ( ptr ); + rc = PASS ; + } + } + /* if not head but tail then there must be more than one + * node in the list so go ahead and chop the tail. + */ + else if ( ptr == tail ) + { + dlog ("Multiple Node -> Tail Case\n"); + tail = tail->prev ; + tail->next = NULL ; + delNode ( ptr ); + rc = PASS ; + } + else + { + dlog ("Multiple Node -> Full Splice Out\n"); + ptr->prev->next = ptr->next ; + ptr->next->prev = ptr->prev ; + delNode( ptr ); + rc = PASS ; + } + hosts-- ; + + /* (re)build the Resource Reference Array */ + if ( heartbeat ) + build_rra (); + + return rc ; +} + +/** + * Node state set'ers and get'ers + */ +mtc_nodeAdminAction_enum nodeLinkClass::get_adminAction ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + return ( node_ptr->adminAction ); + + elog ("Failed getting 'admin action' for '%s'\n", hostname.c_str()); + return (MTC_ADMIN_ACTION__NONE); +} + +int nodeLinkClass::set_adminAction ( string & hostname, mtc_nodeAdminAction_enum adminAction ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + { + adminActionChange ( node_ptr, adminAction ) ; + return (PASS) ; + } + elog ("Failed setting 'admin action' for '%s'\n", hostname.c_str()); + return (FAIL) ; +} + +mtc_nodeAdminState_enum nodeLinkClass::get_adminState ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + return ( node_ptr->adminState ); + + elog ("Failed getting 'admin state' state for '%s'\n", hostname.c_str()); + return (MTC_ADMIN_STATE__LOCKED); +} + +int nodeLinkClass::set_adminState ( string & hostname, mtc_nodeAdminState_enum adminState ) +{ + int rc = FAIL ; + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + { + rc = nodeLinkClass::adminStateChange ( node_ptr , adminState ); + } + if ( rc ) + { + elog ("Failed setting 'admin state' for '%s'\n", hostname.c_str()); + } + return (rc) ; +} + +mtc_nodeOperState_enum nodeLinkClass::get_operState ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + return ( node_ptr->operState ); + + elog ("Failed getting 'operational state' for '%s'\n", hostname.c_str()); + return (MTC_OPER_STATE__DISABLED); +} + +int nodeLinkClass::set_operState ( string & hostname, mtc_nodeOperState_enum operState ) +{ + int rc = FAIL ; + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + { + rc = nodeLinkClass::operStateChange ( node_ptr , operState ); + } + if ( rc ) + { + elog ("Failed setting 'operational state' for '%s'\n", hostname.c_str()); + } + return (rc) ; +} + +mtc_nodeAvailStatus_enum nodeLinkClass::get_availStatus ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + return ( node_ptr->availStatus ); + + elog ("Failed getting 'availability status' for '%s'\n", hostname.c_str()); + return (MTC_AVAIL_STATUS__OFFDUTY); +} + +int nodeLinkClass::set_availStatus ( string & hostname, mtc_nodeAvailStatus_enum availStatus ) +{ + int rc = FAIL ; + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + rc = nodeLinkClass::availStatusChange ( node_ptr , availStatus ); + } + if ( rc ) + { + elog ("Failed setting 'availability status' for '%s'\n", hostname.c_str()); + } + return (FAIL) ; +} + +/** Return a string representing the data port operational state + * according to the X.731 standard */ +string nodeLinkClass::get_operState_dport ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + { + return ( operState_enum_to_str(node_ptr->operState_dport)); + } + elog ("%s failed getting 'operState_dport'\n", hostname.c_str()); + return (""); +} + +/** Return a string representing the data port availability status + * according to the X.731 standard */ +string nodeLinkClass::get_availStatus_dport ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr ) + { + return ( availStatus_enum_to_str(node_ptr->availStatus_dport)); + } + elog ("%s failed getting 'availStatus_dport'\n", hostname.c_str()); + return (""); +} + +void nodeLinkClass::print_node_info ( nodeLinkClass::node * ptr ) +{ + ilog ("%17s (%15s) %8s %8s-%-9s | %s-%s-%s | %s | %0X", + ptr->hostname.c_str(), + ptr->ip.c_str(), + mtc_nodeAdminState_str[ptr->adminState], + mtc_nodeOperState_str[ptr->operState], + mtc_nodeAvailStatus_str[ptr->availStatus], + ptr->subfunction_str.c_str(), + mtc_nodeOperState_str[ptr->operState_subf], + mtc_nodeAvailStatus_str[ptr->availStatus_subf], + mtc_nodeAdminAction_str [ptr->adminAction], + ptr->degrade_mask); +} + +void nodeLinkClass::print_node_info ( void ) +{ + if ( maintenance ) + { + syslog ( LOG_INFO,"+--------------------------------------+-------------------+-----------------+\n"); + for ( struct node * ptr = head ; ptr != NULL ; ptr = ptr->next ) + { + if ( LARGE_SYSTEM ) + { + syslog ( LOG_INFO, "| %36s | %17s | %15s | %8s %8s-%s", + ptr->uuid.length() ? ptr->uuid.c_str() : "", + ptr->hostname.c_str(), + ptr->ip.c_str(), + mtc_nodeAdminState_str[ptr->adminState], + mtc_nodeOperState_str[ptr->operState], + mtc_nodeAvailStatus_str[ptr->availStatus]); + } + else + { + syslog ( LOG_INFO, "| %36s | %17s | %15s | %8s %8s-%-9s | %s-%s-%s", + ptr->uuid.length() ? ptr->uuid.c_str() : "", + ptr->hostname.c_str(), + ptr->ip.c_str(), + mtc_nodeAdminState_str[ptr->adminState], + mtc_nodeOperState_str[ptr->operState], + mtc_nodeAvailStatus_str[ptr->availStatus], + ptr->subfunction_str.c_str(), + mtc_nodeOperState_str[ptr->operState_subf], + mtc_nodeAvailStatus_str[ptr->availStatus_subf]); + } + // syslog ( LOG_INFO, "\n"); + } + syslog ( LOG_INFO, "+--------------------------------------+-------------------+-----------------+\n\n"); + } + + if ( heartbeat ) + { + for ( int i = 0 ; i < MAX_IFACES ; i++ ) + { + if (( i == INFRA_IFACE ) && ( infra_network_provisioned == false )) + continue ; + + syslog ( LOG_INFO, "+--------------+-----+-----+------+-----+------+------------+-----------------+\n"); + syslog ( LOG_INFO, "| %s: %3d | Mon | Mis | Max | Deg | Fail | Pulses | %s (%4d) |\n" , + get_iface_name_str ((iface_enum)i), hosts, hbs_disabled ? "DISABLED" : "Enabled ", hbs_pulse_period ); + syslog ( LOG_INFO, "+--------------+-----+-----+------+-----+------+------------+-----------------+\n"); + + for ( struct node * ptr = head ; ptr != NULL ; ptr = ptr->next ) + { + syslog ( LOG_INFO, "| %-12s | %c | %3i | %4i | %3i | %4i | %8x | %d msec\n", + ptr->hostname.c_str(), + ptr->monitor[i] ? 'Y' : 'n', + ptr->b2b_misses_count[i], + ptr->max_count[i], + ptr->hbs_degrade_count[i], + ptr->hbs_failure_count[i], + ptr->hbs_count[i], + hbs_pulse_period ); + } + } + syslog ( LOG_INFO, "+--------------+-----+-----+------+-----+------+------------+-----------------+\n"); + } +} + +/** Convert the supplied string to a valid maintenance Admin State enum */ +mtc_nodeAdminState_enum nodeLinkClass::adminState_str_to_enum ( const char * admin_ptr ) +{ + /* Default state */ + mtc_nodeAdminState_enum temp = MTC_ADMIN_STATE__LOCKED; + + if ( admin_ptr == NULL ) + { + wlog ("Administrative state is Null\n"); + } + else if ( !strcmp ( &mtc_nodeAdminState_str[MTC_ADMIN_STATE__UNLOCKED][0], admin_ptr )) + temp = MTC_ADMIN_STATE__UNLOCKED ; + + return (temp) ; +} + +/** Convert the supplied string to a valid maintenance Oper State enum */ +mtc_nodeOperState_enum nodeLinkClass::operState_str_to_enum ( const char * oper_ptr ) +{ + /* Default state */ + mtc_nodeOperState_enum temp = MTC_OPER_STATE__DISABLED; + + if ( oper_ptr == NULL ) + { + wlog ("Operation state is Null\n"); + } + else if ( !strcmp ( &mtc_nodeOperState_str[MTC_ADMIN_STATE__UNLOCKED][0], oper_ptr )) + temp = MTC_OPER_STATE__ENABLED ; + + return (temp) ; +} + +/** Convert the supplied string to a valid maintenance Avail Status enum */ +mtc_nodeAvailStatus_enum nodeLinkClass::availStatus_str_to_enum ( const char * avail_ptr ) +{ + /* Default state */ + mtc_nodeAvailStatus_enum temp = MTC_AVAIL_STATUS__OFFDUTY; + + /* Could do this as a loop but this is more resiliant to enum changes */ + /* TODO: consider using a paired list */ + if ( avail_ptr == NULL ) + { + wlog ("Availability status is Null\n"); + } + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__AVAILABLE][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__AVAILABLE ; + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__FAILED][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__FAILED ; + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__INTEST][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__INTEST ; + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__DEGRADED][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__DEGRADED ; + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__OFFLINE][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__OFFLINE ; + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__ONLINE][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__ONLINE ; + else if ( !strcmp ( &mtc_nodeAvailStatus_str[MTC_AVAIL_STATUS__POWERED_OFF][0], avail_ptr )) + temp = MTC_AVAIL_STATUS__POWERED_OFF ; + + return (temp) ; +} + +/** Convert the supplied enum to the corresponding Admin State string */ +string nodeLinkClass::adminAction_enum_to_str ( mtc_nodeAdminAction_enum val ) +{ + if ( val < MTC_ADMIN_ACTIONS ) + { + string adminAction_string = &mtc_nodeAdminAction_str[val][0] ; + return ( adminAction_string ); + } + return ( NULL ); +} + +/** Convert the supplied enum to the corresponding Admin State string */ +string nodeLinkClass::adminState_enum_to_str ( mtc_nodeAdminState_enum val ) +{ + if ( val < MTC_ADMIN_STATES ) + { + string adminState_string = &mtc_nodeAdminState_str[val][0] ; + return ( adminState_string ); + } + return ( NULL ); +} +/** Convert the supplied enum to the corresponding Oper State string */ +string nodeLinkClass::operState_enum_to_str ( mtc_nodeOperState_enum val ) +{ + if ( val < MTC_OPER_STATES ) + { + string operState_string = &mtc_nodeOperState_str[val][0] ; + return ( operState_string ); + } + return ( NULL ); +} +/** Convert the supplied enum to the corresponding Avail Status string */ +string nodeLinkClass::availStatus_enum_to_str ( mtc_nodeAvailStatus_enum val ) +{ + if ( val < MTC_AVAIL_STATUS ) + { + string availStatus_string = &mtc_nodeAvailStatus_str[val][0] ; + return ( availStatus_string ); + } + return ( NULL ); +} + +void nodeLinkClass::host_print ( struct nodeLinkClass::node * node_ptr ) +{ + string uuid ; + + if ( daemon_get_cfg_ptr()->debug_level == 1 ) + { + const char bar [] = { "+-------------+--------------------------------------+" }; + const char uar [] = { "+- Add Host -+--------------------------------------+" }; + syslog ( LOG_INFO, "%s\n", &uar[0]); + syslog ( LOG_INFO, "| uuid : %s\n", node_ptr->uuid.c_str()); + syslog ( LOG_INFO, "| main : %s\n", node_ptr->function_str.c_str()); + syslog ( LOG_INFO, "| subf : %s\n", node_ptr->subfunction_str.c_str()); + syslog ( LOG_INFO, "| name : %s\n", node_ptr->hostname.c_str()); + syslog ( LOG_INFO, "| ip : %s\n", node_ptr->ip.c_str()); + syslog ( LOG_INFO, "| admin : %s\n", adminState_enum_to_str (node_ptr->adminState).c_str()); + syslog ( LOG_INFO, "| oper : %s\n", operState_enum_to_str (node_ptr->operState).c_str()); + syslog ( LOG_INFO, "| avail_subf: %s\n", availStatus_enum_to_str (node_ptr->availStatus_subf).c_str()); + syslog ( LOG_INFO, "| oper_subf: %s\n", operState_enum_to_str (node_ptr->operState_subf).c_str()); + syslog ( LOG_INFO, "%s\n", &bar[0]); + } + /* ec3624cb-d80f-4e8b-a6d7-0c11f6937f6a */ + /* Just print the last 4 chars of the uuid */ + if ( node_ptr->uuid.empty() ) + uuid = "---" ; + else + uuid = node_ptr->uuid.substr(32) ; + + if ( node_ptr->availStatus == MTC_AVAIL_STATUS__AVAILABLE ) + { + ilog ("%s '%s' %s %s-%s (%s)\n", node_ptr->hostname.c_str(), + functions.c_str(), + node_ptr->ip.c_str(), + adminState_enum_to_str (node_ptr->adminState).c_str(), + operState_enum_to_str (node_ptr->operState).c_str(), + uuid.c_str()); + } + else + { + ilog ("%s '%s' %s %s-%s-%s (%s)\n",node_ptr->hostname.c_str(), + functions.c_str(), + node_ptr->ip.c_str(), + adminState_enum_to_str (node_ptr->adminState).c_str(), + operState_enum_to_str (node_ptr->operState).c_str(), + availStatus_enum_to_str(node_ptr->availStatus).c_str(), + uuid.c_str()); + } +} + + +/** Host Administrative State Change public member function */ +int nodeLinkClass::admin_state_change ( string hostname, + string newAdminState ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( hostname ); + if ( node_ptr ) + { + if ( newAdminState.empty() ) + { + rc = FAIL_STRING_EMPTY ; + } + else if ( adminState_str_to_enum ( newAdminState.data() ) == node_ptr->adminState ) + { + rc = PASS ; + } + else if ( adminStateOk ( newAdminState ) ) + { + clog ("%s %s (from %s)\n", hostname.c_str(), newAdminState.c_str(), adminState_enum_to_str (node_ptr->adminState).c_str()); + node_ptr->adminState = adminState_str_to_enum ( newAdminState.data() ); + rc = PASS ; + } + else + { + elog ("%s Invalid 'admin' state (%s)\n", + hostname.c_str(), newAdminState.c_str() ); + } + } + else + { + wlog ("Cannot change 'admin' state for unknown hostname (%s)\n", + hostname.c_str()); + } + return (rc); +} + +/** Host Operational State Change public member function */ +int nodeLinkClass::oper_state_change ( string hostname, string newOperState ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( hostname ); + if ( node_ptr ) + { + if ( newOperState.empty() ) + { + rc = FAIL_STRING_EMPTY ; + } + else if ( operState_str_to_enum ( newOperState.data() ) == node_ptr->operState ) + { + rc = PASS ; + } + else if ( operStateOk ( newOperState ) ) + { + mtc_nodeOperState_enum oper = operState_str_to_enum ( newOperState.data() ); + if (( node_ptr->operState == MTC_OPER_STATE__DISABLED ) && + ( oper == MTC_OPER_STATE__ENABLED )) + { + mtcAlarm_log ( hostname, MTC_LOG_ID__STATUSCHANGE_ENABLED ); + } + + if (( node_ptr->operState == MTC_OPER_STATE__ENABLED ) && + ( oper == MTC_OPER_STATE__DISABLED )) + { + mtcAlarm_log ( hostname, MTC_LOG_ID__STATUSCHANGE_DISABLED ); + } + clog ("%s %s (from %s)\n", hostname.c_str(), newOperState.c_str(), operState_enum_to_str (node_ptr->operState).c_str()); + node_ptr->operState = oper ; + rc = PASS ; + } + else + { + elog ("%s Invalid 'oper' state (%s)\n", + hostname.c_str(), newOperState.c_str() ); + } + } + else + { + wlog ("Cannot change 'oper' state for unknown hostname (%s)\n", + hostname.c_str() ); + } + return (rc); +} + +/** Host Availability Status Change public member function */ +int nodeLinkClass::avail_status_change ( string hostname, + string newAvailStatus ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( hostname ); + if ( node_ptr ) + { + if ( newAvailStatus.empty() ) + { + rc = FAIL_STRING_EMPTY ; + } + else if ( availStatus_str_to_enum ( newAvailStatus.data() ) == node_ptr->availStatus ) + { + rc = PASS ; + } + else if ( availStatusOk ( newAvailStatus )) + { + mtc_nodeAvailStatus_enum avail = availStatus_str_to_enum ( newAvailStatus.data() ); + + /* if we go to the failed state then clear all mtcAlive counts + * so that the last ones don't look like we are online when we + * might not be - we should relearn the on/off line state */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__FAILED ) && + ( avail == MTC_AVAIL_STATUS__FAILED )) + { + node_ptr->mtcAlive_misses = 0 ; + node_ptr->mtcAlive_hits = 0 ; + node_ptr->mtcAlive_gate = false ; + } + + /* check for need to generate power on log */ + if (( node_ptr->availStatus == MTC_AVAIL_STATUS__POWERED_OFF ) && + ( avail != MTC_AVAIL_STATUS__POWERED_OFF )) + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__POWERON ) + { + mtcAlarm_log ( hostname, MTC_LOG_ID__COMMAND_MANUAL_POWER_ON ); + } + else + { + mtcAlarm_log ( hostname, MTC_LOG_ID__COMMAND_AUTO_POWER_ON ); + } + } + + /* check for need to generate power off log */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__POWERED_OFF ) && + ( avail == MTC_AVAIL_STATUS__POWERED_OFF )) + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__POWEROFF ) + { + mtcAlarm_log ( hostname, MTC_LOG_ID__COMMAND_MANUAL_POWER_OFF ); + } + else + { + mtcAlarm_log ( hostname, MTC_LOG_ID__COMMAND_AUTO_POWER_OFF ); + } + } + + /* check for need to generate online log */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__ONLINE ) && + ( avail == MTC_AVAIL_STATUS__ONLINE )) + { + if ( node_ptr->offline_log_reported == true ) + { + mtcAlarm_log ( hostname, MTC_LOG_ID__STATUSCHANGE_ONLINE ); + node_ptr->offline_log_reported = false ; + node_ptr->online_log_reported = true ; + } + } + + /* check for need to generate offline log */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__OFFLINE ) && + ( avail == MTC_AVAIL_STATUS__OFFLINE )) + { + if ( node_ptr->online_log_reported == true ) + { + mtcAlarm_log ( hostname, MTC_LOG_ID__STATUSCHANGE_OFFLINE ); + node_ptr->offline_log_reported = true ; + node_ptr->online_log_reported = false ; + } + } + + /* If the availability status is moving away from off or online then + * be sure we cancel the mtcAlive timer */ + if ((( node_ptr->availStatus == MTC_AVAIL_STATUS__OFFLINE ) || + ( node_ptr->availStatus == MTC_AVAIL_STATUS__ONLINE )) && + (( avail != MTC_AVAIL_STATUS__OFFLINE ) && + ( avail != MTC_AVAIL_STATUS__ONLINE ))) + { + /* Free the mtc timer if in use */ + if ( node_ptr->mtcAlive_timer.tid ) + { + tlog ("%s Stopping mtcAlive timer\n", node_ptr->hostname.c_str()); + mtcTimer_stop ( node_ptr->mtcAlive_timer ); + node_ptr->mtcAlive_timer.ring = false ; + node_ptr->mtcAlive_timer.tid = NULL ; + } + node_ptr->onlineStage = MTC_ONLINE__START ; + } + + clog ("%s %s (from %s)\n", hostname.c_str(), newAvailStatus.c_str(), availStatus_enum_to_str (node_ptr->availStatus).c_str()); + node_ptr->availStatus = avail ; + rc = PASS ; + } + else + { + elog ("%s Invalid 'avail' status (%s)\n", + hostname.c_str(), newAvailStatus.c_str() ); + } + } + else + { + wlog ("Cannot change 'avail' status for unknown hostname (%s)\n", + hostname.c_str()); + } + return (rc); +} + +/** Set host to the disabled failed state and generate the disabled-failed customer log + * This interface allows the disabled-failed state change to be combined so as to avoid + * setting a 'disabled' AND 'disabled-failed' customer log for the failure case */ +int nodeLinkClass::failed_state_change ( struct nodeLinkClass::node * node_ptr ) +{ + int rc = FAIL_NULL_POINTER ; + if ( node_ptr ) + { + node_ptr->availStatus = MTC_AVAIL_STATUS__FAILED ; + node_ptr->operState = MTC_OPER_STATE__DISABLED ; + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__STATUSCHANGE_FAILED ); + rc = PASS ; + } + else + { + slog ("Cannot change to disabled-failed state for null node pointer\n"); + } + return (rc); +} + + +/***************************************************************************** + * + * Name : lazy_graceful_fs_reboot + * + * Description: Issue a lazy reboot and signal SM to shutdown services + * + * Assumptions: No return + * + *****************************************************************************/ + +int nodeLinkClass::lazy_graceful_fs_reboot ( struct nodeLinkClass::node * node_ptr ) +{ + /* issue a lazy reboot to the mtcClient and as a backup launch a sysreq reset thresd */ + send_mtc_cmd ( node_ptr->hostname, MTC_CMD_LAZY_REBOOT, MGMNT_INTERFACE ) ; + fork_sysreq_reboot ( daemon_get_cfg_ptr()->failsafe_shutdown_delay ); + + /* loop until reboot */ + for ( ; ; ) + { + for ( int i = 0 ; i < LAZY_REBOOT_RETRY_DELAY_SECS ; i++ ) + { + daemon_signal_hdlr (); + sleep (MTC_SECS_1); + + /* give sysinv time to handle the response and get its state in order */ + if ( i == SM_NOTIFY_UNHEALTHY_DELAY_SECS ) + { + daemon_log ( SMGMT_UNHEALTHY_FILE, "AIO shutdown request" ); + } + } + /* Should never get there but if we do resend the reboot request + * but this time not Lazy */ + send_mtc_cmd ( node_ptr->hostname, MTC_CMD_REBOOT, MGMNT_INTERFACE ) ; + } + return (FAIL); +} + + +/* Generate a log and a critical alarm if the node config failed */ +int nodeLinkClass::alarm_config_failure ( struct nodeLinkClass::node * node_ptr ) +{ + if ( (node_ptr->degrade_mask & DEGRADE_MASK_CONFIG) == 0 ) + { + node_ptr->degrade_mask |= DEGRADE_MASK_CONFIG ; + } + + if ( node_ptr->alarms[MTC_ALARM_ID__CONFIG] != FM_ALARM_SEVERITY_CRITICAL ) + { + elog ("%s critical config failure\n", node_ptr->hostname.c_str()); + + mtcAlarm_critical ( node_ptr->hostname, MTC_ALARM_ID__CONFIG ); + node_ptr->alarms[MTC_ALARM_ID__CONFIG] = FM_ALARM_SEVERITY_CRITICAL ; + } + return (PASS); +} + +/* Clear the config alarm and degrade flag */ +int nodeLinkClass::alarm_config_clear ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr->degrade_mask & DEGRADE_MASK_CONFIG ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_CONFIG ; + } + + if ( node_ptr->alarms[MTC_ALARM_ID__CONFIG] != FM_ALARM_SEVERITY_CLEAR ) + { + ilog ("%s config alarm clear\n", node_ptr->hostname.c_str()); + + mtcAlarm_clear ( node_ptr->hostname, MTC_ALARM_ID__CONFIG ); + node_ptr->alarms[MTC_ALARM_ID__CONFIG] = FM_ALARM_SEVERITY_CLEAR ; + } + return (PASS); +} + +/* Generate a log and a critical alarm if the node enable failed */ +int nodeLinkClass::alarm_enabled_failure ( struct nodeLinkClass::node * node_ptr ) +{ + if ( (node_ptr->degrade_mask & DEGRADE_MASK_ENABLE) == 0 ) + { + node_ptr->degrade_mask |= DEGRADE_MASK_ENABLE ; + } + + if ( node_ptr->alarms[MTC_ALARM_ID__ENABLE] != FM_ALARM_SEVERITY_CRITICAL ) + { + elog ("%s critical enable failure\n", node_ptr->hostname.c_str()); + + mtcAlarm_critical ( node_ptr->hostname, MTC_ALARM_ID__ENABLE ); + node_ptr->alarms[MTC_ALARM_ID__ENABLE] = FM_ALARM_SEVERITY_CRITICAL ; + } + return (PASS); +} + +/* + * Generate a major (in-service) enable alarm + * - don't downgrade the alarm from critical + * - do nothing if the alarm is already at major level + * + **/ +int nodeLinkClass::alarm_insv_failure ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr ) + { + if ( node_ptr->alarms[MTC_ALARM_ID__ENABLE] != FM_ALARM_SEVERITY_MAJOR ) + { + if ( node_ptr->alarms[MTC_ALARM_ID__ENABLE] != FM_ALARM_SEVERITY_CRITICAL ) + { + elog ("%s major inservice enable failure\n", node_ptr->hostname.c_str()); + node_ptr->degrade_mask |= DEGRADE_MASK_INSV_TEST ; + mtcAlarm_major ( node_ptr->hostname, MTC_ALARM_ID__ENABLE ); + node_ptr->alarms[MTC_ALARM_ID__ENABLE] = FM_ALARM_SEVERITY_MAJOR ; + } + } + } + return (PASS); +} + +/* Clear the enable alarm and degrade flag */ +int nodeLinkClass::alarm_enabled_clear ( struct nodeLinkClass::node * node_ptr, bool force ) +{ + if ( node_ptr->degrade_mask & DEGRADE_MASK_ENABLE ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_ENABLE ; + } + + /* The inservice test degrade flag needs to be cleared too. */ + if ( node_ptr->degrade_mask & DEGRADE_MASK_INSV_TEST ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_INSV_TEST ; + } + + if (( node_ptr->alarms[MTC_ALARM_ID__ENABLE] != FM_ALARM_SEVERITY_CLEAR ) || + ( force == true )) + { + ilog ("%s enable alarm clear\n", node_ptr->hostname.c_str()); + + mtcAlarm_clear ( node_ptr->hostname, MTC_ALARM_ID__ENABLE ); + node_ptr->alarms[MTC_ALARM_ID__ENABLE] = FM_ALARM_SEVERITY_CLEAR ; + } + return (PASS); +} + +/* Generate compute subfunction failure alarm */ +int nodeLinkClass::alarm_compute_failure ( struct nodeLinkClass::node * node_ptr, EFmAlarmSeverityT sev ) +{ + if ( (node_ptr->degrade_mask & DEGRADE_MASK_SUBF) == 0 ) + { + node_ptr->degrade_mask |= DEGRADE_MASK_SUBF ; + } + + if ( node_ptr->alarms[MTC_ALARM_ID__CH_COMP] != sev ) + { + if ( sev == FM_ALARM_SEVERITY_CRITICAL ) + { + elog ("%s critical compute subf failure\n", node_ptr->hostname.c_str()); + mtcAlarm_critical ( node_ptr->hostname, MTC_ALARM_ID__CH_COMP ); + } + else + { + elog ("%s major compute subf failure\n", node_ptr->hostname.c_str()); + mtcAlarm_major ( node_ptr->hostname, MTC_ALARM_ID__CH_COMP ); + } + node_ptr->alarms[MTC_ALARM_ID__CH_COMP] = sev ; + } + return (PASS); +} + +/* Clear the enable alarm if is at the Major severity level */ +int nodeLinkClass::alarm_insv_clear ( struct nodeLinkClass::node * node_ptr, bool force ) +{ + if ( node_ptr->degrade_mask & DEGRADE_MASK_INSV_TEST ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_INSV_TEST ; + } + + if (( node_ptr->alarms[MTC_ALARM_ID__ENABLE] == FM_ALARM_SEVERITY_MAJOR ) || + ( force == true )) + { + ilog ("%s %s enable alarm clear\n", node_ptr->hostname.c_str(), force ? "force" : "major" ); + + mtcAlarm_clear ( node_ptr->hostname, MTC_ALARM_ID__ENABLE ); + node_ptr->alarms[MTC_ALARM_ID__ENABLE] = FM_ALARM_SEVERITY_CLEAR ; + } + + if ( node_ptr->alarms[MTC_ALARM_ID__ENABLE] == FM_ALARM_SEVERITY_CLEAR ) + { + if ( node_ptr->degrade_mask & DEGRADE_MASK_ENABLE ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_ENABLE ; + } + } + + return (PASS); +} + +/* Clear the compute subfunction alarm and degrade flag */ +int nodeLinkClass::alarm_compute_clear ( struct nodeLinkClass::node * node_ptr, bool force ) +{ + if ( node_ptr->degrade_mask & DEGRADE_MASK_SUBF ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_SUBF ; + } + + if (( node_ptr->alarms[MTC_ALARM_ID__CH_COMP] != FM_ALARM_SEVERITY_CLEAR ) || + ( force == true )) + { + ilog ("%s major enable alarm clear\n", node_ptr->hostname.c_str()); + + mtcAlarm_clear ( node_ptr->hostname, MTC_ALARM_ID__CH_COMP ); + node_ptr->alarms[MTC_ALARM_ID__CH_COMP] = FM_ALARM_SEVERITY_CLEAR ; + } + return (PASS); +} + +/** Host Operational State Change public member function */ +int nodeLinkClass::oper_subf_state_change ( string hostname, string newOperState ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( hostname ); + if ( node_ptr ) + { + if ( newOperState.empty() ) + { + rc = FAIL_STRING_EMPTY ; + } + else if ( operStateOk ( newOperState ) ) + { + node_ptr->operState_subf = operState_str_to_enum ( newOperState.data() ); + rc = PASS ; + } + else + { + elog ("%s Invalid subfunction 'oper' state (%s)\n", + hostname.c_str(), newOperState.c_str() ); + } + } + else + { + wlog ("Cannot change subfuction 'oper' state for unknown hostname (%s)\n", + hostname.c_str() ); + } + return (rc); +} + +/** Host Subfunction Availability Status Change public member function */ +int nodeLinkClass::avail_subf_status_change ( string hostname, string newAvailStatus ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( hostname ); + if ( node_ptr ) + { + if ( newAvailStatus.empty() ) + { + rc = FAIL_STRING_EMPTY ; + } + else if ( availStatusOk ( newAvailStatus ) ) + { + node_ptr->availStatus_subf = availStatus_str_to_enum ( newAvailStatus.data() ); + rc = PASS ; + } + else + { + elog ("%s Invalid subfunction 'avail' status (%s)\n", + hostname.c_str(), newAvailStatus.c_str() ); + } + } + else + { + wlog ("Cannot change subfunction 'avail' status for unknown hostname (%s)\n", + hostname.c_str()); + } + return (rc); +} + + + +/** Update the mtce key with value */ +int nodeLinkClass::update_key_value ( string hostname, string key , string value ) +{ + int rc = PASS ; + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( hostname ); + if ( node_ptr ) + { + /* TODO: Add all database members to this utility */ + if ( !key.compare(MTC_JSON_INV_BMIP) ) + node_ptr->bm_ip = value ; + else if ( !key.compare(MTC_JSON_INV_TASK) ) + node_ptr->task = value ; + else + { + wlog ("%s Unsupported key '%s' update with value '%s'\n", + hostname.c_str(), key.c_str(), value.c_str()); + rc = FAIL_BAD_PARM ; + } + } + else + { + wlog ("Cannot change 'admin' state for unknown hostname (%s)\n", + hostname.c_str()); + } + return (rc); +} + +int nodeLinkClass::del_host ( const string uuid ) +{ + string hostname = "unknown" ; + + int rc = FAIL_DEL_UNKNOWN ; + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( uuid ); + if ( node_ptr ) + { + hostname = node_ptr->hostname ; + + if ( node_ptr->mtcTimer.tid ) + mtcTimer_stop ( node_ptr->mtcTimer ); + + if ( nodeLinkClass::maintenance == true ) + { + + if ( node_ptr->bm_provisioned == true ) + { + set_bm_prov ( node_ptr, false); + } + + doneQueue_purge ( node_ptr ); + workQueue_purge ( node_ptr ); + mtcCmd_doneQ_purge ( node_ptr ); + mtcCmd_workQ_purge ( node_ptr ); + + /* Cleanup if this is the inactive controller */ + if ( !node_ptr->hostname.compare(inactive_controller_hostname)) + { + inactive_controller_hostname = "" ; + } + } + rc = rem_host ( hostname ); + if ( rc == PASS ) + { + plog ("%s Deleted\n", hostname.c_str()); + + print_node_info(); + } + else + { + elog ("%s Delete Failed (rc:%d)\n", hostname.c_str(), rc ); + } + this->host_deleted = true ; + } + else + { + wlog ("Unknown uuid: %s\n", uuid.c_str()); + } + return (rc); +} + +int nodeLinkClass::set_host_failed ( node_inv_type & inv ) +{ + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( inv.name ); + if(NULL == node_ptr) + { + return FAIL_UNKNOWN_HOSTNAME; + } + + if( (node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED) && + (node_ptr->operState == MTC_OPER_STATE__ENABLED) ) + { + elog( "%s is being force failed by SM", inv.name.c_str() ); + this->force_full_enable (node_ptr); + } + return PASS; +} + +int nodeLinkClass::mod_host ( node_inv_type & inv ) +{ + int rc = PASS ; + bool modify = false ; + bool modify_bm = false ; + + print_inv (inv); + + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode( inv.uuid ); + if ( node_ptr ) + { + dlog ("%s Modify\n", node_ptr->hostname.c_str()); + +#ifdef WANT_FIT_TESTING + if ( daemon_want_fit ( FIT_CODE__TRANSLATE_LOCK_TO_FORCELOCK , node_ptr->hostname ) ) + { + if ( inv.action.compare("lock") == 0 ) + { + slog ("%s FIT action from 'lock' to 'force-lock'\n", node_ptr->hostname.c_str()); + inv.action = "force-lock"; + } + } +#endif + + /* Handle Administrative state mismatch between SYSINV and Maintenance */ + if ( strcmp ( mtc_nodeAdminState_str[node_ptr->adminState], inv.admin.data())) + { + plog ("%s Modify 'Administrative' state %s -> %sed\n", node_ptr->hostname.c_str(), + mtc_nodeAdminState_str[node_ptr->adminState], inv.action.c_str()); + + modify = true ; /* we have a delta */ + + /* Local admin state takes precedence */ + if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + /* handle a lock request while unlocked */ + if ( !inv.action.compare ( "lock" ) ) + { + if ( node_ptr->dor_recovery_mode == true ) + node_ptr->dor_recovery_mode = false ; + + /* Set action to LOCK and let the FSM run the disable handler */ + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__LOCK ); + } + else + { + ilog ("%s Already Unlocked ; no action required\n", node_ptr->hostname.c_str() ); + } + } + else + { + if ( node_ptr->patching == true ) + { + wlog ("%s cannot unlock host while patching is in progress\n", node_ptr->hostname.c_str()); + rc = FAIL_PATCH_INPROGRESS ; + } + else + { + /* generate command=unlock log */ + mtcAlarm_log ( inv.name, MTC_LOG_ID__COMMAND_UNLOCK ); + + /* Set action to UNLOCK and let the FSM run the enable handler */ + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__UNLOCK ); + } + } + } + else if ( (!inv.action.empty()) && (inv.action.compare ( "none" ))) + { + dlog ("%s Modify Action is '%s'\n", node_ptr->hostname.c_str(), inv.action.c_str() ); + node_ptr->action = inv.action ; + modify = true ; /* we have a delta */ + + /* Do not permit administrative actions while Swact is in progress */ + /* Note: There is a self corrective clause in the mtcTimer_handler + * that will auto clear this flag if it gets stuck for 5 minutes */ + if ( smgrEvent.mutex ) + { + elog ("%s Rejecting '%s' - Swact Operation in-progress\n", + node_ptr->hostname.c_str(), inv.action.c_str()); + rc = FAIL_SWACT_INPROGRESS ; + } + + else if (!inv.action.compare ( "force-lock" )) + { + /* TODO: Create customer log of this action */ + ilog ("%s Force Lock Action\n", node_ptr->hostname.c_str()); + + if ( node_ptr->dor_recovery_mode == true ) + node_ptr->dor_recovery_mode = false ; + + if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__FORCE_LOCK ) + { + ilog ("%s Force Lock Action - already in progress ...\n", node_ptr->hostname.c_str()); + } + else + { + /* generate command=forcelock log */ + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_FORCE_LOCK ); + + /* Set action to LOCK and let the FSM run the disable handler */ + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__FORCE_LOCK ); + } + } + else + { + wlog ("%s Already Locked\n", node_ptr->hostname.c_str() ); + } + } + else if (!inv.action.compare ( "lock" )) + { + if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + if ( node_ptr->dor_recovery_mode == true ) + node_ptr->dor_recovery_mode = false ; + + /* Set action to LOCK and let the FSM run the disable handler */ + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__LOCK ); + } + else + { + wlog ("%s Already Locked\n", node_ptr->hostname.c_str() ); + } + } + else if (!inv.action.compare ( "unlock" )) + { + if ( node_ptr->adminState == MTC_ADMIN_STATE__LOCKED ) + { + if ( node_ptr->patching == true ) + { + wlog ("%s cannot unlock host while patching is in progress\n", node_ptr->hostname.c_str()); + rc = FAIL_PATCH_INPROGRESS ; + } + else + { + recovery_ctrl_init ( node_ptr->hwmon_reset ); + recovery_ctrl_init ( node_ptr->hwmon_powercycle ); + + /* Set action to UNLOCK and let the FSM run the enable handler */ + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__UNLOCK ); + + mtcAlarm_clear ( node_ptr->hostname, MTC_ALARM_ID__LOCK ); + node_ptr->alarms[MTC_ALARM_ID__LOCK] = FM_ALARM_SEVERITY_CLEAR ; + + /* generate command=unlock log */ + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_UNLOCK ); + } + } + else + { + wlog ("%s Already UnLocked\n", node_ptr->hostname.c_str() ); + } + } + else if ( !inv.action.compare ( "swact" ) || + !inv.action.compare ( "force-swact" ) ) + { + if ( !((get_host_function_mask ( inv.type ) & CONTROLLER_TYPE) == CONTROLLER_TYPE) ) + { + elog ("%s Rejecting '%s' - Swact only supported for Controllers\n", + node_ptr->hostname.c_str(), + inv.action.c_str()); + rc = FAIL_NODETYPE ; + } + else if ( nodeLinkClass::is_inactive_controller_main_insv() != true ) + { + elog ("%s Rejecting '%s' - No In-Service Mate\n", + node_ptr->hostname.c_str(), + inv.action.c_str()); + rc = FAIL_SWACT_NOINSVMATE ; + } + else if ( node_ptr->adminAction != MTC_ADMIN_ACTION__NONE ) + { + elog ("%s Rejecting '%s' - '%s' In-Progress\n", + node_ptr->hostname.c_str(), + inv.action.c_str(), + get_adminAction_str( node_ptr->adminAction )); + rc = FAIL_OPER_INPROGRESS ; + } + else if ( smgrEvent.mutex ) + { + elog ("%s Rejecting '%s' - Operation in-progress\n", + node_ptr->hostname.c_str(), + inv.action.c_str()); + rc = FAIL_SWACT_INPROGRESS ; + } + // don't run the patching tests during a force-swact action + else if ( node_ptr->patching == true ) + { + wlog ("%s cannot swact active controller while patching is in progress\n", node_ptr->hostname.c_str()); + rc = FAIL_PATCH_INPROGRESS ; + } + else if ( inactive_controller_is_patching() == true ) + { + wlog ("%s cannot swact to inactive controller while patching is in progress\n", node_ptr->hostname.c_str()); + rc = FAIL_PATCH_INPROGRESS ; + } + // if this is a force-swact action then allow swact to a + // patched node that has not been rebooted yet, since + // this is a recoverable operation. The other two patching tests + // (above) need to be done on all swact actions since it may + // render the system non-recoverable. + else if ( !inv.action.compare ( "swact" ) && + inactive_controller_is_patched() == true ) + { + wlog ("%s cannot swact to a 'patched' but not 'rebooted' host\n", node_ptr->hostname.c_str()); + rc = FAIL_PATCHED_NOREBOOT ; + } + else + { + plog ("%s Action=%s\n", node_ptr->hostname.c_str(), + inv.action.c_str()); + if ( !inv.action.compare ( "force-swact" ) ) + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__FORCE_SWACT ); + else + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__SWACT ); + + /* generate command=swact log */ + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_SWACT ); + + smgrEvent.mutex = true ; + } + } + else if ( !inv.action.compare ( "reboot" ) ) + { + plog ("%s Reboot Action\n", node_ptr->hostname.c_str()); + node_ptr->resetProgStage = MTC_RESETPROG__START ; + node_ptr->retries = 0 ; + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_MANUAL_REBOOT ); + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__REBOOT ); + } + else if ( !inv.action.compare ( "reinstall" ) ) + { + plog ("%s Reinstall Action\n", node_ptr->hostname.c_str()); + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__REINSTALL ); + + /* generate command=reinstall log */ + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_REINSTALL ); + } + else if ( !inv.action.compare ( "reset" ) ) + { + string bm_ip = NONE ; + rc = FAIL_RESET_CONTROL ; + node_ptr->retries = 0 ; + plog ("%s Reset Action\n", node_ptr->hostname.c_str()); + + if ( hostUtil_is_valid_bm_type ( node_ptr->bm_type ) == false ) + { + wlog ("%s reset rejected due to unprovisioned bmc\n", + node_ptr->hostname.c_str()); + rc = FAIL_BM_PROVISION_ERR ; + } + else if ( node_ptr->availStatus == MTC_AVAIL_STATUS__POWERED_OFF ) + { + wlog ("%s reset rejected for powered off host\n", + node_ptr->hostname.c_str()); + rc = FAIL_RESET_POWEROFF; + } + else if ( node_ptr->bm_un.empty() ) + { + wlog ("%s reset rejected due to unconfigured 'bm_username'\n", + node_ptr->bm_un.c_str()); + rc = FAIL_BM_PROVISION_ERR ; + } + else + { + rc = PASS ; + node_ptr->resetStage = MTC_RESET__START ; + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__RESET ); + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_MANUAL_RESET ); + } + } + else if ( !inv.action.compare ( "power-on" ) ) + { + string bm_ip = NONE ; + rc = FAIL_POWER_CONTROL ; + + plog ("%s Power-On Action\n", node_ptr->hostname.c_str()); + + if ( hostUtil_is_valid_bm_type ( node_ptr->bm_type ) == false ) + { + wlog ("%s power-on rejected due to unprovisioned bmc\n", + node_ptr->hostname.c_str()); + rc = FAIL_BM_PROVISION_ERR ; + } + + else if ( node_ptr->bm_un.empty() ) + { + wlog ("%s power-on rejected due to unconfigured 'bm_username'\n", + node_ptr->hostname.c_str()); + rc = FAIL_BM_PROVISION_ERR ; + } + else + { + rc = PASS ; + node_ptr->powerStage = MTC_POWERON__START ; + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__POWERON ); + } + mtcInvApi_update_task ( node_ptr, "" ); + } + else if ( !inv.action.compare ( "power-off" ) ) + { + string bm_ip = NONE ; + rc = FAIL_POWER_CONTROL ; + plog ("%s Power-Off Action\n", node_ptr->hostname.c_str()); + + if ( hostUtil_is_valid_bm_type ( node_ptr->bm_type ) == false ) + { + wlog ("%s power-off rejected due to unprovisioned bmc\n", + node_ptr->hostname.c_str()); + rc = FAIL_BM_PROVISION_ERR ; + } + else if ( node_ptr->bm_un.empty() ) + { + wlog ("%s power-off rejected due to unconfigured 'bm_username'\n", + node_ptr->hostname.c_str()); + rc = FAIL_BM_PROVISION_ERR ; + } + else + { + if (( !hostUtil_is_valid_ip_addr ( node_ptr->bm_ip )) && + ( !hostUtil_is_valid_ip_addr ( bm_ip ))) + { + wlog ("%s power-off may fail ; 'bm_ip' is undiscovered\n", + node_ptr->hostname.c_str()); + } + rc = PASS ; + node_ptr->powerStage = MTC_POWEROFF__START ; + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__POWEROFF ); + } + mtcInvApi_update_task ( node_ptr, "" ); + } + else + { + wlog ("%s Unsupported action '%s'\n", + node_ptr->hostname.c_str(), + inv.action.c_str()); + rc = FAIL_ADMIN_ACTION ; + mtcInvApi_update_task ( node_ptr, "" ); + } + } + if ( node_ptr->uuid.compare ( inv.uuid ) ) + { + send_hwmon_command ( node_ptr->hostname, MTC_CMD_DEL_HOST ); + plog ("%s Modify 'uuid' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->uuid.c_str(), inv.uuid.c_str() ); + node_ptr->uuid = inv.uuid ; + send_hwmon_command ( node_ptr->hostname, MTC_CMD_ADD_HOST ); + modify = true ; /* we have a delta */ + } + if ( node_ptr->type.compare ( inv.type ) ) + { + plog ("%s Modify 'personality' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->type.c_str(), inv.type.c_str() ); + + node_ptr->type = inv.type ; + node_ptr->nodetype = get_host_function_mask ( inv.type ); + + modify = true ; /* we have a delta */ + } + if ( node_ptr->ip.compare ( inv.ip ) ) + { + plog ("%s Modify 'mgmt_ip' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->ip.c_str(), inv.ip.c_str()); + node_ptr->ip = inv.ip ; + + /* Tell the guestAgent the new IP */ + rc = send_guest_command(node_ptr->hostname,MTC_CMD_MOD_HOST); + + modify = true ; /* we have a delta */ + } + if ( node_ptr->mac.compare ( inv.mac ) ) + { + plog ("%s Modify 'mgmt_mac' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->mac.c_str(), inv.mac.c_str() ); + node_ptr->mac = inv.mac ; + + modify = true ; /* we have a delta */ + } + if ( node_ptr->infra_ip.compare ( inv.infra_ip ) ) + { + if (( hostUtil_is_valid_ip_addr ( inv.infra_ip )) || ( hostUtil_is_valid_ip_addr ( node_ptr->infra_ip ))) + { + plog ("%s Modify 'infra_ip' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->infra_ip.c_str(), inv.infra_ip.c_str() ); + + modify = true ; /* we have a delta */ + } + node_ptr->infra_ip = inv.infra_ip ; + } + if ( (!inv.name.empty()) && (node_ptr->hostname.compare ( inv.name)) ) + { + mtcCmd cmd ; + mtcCmd_init ( cmd ); + cmd.stage = MTC_CMD_STAGE__START ; + cmd.cmd = MTC_OPER__MODIFY_HOSTNAME ; + cmd.name = inv.name ; + node_ptr->mtcCmd_work_fifo.push_back(cmd); + plog ("%s Modify 'hostname' to %s (mtcCmd_queue:%ld)\n", + node_ptr->hostname.c_str(), + cmd.name.c_str() , + node_ptr->mtcCmd_work_fifo.size()); + + modify_bm = true ; /* board mgmnt change */ + modify = true ; /* we have some delta */ + } + if ( node_ptr->bm_un.compare ( inv.bm_un ) ) + { + if ( inv.bm_un.empty () ) + inv.bm_un = "none" ; + + plog ("%s Modify 'bm_username' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->bm_un.c_str(), inv.bm_un.c_str()); + + node_ptr->bm_un = inv.bm_un ; + + modify_bm = true ; /* board mgmnt change */ + modify = true ; /* we have some delta */ + } + + /* PATCHBACK - issue found during BMC refactoring user story + * where there was a race condition found where the bmc dnsmasq file + * was updated with a new bm_ip close to when there was an + * administrative operation (unlock in this case). The newly learned + * bm_ip was overwritten by the now stale bm_ip that came in from + * inventory. The bm_ip should never come from sysinv while in + * internal mode. */ + if (( node_ptr->bm_ip.compare ( inv.bm_ip ))) + { + if ( inv.bm_ip.empty () ) + inv.bm_ip = NONE ; + + /* if not empty and not none and already used then reject */ + if ( is_bm_ip_already_used ( inv.bm_ip ) == true ) + { + wlog ("%s cannot use already provisioned bm ip %s\n", + node_ptr->hostname.c_str(), + inv.bm_ip.c_str()); + return (FAIL_DUP_IPADDR); + } + plog ("%s Modify 'bm_ip' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->bm_ip.c_str(), inv.bm_ip.c_str()); + + node_ptr->bm_ip = inv.bm_ip ; + + modify_bm = true ; /* board mgmnt change */ + modify = true ; /* we have some delta */ + } + if ( node_ptr->bm_type.compare ( inv.bm_type ) ) + { + if ( inv.bm_type.empty() ) + inv.bm_type = "none" ; + else + inv.bm_type = tolowercase(inv.bm_type) ; + + plog ("%s Modify 'bm_type' from %s -> %s\n", + node_ptr->hostname.c_str(), + node_ptr->bm_type.c_str(), inv.bm_type.c_str()); + + modify_bm = true ; /* board mgmnt change */ + modify = true ; /* we have some delta */ + } + + /* print a log if we find that there was nothing to modify */ + if ( modify == false ) + { + wlog ("%s Modify request without anything to modify\n", node_ptr->hostname.c_str()); + } + if ( modify_bm == true ) + { + wlog ("%s Board Management provisioning has changed\n", node_ptr->hostname.c_str()); + bool bm_type_was_valid = hostUtil_is_valid_bm_type (node_ptr->bm_type) ; + bool bm_type_now_valid = hostUtil_is_valid_bm_type (inv.bm_type) ; + + /* update bm_type now */ + node_ptr->bm_type = inv.bm_type ; + + /* BM is provisioned */ + if ( bm_type_now_valid == true ) + { + /* force (re)provision */ + manage_bmc_provisioning ( node_ptr ); + } + + /* BM is already provisioned but is now deprovisioned */ + else if (( bm_type_was_valid == true ) && ( bm_type_now_valid == false )) + { + node_ptr->bm_type = NONE ; + node_ptr->bm_ip = NONE ; + node_ptr->bm_un = NONE ; + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_BM_DEPROVISIONED ); + set_bm_prov ( node_ptr, false ); + } + + /* BM was not provisioned and is still not provisioned */ + else + { + /* Handle all other provisioning changes ; username, ip address */ + manage_bmc_provisioning ( node_ptr ); + } + } + } + else + { + elog ("getNode failed to find uuid: %s\n", inv.uuid.c_str()); + } + + return ( rc ); +} + +void nodeLinkClass::start_offline_handler ( struct nodeLinkClass::node * node_ptr ) +{ + bool already_active = false ; + mtc_offlineStages_enum offlineStage_saved = node_ptr->offlineStage ; + + if ( node_ptr->offlineStage == MTC_OFFLINE__IDLE ) + { + node_ptr->offlineStage = MTC_OFFLINE__START ; + } + else + { + already_active = true ; + } + plog ("%s%soffline handler (%s-%s-%s) (stage:%d)\n", + node_ptr->hostname.c_str(), + already_active ? " " : " starting ", + adminState_enum_to_str(node_ptr->adminState).c_str(), + operState_enum_to_str(node_ptr->operState).c_str(), + availStatus_enum_to_str(node_ptr->availStatus).c_str(), + offlineStage_saved); +} + +void nodeLinkClass::stop_offline_handler ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr->offlineStage != MTC_OFFLINE__IDLE ) + { + plog ("%s stopping offline handler (%s-%s-%s) (stage:%d)\n", + node_ptr->hostname.c_str(), + adminState_enum_to_str(node_ptr->adminState).c_str(), + operState_enum_to_str(node_ptr->operState).c_str(), + availStatus_enum_to_str(node_ptr->availStatus).c_str(), + node_ptr->offlineStage); + node_ptr->offlineStage = MTC_OFFLINE__IDLE ; + } +} + +string nodeLinkClass::get_host ( string uuid ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( uuid ); + if ( node_ptr != NULL ) + { + return (node_ptr->hostname) ; + } + return ( "" ); +} + +/** Check to see if the node list already contains any of the following + * information and reject the add or modify if it does + * + * uuid + * hostname + * ip address + * mac address + * + **/ +int nodeLinkClass::add_host_precheck ( node_inv_type & inv ) +{ + struct node * ptr = static_cast(NULL) ; + struct node * node_ptr = static_cast(NULL) ; + int rc = PASS ; + + if ( head == NULL ) + return (PASS); + + for ( node_ptr = head ; ; node_ptr = node_ptr->next ) + { + /* look or the UUID */ + if ( !node_ptr->uuid.compare(inv.uuid)) + { + rc = RETRY ; + dlog ("%s found in mtce\n", node_ptr->uuid.c_str()); + break ; + } + else if (( node_ptr->next == NULL ) || ( node_ptr == tail )) + break ; + } + + /** If that uuid is not found then make sure there + * are no other entries in the list that already + * has the same info that we want to create a + * new host with. + * If so then reject by returning a failure. + */ + for ( ptr = head ; ; ptr = ptr->next ) + { + /* if this uuid is found then see if we are being + * asked to modify and make sure that we are not being + * asked to modify other members to values that are + * used by other hosts + * If so then reject by returning a failure. + * otherwise then allow the modification by returning a retry. + */ + + if (( rc == RETRY ) && ( ptr == node_ptr )) + { + dlog ("%s skip\n", ptr->hostname.c_str()); + /* skip the node we found the UUID on + * but make sure that none of the other nodes + * have the same data */ + } + else + { + dlog ("%s check\n", ptr->hostname.c_str()); + + if ( !ptr->hostname.compare(inv.name)) + { + wlog ("hostname (%s) already used ; rejecting add / modify\n", inv.name.c_str()); + return(FAIL_DUP_HOSTNAME); + } + if ( ptr->ip.compare("none") != 0 && !ptr->ip.compare(inv.ip)) + { + wlog ("ip address (%s) already used ; rejecting add / modify\n", inv.ip.c_str()); + return(FAIL_DUP_IPADDR); + } + if ( !ptr->mac.compare(inv.mac)) + { + wlog ("mac address (%s) already used ; rejecting add / modify\n", inv.mac.c_str()); + return(FAIL_DUP_MACADDR); + } + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return (rc); +} + +int nodeLinkClass::add_host ( node_inv_type & inv ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = static_cast(NULL); + + if ((!inv.name.compare("controller-0")) || + (!inv.name.compare("controller-1"))) + { + dlog ("Adding %s\n", inv.name.c_str()); + node_ptr = nodeLinkClass::getNode(inv.name); + } + else if (( inv.name.empty()) || + ( !inv.name.compare ("none") ) || + ( !inv.name.compare ("None") )) + { + wlog ("Refusing to add host with 'null' or 'invalid' hostname (%s)\n", + inv.uuid.c_str()); + return (FAIL_INVALID_HOSTNAME) ; + } + else if (( inv.uuid.empty()) || + ( !inv.uuid.compare ("none") ) || + ( !inv.uuid.compare ("None") )) + { + wlog ("Refusing to add host with 'null' or 'invalid' uuid (%s)\n", + inv.uuid.c_str()); + return (FAIL_INVALID_UUID) ; + } + + /* Ensure we don't add a host with critical info that is + * already used by other members of inventory like ; + * hostname, uuid, ip, mac, bm_ip */ + else if ( ( rc = add_host_precheck ( inv )) > RETRY ) + { + return (rc); + } + else + { + if ( rc == RETRY ) + { + dlog ("%s modify operation\n", inv.uuid.c_str()); + } + else + { + dlog ("%s add operation\n", inv.uuid.c_str()); + } + node_ptr = nodeLinkClass::getNode(inv.uuid); + } + + if ( node_ptr ) + { + dlog ("%s Already provisioned\n", node_ptr->hostname.c_str()); + + /* update some of the info */ + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } + + /* Send back a retry so that this add is converted to a modify */ + return (RETRY); + } + /* Otherwise add it as a new node */ + else + { + if ( daemon_get_cfg_ptr()->debug_level != 0 ) + print_inv ( inv ); + + unsigned int nodetype_temp = get_host_function_mask ( inv.type ); + if ( (nodetype_temp & CONTROLLER_TYPE) == CONTROLLER_TYPE ) + { + if ( inactive_controller_hostname.empty () == false ) + { + wlog ("Cannot provision more than 2 controllers\n"); + wlog ("%s is already provisioned as inactive\n", + inactive_controller_hostname.c_str()); + return (FAIL); + } + } + + /* Prevent allowing add of a reserved hostname + * with and incorrect node type. Reserved names are + * + * controller-0 and controller-1 must be a controller type + * storage-0 must be a storage type + * + * */ + + if ((( !inv.name.compare ("controller-0")) && (( nodetype_temp & CONTROLLER_TYPE) != CONTROLLER_TYPE )) || + (( !inv.name.compare ("controller-1")) && (( nodetype_temp & CONTROLLER_TYPE ) != CONTROLLER_TYPE)) || + (( !inv.name.compare ("storage-0" )) && (( nodetype_temp & STORAGE_TYPE) != STORAGE_TYPE))) + { + wlog ("Cannot provision '%s' as a '%s' host\n", inv.name.c_str(), inv.type.c_str()); + return (FAIL_RESERVED_NAME); + } + node_ptr = nodeLinkClass::addNode(inv.name); + if ( node_ptr ) + { + bool validStates = false ; + node_ptr->hostname = inv.name ; + + /* set the node type ; string and define code */ + node_ptr->type = inv.type ; + node_ptr->nodetype = get_host_function_mask ( inv.type ) ; + + update_host_functions ( inv.name, inv.func ); + + node_ptr->ip = inv.ip ; + node_ptr->mac = inv.mac ; + node_ptr->uuid = inv.uuid ; + node_ptr->infra_ip = inv.infra_ip ; + + if ( inv.uptime.length() ) + { + sscanf ( inv.uptime.data(), "%u", &node_ptr->uptime ); + dlog2 ("%s Uptime (%s:%u)\n", inv.name.c_str(), inv.uptime.c_str(), node_ptr->uptime ); + } + else + { + node_ptr->uptime = 0 ; + } + + node_ptr->thread_extra_info.bm_ip = node_ptr->bm_ip = inv.bm_ip ; + node_ptr->thread_extra_info.bm_un = node_ptr->bm_un = inv.bm_un ; + node_ptr->thread_extra_info.bm_type= node_ptr->bm_type = inv.bm_type ; + + node_ptr->bm_ping_info.sock = 0 ; + + /* initialize the host power and reset control thread */ + thread_init ( node_ptr->ipmitool_thread_ctrl, + node_ptr->ipmitool_thread_info, + &node_ptr->thread_extra_info, + mtcThread_ipmitool, + DEFAULT_THREAD_TIMEOUT_SECS, + node_ptr->hostname, + THREAD_NAME__IPMITOOL); + + if ( adminStateOk (inv.admin) && + operStateOk (inv.oper ) && + availStatusOk (inv.avail)) + { + validStates = true ; + } + + clog ("%s subf state %s-%s\n", node_ptr->hostname.c_str(), inv.oper_subf.c_str(), inv.avail_subf.c_str() ); + + node_ptr->task = inv.task ; + + /* Add based on 'action' */ + if ((!inv.action.empty()) && (inv.action.compare ("none"))) + { + /* Save current action */ + node_ptr->action = inv.action ; + + if ( !inv.action.compare ("unlock") && validStates ) + { + ilog ("%s Added in 'unlocked' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__UNLOCK ); + } + else if ( !inv.action.compare ("lock") && validStates ) + { + ilog ("%s Added in 'locked' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } + + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__LOCK ); + } + else if ( !inv.action.compare ("force-lock") && validStates ) + { + ilog ("%s Added in 'force-locked' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } + + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__FORCE_LOCK ); + } + else if ( !inv.action.compare ("reboot") && validStates ) + { + ilog ("%s Added with 'reboot' in 'locked' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } +; + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__REBOOT ); + } + else if ( !inv.action.compare ("reset") && validStates ) + { + ilog ("%s Added with 'reset' in 'locked' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } + + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__RESET ); + } + else if ( !inv.action.compare ("power-off") && validStates ) + { + ilog ("%s Added in a 'locked' and 'power-off' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = MTC_ADMIN_STATE__LOCKED ; + node_ptr->operState = MTC_OPER_STATE__DISABLED; + node_ptr->availStatus = MTC_AVAIL_STATUS__POWERED_OFF ; + + node_ptr->operState_subf = MTC_OPER_STATE__DISABLED ; + node_ptr->availStatus_subf = MTC_AVAIL_STATUS__POWERED_OFF ; + + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__POWEROFF ); + } + else if ( !inv.action.compare ("power-on") && validStates ) + { + ilog ("%s Added with 'power-on' in 'locked' state\n", node_ptr->hostname.c_str()); + + print_inv ( inv ); + + node_ptr->adminState = MTC_ADMIN_STATE__LOCKED ; + node_ptr->operState = MTC_OPER_STATE__DISABLED; + node_ptr->availStatus = MTC_AVAIL_STATUS__OFFLINE ; + + node_ptr->operState_subf = MTC_OPER_STATE__DISABLED ; + node_ptr->availStatus_subf = MTC_AVAIL_STATUS__OFFLINE ; + + node_ptr->onlineStage = MTC_ONLINE__START ; + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__POWERON ); + } + else + { + wlog ("%s Need add Action support for '%s' action\n", node_ptr->hostname.c_str(), + inv.action.c_str()); + + print_inv ( inv ); + + /* Load in maintenance states */ + node_ptr->adminState = MTC_ADMIN_STATE__LOCKED ; + node_ptr->operState = MTC_OPER_STATE__DISABLED ; + node_ptr->availStatus = MTC_AVAIL_STATUS__OFFLINE ; + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = MTC_OPER_STATE__DISABLED ; + node_ptr->availStatus_subf = MTC_AVAIL_STATUS__OFFLINE ; + } + + node_ptr->onlineStage = MTC_ONLINE__START ; + + wlog ("%s Need '%s' action enabled here\n", node_ptr->hostname.c_str(), + inv.action.c_str()); + } + } + else + { + node_ptr->adminState = adminState_str_to_enum (inv.admin.data()); + node_ptr->operState = operState_str_to_enum (inv.oper.data ()); + node_ptr->availStatus = availStatus_str_to_enum (inv.avail.data()); + + if ( CPE_SYSTEM ) + { + node_ptr->operState_subf = operState_str_to_enum (inv.oper_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum (inv.avail_subf.data()); + } + } + + /* Clear the heartbeat failure conts for this host */ + for ( int iface = 0 ; iface < MAX_IFACES ; iface++ ) + { + node_ptr->hbs_degrade_count[iface] = 0; + node_ptr->hbs_failure_count[iface] = 0; + } + + /* Add to the end of inventory */ + hostname_inventory.push_back ( node_ptr->hostname ); + rc = PASS ; + } + } + + if (( rc == PASS ) && ( node_ptr )) + { + node_ptr->addStage = MTC_ADD__START ; + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__ADD ); + } + return (rc); +} + +void nodeLinkClass::clear_service_readies ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr ) + { + if ( node_ptr->hbsClient_ready || node_ptr->pmond_ready ) + { + ilog ("%s clearing service ready events\n", node_ptr->hostname.c_str()); + node_ptr->hbsClient_ready = false ; + node_ptr->pmond_ready = false ; + } + } +} + +/* Used by the heartbeat service to add a host to its list */ +int nodeLinkClass::add_heartbeat_host ( const node_inv_type & inv ) +{ + int rc = FAIL ; + struct nodeLinkClass::node * node_ptr = static_cast(NULL); + + dlog ("%s with nodetype %u\n", inv.name.c_str(), inv.nodetype ); + + /* no hostname - no add ! */ + if ( inv.name.length() ) + { + /* Handle the case where we are adding a node that is already */ + /* present if so just update the inventory data not the mtc state */ + node_ptr = nodeLinkClass::getNode(inv.name); + if ( node_ptr ) + { + dlog ("%s already provisioned\n", node_ptr->hostname.c_str()); + rc = RETRY ; + } + /* Otherwise add it as a new node */ + else + { + node_ptr = nodeLinkClass::addNode(inv.name); + if ( node_ptr != NULL ) + { + node_ptr->hostname = inv.name ; + node_ptr->nodetype = inv.nodetype ; + dlog ("%s added to linked list\n", inv.name.c_str()); + rc = PASS ; + } + else + { + elog ("Failed to addNode %s to heartbeat service\n", inv.name.c_str()); + } + } + } + return (rc); +} + +string nodeLinkClass::get_uuid ( string hostname ) +{ + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode(hostname); + if ( node_ptr ) + { + return (node_ptr->uuid); + } + else + { + return (""); + } +} + +void nodeLinkClass::set_uuid ( string hostname, string uuid ) +{ + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode(hostname); + if ( node_ptr ) + { + node_ptr->uuid = uuid ; + } +} + +/* Set the task field in the maintenance class object for the specified host */ +void nodeLinkClass::set_task ( string hostname, string task ) +{ + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode(hostname); + if ( node_ptr ) + { + node_ptr->task = task ; + } +} + +/* Lock Rules + * + * 1. Cannot lock this controller + * 2. Cannot lock inactive controller if storage-0 is locked + * 3. Cannot lock storage node with monitor if inactive conroller is locked or not present + * 4. Cannot lock last storage host. + */ +bool nodeLinkClass::can_uuid_be_locked ( string uuid , int & reason ) +{ + struct nodeLinkClass::node * node_ptr = nodeLinkClass::getNode(uuid); + if ( node_ptr ) + { + dlog1 ("%s Lock permission query\n", node_ptr->hostname.c_str()); + + /* Allow lock of already locked 'any' host */ + if ( node_ptr->adminState == MTC_ADMIN_STATE__LOCKED ) + { + ilog ("%s is already 'locked'\n", node_ptr->hostname.c_str()); + return (true); + } + else if ( node_ptr->operState == MTC_OPER_STATE__DISABLED ) + { + ilog ("%s allowing lock of 'disabled' host\n", node_ptr->hostname.c_str() ); + return (true); + } + else if (is_controller(node_ptr)) + { + /* Rule 1 - Cannot lock active controller */ + if ( THIS_HOST ) + { + elog ("%s Cannot be 'locked' - controller is 'active'\n", node_ptr->hostname.c_str()); + reason = FAIL_UNIT_ACTIVE ; + return (false); + } + /* Rule 2 - Cannot lock inactive controller if the floating storage + * ceph monitor is locked */ + if (( get_storage_backend() == CGCS_STORAGE_CEPH ) && + ( is_storage_mon_enabled () == false )) + { + wlog ("%s cannot be 'locked' - failed storage redundancy check\n", node_ptr->hostname.c_str()); + reason = FAIL_NEED_STORAGE_MON ; + return (false); + } + ilog ("%s can be locked\n", node_ptr->hostname.c_str()); + return (true); + } + else if ( is_compute(node_ptr) ) + { + if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + dlog ("%s is 'unlocked' and can be 'locked'\n", node_ptr->hostname.c_str()); + } + return (true); + } + /* Deal with lock of storage cases - Rules 3 and 4 */ + else if ( is_storage(node_ptr) ) + { + /* Only need to semantic check if this host is unlocked-enabled */ + if ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) + { + /* Both active controllers path ... */ + if ( num_controllers_enabled () >= 2 ) + { + /* If we are locking storage-0 make sure that there + * is another enabled storage node */ + if ( !node_ptr->hostname.compare("storage-0") ) + { + /* We already know that this storage node is enabled so + * we need to see a count greated than 1 */ + if ( enabled_storage_nodes () > 1 ) + { + /* We have 2 enabled controllers and 2 enabled + * storage nodes so we can allow lock of storage-0 */ + ilog ("%s can be locked - there is storage redundancy\n", + node_ptr->hostname.c_str()); + return (true); + } + /* Rule 4 - Cannot lock last storage node */ + else + { + wlog ("%s cannot be locked - no storage redundancy\n", + node_ptr->hostname.c_str()); + reason = FAIL_LOW_STORAGE ; + return (false); + } + } + /* O.K. we are trying to lock a storage host tha is not + * the floating storage monitor */ + else if (( is_storage_mon_enabled () == true ) && + ( enabled_storage_nodes() > 1 )) + { + /* We have - 2 enabled controllers + * - the storage mon is enabled and + * - is not this one. */ + ilog ("%s can be locked - there is storage redundancy\n", + node_ptr->hostname.c_str()); + return (true); + } + /* Rule 4 - Cannot lock last storage node */ + else if (enabled_storage_nodes() <= 1) + { + wlog ("%s cannot be locked - no storage redundancy\n", + node_ptr->hostname.c_str()); + reason = FAIL_LOW_STORAGE ; + return (false); + } + else + { + /* Other redundancy checks here and in SysInv have passed. */ + ilog ("%s can be locked - storage redundancy filters passed.\n", + node_ptr->hostname.c_str()); + return (true); + } + } + + /* Rule 3 - Cannot lock storage node with monitor if inactive + * controller is locked or not present and there is + * not another storage node enabled */ + else + { + /* Cannot lock storage-0 if there is only a single enabled controller */ + if ( !node_ptr->hostname.compare("storage-0") ) + { + wlog ("%s cannot be locked - simplex system\n", + node_ptr->hostname.c_str()); + reason = FAIL_NEED_STORAGE_MON ; + return (false); + } + /* Only allow locking of a storage node if there is another in service */ + else if (( is_storage_mon_enabled () == true ) && + ( enabled_storage_nodes() > 1 )) + { + ilog ("%s can be locked - there is storage redundancy\n", + node_ptr->hostname.c_str()); + return (true); + } + /* Rule 4 - Cannot lock last storage node */ + else + { + wlog ("%s cannot be locked - no redundancy\n", + node_ptr->hostname.c_str()); + reason = FAIL_LOW_STORAGE ; + return (false); + } + } + } + else + { + ilog ("%s allowing lock of disabled storage host\n", + node_ptr->hostname.c_str()); + return (true); + } + } + else + { + elog ("%s unsupported nodetype (%u)\n", + node_ptr->hostname.c_str(), + node_ptr->nodetype); + return (false); + } + } + else + { + dlog ("Unknown uuid: %s\n", uuid.c_str()); + + /* allowing lock as a means to clear up error */ + return (true); + } +} + +int nodeLinkClass::rem_host ( string & hostname ) +{ + int rc = FAIL ; + if ( ! hostname.empty() ) + { + hostname_inventory.remove ( hostname ); + rc = nodeLinkClass::remNode ( hostname ); + } + return ( rc ); +} + +void nodeLinkClass::set_my_hostname ( string hostname ) +{ + struct nodeLinkClass::node * node_ptr ; + + nodeLinkClass::my_hostname = hostname ; + + /* set it in the local inventory as well */ + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->hostname = hostname ; + } +} + + +string nodeLinkClass::get_my_hostname ( void ) +{ + return( nodeLinkClass::my_hostname ); +} + +void nodeLinkClass::set_my_local_ip ( string & ip ) +{ + nodeLinkClass::node* node_ptr ; + + nodeLinkClass::my_local_ip = ip ; + + /* set it in the local inventory as well */ + node_ptr = nodeLinkClass::getNode ( my_hostname ); + if ( node_ptr != NULL ) + { + node_ptr->ip = ip ; + } +} + +string nodeLinkClass::get_my_local_ip ( void ) +{ + return( nodeLinkClass::my_local_ip ); +} + +void nodeLinkClass::set_my_float_ip ( string & ip ) +{ + nodeLinkClass::my_float_ip = ip ; +} + +string nodeLinkClass::get_my_float_ip ( void ) +{ + return( nodeLinkClass::my_float_ip ); +} + +static string null_str = "" ; +string nodeLinkClass::get_hostaddr ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->ip ); + } + return ( null_str ); +} + +string nodeLinkClass::get_infra_hostaddr ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->infra_ip ); + } + return ( null_str ); +} + +string nodeLinkClass::get_hostIfaceMac ( string & hostname, int iface ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + if ( iface == MGMNT_IFACE ) + return ( node_ptr->mac ); + if ( iface == INFRA_IFACE ) + return ( node_ptr->infra_mac ); + } + ilog ("%s has unknown mac address for %s interface\n", hostname.c_str(), get_iface_name_str(iface)); + return ( null_str ); +} + +int nodeLinkClass::set_hostaddr ( string & hostname, string & ip ) +{ + int rc = FAIL ; + + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->ip = ip ; + rc = PASS ; + } + return ( rc ); +} + +int nodeLinkClass::set_infra_hostaddr ( string & hostname, string & ip ) +{ + int rc = FAIL ; + + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->infra_ip = ip ; + rc = PASS ; + } + return ( rc ); +} + +string nodeLinkClass::get_hostname ( string & hostaddr ) +{ + if (( hostaddr == LOOPBACK_IPV6 ) || + ( hostaddr == LOOPBACK_IP ) || + ( hostaddr == LOCALHOST )) + { + return(my_hostname); + } + else + { + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostaddr ); + if ( node_ptr != NULL ) + { + return ( node_ptr->hostname ); + } + return ( null_str ); + } +} + +string nodeLinkClass::get_hostname_from_bm_ip ( string bm_ip ) +{ + if ( head ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ! ptr->bm_ip.compare(bm_ip) ) + { + return ( ptr->hostname ); + } + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return ("") ; +} + +int nodeLinkClass::num_hosts ( void ) +{ + return ( nodeLinkClass::hosts ) ; +} + +void nodeLinkClass::set_cmd_resp ( string & hostname, mtc_message_type & msg ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + if ( is_host_services_cmd ( msg.cmd ) ) + { + /***************************************************** + * Host Services Request's Response Handling + *****************************************************/ + node_ptr->host_services_req.status = msg.parm[0] ; + if ( msg.cmd == node_ptr->host_services_req.cmd ) + { + // print_mtc_message ( &msg, true ); + + /* if num > 1 then expect a host services result message */ + if ( msg.cmd == MTC_CMD_HOST_SVCS_RESULT ) + { + if ( !node_ptr->host_services_req.ack ) + { + slog ("%s %s without initial command ACK\n", + hostname.c_str(), + node_ptr->host_services_req.name.c_str()); + } + node_ptr->host_services_req.rsp = msg.cmd ; + if ( msg.buf[0] != '\0' ) + { + node_ptr->host_services_req.status_string = msg.buf ; + } + } + + /* Check to see if the start/stop host services command + * response demonstrates support for the enhanced host + * services extension. */ + else if (( msg.num > 1 ) && ( msg.parm[1] == MTC_ENHANCED_HOST_SERVICES )) + { + dlog ("%s %s request ack\n", + hostname.c_str(), + node_ptr->host_services_req.name.c_str()); + node_ptr->host_services_req.ack = true ; + } + else + { + ilog ("%s %s request ack (legacy mode)\n", + hostname.c_str(), + node_ptr->host_services_req.name.c_str()); + /* support legacy client by copying the cmd to cmdRsp */ + node_ptr->host_services_req.status = PASS ; + node_ptr->host_services_req.rsp = msg.cmd ; + node_ptr->host_services_req.ack = MTC_CMD_NONE ; + } + } + + if ( msg.num && ( node_ptr->host_services_req.status != PASS )) + { + dlog ("%s %s command failed (rc:%d) [%s]\n", + hostname.c_str(), + get_mtcNodeCommand_str(msg.cmd), + node_ptr->host_services_req.status, + node_ptr->host_services_req.status_string.empty() ? + "no error string" : node_ptr->host_services_req.status_string.c_str()); + } + } + else + { + node_ptr->cmdRsp = msg.cmd ; + if ( msg.num > 0 ) + node_ptr->cmdRsp_status = msg.parm[0] ; + else + node_ptr->cmdRsp_status = -1 ; + + dlog ("%s '%s' command response status [%u:%s]\n", + hostname.c_str(), + node_ptr->cmdName.c_str(), + msg.num ? node_ptr->cmdRsp_status : PASS, + node_ptr->cmdRsp_status_string.empty() ? "empty" : node_ptr->cmdRsp_status_string.c_str()); + } + } +} + +unsigned int nodeLinkClass::get_cmd_resp ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->cmdRsp ) ; + } + return (-1); +} + +mtc_client_enum nodeLinkClass::get_activeClient ( string hostname ) +{ + nodeLinkClass::node* node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->activeClient ) ; + } + else + { + slog ("Host lookup failed for '%s'\n", hostname.c_str()); + } + return (CLIENT_NONE); +} + +int nodeLinkClass::set_activeClient ( string hostname, mtc_client_enum client ) +{ + nodeLinkClass::node* node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->activeClient = client ; + return (PASS); + } + else + { + slog ("Host lookup failed for '%s'\n", hostname.c_str()); + } + return (FAIL_HOSTNAME_LOOKUP); +} + +/***************************************************************************** + * + * Name : set_mtcAlive + * + * Description: + * + * If mtcAlive is ungated then + * + * 1. manage the online/offline state bools + * 2. increment the mtcAlive count and + * 3. set the mtcAlive received bool for the specified interface + * + *****************************************************************************/ +void nodeLinkClass::set_mtcAlive ( string & hostname, int interface ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + if ( node_ptr->mtcAlive_gate == false ) + { + node_ptr->mtcAlive_online = true ; + node_ptr->mtcAlive_offline = false ; + node_ptr->mtcAlive_count++ ; + + if ( interface == INFRA_INTERFACE ) + { + node_ptr->mtcAlive_infra = true ; + } + else + { + node_ptr->mtcAlive_mgmnt = true ; + } + } + } +} + +bool nodeLinkClass::get_mtcAlive_gate ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->mtcAlive_gate ) ; + } + /* If we can't find the node then gate off the alive messages */ + return (true); +} + +void nodeLinkClass::ctl_mtcAlive_gate ( string & hostname, bool gated ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->mtcAlive_gate = gated ; + if ( gated == true ) + { + alog ("%s mtcAlive gated\n", node_ptr->hostname.c_str()); + } + else + { + alog ("%s mtcAlive ungated\n", node_ptr->hostname.c_str()); + } + } +} + +/* Main-Function Go Enabled member Functions */ + +void nodeLinkClass::set_goEnabled ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->goEnabled = true ; + } +} + +bool nodeLinkClass::get_goEnabled ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->goEnabled ) ; + } + return (false); +} + +void nodeLinkClass::set_goEnabled_failed ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->goEnabled_failed = true ; + } +} + +/* Sub-Function Go Enabled Member Functions */ + +void nodeLinkClass::set_goEnabled_subf ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->goEnabled_subf = true ; + } +} + +bool nodeLinkClass::get_goEnabled_subf ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->goEnabled_subf ) ; + } + return (false); +} + +void nodeLinkClass::set_goEnabled_failed_subf ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->goEnabled_failed_subf = true ; + } +} + +/* Set and Get Uptime Member Function */ + +void nodeLinkClass::set_uptime ( struct nodeLinkClass::node * node_ptr, unsigned int uptime, bool force ) +{ + if ( node_ptr != NULL ) + { + /* Force the uptime into the database if + * - passed in value is 0 and current value is !0 + * - passed in value is !0 and current value is 0 + * - if ther force option is used + * Otherwise allow the audit to push time to the database + */ + if ((force == true ) || + (( uptime != 0 ) && ( node_ptr->uptime == 0 )) || + (( node_ptr->uptime != 0 ) && ( uptime == 0 ))) + { + mtcInvApi_update_uptime ( node_ptr, uptime ); + } + node_ptr->uptime = uptime ; + } +} + +void nodeLinkClass::set_uptime ( string & hostname, unsigned int uptime, bool force ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + set_uptime ( node_ptr, uptime, force ); +} + + +unsigned int nodeLinkClass::get_uptime ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->uptime ) ; + } + return (0); +} + +void nodeLinkClass::set_uptime_refresh_ctr ( string & hostname, int value ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->uptime_refresh_counter = value ; + } +} + + +int nodeLinkClass::get_uptime_refresh_ctr ( string & hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->uptime_refresh_counter ) ; + } + return (0); +} + +void nodeLinkClass::set_mtce_flags ( string hostname, int flags ) +{ + nodeLinkClass::node* node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + /* Deal with host level */ + node_ptr->mtce_flags = flags ; + if ( flags & MTC_FLAG__MAIN_GOENABLED ) + node_ptr->goEnabled = true ; + else + node_ptr->goEnabled = false ; + + /* Track host patching state by Out-Of-Band flag */ + if ( flags & MTC_FLAG__PATCHING ) + { + if ( node_ptr->patching == false ) + { + plog ("%s software patching has begun\n", node_ptr->hostname.c_str()); + } + node_ptr->patching = true ; + } + else + { + if ( node_ptr->patching == true ) + { + plog ("%s software patching done\n", node_ptr->hostname.c_str()); + } + node_ptr->patching = false ; + } + + /* Track host patched state by Out-Of-Band flag. + * This flag is set when the host is patched but not reset */ + if ( flags & MTC_FLAG__PATCHED ) + { + if ( node_ptr->patched == false ) + { + plog ("%s software patched\n", node_ptr->hostname.c_str()); + } + node_ptr->patched = true ; + } + else + { + if ( node_ptr->patched == true ) + { + plog ("%s software patch is applied\n", node_ptr->hostname.c_str()); + } + node_ptr->patched = false ; + } + + + /* Deal with sub-function if combo host */ + if ( CPE_SYSTEM ) + { + if ( flags & MTC_FLAG__SUBF_GOENABLED ) + { + if ( node_ptr->operState_subf == MTC_OPER_STATE__ENABLED ) + { + node_ptr->goEnabled_subf = true ; + } + } + else + { + node_ptr->goEnabled_subf = false ; + } + } + } +} + +void nodeLinkClass::set_health ( string & hostname, int health ) +{ + switch ( health ) + { + case NODE_HEALTH_UNKNOWN: + case NODE_HEALTHY: + case NODE_UNHEALTHY: + { + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + if ( health == NODE_UNHEALTHY ) + { + if ( node_ptr->health != NODE_UNHEALTHY ) + { + if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + wlog ("%s Health State Change -> UNHEALTHY\n", hostname.c_str()); + } + } + } + node_ptr->health = health ; + } + break ; + } + default: + { + wlog ("%s Unexpected health code (%d), defaulting to (unknown)\n", hostname.c_str(), health ); + break ; + } + } +} + +/************************************************************************************* + * + * Name : manage_bmc_provisioning + * + * Description: This utility manages a change in bmc provisioning for + * bm region EXTERNAL mode. Creates provisioning logs and + * sends START and STOP monitoring commands to the hardware monitor. + * + * Warning : Should only be called when there is a change to BM provisioning. + * as it will first always first disable provisioning and then + * decides whether it needs to be re-enabled or not. + * + *************************************************************************************/ + +int nodeLinkClass::manage_bmc_provisioning ( struct node * node_ptr ) +{ + int rc = PASS ; + + bool was_provisioned = node_ptr->bm_provisioned ; + + set_bm_prov ( node_ptr, false); + if ((hostUtil_is_valid_ip_addr ( node_ptr->bm_ip )) && + (!node_ptr->bm_un.empty())) + { + if ( was_provisioned == true ) + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_BM_REPROVISIONED ); + } + else + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_BM_PROVISIONED ); + } + + set_bm_prov ( node_ptr, true ); + } + else if ( was_provisioned == true ) + { + send_hwmon_command(node_ptr->hostname,MTC_CMD_STOP_HOST); + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_BM_DEPROVISIONED ); + } + + /* Send hmond updated bm info */ + ilog ("%s sending board management info update to hwmond\n", node_ptr->hostname.c_str() ); + if ( ( rc = send_hwmon_command(node_ptr->hostname,MTC_CMD_MOD_HOST) ) == PASS ) + { + if ( node_ptr->bm_provisioned == true ) + { + rc = send_hwmon_command(node_ptr->hostname,MTC_CMD_START_HOST); + } + else + { + rc = send_hwmon_command(node_ptr->hostname,MTC_CMD_STOP_HOST); + } + if ( rc ) + { + wlog ("%s failed to send START or STOP command to hwmond\n", node_ptr->hostname.c_str()); + } + } + else + { + wlog ("%s failed to send MODIFY command to hwmond\n", node_ptr->hostname.c_str()); + } + return (rc); +} + +bool nodeLinkClass::is_bm_ip_already_used ( string bm_ip ) +{ + if ( hostUtil_is_valid_ip_addr ( bm_ip ) == true ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( !bm_ip.compare(ptr->bm_ip) ) + { + return (true); + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return (false); +} + +int nodeLinkClass::set_bm_type ( string hostname , string bm_type ) +{ + int rc = FAIL_HOSTNAME_LOOKUP ; + + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->bm_type = bm_type ; + dlog ("%s '%s' updated to '%s'\n", + hostname.c_str(), + MTC_JSON_INV_BMTYPE, + node_ptr->bm_type.c_str()); + rc = PASS ; + } + return (rc); +} + +int nodeLinkClass::set_bm_un ( string hostname , string bm_un ) +{ + int rc = FAIL_HOSTNAME_LOOKUP ; + + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + if ( bm_un.length() ) + { + node_ptr->bm_un = bm_un ; + } + else + { + node_ptr->bm_un = NONE ; + } + dlog ("%s '%s' updated to '%s'\n", + hostname.c_str(), + MTC_JSON_INV_BMUN, + node_ptr->bm_un.c_str()); + rc = PASS ; + } + return (rc); +} + +int nodeLinkClass::set_bm_ip ( string hostname , string bm_ip ) +{ + int rc = FAIL_HOSTNAME_LOOKUP ; + + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->bm_ip = bm_ip ; + + dlog ("%s '%s' updated to '%s'\n", + hostname.c_str(), + MTC_JSON_INV_BMIP, + node_ptr->bm_ip.c_str()); + rc = PASS ; + } + return (rc); +} + +void nodeLinkClass::bmc_access_data_init ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr ) + { + node_ptr->bm_accessible = false; + node_ptr->mc_info_query_active = false ; + node_ptr->mc_info_query_done = false ; + node_ptr->reset_cause_query_active = false ; + node_ptr->reset_cause_query_done = false ; + node_ptr->power_status_query_active = false; + node_ptr->power_status_query_done = false ; + } +} + +/***************************************************************************** + * + * Name : set_bm_prov + * + * Description: Manage the local provisioning state of the + * board management connection. + * + * Assumptions: Does not set HTTP requests to sysinv so it is + * safe to call from thje modify handler + * + * Does not clear alarms. + * + ******************************************************************************/ +int nodeLinkClass::set_bm_prov ( struct nodeLinkClass::node * node_ptr, bool state ) +{ + int rc = FAIL_HOSTNAME_LOOKUP ; + if ( node_ptr != NULL ) + { + ilog ("%s bmc %sprovision request (provisioned:%s)\n", // ERIC blog + node_ptr->hostname.c_str(), + state ? "" : "de", + node_ptr->bm_provisioned ? "Yes" : "No" ); + + /* Clear the alarm if we are starting fresh from an unprovisioned state */ + if (( node_ptr->bm_provisioned == false ) && ( state == true )) + { + /* BMC is managed by IPMI/IPMITOOL */ + ilog ("%s starting BM ping monitor to address '%s'\n", + node_ptr->hostname.c_str(), + node_ptr->bm_ip.c_str()); + + // mtcTimer_reset ( node_ptr->bm_ping_info.timer ); + node_ptr->bm_ping_info.ip = node_ptr->bm_ip ; + node_ptr->bm_ping_info.stage = PINGUTIL_MONITOR_STAGE__OPEN ; + bmc_access_data_init ( node_ptr ); + node_ptr->bm_ping_info.timer_handler = &mtcTimer_handler ; + + node_ptr->thread_extra_info.bm_pw = + node_ptr->bm_pw = + get_bm_password (node_ptr->uuid.data()); + + node_ptr->thread_extra_info.bm_ip = node_ptr->bm_ip ; + node_ptr->thread_extra_info.bm_un = node_ptr->bm_un ; + + send_hwmon_command(node_ptr->hostname, MTC_CMD_ADD_HOST); + send_hwmon_command(node_ptr->hostname, MTC_CMD_START_HOST); + } + + /* handle the case going from provisioned to not provisioned */ + else if (( node_ptr->bm_provisioned == true ) && ( state == false )) + { + /* BMC is managed by IPMI/IPMITOOL */ + ilog ("%s deprovisioning bmc ; accessible:%s\n", + node_ptr->hostname.c_str(), + node_ptr->bm_accessible ? "Yes" : "No" ); + + pingUtil_fini ( node_ptr->bm_ping_info ); + bmc_access_data_init ( node_ptr ); + node_ptr->bm_accessible = false; + + if ( !thread_idle( node_ptr->ipmitool_thread_ctrl ) ) + { + thread_kill ( node_ptr->ipmitool_thread_ctrl , node_ptr->ipmitool_thread_info); + } + node_ptr->mc_info_query_active = false ; + node_ptr->mc_info_query_done = false ; + node_ptr->reset_cause_query_active = false ; + node_ptr->reset_cause_query_done = false ; + node_ptr->power_status_query_active = false; + node_ptr->power_status_query_done = false ; + + /* send a delete to hwmon if the provisioning data is NONE */ + if ( hostUtil_is_valid_bm_type ( node_ptr->bm_type ) == false ) + { + send_hwmon_command(node_ptr->hostname, MTC_CMD_DEL_HOST); + } + } + if (( node_ptr->bm_provisioned == false ) && ( state == true )) + { + /* start the connection timer - if it expires before we + * are 'accessible' then the BM Alarm is raised. + * Timer is further managed in mtcNodeHdlrs.cpp */ + plog ("%s bmc access timer started (%d secs)\n", node_ptr->hostname.c_str(), MTC_MINS_2); + mtcTimer_reset ( node_ptr->bmc_access_timer ); + mtcTimer_start ( node_ptr->bmc_access_timer, mtcTimer_handler, MTC_MINS_2 ); + } + + node_ptr->bm_provisioned = state ; + } + return (rc); +} + +string nodeLinkClass::get_bm_ip ( string hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return (node_ptr->bm_ip); + } + elog ("%s bm ip lookup failed\n", hostname.c_str() ); + return (""); +} + +string nodeLinkClass::get_bm_un ( string hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return (node_ptr->bm_un); + } + elog ("%s bm username lookup failed\n", hostname.c_str() ); + return (""); +} + +string nodeLinkClass::get_bm_type ( string hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return (node_ptr->bm_type); + } + elog ("%s bm type lookup failed\n", hostname.c_str() ); + return (""); +} + +string nodeLinkClass::get_hwmon_info ( string hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + string hwmon_info = "" ; + + hwmon_info.append( "{ \"personality\":\"" ) ; + hwmon_info.append( node_ptr->type ); + hwmon_info.append( "\""); + + hwmon_info.append( ",\"hostname\":\"" ) ; + hwmon_info.append( node_ptr->hostname ); + hwmon_info.append( "\""); + + hwmon_info.append( ",\"bm_ip\":\"" ) ; + hwmon_info.append( node_ptr->bm_ip ); + hwmon_info.append( "\""); + + hwmon_info.append( ",\"bm_type\":\""); + hwmon_info.append( node_ptr->bm_type ); + hwmon_info.append( "\""); + + hwmon_info.append( ",\"bm_username\":\""); + hwmon_info.append( node_ptr->bm_un ); + hwmon_info.append( "\""); + + hwmon_info.append( ",\"uuid\":\"" ) ; + hwmon_info.append( node_ptr->uuid ); + hwmon_info.append( "\" }"); + + return (hwmon_info); + } + elog ("%s hwmon info lookup failed\n", hostname.c_str() ); + return (""); +} + + + +int nodeLinkClass::manage_shadow_change ( string hostname ) +{ + int rc = FAIL ; + if ( ! hostname.empty() ) + { + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + rc = PASS ; + if ( node_ptr->configAction == MTC_CONFIG_ACTION__NONE ) + { + node_ptr->configStage = MTC_CONFIG__START ; + node_ptr->configAction = MTC_CONFIG_ACTION__CHANGE_PASSWD ; + } + else + { + node_ptr->configAction = MTC_CONFIG_ACTION__CHANGE_PASSWD_AGAIN ; + } + } + } + return (rc); +} + +/** Returns the number of compute hosts that are operationally 'enabled' */ +int nodeLinkClass::enabled_compute_nodes ( void ) +{ + int temp_count = 0 ; + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if (( is_compute( ptr )) && + ( ptr->operState == MTC_OPER_STATE__ENABLED )) + { + temp_count++ ; + } + else if (( is_compute_subfunction ( ptr )) && + ( ptr->operState_subf == MTC_OPER_STATE__ENABLED )) + { + temp_count++ ; + } + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return (temp_count); +} + +/** Returns the number of storage hosts that are operationally 'enabled' */ +int nodeLinkClass::enabled_storage_nodes ( void ) +{ + int temp_count = 0 ; + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if (( is_storage( ptr ) ) && + ( ptr->operState == MTC_OPER_STATE__ENABLED )) + { + temp_count++ ; + } + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return (temp_count); +} + +int nodeLinkClass::enabled_nodes ( void ) +{ + int temp_count = 0 ; + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->operState == MTC_OPER_STATE__ENABLED ) + { + temp_count++ ; + } + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + /* Remove the active controller from the count */ + if (temp_count) + temp_count-- ; + + return (temp_count); +} + +/** Returns the system's storage back end type ceph or nfs */ +int nodeLinkClass::get_storage_backend ( void ) +{ + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( is_storage(ptr) ) + return ( CGCS_STORAGE_CEPH ) ; + + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return (CGCS_STORAGE_NFS); +} + +/** Returns true if the storage pool has a monitor running on + * an unlocked-enabled storage host */ +bool nodeLinkClass::is_storage_mon_enabled ( void ) +{ + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if (( is_storage(ptr) ) && + ( ptr->operState == MTC_OPER_STATE__ENABLED ) && + ( !ptr->hostname.compare("storage-0"))) + { + return ( true ) ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return (false); +} + +/** Returns number of enabled controllers */ +int nodeLinkClass::num_controllers_enabled ( void ) +{ + int cnt = 0 ; + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if (( is_controller(ptr) ) && + ( ptr->operState == MTC_OPER_STATE__ENABLED )) + { + ++cnt ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + return (cnt); +} + +int nodeLinkClass::service_netlink_events ( int nl_socket , int ioctl_socket ) +{ + std::list links_gone_down ; + std::list links_gone_up ; + std::list::iterator iter_curr_ptr ; + if ( get_netlink_events ( nl_socket, links_gone_down, links_gone_up )) + { + const char * mgmnt_iface_ptr = daemon_get_cfg_ptr()->mgmnt_iface ; + const char * infra_iface_ptr = daemon_get_cfg_ptr()->infra_iface ; + bool running = false ; + if ( !links_gone_down.empty() ) + { + //wlog ("one or more links have dropped\n"); + /* Look at the down list */ + for ( iter_curr_ptr = links_gone_down.begin(); + iter_curr_ptr != links_gone_down.end() ; + iter_curr_ptr++ ) + { + bool care = false ; + if ( iter_curr_ptr->size() == 0 ) + continue ; + + if ( !strcmp (mgmnt_iface_ptr, iter_curr_ptr->data())) + { + care = true ; + mgmnt_link_up_and_running = false ; + wlog ("Management link %s is down\n", mgmnt_iface_ptr ); + } + if ( !strcmp (infra_iface_ptr, iter_curr_ptr->data())) + { + care = true ; + infra_link_up_and_running = false ; + wlog ("Infrastructure link %s is down\n", infra_iface_ptr ); + } + + if ( care == true ) + { + if ( get_link_state ( ioctl_socket, iter_curr_ptr->data(), &running ) == PASS ) + { + wlog ("%s is down (oper:%s)\n", iter_curr_ptr->c_str(), running ? "up" : "down" ); + } + else + { + wlog ("%s is down (driver query failed)\n", iter_curr_ptr->c_str() ); + } + } + } + } + if ( !links_gone_up.empty() ) + { + // wlog ("one or more links have recovered\n"); + /* Look at the up list */ + for ( iter_curr_ptr = links_gone_up.begin(); + iter_curr_ptr != links_gone_up.end() ; + iter_curr_ptr++ ) + { + bool care = false ; + if ( iter_curr_ptr->size() == 0 ) + continue ; + if ( !strcmp (mgmnt_iface_ptr, iter_curr_ptr->data())) + { + mgmnt_link_up_and_running = true ; + wlog ("Management link %s is up\n", mgmnt_iface_ptr ); + } + if ( !strcmp (infra_iface_ptr, iter_curr_ptr->data())) + { + infra_link_up_and_running = true ; + wlog ("Infrastructure link %s is up\n", infra_iface_ptr ); + } + if ( care == true ) + { + if ( get_link_state ( ioctl_socket, iter_curr_ptr->data(), &running ) == PASS ) + { + wlog ("%s is up (oper:%s)\n", iter_curr_ptr->c_str(), running ? "up" : "down" ); + } + else + { + wlog ("%s is up (driver query failed)\n", iter_curr_ptr->c_str() ); + } + } + } + } + } + return (PASS); +} + + +/* *************************************************************************** + * + * Name : hbs_minor_clear + * + * Description: Clear the heartbeat minor state from the specified host. + * + * Manage overall mnfa counts and call mnfa_exit when the number crosses + * the recovery threwshold. + * + ******************************************************************************/ +void nodeLinkClass::hbs_minor_clear ( struct nodeLinkClass::node * node_ptr, iface_enum iface ) +{ + if ( mnfa_host_count[iface] == 0 ) + return ; + + /* Nothing to do if this host is not in the hbs_minor state */ + if ( node_ptr->hbs_minor[iface] == true ) + { + /* clear it - possibly temporarily */ + node_ptr->hbs_minor[iface] = false ; + + /* manage counts over heartbeat failure */ + if ( mnfa_host_count[iface] ) + { + /* If we are mnfa_active AND now below the threshold + * then trigger mnfa_exit */ + if (( --mnfa_host_count[iface] < mnfa_calculate_threshold( node_ptr->hostname ) ) && + ( mnfa_active == true )) + { + + wlog ("%s MNFA exit with graceful recovery (%s:%d)\n", + node_ptr->hostname.c_str(), + get_iface_name_str(iface), + mnfa_host_count[iface] ); + + /* re-activate this to true so that it is part + * of the recovery group in mnfa_exit */ + node_ptr->hbs_minor[iface] = true ; + mnfa_exit ( false ); + } + + /* Otherwise this is a single host that has recovered + * possibly as part of a mnfa group or simply a lone wolf */ + else + { + if ( node_ptr->mnfa_graceful_recovery == true ) + { + ilog ("%s MNFA removed from pool\n", node_ptr->hostname.c_str() ); + mnfa_awol_list.remove(node_ptr->hostname); + } + + mnfa_recover_host ( node_ptr ); + + if ( mnfa_active == true ) + { + /* Restart the heartbeat for this recovered host */ + send_hbs_command ( node_ptr->hostname, MTC_RESTART_HBS ); + + /* don't restart graceful recovery for this host if its already in that FSM */ + if ( node_ptr->adminAction != MTC_ADMIN_ACTION__RECOVER ) + { + recoveryStageChange ( node_ptr, MTC_RECOVERY__START ); + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__RECOVER ); + } + } + } + } + } + + /* lets clean-up - walk the inventory and make sure the + * avoidance count meets the number of hosts in the minor + * degrade state */ + int temp_count = 0 ; + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->hbs_minor[iface] == true ) + { + if ( ptr->operState != MTC_OPER_STATE__ENABLED ) + { + slog ("%s found hbs_minor set for disabled host\n" , ptr->hostname.c_str() ); + } + temp_count++ ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + + if ( temp_count != mnfa_host_count[iface] ) + { + slog ("%s MNFA host tally (%s:%d incorrect - expected %d) ; correcting\n", + node_ptr->hostname.c_str(), + get_iface_name_str(iface), + mnfa_host_count[iface], temp_count ); + mnfa_host_count[iface] = temp_count ; + mnfa_host_count[iface] = temp_count ; + } + else + { + wlog ("%s MNFA host tally (%s:%d)\n", + node_ptr->hostname.c_str(), + get_iface_name_str(iface), + mnfa_host_count[iface] ); + } +} + +/**************************************************************************** + * + * Name : manage_dor_recovery + * + * Description: Enable DOR recovery mode for this host. + * Generate log + * + * The severity parm is used to enhance the logs to indicate what + * severity level this utility was called from ; + * minor, major, or critical + * + ***************************************************************************/ + +void nodeLinkClass::manage_dor_recovery ( struct nodeLinkClass::node * node_ptr, + EFmAlarmSeverityT severity ) +{ + if (( severity == FM_ALARM_SEVERITY_CLEAR ) && + ( node_ptr->dor_recovery_mode == true )) + { + node_ptr->dor_recovery_mode = false ; + node_ptr->was_dor_recovery_mode = true ; + } + + else if (( severity == FM_ALARM_SEVERITY_CRITICAL ) && + ( node_ptr->dor_recovery_mode == false )) + { + struct timespec ts ; + clock_gettime (CLOCK_MONOTONIC, &ts ); + wlog ("%-12s is waiting ; DOR recovery %2ld:%02ld mins (%4ld secs)\n", + node_ptr->hostname.c_str(), + ts.tv_sec/60, + ts.tv_sec%60, + ts.tv_sec); + + node_ptr->dor_recovery_time = 0 ; + node_ptr->dor_recovery_mode = true ; + node_ptr->hbsClient_ready = false ; + mtcInvApi_update_task ( node_ptr, MTC_TASK_RECOVERY_WAIT ); + + /* don't restart graceful recovery for this host if its already in that FSM */ + if (( node_ptr->adminAction != MTC_ADMIN_ACTION__RECOVER ) && + ( node_ptr->adminAction != MTC_ADMIN_ACTION__LOCK )) + { + recoveryStageChange ( node_ptr, MTC_RECOVERY__START ); + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__RECOVER ); + } + } +} + + +/** Manage heartbeat failure events */ +void nodeLinkClass::manage_heartbeat_failure ( string hostname, iface_enum iface, bool clear_event ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown host\n", hostname.c_str()); + return ; + } + + /* Handle clear */ + if ( clear_event == true ) + { + hbs_minor_clear ( node_ptr, iface ); + + plog ("%s %s Heartbeat failure clear\n", hostname.c_str(), get_iface_name_str(iface)); + + // if (( mnfa_host_count == 0 ) || ( iface == INFRA_IFACE )) + if ( mnfa_host_count[iface] == 0 ) // || ( iface == INFRA_IFACE )) + { + slog ("%s %s Heartbeat failure clear\n", hostname.c_str(), get_iface_name_str(iface)); + node_ptr->hbs_failure[iface] = false ; + } + } + else if ( this->mtcTimer_dor.tid ) + { + manage_dor_recovery ( node_ptr, FM_ALARM_SEVERITY_CRITICAL ); + } + else + { + mnfa_add_host ( node_ptr , iface ); + + if ( mnfa_active == false ) + { + elog ("%s %s *** Heartbeat Loss ***\n", hostname.c_str(), get_iface_name_str(iface)); + if ( iface == INFRA_IFACE ) + { + node_ptr->heartbeat_failed[INFRA_IFACE] = true ; + } + else if ( iface == MGMNT_IFACE ) + { + node_ptr->heartbeat_failed[MGMNT_IFACE] = true ; + } + if ( mnfa_host_count[iface] < mnfa_calculate_threshold( hostname )) + { + + elog ("%s %s network heartbeat failure\n", hostname.c_str(), get_iface_name_str(iface)); + + nodeLinkClass::set_availStatus ( hostname, MTC_AVAIL_STATUS__FAILED ); + if ( node_ptr->alarms[MTC_ALARM_ID__ENABLE] != FM_ALARM_SEVERITY_CRITICAL ) + { + mtcAlarm_critical ( node_ptr->hostname, MTC_ALARM_ID__ENABLE ); + node_ptr->alarms[MTC_ALARM_ID__ENABLE] = FM_ALARM_SEVERITY_CRITICAL; + } + + if (( node_ptr->adminAction != MTC_ADMIN_ACTION__ENABLE ) && + ( node_ptr->adminAction != MTC_ADMIN_ACTION__UNLOCK )) + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__RECOVER ) + { + wlog ("%s restarting graceful recovery\n", hostname.c_str() ); + } + else + { + wlog ("%s starting graceful recovery\n", hostname.c_str() ); + } + recoveryStageChange ( node_ptr, MTC_RECOVERY__START ); + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__RECOVER ); + } + else + { + mtcInvApi_update_task ( node_ptr, MTC_TASK_ENABLE_FAIL_HB ); + enableStageChange ( node_ptr, MTC_ENABLE__FAILURE ); + } + } + } + } +} + +void nodeLinkClass::manage_heartbeat_clear ( string hostname, iface_enum iface ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown host\n", hostname.c_str()); + return ; + } + if ( iface == MAX_IFACES ) + { + for ( int i = 0 ; i < MAX_IFACES ; i++ ) + { + node_ptr->heartbeat_failed[i] = false ; + } + } + else + { + node_ptr->heartbeat_failed[iface] = false ; + } +} + +/** Manage compute host maintenance based on this heartbeat + * degrade event and others that may be present at this moment */ +void nodeLinkClass::manage_heartbeat_degrade ( string hostname, iface_enum iface, bool clear_event ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown host\n", hostname.c_str()); + return ; + } + + if ( clear_event == true ) + { + alog ("%s %s Heartbeat Degrade (clear)\n", hostname.c_str(), get_iface_name_str(iface)); + manage_heartbeat_clear ( hostname, iface ); + + if ( iface == MGMNT_IFACE ) + { + node_ptr->no_work_log_throttle = 0 ; + node_ptr->degrade_mask &= ~DEGRADE_MASK_HEARTBEAT_MGMNT ; + } + + else if ( iface == INFRA_IFACE ) + { + node_ptr->no_work_log_throttle = 0 ; + node_ptr->degrade_mask &= ~DEGRADE_MASK_HEARTBEAT_INFRA ; + } + + hbs_minor_clear ( node_ptr, iface ); + + /* Set the host available if the degrade mask is now + * cleared and we are degraded */ + if ( node_ptr->degrade_mask == 0 ) + { + if ( get_availStatus ( hostname ) == MTC_AVAIL_STATUS__DEGRADED ) + { + set_availStatus ( hostname, MTC_AVAIL_STATUS__AVAILABLE ); + } + } + } + else if ( this->mtcTimer_dor.tid ) + { + manage_dor_recovery ( node_ptr, FM_ALARM_SEVERITY_MAJOR ); + } + else + { + if ( mnfa_active == false ) + { + wlog ("%s %s *** Heartbeat Miss ***\n", hostname.c_str(), get_iface_name_str(iface) ); + } + + mnfa_add_host ( node_ptr, iface ); + + if ( nodeLinkClass::get_operState ( hostname ) == MTC_OPER_STATE__ENABLED ) + { + if ( iface == MGMNT_IFACE ) + { + /* Don't raise the alarm again if this host is already degraded */ + if ( !(node_ptr->degrade_mask & DEGRADE_MASK_HEARTBEAT_MGMNT) ) + { + node_ptr->degrade_mask |= DEGRADE_MASK_HEARTBEAT_MGMNT ; + } + } + if ( iface == INFRA_IFACE ) + { + if ( !(node_ptr->degrade_mask & DEGRADE_MASK_HEARTBEAT_INFRA) ) + { + node_ptr->degrade_mask |= DEGRADE_MASK_HEARTBEAT_INFRA ; + } + } + + /* No point in changing if we are already degraded */ + if ( nodeLinkClass::get_availStatus ( hostname ) == MTC_AVAIL_STATUS__AVAILABLE ) + { + set_availStatus ( hostname, MTC_AVAIL_STATUS__DEGRADED ); + } + } + } +} + +/** Manage heartbeat minor events */ +void nodeLinkClass::manage_heartbeat_minor ( string hostname, iface_enum iface, bool clear_event ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown host\n", hostname.c_str()); + return ; + } + + /* is this a clear event ? */ + if ( clear_event == true ) + { + alog ("%s %s Heartbeat Minor (clear)\n", hostname.c_str(), get_iface_name_str(iface)); + hbs_minor_clear ( node_ptr, iface ); + } + /* if not a clear then only set if the host is enabled + * - we don't care about disabled hosts */ + else if ( nodeLinkClass::get_operState ( hostname ) == MTC_OPER_STATE__ENABLED ) + { + if ( this->mtcTimer_dor.tid ) + { + manage_dor_recovery ( node_ptr, FM_ALARM_SEVERITY_MINOR ); + } + + else if ( node_ptr->hbs_minor[iface] != true ) + { + mnfa_add_host ( node_ptr, iface ); + } + } +} + + +/** Interface to declare that a key service on the + * specified host is up, running and ready */ +int nodeLinkClass::declare_service_ready ( string & hostname, + unsigned int service ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host\n", hostname.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( service == MTC_SERVICE_PMOND ) + { + node_ptr->pmond_ready = true ; + plog ("%s got pmond ready event\n", hostname.c_str()); + + /* A ready event means that pmond pocess has started. + * Any previous history is gone. Cleanup mtce. + * If there are still process issues on this host then + * they will be reported again.*/ + node_ptr->degrade_mask &= ~DEGRADE_MASK_PMON ; + if ( node_ptr->degrade_mask == DEGRADE_MASK_NONE ) + { + if ( node_ptr->availStatus == MTC_AVAIL_STATUS__DEGRADED ) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__AVAILABLE ); + } + } + return (PASS); + } + else if ( service == MTC_SERVICE_HWMOND ) + { + node_ptr->hwmond_ready = true ; + plog ("%s got hwmond ready event\n", hostname.c_str()); + if ( node_ptr->bm_provisioned == true ) + { + send_hwmon_command ( node_ptr->hostname, MTC_CMD_ADD_HOST ); + send_hwmon_command ( node_ptr->hostname, MTC_CMD_START_HOST ); + } + return (PASS); + } + else if ( service == MTC_SERVICE_RMOND ) + { + node_ptr->rmond_ready = true ; + plog ("%s got rmond ready event\n", hostname.c_str()); + return (PASS); + } + else if ( service == MTC_SERVICE_HEARTBEAT ) + { + if ( node_ptr->hbsClient_ready == false ) + { + node_ptr->hbsClient_ready = true ; + plog ("%s got hbsClient ready event\n", hostname.c_str()); + } + return (PASS); + } + else + { + return (FAIL_BAD_CASE); + } +} + +/** Clear pmond degrade flag */ +int nodeLinkClass::degrade_pmond_clear ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host\n", hostname.c_str()); + return (FAIL_UNKNOWN_HOSTNAME) ; + } + if ( node_ptr->degrade_mask ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_PMON ; + + if ( !node_ptr->degrade_mask ) + { + if ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__AVAILABLE ); + } + } + } + + /* The only detectable inservice failures are process failures */ + node_ptr->inservice_failed_subf = false ; + node_ptr->inservice_failed = false ; + return (PASS); +} + +/** Resource Monitor 'Clear' Event handler. + * + * The resource specified will be removed from the + * 'degraded_resources_list' for specified host. + * if there are no other degraded resources or other + * degraded services/reasons against that host then + * this handler will clear the degrade state for the + * specified host all together. */ +int nodeLinkClass::degrade_resource_clear ( string & hostname, + string & resource ) +{ + /* lr - Log Prefix Rmon */ + string lr = hostname ; + lr.append (" rmond:"); + + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host\n", lr.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + /* Clear all resource degrade conditions if there is no resource specified */ + /* this is used as a cleanup audit just in case things get stuck */ + if ( resource.empty() ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_RESMON ; + node_ptr->degraded_resources_list.clear () ; + } + else if (( node_ptr->degraded_resources_list.empty()) || + ( node_ptr->degrade_mask == DEGRADE_MASK_NONE )) + { + dlog ("%s '%s' Non-Degraded Clear\n", + lr.c_str(), resource.c_str()); + } + else + { + if (is_string_in_string_list (node_ptr->degraded_resources_list, resource)) + { + node_ptr->degraded_resources_list.remove(resource); + ilog ("%s '%s' Degrade Clear\n", + lr.c_str(), resource.c_str()); + } + else + { + wlog ("%s '%s' Unexpected Degrade Clear\n", + lr.c_str(), resource.c_str()); + } + + if ( node_ptr->degraded_resources_list.empty() ) + { + node_ptr->degrade_mask &= ~DEGRADE_MASK_RESMON ; ; + if ( node_ptr->degrade_mask == DEGRADE_MASK_NONE ) + { + if ( node_ptr->availStatus == MTC_AVAIL_STATUS__DEGRADED ) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__AVAILABLE ); + } + } + else + { + wlog ("%s Remains Degraded - Reason Mask:0x%08x\n", + hostname.c_str(), node_ptr->degrade_mask ); + } + } + else + { + string degraded_resources = + get_strings_in_string_list ( node_ptr->degraded_resources_list ); + wlog ("%s Degraded Resource List: %s\n", + lr.c_str(), degraded_resources.c_str()); + } + } + + } + return (PASS); +} + +/********************************************************************************* + * + * Name : node_degrade_control + * + * Purpose : Accept and handle degrade raise and clear requests from + * external services. + * + * Description: Maintenance maintains a degrade mask with a bit representing + * various services. The assertion of any one bit causes the host + * to be degraded. All bits need to be cleared in orde to exit + * the degrade state. + * + * Supported 'services' include + * + * "hwmon" - The Hardware Monitor process + * + * + * Future services might be rmon and pmon + * + **********************************************************************************/ +int nodeLinkClass::node_degrade_control ( string & hostname, int state, string service ) +{ + int rc = FAIL_UNKNOWN_HOSTNAME ; + + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr ) + { + unsigned int service_flag = 0 ; + + /* convert service string to degrade mask flag + * - handle empty string and unsupported service */ + if ( service.empty() ) + { + slog ("%s service not specified", hostname.c_str()); + return (FAIL_STRING_EMPTY); + } + else if ( !service.compare("hwmon") ) + { + service_flag = DEGRADE_MASK_HWMON ; + } + else + { + slog ("%s service '%s' not supported\n", + hostname.c_str(), + service.c_str()); + return (FAIL_INVALID_DATA); + } + + switch ( state ) + { + /* Handle clear case */ + case MTC_DEGRADE_CLEAR: + { + if ( node_ptr->degrade_mask & service_flag ) + { + ilog ("%s degrade 'clear' from '%s'\n", hostname.c_str(), service.c_str() ); + } + + /* clear the mask regardless of host state */ + node_ptr->degrade_mask &= ~service_flag ; + + /* only applies if host is unlocked-enabled-degraded and + * there are no other degrade flags in the degrade mask */ + if (( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) && + ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) && + ( node_ptr->availStatus == MTC_AVAIL_STATUS__DEGRADED )) + { + if ( node_ptr->degrade_mask == DEGRADE_MASK_NONE ) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__AVAILABLE ); + } + else + { + /* TODO: convert lask to a sring or services and print that string */ + wlog ("%s remains degraded - degrade mask:0x%08x\n", + hostname.c_str(), + node_ptr->degrade_mask ); + } + } + else + { + dlog ("%s unexpected degrade clear for '%s' service\n", + hostname.c_str(), service.c_str() ); + } + rc = PASS ; + break ; + } + + /* Handle assertion case */ + case MTC_DEGRADE_RAISE: + { + if (( node_ptr->degrade_mask & service_flag ) == 0 ) + { + wlog ("%s degrade 'assert' from '%s'\n", hostname.c_str(), service.c_str() ); + node_ptr->degrade_mask |= service_flag ; + } + + if (( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) && + ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) && + ( node_ptr->availStatus == MTC_AVAIL_STATUS__AVAILABLE )) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__DEGRADED ); + } + rc = PASS ; + break ; + } + default: + { + wlog ("%s invalid degrade control request '%d'\n", hostname.c_str(), state); + rc = FAIL_BAD_CASE ; + break ; + } + } /* end switch */ + } + else + { + dlog ("%s Unknown Host\n", hostname.c_str()); + } + return (rc); +} + + +int nodeLinkClass::hwmon_recovery_monitor ( struct nodeLinkClass::node * node_ptr, int hwmon_event ) +{ + int delay = MTC_MINS_15 ; + if ( hwmon_event == MTC_EVENT_HWMON_POWERCYCLE ) + { + node_ptr->hwmon_powercycle.retries = 0 ; + node_ptr->hwmon_powercycle.queries = 0 ; + node_ptr->hwmon_powercycle.state = RECOVERY_STATE__MONITOR ; + + mtcTimer_reset ( node_ptr->hwmon_powercycle.recovery_timer ); + mtcTimer_start ( node_ptr->hwmon_powercycle.recovery_timer, mtcTimer_handler, delay ); + + ilog ("%s starting hwmon 'powercycle' recovery monitor", node_ptr->hostname.c_str()); + ilog ("%s ... uninterrupted completion time: %s", node_ptr->hostname.c_str(), future_time(delay)); + } + else if ( hwmon_event == MTC_EVENT_HWMON_RESET ) + { + node_ptr->hwmon_reset.retries = 0 ; + node_ptr->hwmon_reset.queries = 0 ; + node_ptr->hwmon_reset.state = RECOVERY_STATE__MONITOR ; + + mtcTimer_reset ( node_ptr->hwmon_reset.recovery_timer ); + mtcTimer_start ( node_ptr->hwmon_reset.recovery_timer, mtcTimer_handler, delay ); + + ilog ("%s starting hwmon 'reset' recovery monitor", node_ptr->hostname.c_str()); + ilog ("%s ... uninterrupted completion time: %s", node_ptr->hostname.c_str(), future_time(delay)); + } + return (PASS); +} + +/* Hardware Monitor 'Action' Event method + * + * The hardware monitor daemon is calling out a sensor that + * is operating out of spec. The command is the accompanying + * action that hwmond requested as a recovery action to this failure. + * The sensor is the sensor name that triggersed the event. */ +int nodeLinkClass::invoke_hwmon_action ( string & hostname, int action, string & sensor ) +{ + int rc = PASS ; + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + + dlog ("%s request to '%s' due to critical sensor '%s' reading\n", + hostname.c_str(), + get_event_str(action).c_str(), + sensor.c_str()); + + if ( node_ptr ) + { + if ( node_ptr->bm_accessible == false ) + { + wlog ("%s rejecting %s hwmon action request for '%s' sensor ; BMC not accessible\n", + hostname.c_str(), + get_event_str(action).c_str(), + sensor.c_str()); + + return (PASS); + } + if ( action == MTC_EVENT_HWMON_RESET ) + { + if ( is_active_controller (hostname) == true ) + { + wlog ("%s refusing to 'reset' self due to critical '%s' sensor event\n", + hostname.c_str(), sensor.c_str()); + recovery_ctrl_init ( node_ptr->hwmon_reset ); + return(rc); + } + + /* Avoid interrupting higher priority powercycle action */ + else if (( node_ptr->adminAction == MTC_ADMIN_ACTION__POWERCYCLE ) || + ( node_ptr->hwmon_powercycle.state != RECOVERY_STATE__INIT )) + { + wlog ("%s bypassing 'reset' request while 'powercycle' already in progress (%s)\n", + hostname.c_str(), sensor.c_str()); + } + else if ( node_ptr->adminAction != MTC_ADMIN_ACTION__NONE ) + { + wlog ("%s bypassing 'reset' request while '%s' action in progress (%s)\n", + hostname.c_str(), get_adminAction_str(node_ptr->adminAction), sensor.c_str()); + } + else if ( node_ptr->hwmon_reset.state ) + { + wlog ("%s rejecting 'reset' request while already in progress (%s)\n", + hostname.c_str(), sensor.c_str()); + } + else + { + if (( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) && + ( node_ptr->operState == MTC_OPER_STATE__ENABLED )) + { + mtcTimer_reset ( node_ptr->hwmon_reset.recovery_timer ); + mtcTimer_start ( node_ptr->hwmon_reset.recovery_timer, mtcTimer_handler, MTC_MINS_15 ); + + force_full_enable ( node_ptr ); + } + else + { + if ( node_ptr->adminAction != MTC_ADMIN_ACTION__RESET ) + { + elog ("%s starting 'reset' FSM\n", hostname.c_str()); + + mtcTimer_reset ( node_ptr->hwmon_reset.recovery_timer ); + mtcTimer_start ( node_ptr->hwmon_reset.recovery_timer, mtcTimer_handler, MTC_MINS_15 ); + + adminActionChange ( node_ptr , MTC_ADMIN_ACTION__RESET ); + } + else + { + wlog ("%s mtce 'reset' action already in progress\n", hostname.c_str()); + } + } + node_ptr->hwmon_reset.state = RECOVERY_STATE__HOLDOFF ; + } + } + else if ( action == MTC_EVENT_HWMON_POWERCYCLE ) + { + if ( node_ptr->hwmon_powercycle.attempts > MAX_POWERCYCLE_ATTEMPT_RETRIES ) + { + wlog ("%s ignoring 'powercycle' request ; too many failed attempts (%d)\n", + node_ptr->hostname.c_str(), node_ptr->hwmon_powercycle.attempts ); + } + else if ( is_active_controller (hostname) == true ) + { + wlog ("%s refusing to 'powercycle' self due to critical '%s' sensor event\n", + hostname.c_str(), sensor.c_str()); + recovery_ctrl_init ( node_ptr->hwmon_powercycle ) ; + } + else + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__POWERCYCLE ) + { + wlog ("%s bypassing 'powercycle' request while already in progress (%s)\n", + hostname.c_str(), sensor.c_str()); + } + else if ( node_ptr->adminAction != MTC_ADMIN_ACTION__NONE ) + { + wlog ("%s bypassing 'powercycle' request while '%s' action in progress (%s)\n", + hostname.c_str(), + get_adminAction_str(node_ptr->adminAction), + sensor.c_str()); + } + else if ( node_ptr->hwmon_powercycle.state == RECOVERY_STATE__COOLOFF ) + { + wlog ("%s avoiding 'powercycle' request while in powercycle recovery cooloff (%s)\n", + hostname.c_str(), sensor.c_str()); + } + else if ( node_ptr->hwmon_powercycle.state == RECOVERY_STATE__HOLDOFF ) + { + wlog ("%s avoiding 'powercycle' request while in powercycle recovery holdoff (%s)\n", + hostname.c_str(), sensor.c_str()); + } + else if ( node_ptr->hwmon_powercycle.state == RECOVERY_STATE__ACTION ) + { + wlog ("%s avoiding 'powercycle' request while already handling powercycle (%s)\n", + hostname.c_str(), sensor.c_str()); + } + else if ( node_ptr->hwmon_powercycle.state == RECOVERY_STATE__BLOCKED ) + { + wlog ("%s avoiding 'powercycle' request ; host is powered off due to protect hardware from damage due to critical '%s' sensor\n", + hostname.c_str(), sensor.c_str()); + } + else + { + if ( node_ptr->hwmon_powercycle.state == RECOVERY_STATE__MONITOR ) + { + wlog ("%s 'powercycle' request while in monitor phase (%s)\n", + hostname.c_str(), sensor.c_str()); + } + + /* Cancel the recovery timer only to have it started once the + * next power cycle phase is complete */ + mtcTimer_reset ( node_ptr->hwmon_powercycle.recovery_timer ); + + wlog ("%s invoking 'powercycle' due to critical '%s' sensor assertion\n", hostname.c_str(), sensor.c_str()); + powercycleStageChange ( node_ptr, MTC_POWERCYCLE__START ); + subStageChange ( node_ptr, MTC_SUBSTAGE__START ); + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__POWERCYCLE ); + } + } + } + else + { + slog ("%s '%s' action not supported as request from hwmond\n", + hostname.c_str(), + get_event_str(action).c_str()); + rc = FAIL_BAD_PARM ; + } + } + else + { + slog ("%s cannot '%s' due to unknown host\n", hostname.c_str(), get_event_str(action).c_str()); + rc = FAIL_UNKNOWN_HOSTNAME ; + } + return (rc); +} + +/* Generate a log for the reported failed process if that host is + * unlocked */ +int nodeLinkClass::log_process_failure ( string & hostname, string & process ) +{ + /* lp - Log Prefix */ + string lp = hostname ; + lp.append (" pmon:"); + + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host ; '%s' failed (minor)\n", + lp.c_str(), process.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) + { + if ( process.compare("ntpd") ) + { + wlog ("%s '%s' process failed and is being auto recovered\n", + lp.c_str(), + process.c_str()); + } + else + { + wlog ("%s '%s' process has failed ; manual recovery action required\n", + lp.c_str(), + process.c_str()); + } + } + return (PASS); +} + +/* if unlocked-enabled generate an alarm for the reported failed process */ +int nodeLinkClass::alarm_process_failure ( string & hostname, string & process ) +{ + /* lp - Log Prefix */ + string lp = hostname ; + lp.append (" pmon:"); + + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host ; '%s' failed (minor)\n", + lp.c_str(), process.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) + { + /* TODO: Generate Alarm here */ + + wlog ("%s '%s' failed (minor)\n", lp.c_str(), process.c_str()); + } + return (PASS); +} + +/* Generate a log for the reported failed resource if that host is + * unlocked */ +int nodeLinkClass::log_resource_failure ( string & hostname, string & resource ) +{ + /* lr - Log Prefix Rmond */ + string lr = hostname ; + lr.append (" rmond:"); + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host ; '%s' failed (minor)\n", + lr.c_str(), resource.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) + { + ilog ("%s '%s' failed (minor)\n", + lr.c_str(), resource.c_str()); + } + return (PASS); +} + +/** Process Monitor Degrade Event handler. + * + * The host will enter degrade state due to the specified process + * not running properly. The process name is recorded in the + * 'degraded_processes_list' for specified host. + * Clearing degrade against this process requires that host to + * send a clear event against that process or for that host to + * fully re-enable */ +int nodeLinkClass::degrade_process_raise ( string & hostname, + string & process ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host\n", hostname.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + if ( (node_ptr->degrade_mask & DEGRADE_MASK_PMON) == 0 ) + { + node_ptr->degrade_mask |= DEGRADE_MASK_PMON ; + wlog ("%s is degraded due to '%s' process failure\n", hostname.c_str(), process.c_str()); + if ( node_ptr->availStatus == MTC_AVAIL_STATUS__AVAILABLE ) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__DEGRADED ); + } + } + } + return (PASS); +} + +/* + * Name : update_dport_states + * + * Purpose: Update data port states based on the event severity + * + * CLEAR = enabled-available + * MAJOR = enabled-degraded + * CRITICAL = disabled-failed + * + */ +int update_dport_states_throttle = 0 ; +int nodeLinkClass::update_dport_states ( struct nodeLinkClass::node * node_ptr, int event ) +{ + int rc = PASS ; + + /* if the host is locked then report the data ports as offline */ + if ( node_ptr->adminState == MTC_ADMIN_STATE__LOCKED ) + { + event = MTC_EVENT_AVS_OFFLINE ; + } + + switch (event) + { + case MTC_EVENT_AVS_OFFLINE: + { + if ( node_ptr->operState_dport != MTC_OPER_STATE__DISABLED ) + { + ilog ("%s data port 'operState' change from '%s' -> 'disabled'", + node_ptr->hostname.c_str(), + operState_enum_to_str(node_ptr->operState_dport).c_str()); + + node_ptr->operState_dport = MTC_OPER_STATE__DISABLED ; + } + + if ( node_ptr->availStatus_dport != MTC_AVAIL_STATUS__OFFLINE ) + { + ilog ("%s data port 'availStat' change from '%s' -> 'offline'", + node_ptr->hostname.c_str(), + availStatus_enum_to_str(node_ptr->availStatus_dport).c_str()); + + node_ptr->availStatus_dport = MTC_AVAIL_STATUS__OFFLINE ; + } + break ; + } + case MTC_EVENT_AVS_CLEAR: + { + bool state_change = false ; + if ( node_ptr->operState_dport != MTC_OPER_STATE__ENABLED ) + { + ilog ("%s data port 'operState' change from '%s' -> 'enabled'", + node_ptr->hostname.c_str(), + operState_enum_to_str(node_ptr->operState_dport).c_str()); + + node_ptr->operState_dport = MTC_OPER_STATE__ENABLED ; + state_change = true ; + } + + if ( node_ptr->availStatus_dport != MTC_AVAIL_STATUS__AVAILABLE ) + { + ilog ("%s data port 'availStat' change from '%s' -> 'available'", + node_ptr->hostname.c_str(), + availStatus_enum_to_str(node_ptr->availStatus_dport).c_str()); + + node_ptr->availStatus_dport = MTC_AVAIL_STATUS__AVAILABLE ; + state_change = true ; + } + /** If there has been s state change as a result of a + * clear then send that to the VIM immediately + **/ + if ( state_change == true ) + { + /* Inform the VIM of the data port state change */ + mtcVimApi_state_change ( node_ptr, VIM_DPORT_CLEARED, 3 ); + } + break ; + } + case MTC_EVENT_AVS_MAJOR: + { + if ( node_ptr->operState_dport != MTC_OPER_STATE__ENABLED ) + { + ilog ("%s data port 'operState' change from '%s' -> 'enabled'", + node_ptr->hostname.c_str(), + operState_enum_to_str(node_ptr->operState_dport).c_str()); + + node_ptr->operState_dport = MTC_OPER_STATE__ENABLED ; + } + + if ( node_ptr->availStatus_dport != MTC_AVAIL_STATUS__DEGRADED ) + { + wlog ("%s data port 'availStat' change from '%s' -> 'degraded'", + node_ptr->hostname.c_str(), + availStatus_enum_to_str(node_ptr->availStatus_dport).c_str()); + + node_ptr->availStatus_dport = MTC_AVAIL_STATUS__DEGRADED ; + } + break ; + } + case MTC_EVENT_AVS_CRITICAL: + { + if ( node_ptr->operState_dport != MTC_OPER_STATE__DISABLED ) + { + elog ("%s data port 'operState' change from '%s' -> 'disabled'", + node_ptr->hostname.c_str(), + operState_enum_to_str(node_ptr->operState_dport).c_str()); + + node_ptr->operState_dport = MTC_OPER_STATE__DISABLED ; + } + + if ( node_ptr->availStatus_dport != MTC_AVAIL_STATUS__FAILED ) + { + elog ("%s data port 'availStat' change from '%s' -> 'failed'", + node_ptr->hostname.c_str(), + availStatus_enum_to_str(node_ptr->availStatus_dport).c_str()); + + node_ptr->availStatus_dport = MTC_AVAIL_STATUS__FAILED ; + } + break ; + } + default: + { + wlog_throttled (update_dport_states_throttle, 10, "Invalid port state (%x)\n", event ); + rc = FAIL_BAD_CASE ; + } + } + return (rc); +} + +/** Resource Monitor 'Raise' Event handler. + * + * The host will enter degrade state due to the specified resource + * threshold being surpased. The resource name is recorded in the + * 'degraded_resources_list' for specified host. + * Clearing degrade against this resource requires that host to + * send a clear event against that resource or for that host to + * fully re-enable */ +int nodeLinkClass::degrade_resource_raise ( string & hostname, + string & resource ) +{ + /* lr - Log Prefix Rmond */ + string lr = hostname ; + lr.append (" rmond:"); + + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s Unknown Host\n", lr.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + else if ( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) + { + if ( is_string_in_string_list ( node_ptr->degraded_resources_list, resource ) == false ) + { + string degraded_resources = ""; + + ilog ("%s '%s' Degraded\n", lr.c_str(), resource.c_str()); + node_ptr->degraded_resources_list.push_back (resource); + node_ptr->degrade_mask |= DEGRADE_MASK_RESMON ; + + /* Cleanup the list */ + node_ptr->degraded_resources_list.sort (); + node_ptr->degraded_resources_list.unique (); + + degraded_resources = + get_strings_in_string_list ( node_ptr->degraded_resources_list ); + wlog ("%s Failing Resources: %s\n", + lr.c_str(), degraded_resources.c_str()); + } + else + { + dlog ("%s '%s' Degraded (again)\n", lr.c_str(), resource.c_str()); + } + if ( node_ptr->availStatus == MTC_AVAIL_STATUS__AVAILABLE ) + { + availStatusChange ( node_ptr, MTC_AVAIL_STATUS__DEGRADED ); + } + + } + return (PASS); +} + +/** Process Monitor 'Critical Process Failed' Event handler. + * + * This utility handles critical process failure event notifications. + * Typically this interface will force a host re-enable through reset. + * + * For CPE Simplex this failure sets the auto recovery bool + * so that the main enable FSM can handle it through a thresholded + * self reboot. + * + * That as well as all other failure handling cases are deferred to + * the enable handler's from failure case. + * + **/ +int nodeLinkClass::critical_process_failed( string & hostname, + string & process, + unsigned int nodetype ) +{ + UNUSED(nodetype); + + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s pmon: Unknown host\n", hostname.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + + if (( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) && + ( node_ptr->operState == MTC_OPER_STATE__ENABLED )) + { + elog ("%s has critical '%s' process failure\n", hostname.c_str(), process.c_str()); + + node_ptr->degrade_mask |= DEGRADE_MASK_PMON ; + + /* Special critical process failure handling for AIO system */ + if ( THIS_HOST && ( is_inactive_controller_main_insv() == false )) + { + if ( this->autorecovery_disabled == true ) + { + dlog ("%s bypassing persistent critical process failure\n", + node_ptr->hostname.c_str()); + return (PASS); + } + + dlog ("%s critical process failure (aio)\n", + node_ptr->hostname.c_str()); /* dlog */ + } + + /* Start fresh the next time we enter graceful recovery handler */ + node_ptr->graceful_recovery_counter = 0 ; + + /* Set node as unlocked-disabled-failed */ + allStateChange ( node_ptr, MTC_ADMIN_STATE__UNLOCKED, + MTC_OPER_STATE__DISABLED, + MTC_AVAIL_STATUS__FAILED ); + + enableStageChange ( node_ptr, MTC_ENABLE__FAILURE ); + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__NONE ); + + dlog ("%s adminState:%s EnableStage:%s\n", + node_ptr->hostname.c_str(), + adminAction_enum_to_str(node_ptr->adminAction).c_str(), + get_enableStages_str(node_ptr->handlerStage.enable).c_str()); + } + return (PASS); +} + +/** Resource Monitor 'Failed' Event handler. + * + * The host will go out of service, be reset and + * automatically re-enabled. */ +int nodeLinkClass::critical_resource_failed( string & hostname, + string & resource ) +{ + nodeLinkClass::node * node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + wlog ("%s rmond: Unknown host\n", hostname.c_str()); + return FAIL_UNKNOWN_HOSTNAME ; + } + + if (( node_ptr->adminState == MTC_ADMIN_STATE__UNLOCKED ) && + ( node_ptr->operState == MTC_OPER_STATE__ENABLED )) + { + /* Start fresh the next time we enter graceful recovery handler */ + node_ptr->graceful_recovery_counter = 0 ; + + elog ("%s rmond: Critical Resource '%s' Failure\n", hostname.c_str(), resource.c_str()); + + /* Set node as unlocked-enabled */ + allStateChange ( node_ptr, MTC_ADMIN_STATE__UNLOCKED, + MTC_OPER_STATE__DISABLED, + MTC_AVAIL_STATUS__FAILED ); + } + return (PASS); +} + +bool nodeLinkClass::is_active_controller ( string hostname ) +{ + if ( nodeLinkClass::my_hostname.compare(hostname) ) + { + return (false) ; + } + return (true); +} + +string nodeLinkClass::get_inactive_controller_hostname ( void ) +{ + return (inactive_controller_hostname); +} + +void nodeLinkClass::set_inactive_controller_hostname ( string hostname ) +{ + inactive_controller_hostname = hostname ; +} + +string nodeLinkClass::get_active_controller_hostname ( void ) +{ + return (active_controller_hostname); +} + +void nodeLinkClass::set_active_controller_hostname ( string hostname ) +{ + active_controller_hostname = hostname ; +} + +bool nodeLinkClass::inactive_controller_is_patched ( void ) +{ + nodeLinkClass::node * node_ptr = getNode ( inactive_controller_hostname ) ; + if ( node_ptr != NULL ) + { + return ( node_ptr->patched ); + } + return (false) ; +} + +bool nodeLinkClass::inactive_controller_is_patching ( void ) +{ + nodeLinkClass::node * node_ptr = getNode ( inactive_controller_hostname ) ; + if ( node_ptr != NULL ) + { + return ( node_ptr->patching ); + } + return (false) ; +} + +bool nodeLinkClass::is_inactive_controller_main_insv ( void ) +{ + nodeLinkClass::node * node_ptr = getNode ( inactive_controller_hostname ) ; + if ( node_ptr != NULL ) + { + if ( node_ptr->operState == MTC_OPER_STATE__ENABLED ) + { + return (true) ; + } + } + return (false) ; +} + +bool nodeLinkClass::is_inactive_controller_subf_insv ( void ) +{ + nodeLinkClass::node * node_ptr = getNode ( inactive_controller_hostname ) ; + if ( node_ptr != NULL ) + { + if ( node_ptr->operState_subf == MTC_OPER_STATE__ENABLED ) + { + return (true) ; + } + } + return (false) ; +} + +int nodeLinkClass::set_subf_info ( string hostname, + string functions, + string operState_subf, + string availState_subf ) +{ + int rc = FAIL_HOSTNAME_LOOKUP ; + if ( functions.empty() ) + { + elog ("%s called with empty 'functions' string\n", hostname.c_str()); + return (FAIL_STRING_EMPTY); + } + + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + node_ptr->functions = functions ; + node_ptr->operState_subf = operState_str_to_enum(operState_subf.data()); + node_ptr->availStatus_subf = availStatus_str_to_enum(availState_subf.data()); + rc = update_host_functions ( hostname, functions ); + } + return (rc); +} + + + +/********************************************************************************** + * + * Name : update_host_functions + * + * Purpose: Loads a nodeLinkClass with function information based on a comma + * delimited function string like. + * + * controller + * compute + * storage + * controller,compute + * controller,storage + * + **********************************************************************************/ +int nodeLinkClass::update_host_functions ( string hostname , string functions ) +{ + int rc = FAIL ; + + if ( functions.empty() ) + { + elog ("%s called with empty 'functions' string\n", hostname.c_str()); + return (rc); + } + + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + node_ptr->functions = functions ; + if ( set_host_functions ( functions, &node_ptr->nodetype, &node_ptr->function, &node_ptr->subfunction ) != PASS ) + { + elog ("%s failed to extract nodetype\n", hostname.c_str()); + rc = FAIL_NODETYPE; + } + else + { + if ( node_ptr->function == CONTROLLER_TYPE ) + node_ptr->function_str = "controller" ; + else if ( node_ptr->function == COMPUTE_TYPE ) + node_ptr->function_str = "compute" ; + else if ( node_ptr->function == STORAGE_TYPE ) + node_ptr->function_str = "storage" ; + else + node_ptr->function_str = "" ; + + if ( node_ptr->subfunction == COMPUTE_TYPE ) + { + node_ptr->subfunction_str = "compute" ; + } + else if ( node_ptr->subfunction == STORAGE_TYPE ) + { + node_ptr->subfunction_str = "storage" ; + } + else + node_ptr->subfunction_str = "" ; + } + rc = PASS ; + } + return (rc); +} + + + + + +/** Fetch the node type (compute or controller) by hostname */ +int nodeLinkClass::get_nodetype ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + return ( node_ptr->nodetype ); + } + return (false); +} + +/** Check if a node is a controller */ +bool nodeLinkClass::is_controller ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr != NULL ) + { + if ( (node_ptr->function & CONTROLLER_TYPE ) == CONTROLLER_TYPE ) + { + return (true); + } + } + return (false); +} + +/** Check if a node is a compute */ +bool nodeLinkClass::is_compute_subfunction ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr != NULL ) + { + if ( (node_ptr->subfunction & COMPUTE_TYPE ) == COMPUTE_TYPE ) + { + return (true); + } + } + return (false); +} + +/** Check if a node is a compute */ +bool nodeLinkClass::is_compute ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr != NULL ) + { + if ( (node_ptr->function & COMPUTE_TYPE ) == COMPUTE_TYPE ) + { + return (true); + } + } + return (false); +} + +/** Check if a node is a storage */ +bool nodeLinkClass::is_storage ( struct nodeLinkClass::node * node_ptr ) +{ + if ( node_ptr != NULL ) + { + if ( (node_ptr->function & STORAGE_TYPE ) == STORAGE_TYPE ) + { + return (true); + } + } + return (false); +} + +string nodeLinkClass::get_node_function_str ( string hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ); + if ( node_ptr != NULL ) + { + return node_ptr->function_str ; + } + return "unknown" ; +} + +string nodeLinkClass::get_node_subfunction_str ( string hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ); + if ( node_ptr != NULL ) + { + return node_ptr->subfunction_str ; + } + return "unknown" ; +} + +/** Check if a node is a controller */ +bool nodeLinkClass::is_controller ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ); + return is_controller(node_ptr); +} + +/** Check if a node is a compute */ +bool nodeLinkClass::is_compute ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ); + return is_compute(node_ptr); +} + +/** Check if a node is a compute */ +bool nodeLinkClass::is_compute_subfunction ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ); + return is_compute_subfunction(node_ptr); +} + +/** Check if a node is a storage */ +bool nodeLinkClass::is_storage ( string & hostname ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ); + return is_storage(node_ptr); +} + +/** Maintenance FSM Test Case Setup procedure */ +int nodeLinkClass::set_enableStage ( string & hostname, + mtc_enableStages_enum stage ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + node_ptr->handlerStage.enable = stage ; + return (PASS); + } + return (FAIL); +} + +/* Set the reboot stage */ +int nodeLinkClass::set_rebootStage ( string & hostname, mtc_resetProgStages_enum stage ) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + node_ptr->resetProgStage = stage ; + return (PASS); + } + return (FAIL); +} + +/** Maintenance FSM Test Case Setup procedure */ +mtc_enableStages_enum nodeLinkClass::get_enableStage ( string & hostname) +{ + nodeLinkClass::node * node_ptr = getNode ( hostname ) ; + if ( node_ptr != NULL ) + { + return ( node_ptr->handlerStage.enable ) ; + } + return (MTC_ENABLE__STAGES); +} + +int nodeLinkClass::allStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAdminState_enum adminState, + mtc_nodeOperState_enum operState, + mtc_nodeAvailStatus_enum availStatus ) +{ + int rc = FAIL ; + + if (( adminState < MTC_ADMIN_STATES ) && + ( operState < MTC_OPER_STATES ) && + ( availStatus < MTC_AVAIL_STATUS )) + { + bool change = false ; + if (( node_ptr->adminState != adminState ) || + ( node_ptr->operState != operState ) || + ( node_ptr->availStatus != availStatus )) + { + change = true ; + } + + string admin = mtc_nodeAdminState_str [adminState ] ; + string oper = mtc_nodeOperState_str [operState ] ; + string avail = mtc_nodeAvailStatus_str[availStatus] ; + + rc = mtcInvApi_force_states ( node_ptr, admin, oper, avail ); + + admin_state_change ( node_ptr->hostname, admin ); + + if ((( operState == MTC_OPER_STATE__DISABLED ) && ( node_ptr->operState != MTC_OPER_STATE__DISABLED )) && + (( availStatus == MTC_AVAIL_STATUS__FAILED ) && ( node_ptr->availStatus != MTC_AVAIL_STATUS__FAILED ))) + { + failed_state_change ( node_ptr ); + } + else + { + oper_state_change ( node_ptr->hostname, oper ); + avail_status_change ( node_ptr->hostname, avail ); + } + + if ( change == true ) + { + /* after */ + ilog ("%s %s-%s-%s (seq:%d)\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState ], + mtc_nodeOperState_str [node_ptr->operState ], + mtc_nodeAvailStatus_str[node_ptr->availStatus], + node_ptr->oper_sequence-1); + } + } + else + { + slog ("Invalid State (%d:%d:%d)\n", adminState, operState, availStatus ); + } + return (rc); +} + +int nodeLinkClass::subfStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeOperState_enum operState_subf, + mtc_nodeAvailStatus_enum availStatus_subf ) +{ + int rc = FAIL ; + + if (( operState_subf < MTC_OPER_STATES ) && + ( availStatus_subf < MTC_AVAIL_STATUS )) + { + bool change = false ; + if (( node_ptr->operState_subf != operState_subf ) || + ( node_ptr->availStatus_subf != availStatus_subf )) + { + change = true ; + } + + string oper = mtc_nodeOperState_str [operState_subf ] ; + string avail = mtc_nodeAvailStatus_str[availStatus_subf] ; + + rc = mtcInvApi_subf_states ( node_ptr, oper, avail ); + + node_ptr->operState_subf = operState_subf ; + node_ptr->availStatus_subf = availStatus_subf; + + if ( change == true ) + { + /* after */ + ilog ("%s-%s %s-%s-%s (seq:%d)\n", + node_ptr->hostname.c_str(), + node_ptr->subfunction_str.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState ], + mtc_nodeOperState_str [node_ptr->operState_subf ], + mtc_nodeAvailStatus_str[node_ptr->availStatus_subf], + node_ptr->oper_sequence-1); + } + } + else + { + slog ("Invalid State (%d:%d:%d)\n", node_ptr->adminState, availStatus_subf, availStatus_subf ); + } + return (rc); +} + + + + + +/** + * Set the required action and then let the FSP and handlers deal with it + * If we are in an action already then just add the action to the + * action todo list. When we chnage the action to none then query the + * todo list and pop it off and apply it + **/ +int nodeLinkClass::adminActionChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAdminAction_enum newActionState ) +{ + int rc = FAIL ; + + + if (( newActionState < MTC_ADMIN_ACTIONS ) && + ( node_ptr->adminAction < MTC_ADMIN_ACTIONS )) + { + rc = PASS ; + + if ( node_ptr->adminAction == newActionState ) + { + /* no action change */ + return (rc); + } + + /** + * Any of these actions need to complete before any + * other action can take effect. + * If its not one of these action then just proceed with it + **/ + if (( node_ptr->adminAction != MTC_ADMIN_ACTION__ADD ) && + ( node_ptr->adminAction != MTC_ADMIN_ACTION__FORCE_LOCK )) + { + clog ("%s Administrative Action '%s' -> '%s'\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [node_ptr->adminAction], + mtc_nodeAdminAction_str [newActionState]); + } + /* handle queue'd requests if here are any and + * we are done with the curent action */ + else if (( newActionState == MTC_ADMIN_ACTION__NONE ) && + ( !node_ptr->adminAction_todo_list.empty())) + { + newActionState = *(node_ptr->adminAction_todo_list.begin()); + node_ptr->adminAction_todo_list.pop_front(); + + clog ("%s Administrative Action '%s' -> '%s' from queue\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [node_ptr->adminAction], + mtc_nodeAdminAction_str [newActionState]); + } + /* queue the request if we are already acting on a current action + * ... handle unsupported action queueing conditions */ + else if (( node_ptr->adminAction != MTC_ADMIN_ACTION__NONE ) && + ( newActionState != MTC_ADMIN_ACTION__NONE )) + { + /* refuse to add duplicate action */ + if ( newActionState == node_ptr->adminAction ) + { + wlog ("%s refusing to queue duplicate of current action (%s)\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [node_ptr->adminAction] ); + + return (FAIL); + } + else if ( node_ptr->adminAction_todo_list.size() >= MTC_MAX_QUEUED_ACTIONS ) + { + wlog ("%s rejecting action '%s' request ; max queued actions reached (%ld of %d)\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [newActionState], + node_ptr->adminAction_todo_list.size(), + MTC_MAX_QUEUED_ACTIONS ); + return (FAIL); + } + + /* refuse to queue action that already exists in the queue */ + else + { + list::iterator adminAction_todo_list_ptr ; + for ( adminAction_todo_list_ptr = node_ptr->adminAction_todo_list.begin(); + adminAction_todo_list_ptr != node_ptr->adminAction_todo_list.end(); + adminAction_todo_list_ptr++ ) + { + if ( *adminAction_todo_list_ptr == newActionState ) + { + wlog ("%s refusing to queue duplicate already queued action (%s)\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [*adminAction_todo_list_ptr]); + + return (FAIL); + } + } + } + /* Add the action to the action todo list */ + node_ptr->adminAction_todo_list.push_back( newActionState ); + + ilog ("%s Administrative Action '%s' queued ; already handling '%s' action\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [newActionState], + mtc_nodeAdminAction_str [node_ptr->adminAction]); + return (PASS); + } + /* otherwise just take the action change */ + else + { + clog ("%s Administrative Action '%s' -> '%s'\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [node_ptr->adminAction], + mtc_nodeAdminAction_str [newActionState]); + } + + mtc_nodeAdminAction_enum oldActionState = node_ptr->adminAction ; + log_adminAction ( node_ptr->hostname, oldActionState, newActionState ); + + node_ptr->adminAction = newActionState ; + node_ptr->action = mtc_nodeAdminAction_str [node_ptr->adminAction] ; + + /* If we are starting a new ( not 'none' ) action ... + * be sure we start at the beginning */ + if ( newActionState != MTC_ADMIN_ACTION__NONE ) + { + if (( oldActionState == MTC_ADMIN_ACTION__POWERCYCLE ) && + (( newActionState != MTC_ADMIN_ACTION__POWERCYCLE ) && + ( newActionState != MTC_ADMIN_ACTION__POWEROFF ))) + { + blog ("%s (mon:%d:prov:%d)\n", node_ptr->hostname.c_str(), node_ptr->hwmond_monitor, node_ptr->bm_provisioned ); + + if (( node_ptr->hwmond_monitor == false ) && ( node_ptr->bm_provisioned == true )) + { + send_hwmon_command ( node_ptr->hostname, MTC_CMD_ADD_HOST ); + send_hwmon_command ( node_ptr->hostname, MTC_CMD_START_HOST ); + } + } + /* Lets ensure that the handlers start in the right stage + * The enable_handler -> MTC_ENABLE__START + * The disable_handler -> MTC_DISABLE__START + * The reset_handler -> MTC_RESET__START + * The reboot_handler -> MTC_RESET__START + * + * This is a little detailed but exists for maintainability + * All START stages are 0. + */ + switch ( newActionState ) + { + case MTC_ADMIN_ACTION__UNLOCK: + { + if ( oldActionState != MTC_ADMIN_ACTION__UNLOCK ) + { + node_ptr->node_unlocked_counter++ ; + } + + if ( is_controller ( node_ptr ) ) + autorecovery_clear (node_ptr->hostname); + + node_ptr->handlerStage.enable = MTC_ENABLE__START ; + break ; + } + case MTC_ADMIN_ACTION__LOCK: + case MTC_ADMIN_ACTION__FORCE_LOCK: + { + node_ptr->handlerStage.disable = MTC_DISABLE__START ; + break ; + } + case MTC_ADMIN_ACTION__RESET: + { + node_ptr->resetStage = MTC_RESET__START ; + break ; + } + case MTC_ADMIN_ACTION__REBOOT: + { + break ; + } + case MTC_ADMIN_ACTION__REINSTALL: + { + node_ptr->reinstallStage = MTC_REINSTALL__START ; + break ; + } + case MTC_ADMIN_ACTION__POWERON: + { + node_ptr->powerStage = MTC_POWERON__START ; + break ; + } + case MTC_ADMIN_ACTION__RECOVER: + { + if ( node_ptr->mtcTimer.tid ) + { + mtcTimer_stop ( node_ptr->mtcTimer ) ; + } + if ( node_ptr->mtcSwact_timer.tid ) + { + mtcTimer_stop ( node_ptr->mtcSwact_timer ) ; + } + node_ptr->recoveryStage = MTC_RECOVERY__START ; + break ; + } + + case MTC_ADMIN_ACTION__POWEROFF: + { + node_ptr->powerStage = MTC_POWEROFF__START ; + break ; + } + case MTC_ADMIN_ACTION__DELETE: + { + node_ptr->delStage = MTC_DEL__START ; + break ; + } + case MTC_ADMIN_ACTION__ENABLE: + default: + { + break ; + } + } + } + } + return (rc); +} + +int nodeLinkClass::adminStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAdminState_enum newAdminState ) +{ + int rc = FAIL ; + + if (( newAdminState < MTC_ADMIN_STATES ) && + ( node_ptr->adminState < MTC_ADMIN_STATES )) + { + rc = PASS ; + + /* See if we are actually changing the state */ + if ( node_ptr->adminState != newAdminState ) + { + ilog ("%s %s-%s-%s' -> %s-%s-%s\n", node_ptr->hostname.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState], + mtc_nodeOperState_str [node_ptr->operState], + mtc_nodeAvailStatus_str[node_ptr->availStatus], + mtc_nodeAdminState_str [newAdminState], + mtc_nodeOperState_str [node_ptr->operState], + mtc_nodeAvailStatus_str[node_ptr->availStatus]); + node_ptr->adminState = newAdminState ; + } + } + else + { + slog ("Invalid Host Operational State (now:%d new:%d)\n", + node_ptr->adminState, newAdminState ); + } + return (rc); +} + + +int nodeLinkClass::operStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeOperState_enum newOperState ) +{ + int rc = FAIL ; + + if (( newOperState < MTC_OPER_STATES ) && + ( node_ptr->operState < MTC_OPER_STATES )) + { + rc = PASS ; + + /* See if we are actually changing the state */ + if ( node_ptr->operState != newOperState ) + { + clog ("%s %s-%s-%s\n", node_ptr->hostname.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState], + mtc_nodeOperState_str [node_ptr->operState], + mtc_nodeAvailStatus_str[node_ptr->availStatus]); + + /* Push it to the database */ + if ( node_ptr->uuid.length() == UUID_LEN ) + { + string key = MTC_JSON_INV_OPER ; + string value = operState_enum_to_str(newOperState) ; + rc = mtcInvApi_update_state ( node_ptr, key, value ); + } + else + { + wlog ("%s has invalid uuid:%s so %s state not written to database\n", + node_ptr->hostname.c_str(), + node_ptr->uuid.c_str(), + operState_enum_to_str(newOperState).c_str()); + } + + node_ptr->operState = newOperState ; + + clog ("%s %s-%s-%s\n", node_ptr->hostname.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState], + mtc_nodeOperState_str [node_ptr->operState], + mtc_nodeAvailStatus_str[node_ptr->availStatus]); + } + } + else + { + slog ("Invalid Host Operational State (now:%d new:%d)\n", + node_ptr->operState, newOperState ); + } + return (rc); +} + +int nodeLinkClass::availStatusChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAvailStatus_enum newAvailStatus ) +{ + int rc = FAIL ; + + if (( newAvailStatus < MTC_AVAIL_STATUS ) && + ( node_ptr->availStatus < MTC_AVAIL_STATUS )) + { + rc = PASS ; + + /* See if we are actually changing the state */ + if ( node_ptr->availStatus != newAvailStatus ) + { + clog ("%s %s-%s-%s\n", node_ptr->hostname.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState], + mtc_nodeOperState_str [node_ptr->operState], + mtc_nodeAvailStatus_str[node_ptr->availStatus]); + + /* Push it to the database */ + if ( node_ptr->uuid.length() == UUID_LEN ) + { + string key = MTC_JSON_INV_AVAIL ; + string value = availStatus_enum_to_str(newAvailStatus) ; + rc = mtcInvApi_update_state ( node_ptr, key, value ); + if ( rc != PASS ) + { + wlog ("%s Failed to update availability '%s' to '%s'\n", + node_ptr->hostname.c_str(), + mtc_nodeAvailStatus_str[node_ptr->availStatus], + mtc_nodeAvailStatus_str[newAvailStatus]); + } + } + else + { + wlog ("%s has invalid uuid:%s so %s state not written to database\n", + node_ptr->hostname.c_str(), + node_ptr->uuid.c_str(), + availStatus_enum_to_str(newAvailStatus).c_str()); + } + + if (( node_ptr->operState == MTC_OPER_STATE__ENABLED ) && + (( node_ptr->availStatus == MTC_AVAIL_STATUS__AVAILABLE ) || + ( node_ptr->availStatus == MTC_AVAIL_STATUS__DEGRADED )) && + ( newAvailStatus == MTC_AVAIL_STATUS__FAILED )) + { + enableStageChange ( node_ptr, MTC_ENABLE__START ); + } + + /* if we go to the failed state then clear all mtcAlive counts + * so that the last ones don't look like we are online when we + * might not be - we should relearn the on/off line state */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__FAILED ) && + ( newAvailStatus == MTC_AVAIL_STATUS__FAILED )) + { + node_ptr->mtcAlive_misses = 0 ; + node_ptr->mtcAlive_hits = 0 ; + node_ptr->mtcAlive_gate = false ; + } + + /* check for need to generate power on log */ + if (( node_ptr->availStatus == MTC_AVAIL_STATUS__POWERED_OFF ) && + ( newAvailStatus != MTC_AVAIL_STATUS__POWERED_OFF )) + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__POWERON ) + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_MANUAL_POWER_ON ); + } + else + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_AUTO_POWER_ON ); + } + } + + /* check for need to generate power off log */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__POWERED_OFF ) && + ( newAvailStatus == MTC_AVAIL_STATUS__POWERED_OFF )) + { + if ( node_ptr->adminAction == MTC_ADMIN_ACTION__POWEROFF ) + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_MANUAL_POWER_OFF ); + } + else + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__COMMAND_AUTO_POWER_OFF ); + } + } + + /* check for need to generate online log */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__ONLINE ) && + ( newAvailStatus == MTC_AVAIL_STATUS__ONLINE )) + { + if ( node_ptr->offline_log_reported == true ) + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__STATUSCHANGE_ONLINE ); + node_ptr->offline_log_reported = false ; + node_ptr->online_log_reported = true ; + } + } + + /* check for need to generate offline log */ + if (( node_ptr->availStatus != MTC_AVAIL_STATUS__OFFLINE ) && + ( newAvailStatus == MTC_AVAIL_STATUS__OFFLINE )) + { + if ( node_ptr->online_log_reported == true ) + { + mtcAlarm_log ( node_ptr->hostname, MTC_LOG_ID__STATUSCHANGE_OFFLINE ); + node_ptr->offline_log_reported = true ; + node_ptr->online_log_reported = false ; + } + } + + /* If the availability status is moving away from off or online then + * be sure we cancel the mtcAlive timer */ + if ((( node_ptr->availStatus == MTC_AVAIL_STATUS__OFFLINE ) || + ( node_ptr->availStatus == MTC_AVAIL_STATUS__ONLINE )) && + (( newAvailStatus != MTC_AVAIL_STATUS__OFFLINE ) && + ( newAvailStatus != MTC_AVAIL_STATUS__ONLINE ))) + { + /* Free the mtc timer if in use */ + if ( node_ptr->mtcAlive_timer.tid ) + { + tlog ("%s Stopping mtcAlive timer\n", node_ptr->hostname.c_str()); + mtcTimer_stop ( node_ptr->mtcAlive_timer ); + node_ptr->mtcAlive_timer.ring = false ; + node_ptr->mtcAlive_timer.tid = NULL ; + } + node_ptr->onlineStage = MTC_ONLINE__START ; + } + + + clog ("%s %s-%s-%s\n", node_ptr->hostname.c_str(), + mtc_nodeAdminState_str [node_ptr->adminState], + mtc_nodeOperState_str [node_ptr->operState], + mtc_nodeAvailStatus_str[node_ptr->availStatus]); + + node_ptr->availStatus = newAvailStatus ; + } + } + else + { + slog ("Invalid Host Availability Status (now:%d new:%d)\n", + node_ptr->availStatus, newAvailStatus ); + } + return (rc); +} + +/** Host Enable Handler Stage Change member function */ +int nodeLinkClass::enableStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_enableStages_enum newHdlrStage ) +{ + /* TODO: Consider converting stage to strings ... */ + if (( newHdlrStage >= MTC_ENABLE__STAGES ) || + ( node_ptr->handlerStage.enable >= MTC_ENABLE__STAGES )) + { + slog ("%s has invalid Enable stage (%d:%d)\n", + node_ptr->hostname.c_str(), + node_ptr->handlerStage.enable, + newHdlrStage ); + + node_ptr->handlerStage.enable = MTC_ENABLE__FAILURE ; + + /* TODO: cause failed or degraded state ? */ + return (FAIL); + } + else if ( node_ptr->handlerStage.enable != newHdlrStage ) + { + clog ("%s %s -> %s\n", + node_ptr->hostname.c_str(), + get_enableStages_str(node_ptr->handlerStage.enable).c_str(), + get_enableStages_str(newHdlrStage).c_str()); + + node_ptr->handlerStage.enable = newHdlrStage ; + return (PASS); + } + else + { + /* No state change */ + dlog1 ("%s %s -> %s\n", + node_ptr->hostname.c_str(), + get_enableStages_str(node_ptr->handlerStage.enable).c_str(), + get_enableStages_str(newHdlrStage).c_str()); + return (PASS); + } +} + +/** Host Disable Handler Stage Change member function */ +int nodeLinkClass::disableStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_disableStages_enum newHdlrStage ) +{ + /* TODO: Consider converting stage to strings ... */ + if (( newHdlrStage >= MTC_DISABLE__STAGES ) || + ( node_ptr->handlerStage.disable >= MTC_DISABLE__STAGES )) + { + slog ("%s has invalid disable stage (%d:%d)\n", + node_ptr->hostname.c_str(), + node_ptr->handlerStage.disable, + newHdlrStage ); + + node_ptr->handlerStage.disable = MTC_DISABLE__DISABLED ; + + /* TODO: cause failed or degraded state ? */ + return (FAIL); + } + else + { + clog ("%s %s -> %s\n", + node_ptr->hostname.c_str(), + get_disableStages_str(node_ptr->handlerStage.disable).c_str(), + get_disableStages_str(newHdlrStage).c_str()); + + node_ptr->handlerStage.disable = newHdlrStage ; + return (PASS); + } +} + +/** Validate and log Recovery stage changes */ +int nodeLinkClass::recoveryStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_recoveryStages_enum newHdlrStage ) +{ + int rc = PASS ; + + if (( newHdlrStage >= MTC_RECOVERY__STAGES ) || + ( node_ptr->recoveryStage >= MTC_RECOVERY__STAGES )) + { + slog ("%s Invalid recovery stage (%d:%d)\n", + node_ptr->hostname.c_str(), + node_ptr->recoveryStage, + newHdlrStage ); + + if ( newHdlrStage < MTC_RECOVERY__STAGES ) + { + clog ("%s ? -> %s\n", + node_ptr->hostname.c_str(), + get_recoveryStages_str(newHdlrStage).c_str()); + + node_ptr->recoveryStage = newHdlrStage ; + } + else + { + node_ptr->recoveryStage = MTC_RECOVERY__FAILURE ; + rc = FAIL ; + } + } + else + { + clog ("%s %s -> %s\n", + node_ptr->hostname.c_str(), + get_recoveryStages_str(node_ptr->recoveryStage).c_str(), + get_recoveryStages_str(newHdlrStage).c_str()); + + node_ptr->recoveryStage = newHdlrStage ; + } + return (rc) ; +} + + +/** Validate and log Recovery stage changes */ +int nodeLinkClass::configStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_configStages_enum newHdlrStage ) +{ + int rc = PASS ; + + if (( newHdlrStage >= MTC_CONFIG__STAGES ) || + ( node_ptr->configStage >= MTC_CONFIG__STAGES )) + { + slog ("%s Invalid config stage (%d:%d)\n", + node_ptr->hostname.c_str(), + node_ptr->configStage, + newHdlrStage ); + + if ( newHdlrStage < MTC_CONFIG__STAGES ) + { + clog ("%s ? -> %s\n", + node_ptr->hostname.c_str(), + get_configStages_str(newHdlrStage).c_str()); + + node_ptr->configStage = newHdlrStage ; + } + else + { + node_ptr->configStage = MTC_CONFIG__FAILURE ; + rc = FAIL ; + } + } + else + { + clog ("%s %s -> %s\n", + node_ptr->hostname.c_str(), + get_configStages_str(node_ptr->configStage).c_str(), + get_configStages_str(newHdlrStage).c_str()); + + node_ptr->configStage = newHdlrStage ; + } + return (rc) ; +} + +/** Host Reset Handler Stage Change member function */ +int nodeLinkClass::resetStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_resetStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_RESET__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_resetStages_str(node_ptr->resetStage).c_str(), + get_resetStages_str(newHdlrStage).c_str()); + + node_ptr->resetStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid reset stage (%d)\n", node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->resetStage = MTC_RESET__DONE ; + return (FAIL) ; + } +} + +/* Host Reset Handler Stage Change member function */ +int nodeLinkClass::reinstallStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_reinstallStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_REINSTALL__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_reinstallStages_str(node_ptr->reinstallStage).c_str(), + get_reinstallStages_str(newHdlrStage).c_str()); + + node_ptr->reinstallStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid reinstall stage (%d)\n", node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->reinstallStage = MTC_REINSTALL__DONE ; + return (FAIL) ; + } +} + +/** Host Power control Handler Stage Change member function */ +int nodeLinkClass::powerStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_powerStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_POWER__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_powerStages_str(node_ptr->powerStage).c_str(), + get_powerStages_str(newHdlrStage).c_str()); + + node_ptr->powerStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid power control stage (%d)\n", + node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->powerStage = MTC_POWER__DONE ; + return (FAIL) ; + } +} + +/** Host Power Cycle control Handler Stage Change member function */ +int nodeLinkClass::powercycleStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_powercycleStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_POWERCYCLE__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_powercycleStages_str(node_ptr->powercycleStage).c_str(), + get_powercycleStages_str(newHdlrStage).c_str()); + + node_ptr->powercycleStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid powercycle stage (%d)\n", + node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->powercycleStage = MTC_POWERCYCLE__DONE ; + return (FAIL) ; + } +} + + +/** Host Out-Of-Service Stage Change member function */ +int nodeLinkClass::oosTestStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_oosTestStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_OOS_TEST__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_oosTestStages_str(node_ptr->oosTestStage).c_str(), + get_oosTestStages_str(newHdlrStage).c_str()); + + node_ptr->oosTestStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid oos test stage (%d)\n", node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->oosTestStage = MTC_OOS_TEST__DONE ; + return (FAIL) ; + } +} + +/** Host in-Service Stage Change member function */ +int nodeLinkClass::insvTestStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_insvTestStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_INSV_TEST__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_insvTestStages_str(node_ptr->insvTestStage).c_str(), + get_insvTestStages_str(newHdlrStage).c_str()); + + node_ptr->insvTestStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid insv test stage (%d)\n", node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->insvTestStage = MTC_INSV_TEST__START ; + return (FAIL) ; + } +} + +/** SubStage Change member function */ +int nodeLinkClass::subStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_subStages_enum newHdlrStage ) +{ + if ( newHdlrStage < MTC_SUBSTAGE__STAGES ) + { + clog ("%s stage %s -> %s\n", + node_ptr->hostname.c_str(), + get_subStages_str(node_ptr->subStage).c_str(), + get_subStages_str(newHdlrStage).c_str()); + + node_ptr->subStage = newHdlrStage ; + return (PASS) ; + } + else + { + slog ("%s Invalid 'subStage' stage (%d)\n", + node_ptr->hostname.c_str(), newHdlrStage ); + node_ptr->subStage = MTC_SUBSTAGE__DONE ; + return (FAIL) ; + } +} + +struct nodeLinkClass::node * nodeLinkClass::get_mtcTimer_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->mtcTimer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_mtcCmd_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->mtcCmd_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_host_services_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->host_services_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_http_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->http_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_thread_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->ipmitool_thread_ctrl.timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_ping_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->bm_ping_info.timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_bm_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->bm_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_bmc_access_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->bmc_access_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + + + +struct nodeLinkClass::node * nodeLinkClass::get_mtcConfig_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->mtcConfig_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_powercycle_control_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->hwmon_powercycle.control_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_reset_control_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->hwmon_reset.control_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_powercycle_recovery_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->hwmon_powercycle.recovery_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_reset_recovery_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->hwmon_reset.recovery_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_mtcAlive_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->mtcAlive_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + + +struct nodeLinkClass::node * nodeLinkClass::get_offline_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->offline_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + + +struct nodeLinkClass::node * nodeLinkClass::get_mtcSwact_timer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->mtcSwact_timer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_oosTestTimer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->oosTestTimer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + +struct nodeLinkClass::node * nodeLinkClass::get_insvTestTimer ( timer_t tid ) +{ + /* check for empty list condition */ + if ( tid != NULL ) + { + for ( struct node * ptr = head ; ; ptr = ptr->next ) + { + if ( ptr->insvTestTimer.tid == tid ) + { + return ptr ; + } + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + } + return static_cast(NULL); +} + + +/***************************************************************************** + * + * Name : autorecovery_clear + * + * Assumptions: Applies when simplex. + * + * Description: Removes the auto recovery count file if it exists. + * + * Auto recovery count is tracked/preserved in a host named auto recovery + * counter file /tmp/hostname_ar_count. + * + *****************************************************************************/ + +#define TMP_DIR_PATH ((const char *)"/etc/mtc/tmp/") +#define AUTO_RECOVERY_FILE_SUFFIX ((const char *)"_ar_count") + +void autorecovery_clear ( string hostname ) +{ + string ar_file = TMP_DIR_PATH + hostname + AUTO_RECOVERY_FILE_SUFFIX ; + if ( daemon_is_file_present (ar_file.data())) + { + wlog ("%s clearing autorecovery counter\n", hostname.c_str()); + daemon_remove_file (ar_file.data()); + } +} + +/***************************************************************************** + * + * Name : manage_autorecovery + * + * Assumptions: Applies to the active controller only while simplex. + * + * Description: Issues an immediate lazy reboot if the autorecovery threshold + * is reached. Otherwise it disables autorecovery and returns + * do we don't get a rolling boot loop. + * + * Auto recovery count is tracked/preserved in a host named auto recovery + * counter file /etc/mtc/tmp/hostname_ar_count. + * + * in the event of a persistent autorecovery failure that results in a + * disable then the active controller goes enabled-degraded with a horizon + * status that indicates the active controller has a critical failure but + * auto recovery is disabled. The enable alarm is raised. + * + *****************************************************************************/ + +void nodeLinkClass::manage_autorecovery ( struct nodeLinkClass::node * node_ptr ) +{ + /* manage removing the auto recovery threshold count file */ + if ( ( THIS_HOST ) && + ( this->autorecovery_enabled == true ) && + ( this->autorecovery_disabled == false ) && + ( is_inactive_controller_main_insv() == false )) + { + int value = 0 ; + string ar_file = TMP_DIR_PATH + node_ptr->hostname + AUTO_RECOVERY_FILE_SUFFIX ; + int threshold = daemon_get_cfg_ptr()->autorecovery_threshold ; + + if ( daemon_is_file_present (ar_file.data())) + { + /* if the file is there then read the count and increment it */ + value = daemon_get_file_int ( ar_file.data() ); + } + value++ ; + + /* Save the new value in the file */ + daemon_log_value ( ar_file.data(), value ); + + /* set rc to reflect what the caller should do */ + if ( value > threshold ) + { + elog ("%s auto recovery threshold exceeded (%d)\n", + node_ptr->hostname.c_str(), threshold ); + + this->autorecovery_disabled = true ; + + if ( this->system_type == SYSTEM_TYPE__CPE_MODE__SIMPLEX ) + { + alarm_compute_failure ( node_ptr , FM_ALARM_SEVERITY_CRITICAL ) ; + } + else + { + alarm_enabled_failure ( node_ptr ) ; + } + + allStateChange ( node_ptr, node_ptr->adminState, + MTC_OPER_STATE__ENABLED, + MTC_AVAIL_STATUS__DEGRADED ); + + mtcInvApi_update_task ( node_ptr, + MTC_TASK_AUTO_RECOVERY_DISABLED ); + + return ; + } + + wlog ("%s auto recovery (try %d of %d)\n", + node_ptr->hostname.c_str(), value , threshold ); + + mtcInvApi_update_states_now ( node_ptr, + "unlocked", + "disabled", + "failed", + "disabled", + "failed" ); + + mtcInvApi_update_task_now ( node_ptr, + MTC_TASK_AUTO_RECOVERY ); + + lazy_graceful_fs_reboot ( node_ptr ); + } +} + +/**************************************************************************** + * + * Name : report_dor_recovery + * + * Description: Create a specifically formatted log for the the specified + * hosts DOR recovery state and timing. + * + * Parameters : The node and a caller prefix string that states if the node + * is ENABELD + * is FAILED + * is ENMABLED-degraded + * etc. + * + ***************************************************************************/ +void nodeLinkClass::report_dor_recovery ( struct nodeLinkClass::node * node_ptr, + string node_state_log_prefix ) +{ + struct timespec ts ; + clock_gettime (CLOCK_MONOTONIC, &ts ); + node_ptr->dor_recovery_time = ts.tv_sec ; + plog ("%-12s %s ; DOR Recovery %2d:%02d mins (%4d secs) (uptime:%2d:%02d mins)\n", + node_ptr->hostname.c_str(), + node_state_log_prefix.c_str(), + node_ptr->dor_recovery_time/60, + node_ptr->dor_recovery_time%60, + node_ptr->dor_recovery_time, + node_ptr->uptime/60, + node_ptr->uptime%60 ); + + node_ptr->dor_recovery_mode = false ; + node_ptr->was_dor_recovery_mode = false ; +} + +void nodeLinkClass::force_full_enable ( struct nodeLinkClass::node * node_ptr ) +{ + /* don't do a full enable if active controller in simplex mode */ + if ( THIS_HOST && SIMPLEX ) + { + wlog ("%s avoiding full enable of simplex system\n", node_ptr->hostname.c_str()); + wlog ("%s ... lock and unlock host to force recovery\n", node_ptr->hostname.c_str()); + return ; + } + + if ( node_ptr->was_dor_recovery_mode ) + { + report_dor_recovery ( node_ptr , "is FAILED " ); + } + + plog ("%s Forcing Full Enable Sequence\n", node_ptr->hostname.c_str()); + + /* Raise Critical Enable Alarm */ + alarm_enabled_failure ( node_ptr ); + + allStateChange ( node_ptr, node_ptr->adminState, MTC_OPER_STATE__DISABLED, MTC_AVAIL_STATUS__FAILED ); + enableStageChange ( node_ptr, MTC_ENABLE__FAILURE ); + recoveryStageChange ( node_ptr, MTC_RECOVERY__START ); /* reset the fsm */ + // don't override the add action or lock actions / + if (( node_ptr->adminAction != MTC_ADMIN_ACTION__ADD ) && + ( node_ptr->adminAction != MTC_ADMIN_ACTION__LOCK ) && + ( node_ptr->adminAction != MTC_ADMIN_ACTION__FORCE_LOCK )) + { + adminActionChange ( node_ptr, MTC_ADMIN_ACTION__NONE ); // no action + } + else + { + wlog ("%s refusing to override '%s' action with 'none' action\n", + node_ptr->hostname.c_str(), + mtc_nodeAdminAction_str [node_ptr->adminAction]); + } +} + +/***************************************************************************** + * + * Name : launch_host_services_cmd + * + * Description: This is a multi timeslice service that is executed + * by the command handler. + * + * This interface just determines the host type and loads the + * command handler with the host type corresponding host + * services command based on the start bool. If 'subf' is + * specified then the start or stop command defaults to COMPUTE. + * + * Supported Commands are defined in nodeBase.h + * + * start = False (means stop) + * + * MTC_CMD_STOP_CONTROL_SVCS + * MTC_CMD_STOP_COMPUTE_SVCS + * MTC_CMD_STOP_STORAGE_SVCS + * + * start = True + * + * MTC_CMD_START_CONTROL_SVCS + * MTC_CMD_START_COMPUTE_SVCS + * MTC_CMD_START_STORAGE_SVCS + * + * Returns : PASS = launch success + * !PASS = launch failure + * + ****************************************************************************/ + +int nodeLinkClass::launch_host_services_cmd ( struct nodeLinkClass::node * node_ptr, bool start, bool subf ) +{ + if ( !node_ptr ) + return (FAIL_NULL_POINTER); + + /* Initialize the host's command request control structure */ + mtcCmd_init ( node_ptr->host_services_req ); + + /* Service subfunction override first, efficiency. */ + if ( subf == true ) + { + /* only supported subfunction (right now) is COMPUTE */ + if ( start == true ) + node_ptr->host_services_req.cmd = MTC_CMD_START_COMPUTE_SVCS ; + else + node_ptr->host_services_req.cmd = MTC_CMD_STOP_COMPUTE_SVCS ; + } + else if ( start == true ) + { + if ( is_controller (node_ptr) ) + node_ptr->host_services_req.cmd = MTC_CMD_START_CONTROL_SVCS ; + else if ( is_compute (node_ptr) ) + node_ptr->host_services_req.cmd = MTC_CMD_START_COMPUTE_SVCS ; + else if ( is_storage (node_ptr) ) + node_ptr->host_services_req.cmd = MTC_CMD_START_STORAGE_SVCS ; + else + { + slog ("%s start host services is not supported for this host type\n", + node_ptr->hostname.c_str()); + return (FAIL_BAD_CASE) ; + } + } + else + { + if ( is_controller (node_ptr) ) + node_ptr->host_services_req.cmd = MTC_CMD_STOP_CONTROL_SVCS ; + else if ( is_compute (node_ptr) ) + node_ptr->host_services_req.cmd = MTC_CMD_STOP_COMPUTE_SVCS ; + else if ( is_storage (node_ptr) ) + node_ptr->host_services_req.cmd = MTC_CMD_STOP_STORAGE_SVCS ; + else + { + slog ("%s stop host services is not supported for this host type\n", + node_ptr->hostname.c_str()); + return (FAIL_BAD_CASE); + } + } + + /* Translate that command to its named string */ + node_ptr->host_services_req.name = + get_mtcNodeCommand_str(node_ptr->host_services_req.cmd); + + /* Get the host services timeout and add MTC_AGENT_TIMEOUT_EXTENSION + * seconds so that it is a bit longer than the mtcClient timeout */ + int timeout = daemon_get_cfg_ptr()->host_services_timeout ; + timeout+= MTC_AGENT_TIMEOUT_EXTENSION ; + + ilog ("%s %s launch\n", + node_ptr->hostname.c_str(), + node_ptr->host_services_req.name.c_str()); + + /* The launch part. + * init the */ + mtcCmd_init ( node_ptr->cmd ); + node_ptr->cmd.stage = MTC_CMD_STAGE__START ; + node_ptr->cmd.cmd = MTC_OPER__HOST_SERVICES_CMD ; + + node_ptr->mtcCmd_work_fifo.clear() ; + node_ptr->mtcCmd_work_fifo.push_front(node_ptr->cmd); + + /* start an unbrella timer and start waiting for the result, + * a little longer than the mtcClient version */ + mtcTimer_reset ( node_ptr->host_services_timer ); + mtcTimer_start ( node_ptr->host_services_timer, mtcTimer_handler, timeout ) ; + + + return (PASS); +} + +int send_event ( string & hostname, unsigned int cmd, iface_enum iface ); + +int nodeLinkClass::mon_host ( const string & hostname, iface_enum iface, bool true_false ) +{ + int rc = FAIL ; + if ( ! hostname.empty() ) + { + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->monitor[iface] = true_false ; + if ( true_false == true ) + { + node_ptr->no_work_log_throttle = 0 ; + node_ptr->b2b_misses_count[iface] = 0 ; + node_ptr->max_count[iface] = 0 ; + node_ptr->hbs_failure[iface] = false ; + send_event ( node_ptr->hostname, MTC_EVENT_HEARTBEAT_MINOR_CLR, iface ) ; + node_ptr->hbs_minor[iface] = false ; + send_event ( node_ptr->hostname, MTC_EVENT_HEARTBEAT_DEGRADE_CLR, iface ) ; + node_ptr->hbs_degrade[iface] = false ; + } + return PASS ; + } + } + return ( rc ); +} + +/* store the current hardware monitor monitoring state */ +void nodeLinkClass::set_hwmond_monitor_state ( string & hostname, bool state ) +{ + if ( hostname.length() ) + { + struct nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + node_ptr->hwmond_monitor = state ; + } + } +} + +/* get the current hardware monitor monitoring state */ +bool nodeLinkClass::get_hwmond_monitor_state ( string & hostname ) +{ + bool state = false ; + if ( hostname.length() ) + { + struct nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + state = node_ptr->hwmond_monitor ; + } + } + return (state); +} + +/* get the current heartbeat monitoring state */ +bool nodeLinkClass::get_hbs_monitor_state ( string & hostname, int iface ) +{ + bool state = false ; + if ( hostname.length() ) + { + struct nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + state = node_ptr->monitor[iface] ; + } + } + return (state); +} + +/* Manage the heartbeat pulse flags by hostname */ +void nodeLinkClass::manage_pulse_flags ( string & hostname, unsigned int flags ) +{ + if ( hostname.length() ) + { + struct nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + manage_pulse_flags ( node_ptr, flags ); + } + } +} + + +/* Manage the heartbeat pulse flags by pulse_ptr */ +void nodeLinkClass::manage_pulse_flags ( struct nodeLinkClass::node * node_ptr, unsigned int flags ) +{ + /* Do nothing with the flags for missing pulse + * responses (identified with flags=NULL_PULSE_FLAGS) */ + if ( flags == NULL_PULSE_FLAGS ) + { + return ; + } + + /* Code that manages enabling of Infrastructrure network moonitoring + * + * Algorithm: Only monitor a hosts infrastructure network while the + * management network of that same host is being monitored + * and while that host indicates support for the infrastructure + * network by setting the INFRA_FLAG in its management network + * pulse responses. */ + if ( node_ptr->monitor[MGMNT_IFACE] == false ) + { + node_ptr->monitor[INFRA_IFACE] = false ; + } + else if ( flags & INFRA_FLAG ) + { + /* TODO: Does this need to be debounced ??? */ + node_ptr->monitor[INFRA_IFACE] = true ; + } + + /* A host indicates that its process monitor is running by setting the + * PMOND_FLAG occasionally in its pulse response. + * The following if/else if clauses manage raising an alarm and degrading + * a host has stopped sending the PMOND_FLAG. */ + if ( flags & PMOND_FLAG ) + { + if ( node_ptr->pmon_degraded == true ) + { + if ( node_ptr->alarms[HBS_ALARM_ID__PMOND] != FM_ALARM_SEVERITY_CLEAR ) + { + alarm_clear ( node_ptr->hostname, PMOND_ALARM_ID, "pmond" ); + } + if ( send_event ( node_ptr->hostname, MTC_EVENT_PMOND_CLEAR, MGMNT_IFACE ) == PASS ) + { + node_ptr->alarms[HBS_ALARM_ID__PMOND] = FM_ALARM_SEVERITY_CLEAR ; + node_ptr->pmon_degraded = false ; + } + } + node_ptr->pmon_missing_count = 0 ; + node_ptr->stall_monitor_log_throttle = 0 ; + node_ptr->stall_recovery_log_throttle = 0 ; + } + else if ( ++node_ptr->pmon_missing_count > PMOND_MISSING_THRESHOLD ) + { + if ( node_ptr->pmon_degraded == false ) + { + wlog ("%s sending pmon degrade event to maintenance\n", node_ptr->hostname.c_str()); + if ( send_event ( node_ptr->hostname, MTC_EVENT_PMOND_RAISE, MGMNT_IFACE ) == PASS ) + { + node_ptr->pmon_degraded = true ; + node_ptr->alarms[HBS_ALARM_ID__PMOND] = FM_ALARM_SEVERITY_MAJOR ; + alarm_major ( node_ptr->hostname, PMOND_ALARM_ID, "pmond" ); + } + } + } + + /* A host indicates that a process stall condition exists by setting the + * STALL_REC_FLAG it its heartbeat pulse response messages */ + if ( flags & STALL_REC_FLAG ) + { + wlog ("%s hbsClient stall recovery action (flags:%08x)\n", node_ptr->hostname.c_str(), flags); + if ( node_ptr->stall_recovery_log_throttle++ == 0 ) + { + send_event ( node_ptr->hostname, MTC_EVENT_HOST_STALLED , MGMNT_IFACE ); + } + } + else if ( flags & STALL_MON_FLAG ) + { + if ( node_ptr->stall_monitor_log_throttle++ == 0 ) + { + wlog ("%s hbsClient running stall monitor (flags:%08x)\n", node_ptr->hostname.c_str(), flags ); + } + else if ( flags & STALL_ERROR_FLAGS ) + { + wlog ("%s hbsClient running stall monitor (flags:%08x)\n", node_ptr->hostname.c_str(), flags ); + } + } + + if ( node_ptr->stall_recovery_log_throttle > STALL_MSG_THLD ) + { + node_ptr->stall_recovery_log_throttle = 0 ; + } + if ( node_ptr->stall_monitor_log_throttle > STALL_MSG_THLD ) + { + node_ptr->stall_monitor_log_throttle = 0 ; + } +} + +/* Create the monitored pulse list for the specified interface */ +int nodeLinkClass::create_pulse_list ( iface_enum iface ) +{ + struct node * ptr = head ; + pulses[iface] = 0 ; + + /* No check-in list if there is no inventory */ + if (( head == NULL ) || ( hosts == 0 )) + { + return (pulses[iface]) ; + } + + if ( iface >= MAX_IFACES ) + { + dlog ("Invalid interface (%d)\n", iface ); + return (pulses[iface]); + } + + pulse_list[iface].last_ptr = NULL ; + pulse_list[iface].head_ptr = NULL ; + pulse_list[iface].tail_ptr = NULL ; + + /* walk the node list looking for nodes that should be monitored */ + for ( ; ptr != NULL ; ptr = ptr->next ) + { + if ( ptr->monitor[iface] == true ) + { + /* current monitored node pointer */ + pulse_ptr = ptr ; + + /* if first pulse node */ + if ( pulse_list[iface].head_ptr == NULL ) + { + /* need to keep track of the last node so we can deal with + * skipped nodes when they are not in monitor mode */ + pulse_list[iface].last_ptr = pulse_ptr ; + pulse_list[iface].head_ptr = pulse_ptr ; + pulse_list[iface].tail_ptr = pulse_ptr ; + pulse_ptr->pulse_link[iface].prev_ptr = NULL ; + } + else + { + pulse_list[iface].last_ptr->pulse_link[iface].next_ptr = pulse_ptr ; + pulse_ptr->pulse_link[iface].prev_ptr = pulse_list[iface].last_ptr ; + pulse_list[iface].last_ptr = pulse_ptr ; /* save current to handle a skip */ + pulse_list[iface].tail_ptr = pulse_ptr ; /* migrate tail as list is built */ + } + pulse_ptr->pulse_link[iface].next_ptr = NULL ; + + pulse_ptr->linknum[iface] = ++pulses[iface] ; + + mlog2 ("%s %s Pulse Info: %d:%d - %d:%p\n", + pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->linknum[iface], + pulses[iface], + pulse_ptr->rri, + pulse_ptr); + } + } + print_pulse_list(iface); + return (pulses[iface]); +} + + +/** Build the Reasource Reference Array */ +void nodeLinkClass::build_rra ( void ) +{ + struct node * ptr = NULL ; + int x = 1 ; + for ( ptr = head ; ptr != NULL ; ptr = ptr->next ) + { + hbs_rra [x] = ptr ; + ptr->rri=x ; + x++ ; + if (( ptr->next == NULL ) || ( ptr == tail )) + break ; + } + + if ( ptr != NULL ) + { + dlog ("%s forced RRA build (%d)\n", ptr->hostname.c_str(), x-1); + } + + /* fill the rest with NULL */ + for ( ; x < MAX_NODES ; x++ ) + hbs_rra[x] = NULL ; + + /* Reset the "Running RRI" */ + rrri = 0 ; +} + +/** Gets the next hostname and resource reference identifier + * (the rra index) and updates the callers variables with them. + * + * This is a helper function in support of the fast resource lookup feature. + * During steady state operation the heartbeat agent cycles through + * all the resources , one per heartbeat request, sending new + * reference identifiers (name and index) to the monitored resources. + * Each time this is called it get the next set. + * */ +void nodeLinkClass::get_rris ( string & hostname, int & rri ) +{ + if ( hosts ) + { + hostname = "none" ; + rrri++ ; + if ( rrri > hosts ) + { + rrri = 1 ; + } + hostname = hbs_rra[rrri]->hostname ; + rri = rrri ; + } +} + +struct nodeLinkClass::node* nodeLinkClass::getPulseNode ( string & hostname , iface_enum iface ) +{ + /* check for empty list condition */ + if ( pulse_list[iface].head_ptr == NULL ) + return NULL ; + + for ( pulse_ptr = pulse_list[iface].head_ptr ; ; pulse_ptr = pulse_ptr->pulse_link[iface].next_ptr ) + { + if ( !hostname.compare ( pulse_ptr->hostname )) + { + return pulse_ptr ; + } + if (( pulse_ptr->pulse_link[iface].next_ptr == NULL ) || + ( pulse_ptr==pulse_list[iface].tail_ptr )) + { + break ; + } + } + return static_cast(NULL); +} + +/* Find the node in the list of nodes being heartbeated and splice it out */ +int nodeLinkClass::remPulse_by_index ( string hostname, int index, iface_enum iface, bool clear_b2b_misses_count, unsigned int flags ) +{ + int rc = FAIL ; + if (( index > 0 ) && ( !(index > hosts))) + { + if ( hbs_rra[index] != NULL ) + { + struct nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + if (( hbs_rra[index] == node_ptr ) && + ( ! node_ptr->hostname.compare(hostname))) + { + node_ptr->lookup_mismatch_log_throttle = 0 ; + if ( node_ptr->monitor[iface] == true ) + { + node_ptr->unexpected_pulse_log_throttle = 0 ; + return ( remPulse ( hbs_rra[index], iface, clear_b2b_misses_count, flags )); + } + else + { + wlog_throttled ( node_ptr->unexpected_pulse_log_throttle, 200, "%s is not being monitored\n", hostname.c_str()); + rc = PASS; + } + } + else + { + rc = remPulse_by_name ( hostname, iface, clear_b2b_misses_count, flags ); + wlog_throttled ( node_ptr->lookup_mismatch_log_throttle, 200, "%s rri lookup mismatch (%s:%d) ; %s\n", hostname.c_str(), node_ptr->hostname.c_str(), index, rc ? "" : "removed by hostname" ); + return (rc); + } + } + else + { + dlog ("%s could not lookup by index or hostname (%d)\n", hostname.c_str(), index ); + rc = FAIL_HOSTNAME_LOOKUP ; + } + } + } + return (rc); +} + +/* Find the node in the list of nodes being heartbeated and splice it out */ +int nodeLinkClass::remPulse_by_name ( string & hostname, iface_enum iface, bool clear_b2b_misses_count, unsigned int flags ) +{ + return ( remPulse ( getPulseNode ( hostname, iface ), iface, clear_b2b_misses_count, flags )); +} + +/** WANT_LINKLIST_FIT is not defined by default. + * Needs to be explicitely defined and the undef commented out for testing + **/ +#ifdef WANT_LINKLIST_FIT +#undef WANT_LINKLIST_FIT +#endif + +#ifdef WANT_LINKLIST_FIT +static bool already_fit = false ; +#endif + +/* Find the node in the list of nodes being heartbeated and splice it out */ +int nodeLinkClass::remPulse ( struct node * node_ptr, iface_enum iface, bool clear_b2b_misses_count, unsigned int flags ) +{ + /* This default RC allows the caller to filter out unexpected pulse responses */ + int rc = ENXIO ; + + if ( head == NULL ) + { + return -ENODEV ; + } + else if ( node_ptr == NULL ) + { + return (rc) ; + } + + struct node * ptr = node_ptr ; + + // dlog ("%s\n", node_ptr->hostname.c_str()); + + /* Splice the node out of the pulse monitor list */ + + /* Does the pulse monitor list exist and is the node in the list */ + /* Need to gracefully handle being called when there is no pulse */ + /* list and/or the specified host is not in the pulse list */ + if (( pulse_list[iface].head_ptr != NULL ) && ( ptr != NULL ) && ( ptr->linknum[iface] != 0)) + { + pulse_ptr = ptr ; + ptr->hbs_count[iface]++ ; + + manage_pulse_flags ( pulse_ptr , flags ); + + if ( clear_b2b_misses_count == true ) + { + if ( ptr->b2b_misses_count[iface] > hbs_degrade_threshold ) + { + ilog ("%s %s Pulse Rxed (after %d misses)\n", + node_ptr->hostname.c_str(), + get_iface_name_str(iface), + node_ptr->b2b_misses_count[iface]); + } + + manage_heartbeat_alarm ( pulse_ptr, FM_ALARM_SEVERITY_CLEAR, iface ); + + ptr->b2b_misses_count[iface] = 0 ; + if ( pulse_ptr->hbs_degrade[iface] == true ) + { + /* Send a degrade clear event to maintenance */ + if ( send_event ( pulse_ptr->hostname, MTC_EVENT_HEARTBEAT_DEGRADE_CLR, iface ) == PASS ) + { + pulse_ptr->hbs_degrade[iface] = false ; + } + } + if ( pulse_ptr->hbs_minor[iface] == true ) + { + if ( send_event ( pulse_ptr->hostname, MTC_EVENT_HEARTBEAT_MINOR_CLR, iface ) == PASS ) + { + pulse_ptr->hbs_minor[iface] = false ; + } + } + } + rc = PASS ; +#ifdef WANT_LINKLIST_FIT + if ( already_fit == false ) + { + if ( daemon_is_file_present ( MTC_CMD_FIT__LINKLIST ) == true ) + { + if ( pulse_list[iface].head_ptr->pulse_link[iface].next_ptr != NULL ) + { + slog ("FIT of next pointer\n"); + pulse_list[iface].head_ptr->pulse_link[iface].next_ptr = NULL ; + already_fit = true ; + } + } + } +#endif + if ( pulse_list[iface].head_ptr == pulse_ptr ) + { + if ( pulse_list[iface].head_ptr == pulse_list[iface].tail_ptr ) + { + qlog2 ("%s Pulse: Single Node -> Head Case : %d of %d\n", node_ptr->hostname.c_str(), pulse_ptr->linknum[iface], pulses[iface] ); + pulse_list[iface].head_ptr = NULL ; + pulse_list[iface].tail_ptr = NULL ; + } + else + { + qlog2 ("%s Pulse: Multiple Node -> Head Case : %d of %d\n", node_ptr->hostname.c_str(), pulse_ptr->linknum[iface], pulses[iface] ); + if ( pulse_list[iface].head_ptr->pulse_link[iface].next_ptr == NULL ) + { + slog ("%s unexpected NULL next_ptr ; aborting this pulse window\n", node_ptr->hostname.c_str()); + pulse_list[iface].head_ptr = NULL ; + pulse_list[iface].tail_ptr = NULL ; + pulse_ptr->linknum[iface] = 0 ; + pulses[iface] = 0 ; + return (FAIL_NULL_POINTER); + } + else + { + pulse_list[iface].head_ptr = pulse_list[iface].head_ptr->pulse_link[iface].next_ptr ; + pulse_list[iface].head_ptr->pulse_link[iface].prev_ptr = NULL ; + } + } + } + else if ( pulse_list[iface].tail_ptr == pulse_ptr ) + { + qlog2 ("%s Pulse: Multiple Node -> Tail Case : %d of %d\n", node_ptr->hostname.c_str(), pulse_ptr->linknum[iface], pulses[iface] ); + if ( pulse_list[iface].tail_ptr->pulse_link[iface].prev_ptr == NULL ) + { + slog ("%s unexpected NULL prev_ptr ; aborting this pulse window\n", node_ptr->hostname.c_str()); + pulse_list[iface].head_ptr = NULL ; + pulse_list[iface].tail_ptr = NULL ; + pulse_ptr->linknum[iface] = 0 ; + pulses[iface] = 0 ; + return (FAIL_NULL_POINTER); + } + else + { + pulse_list[iface].tail_ptr = pulse_list[iface].tail_ptr->pulse_link[iface].prev_ptr ; + pulse_list[iface].tail_ptr->pulse_link[iface].next_ptr = NULL ; + } + } + else + { + /* July 1 emacdona: Make failure path case more robust */ + if ( pulse_ptr == NULL ) { slog ("Internal Err 1\n"); rc = FAIL; } + else if ( pulse_ptr->pulse_link[iface].prev_ptr == NULL ) { slog ("Internal Err 2\n"); rc = FAIL; } + else if ( pulse_ptr->pulse_link[iface].prev_ptr->pulse_link[iface].next_ptr == NULL ) { slog ("Internal Err 3\n"); rc = FAIL; } + else if ( pulse_ptr->pulse_link[iface].next_ptr == NULL ) { slog ("Internal Err 4\n"); rc = FAIL; } + else if ( pulse_ptr->pulse_link[iface].next_ptr->pulse_link[iface].prev_ptr == NULL ) { slog ("Internal Err 5\n"); rc = FAIL; } + + if ( rc == FAIL ) + { + slog ("%s Null pointer error splicing %s out of pulse list with %d pulses remaining (Monitoring:%s)\n", + node_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulses[iface], + node_ptr->monitor[iface] ? "Yes" : "No" ); + } + else + { + pulse_ptr->pulse_link[iface].prev_ptr->pulse_link[iface].next_ptr = pulse_ptr->pulse_link[iface].next_ptr ; + pulse_ptr->pulse_link[iface].next_ptr->pulse_link[iface].prev_ptr = pulse_ptr->pulse_link[iface].prev_ptr ; + } + } + if ( rc == PASS ) + { + pulse_ptr->linknum[iface]-- ; // = 0 ; + } + pulses[iface]-- ; + } + + return rc ; +} + +/** This utility will try and remove a pluse from the pulse + * linked list first by index and then by hostname. + * + * By index does not require a lookup whereas hostname does */ +int nodeLinkClass::remove_pulse ( string & hostname, iface_enum iface, int index, unsigned int flags ) +{ + if ( index ) + { + int rc = remPulse_by_index ( hostname, index , iface, true , flags ); + switch (rc) + { + case PASS: return (rc) ; + case ENXIO: return (rc); + default: mlog ("%s RRI Miss (rri:%d) (rc:%d)\n", hostname.c_str(), index, rc ); + } + } + else + { + if ( hostname.compare("localhost") ) + { + if ( get_hbs_monitor_state ( hostname , iface ) == true ) + { + wlog ("%s Not Offering RRI\n", hostname.c_str()); + } + } + else + { + /* localhost is not a supported hostname and indicates + * an unconfigured host response ; return the ignore response */ + return(ENXIO); + } + } + return ( remPulse_by_name ( hostname , iface, true, flags )); +} + +void nodeLinkClass::clear_pulse_list ( iface_enum iface ) +{ + struct node * ptr = head ; + for ( ; ptr != NULL ; ptr = ptr->next ) + { + ptr->pulse_link[iface].prev_ptr = NULL ; + ptr->pulse_link[iface].next_ptr = NULL ; + } + pulse_list[iface].head_ptr = NULL ; + pulse_list[iface].tail_ptr = NULL ; + + if ( ptr != NULL ) + { + ptr->linknum[iface] = 0 ; + pulses[iface] = 0 ; + } +} + + +/** Runs in the hbsAgent to set or clear heartbat alarms for all supported interfaces */ +void nodeLinkClass::manage_heartbeat_alarm ( struct nodeLinkClass::node * node_ptr, EFmAlarmSeverityT sev, int iface ) +{ + if ( this->heartbeat != true ) + return ; + + bool make_alarm_call = false ; + alarm_id_enum id ; + EFmAlarmStateT state = FM_ALARM_STATE_SET ; + const char * alarm_id_ptr = NULL ; + const char * entity_ptr = NULL ; + if ( iface == MGMNT_IFACE ) + { + entity_ptr = MGMNT_NAME ; + id = HBS_ALARM_ID__HB_MGMNT ; + alarm_id_ptr = MGMNT_HB_ALARM_ID; + } + else + { + entity_ptr = INFRA_NAME ; + id = HBS_ALARM_ID__HB_INFRA ; + alarm_id_ptr = INFRA_HB_ALARM_ID; + } + + if ( sev == FM_ALARM_SEVERITY_CLEAR ) + { + state = FM_ALARM_STATE_CLEAR ; + if ( node_ptr->alarms[id] != FM_ALARM_SEVERITY_CLEAR ) + { + make_alarm_call = true ; + node_ptr->alarms[id] = sev ; + } + } + else if ( sev == FM_ALARM_SEVERITY_MAJOR ) + { + if ( node_ptr->alarms[id] == FM_ALARM_SEVERITY_CRITICAL ) + { + ; /* we don't go from critical to degrade + need a clear first */ + } + else if ( node_ptr->alarms[id] != FM_ALARM_SEVERITY_MAJOR ) + { + make_alarm_call = true ; + node_ptr->alarms[id] = FM_ALARM_SEVERITY_MAJOR ; + } + } + else if ( sev == FM_ALARM_SEVERITY_CRITICAL ) + { + if ( node_ptr->alarms[id] != sev ) + { + make_alarm_call = true ; + node_ptr->alarms[id] = sev ; + } + } + else if ( sev == FM_ALARM_SEVERITY_MINOR ) + { + if ( node_ptr->alarms[id] != sev ) + { + make_alarm_call = true ; + node_ptr->alarms[id] = sev ; + } + } + else + { + if ( node_ptr->alarms[id] != FM_ALARM_SEVERITY_WARNING ) + { + make_alarm_call = true ; + node_ptr->alarms[id] = FM_ALARM_SEVERITY_WARNING ; + } + } + if ( make_alarm_call == true ) + { + alarm_ ( node_ptr->hostname, alarm_id_ptr, state, sev, entity_ptr , ""); + } +} + + + + +int nodeLinkClass::lost_pulses ( iface_enum iface ) +{ + int rc = PASS ; + + for ( ; pulse_list[iface].head_ptr != NULL ; ) + { + daemon_signal_hdlr (); + pulse_ptr = pulse_list[iface].head_ptr ; + if ( active ) + { + string flat = "Flat Line:" ; + pulse_ptr->b2b_misses_count[iface]++ ; + // pulse_ptr->max_count[iface]++ ; + + /* Don't log single misses unless in debug mode */ + if ( pulse_ptr->b2b_misses_count[iface] > 1 ) + { + // if ( pulse_ptr->b2b_misses_count[iface] >= 25 ) + if ( pulse_ptr->b2b_misses_count[iface] >= hbs_failure_threshold ) + { + // if ( pulse_ptr->b2b_misses_count[iface] == 25 ) + if ( pulse_ptr->b2b_misses_count[iface] == hbs_failure_threshold ) + { + ilog ("%-13s %s Pulse Miss (%d) (log throttled to every %d)\n", + pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface], + 0xfff); + } + /* Once the misses exceed 25 then throttle the logging to avoid flooding */ + if ( (pulse_ptr->b2b_misses_count[iface] & 0xfff) == 0 ) + { + ilog ("%-13s %s Pulse Miss (%d)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface] ); + } + } + else + { + if ( pulse_ptr->b2b_misses_count[iface] > hbs_failure_threshold ) + { + ilog ("%-13s %s Pulse Miss (%3d) (in failure)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface] ); + } + else if ( pulse_ptr->b2b_misses_count[iface] > hbs_degrade_threshold ) + { + ilog ("%-13s %s Pulse Miss (%3d) (max:%3d) (in degrade)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface], + pulse_ptr->max_count[iface]); + } + else if ( pulse_ptr->b2b_misses_count[iface] > hbs_minor_threshold ) + { + ilog ("%-13s %s Pulse Miss (%3d) (max:%3d) (in minor)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface] , + pulse_ptr->max_count[iface]); + } + else + { + ilog ("%-13s %s Pulse Miss (%3d) (max:%3d)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface], + pulse_ptr->max_count[iface]); + } + } + } + else + { + dlog ("%-13s %s Pulse Miss (%d)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface), + pulse_ptr->b2b_misses_count[iface] ); + } + mem_log ( flat, pulse_ptr->b2b_misses_count[iface], pulse_ptr->hostname.c_str()); + + if ( iface == MGMNT_IFACE ) + { + if ( pulse_ptr->b2b_misses_count[iface] == hbs_minor_threshold ) + { + send_event ( pulse_ptr->hostname, MTC_EVENT_HEARTBEAT_MINOR_SET, iface ); + pulse_ptr->hbs_minor[iface] = true ; + pulse_ptr->hbs_minor_count[iface]++ ; + wlog ("%s %s -> MINOR\n", pulse_ptr->hostname.c_str(), get_iface_name_str(iface)); + } + } + if ( pulse_ptr->b2b_misses_count[iface] == hbs_degrade_threshold ) + { + manage_heartbeat_alarm ( pulse_ptr, FM_ALARM_SEVERITY_MAJOR, iface ); + + /* report this host as failed */ + if ( send_event ( pulse_ptr->hostname, MTC_EVENT_HEARTBEAT_DEGRADE_SET, iface ) == PASS ) + { + pulse_ptr->hbs_degrade[iface] = true ; + } + wlog ("%s %s -> DEGRADED\n", pulse_ptr->hostname.c_str(), get_iface_name_str(iface)); + pulse_ptr->hbs_degrade_count[iface]++ ; + + } + /* Handle lost degrade event case */ + if (( pulse_ptr->b2b_misses_count[iface] > hbs_degrade_threshold ) && + ( pulse_ptr->hbs_degrade[iface] == false )) + { + wlog ("%s -> DEGRADED - Auto-Correction\n", pulse_ptr->hostname.c_str()); + + manage_heartbeat_alarm ( pulse_ptr, FM_ALARM_SEVERITY_MAJOR, iface ); + + /* report this host as failed */ + if ( send_event ( pulse_ptr->hostname, MTC_EVENT_HEARTBEAT_DEGRADE_SET, iface ) == PASS ) + { + pulse_ptr->hbs_degrade[iface] = true ; + } + } + + /* Turn the infra heartbeat loss into a degrade only + * condition if the infra_degrade_only flag is set */ + if (( iface == INFRA_IFACE ) && + ( pulse_ptr->b2b_misses_count[iface] >= hbs_failure_threshold ) && + ( infra_degrade_only == true )) + { + /* Only print the log at the threshold boundary */ + if ( pulse_ptr->b2b_misses_count[iface] == hbs_failure_threshold ) + { + manage_heartbeat_alarm ( pulse_ptr, FM_ALARM_SEVERITY_CRITICAL, iface ); + + wlog_throttled ( pulse_ptr->no_work_log_throttle, 500, + "%s %s *** Heartbeat Loss *** (degrade only)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface) ); + } + } + + /* Turn the infra heartbeat loss into a degrade only + * condition for inactive controller on normal system. */ + else if (( iface == INFRA_IFACE ) && + ( pulse_ptr->b2b_misses_count[iface] >= hbs_failure_threshold ) && + ( this->system_type == SYSTEM_TYPE__NORMAL ) && + (( pulse_ptr->nodetype & CONTROLLER_TYPE) == CONTROLLER_TYPE )) + { + /* Only print the log at the threshold boundary */ + if ( pulse_ptr->b2b_misses_count[iface] == hbs_failure_threshold ) + { + manage_heartbeat_alarm ( pulse_ptr, FM_ALARM_SEVERITY_CRITICAL, iface ); + + wlog_throttled ( pulse_ptr->no_work_log_throttle, 500, + "%s %s *** Heartbeat Loss *** (degrade only)\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface) ); + } + } + + else if (( pulse_ptr->b2b_misses_count[iface] == hbs_failure_threshold ) && + ( pulse_ptr->hbs_failure[iface] == false )) + { + elog ("%s %s -> FAILED\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface) ); + elog ("%s %s *** Heartbeat Loss ***\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface) ); + + manage_heartbeat_alarm ( pulse_ptr, FM_ALARM_SEVERITY_CRITICAL, iface ); + + /* report this host as failed */ + if ( send_event ( pulse_ptr->hostname, MTC_EVENT_HEARTBEAT_LOSS , iface ) == PASS ) + { + pulse_ptr->hbs_failure[iface] = true ; + } + + pulse_ptr->hbs_failure_count[iface]++ ; + } + if ( pulse_ptr->b2b_misses_count[iface] > pulse_ptr->max_count[iface] ) + pulse_ptr->max_count[iface] = pulse_ptr->b2b_misses_count[iface] ; + } + rc = remPulse_by_name ( pulse_ptr->hostname, iface, false, NULL_PULSE_FLAGS ); + if ( rc != PASS ) + { + elog ("%s %s not in pulse list\n", pulse_ptr->hostname.c_str(), + get_iface_name_str(iface)); + clear_pulse_list ( iface ); + break ; + } + if ( pulse_list[iface].head_ptr == NULL ) + { + // dlog ("Pulse list is Empty\n"); + break ; + } + } + return (rc); +} + +/* Return true if the specified interface is being monitored for this host */ +bool nodeLinkClass::monitored_pulse ( string hostname , iface_enum iface ) +{ + if ( hostname.length() ) + { + struct nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr != NULL ) + { + return ( node_ptr->monitor[iface] ) ; + } + } + return(false); +} + +/* Reports pulse list empty status. + * true if empty + * false if not empty + */ +bool nodeLinkClass::pulse_list_empty ( iface_enum iface ) +{ + if ( pulse_list[iface].head_ptr == NULL ) + return true ; + return false ; +} + +void nodeLinkClass::print_pulse_list ( iface_enum iface ) +{ + string pulse_host_list = "- " ; + + if ( pulse_list[iface].head_ptr != NULL ) + { + for ( pulse_ptr = pulse_list[iface].head_ptr ; + pulse_ptr != NULL ; + pulse_ptr = pulse_ptr->pulse_link[iface].next_ptr ) + { + pulse_host_list.append(pulse_ptr->hostname.c_str()); + pulse_host_list.append(" "); + } + dlog ("Patients: %s\n", pulse_host_list.c_str()); + } + if ( pulses[iface] && !pulse_host_list.empty() ) + { + string temp = get_iface_name_str(iface) ; + temp.append(" Patients :") ; + mem_log ( temp, pulses[iface], pulse_host_list ); + } +} + + + +/* Clear all degrade flags except for the HWMON one */ +void clear_host_degrade_causes ( unsigned int & degrade_mask ) +{ + if ( degrade_mask & DEGRADE_MASK_HWMON ) + { + degrade_mask = DEGRADE_MASK_HWMON ; + } + else + { + degrade_mask = 0 ; + } +} + +/***************************************************************************/ +/******************* State Dump Utilities ***********************/ +/***************************************************************************/ + + + +void nodeLinkClass::mem_log_general ( void ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s %s %s %s:%s %s:%s \n", + my_hostname.c_str(), + my_local_ip.c_str(), + my_float_ip.c_str(), + daemon_get_cfg_ptr()->mgmnt_iface, + mgmnt_link_up_and_running ? "Up" : "Down", + daemon_get_cfg_ptr()->infra_iface, + infra_link_up_and_running ? "Up" : "Down"); + mem_log (str); +} + +void nodeLinkClass::mem_log_dor ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s DOR - Active: %c Was: %c Time: %5d (00:%02d:%02d)\n", + node_ptr->hostname.c_str(), + node_ptr->dor_recovery_mode ? 'Y' : 'N', + node_ptr->was_dor_recovery_mode ? 'Y' : 'N', + node_ptr->dor_recovery_time, + node_ptr->dor_recovery_time ? node_ptr->dor_recovery_time/60 : 0, + node_ptr->dor_recovery_time ? node_ptr->dor_recovery_time%60 : 0); + mem_log (str); +} + + + +/* Multi-Node Failure Avoidance Data */ +void nodeLinkClass::mem_log_mnfa ( void ) +{ + char str[MAX_MEM_LOG_DATA] ; + + int temp = mnfa_threshold_number ; + if ( mnfa_threshold_type == MNFA_PERCENT ) + temp = mnfa_threshold_percent ; + + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s MNFA: Mode:%s:%d State:%s Hosts:%d:%d Cases:%d Threshold:%d\n", + my_hostname.c_str(), + mnfa_threshold_type ? "Percent" : "Number", + temp, + mnfa_active ? "ACTIVE" : "inactive", + mnfa_host_count[MGMNT_IFACE], + mnfa_host_count[INFRA_IFACE], + mnfa_calculate_threshold( "" ), + mnfa_occurances); + mem_log (str); +} + +void nodeLinkClass::mem_log_general_mtce_hosts ( void ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s EnableHosts -> Cont:%d Comp:%d Stor:%d StorType:%d\n", + my_hostname.c_str(), + num_controllers_enabled(), + enabled_compute_nodes(), + enabled_storage_nodes(), + get_storage_backend()); + mem_log (str); +} + +void nodeLinkClass::mem_log_bm ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tbm_ip:%s bm_un:%s bm_type:%s provisioned: %s\n", + node_ptr->hostname.c_str(), + node_ptr->bm_ip.c_str(), + node_ptr->bm_un.c_str(), + node_ptr->bm_type.c_str(), + node_ptr->bm_provisioned ? "Yes" : "No" ); + mem_log (str); +} + +void nodeLinkClass::mem_log_identity ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s %s (%u)\n", + node_ptr->hostname.c_str(), + node_ptr->uuid.c_str(), + node_ptr->type.c_str(), + node_ptr->nodetype); + mem_log (str); +} + +void nodeLinkClass::mem_log_state1 ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + string ad = adminState_enum_to_str(node_ptr->adminState) ; + string op = operState_enum_to_str(node_ptr->operState) ; + string av = availStatus_enum_to_str(node_ptr->availStatus); + + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s-%s-%s degrade_mask:%08x\n", + node_ptr->hostname.c_str(), + ad.c_str(), + op.c_str(), + av.c_str(), + node_ptr->degrade_mask); + mem_log (str); + op = operState_enum_to_str(node_ptr->operState_subf) ; + av = availStatus_enum_to_str(node_ptr->availStatus_subf); + if ( node_ptr->subfunction_str.empty() ) + { + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tFunction: %s %s-%s-%s\n", + node_ptr->hostname.c_str(), + node_ptr->function_str.c_str(), + ad.c_str(), + op.c_str(), + av.c_str()); + } + else + { + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tFunctions %s-%s %s-%s-%s\n", + node_ptr->hostname.c_str(), + node_ptr->function_str.c_str(), + node_ptr->subfunction_str.c_str(), + ad.c_str(), + op.c_str(), + av.c_str()); + } + mem_log (str); +} + +void nodeLinkClass::mem_log_state2 ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + string aa = adminAction_enum_to_str(node_ptr->adminAction) ; + + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tmtcAction:%s invAction:%s Task:%s\n", + node_ptr->hostname.c_str(), + aa.c_str(), + node_ptr->action.c_str(), + node_ptr->task.c_str()); + mem_log (str); +} + +void nodeLinkClass::mem_log_mtcalive ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tmtcAlive: on:%c off:%c Cnt:%d State:%s Misses:%d\n", + node_ptr->hostname.c_str(), + node_ptr->mtcAlive_online ? 'Y' : 'N', + node_ptr->mtcAlive_offline ? 'Y' : 'N', + node_ptr->mtcAlive_count, + node_ptr->mtcAlive_gate ? "gated" : "rxing", + node_ptr->mtcAlive_misses); + mem_log (str); +} + +void nodeLinkClass::mem_log_alarm1 ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tAlarm List:%s%s%s%s%s%s\n", + node_ptr->hostname.c_str(), + node_ptr->alarms[MTC_ALARM_ID__LOCK ] ? " Locked" : " .", + node_ptr->alarms[MTC_ALARM_ID__CONFIG ] ? " Config" : " .", + node_ptr->alarms[MTC_ALARM_ID__ENABLE ] ? " Enable" : " .", + node_ptr->alarms[MTC_ALARM_ID__CH_CONT ] ? " Control" : " .", + node_ptr->alarms[MTC_ALARM_ID__CH_COMP ] ? " Compute" : " .", + node_ptr->alarms[MTC_ALARM_ID__BM ] ? " Brd Mgmt" : " ."); + mem_log (str); +} + +void nodeLinkClass::mem_log_stage ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tAdd:%d Offline:%d: Swact:%d Recovery:%d Able:%d\n", + node_ptr->hostname.c_str(), + node_ptr->addStage, + node_ptr->offlineStage, + node_ptr->swactStage, + node_ptr->recoveryStage, + node_ptr->handlerStage.raw); + mem_log (str); +} + +void nodeLinkClass::mem_log_power_info ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tStage:%s Attempts:%d: Holdoff:%d Retry:%d State:%x ctid:%p rtid:%p\n", + node_ptr->hostname.c_str(), + get_powercycleStages_str(node_ptr->powercycleStage).c_str(), + node_ptr->hwmon_powercycle.attempts, + node_ptr->hwmon_powercycle.holdoff, + node_ptr->hwmon_powercycle.retries, + node_ptr->hwmon_powercycle.state, + node_ptr->hwmon_powercycle.control_timer.tid, + node_ptr->hwmon_powercycle.recovery_timer.tid); + mem_log (str); +} + +void nodeLinkClass::mem_log_reset_info ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tStage:%s Attempts:%d: Holdoff:%d Retry:%d State:%x ctid:%p rtid:%p\n", + node_ptr->hostname.c_str(), + get_resetStages_str(node_ptr->resetStage).c_str(), + node_ptr->hwmon_reset.attempts, + node_ptr->hwmon_reset.holdoff, + node_ptr->hwmon_reset.retries, + node_ptr->hwmon_reset.state, + node_ptr->hwmon_reset.control_timer.tid, + node_ptr->hwmon_reset.recovery_timer.tid); + mem_log (str); +} + +void nodeLinkClass::mem_log_network ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s %s infra_ip: %s Uptime: %u\n", + node_ptr->hostname.c_str(), + node_ptr->mac.c_str(), + node_ptr->ip.c_str(), + node_ptr->infra_ip.c_str(), + node_ptr->uptime ); + mem_log (str); +} + +void nodeLinkClass::mem_log_heartbeat ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + for ( int iface = 0 ; iface < MAX_IFACES ; iface++ ) + { + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s Minor:%s Degrade:%s Failed:%s Monitor:%s\n", + node_ptr->hostname.c_str(), + get_iface_name_str (iface), + node_ptr->hbs_minor[iface] ? "true " : "false", + node_ptr->hbs_degrade[iface] ? "true " : "false", + node_ptr->hbs_failure[iface] ? "true " : "false", + node_ptr->monitor[iface] ? "YES" : "no" ); + mem_log (str); + } +} + +void nodeLinkClass::mem_log_hbs_cnts ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + for ( int iface = 0 ; iface < MAX_IFACES ; iface++ ) + { + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\t%s Counts Minor:%d Degrade:%d Failed:%d Max:%d Cur:%d\n", + node_ptr->hostname.c_str(), + get_iface_name_str(iface), + node_ptr->hbs_minor_count[iface], + node_ptr->hbs_degrade_count[iface], + node_ptr->hbs_failure_count[iface], + node_ptr->max_count[iface], + node_ptr->hbs_count[iface]); + mem_log (str); + } +} + +void nodeLinkClass::mem_log_test_info ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tOOS Stage:%s Runs:%d - INSV Stage:%s Runs:%d\n", + node_ptr->hostname.c_str(), + get_oosTestStages_str(node_ptr->oosTestStage).c_str(), + node_ptr->oos_test_count, + get_insvTestStages_str(node_ptr->insvTestStage).c_str(), + node_ptr->insv_test_count); + mem_log (str); +} + +void nodeLinkClass::mem_log_thread_info ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tThread Stage:%d Runs:%d Progress:%d Ctrl Status:%d Thread Status:%d\n", + node_ptr->hostname.c_str(), + node_ptr->ipmitool_thread_ctrl.stage, + node_ptr->ipmitool_thread_ctrl.runcount, + node_ptr->ipmitool_thread_info.progress, + node_ptr->ipmitool_thread_ctrl.status, + node_ptr->ipmitool_thread_info.status); + mem_log (str); +} + + +void nodeLinkClass::mem_log_type_info ( struct nodeLinkClass::node * node_ptr ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tSystem:%d NodeMask: %x Function: %s (%u)\n", + node_ptr->hostname.c_str(), + this->system_type, + node_ptr->nodetype, + node_ptr->function_str.c_str(), + node_ptr->function); + mem_log (str); + + if ( CPE_SYSTEM ) + { + snprintf (&str[0], MAX_MEM_LOG_DATA, "%s\tSub-Function: %s (%u) (SubFunc Enabled:%c)\n", + node_ptr->hostname.c_str(), + node_ptr->subfunction_str.c_str(), node_ptr->subfunction, + node_ptr->subf_enabled ? 'Y' : 'n' ); + mem_log (str); + } +} + +void mem_log_delimit_host ( void ) +{ + char str[MAX_MEM_LOG_DATA] ; + snprintf (&str[0], MAX_MEM_LOG_DATA, "-------------------------------------------------------------\n"); + mem_log (str); +} + +void nodeLinkClass::memDumpNodeState ( string hostname ) +{ + nodeLinkClass::node* node_ptr ; + node_ptr = nodeLinkClass::getNode ( hostname ); + if ( node_ptr == NULL ) + { + mem_log ( hostname, ": ", "Not Found\n" ); + return ; + } + else + { + if ( maintenance == true ) + { + mem_log_dor ( node_ptr ); + mem_log_identity ( node_ptr ); + mem_log_type_info ( node_ptr ); + mem_log_network ( node_ptr ); + mem_log_state1 ( node_ptr ); + mem_log_state2 ( node_ptr ); + // mem_log_reset_info ( node_ptr ); + mem_log_power_info ( node_ptr ); + mem_log_alarm1 ( node_ptr ); + mem_log_mtcalive ( node_ptr ); + mem_log_stage ( node_ptr ); + mem_log_bm ( node_ptr ); + mem_log_test_info ( node_ptr ); + mem_log_thread_info( node_ptr ); + workQueue_dump ( node_ptr ); + } + if ( heartbeat == true ) + { + mem_log_heartbeat( node_ptr ); + mem_log_hbs_cnts ( node_ptr ); + } + mem_log_delimit_host (); + } +} + +void nodeLinkClass::memDumpAllState ( void ) +{ + mem_log_delimit_host (); + mem_log_general (); + + if ( nodeLinkClass::maintenance == true ) + { + mem_log_general_mtce_hosts(); + mem_log_mnfa (); + } + + mem_log_delimit_host (); + + /* walk the node list looking for nodes that should be monitored */ + for ( struct node * ptr = head ; ptr != NULL ; ptr = ptr->next ) + { + memDumpNodeState ( ptr->hostname ); + } +} + + +/*************************************************************************** + * * + * Module Test Head * + * * + ***************************************************************************/ + +int nodeLinkClass::testhead ( int test ) +{ + UNUSED(test); + return (PASS) ; +} diff --git a/mtce-common/cgts-mtce-common-1.0/common/nodeClass.h b/mtce-common/cgts-mtce-common-1.0/common/nodeClass.h new file mode 100755 index 00000000..2b9b72ad --- /dev/null +++ b/mtce-common/cgts-mtce-common-1.0/common/nodeClass.h @@ -0,0 +1,2033 @@ +#ifndef __INCLUDE_NODECLASS_H__ +#define __INCLUDE_NODECLASS_H__ +/* + * Copyright (c) 2013-2016 Wind River Systems, Inc. +* +* SPDX-License-Identifier: Apache-2.0 +* + */ + +/** + * @file + * Wind River CGTS Platform Node Maintenance "Node Manager" + * class, support structs and enums. + */ + +#include +#include +#include +#include +#include +#include + +#define WANT_MTC +#define WANT_HBS + +using namespace std; + +/* Include base class definition header */ +#include "nodeBase.h" +#include "hostUtil.h" /* for ... server_code and others */ +#include "nodeTimers.h" +#include "threadUtil.h" /* for ... thread_info_type thread_ctrl_type*/ +#include "pingUtil.h" /* for ... ping_info_type */ +#include "nodeCmds.h" /* for ... mtcCmd type */ +#include "httpUtil.h" /* for ... libevent stuff */ +#include "ipmiUtil.h" /* for ... mc_info_type */ +#include "mtcHttpUtil.h" /* for ... libevent stuff */ +#include "mtcSmgrApi.h" /* */ +#include "alarmUtil.h" /* for ... SFmAlarmDataT */ +#include "mtcAlarm.h" /* for ... MTC_ALARM_ID__xx and utils */ +#include "mtcThreads.h" /* for ... mtcThread_ipmitool */ + +/**Default back-to-back heartbeat failures for disabled-failed condition */ +#define HBS_FAILURE_THRESHOLD 10 + +/** Default back-to-back heartbeat failures for enabled-degraded condition */ +#define HBS_DEGRADE_THRESHOLD 6 + +/** Default back-to-back heartbeat failures for enabled-degraded condition */ +#define HBS_MINOR_THRESHOLD 4 + +/** If Debug, this number of missed heartbeats in a row creates a info log */ +#define HBS_DBG_LOG_THRESHOLD 1 + +/** Clear (reset) heartbeat counter value */ +#define HBS_CLEAR_COUNT 0 + +#ifdef SIMPLEX +#undef SIMPLEX +#endif +#define SIMPLEX \ + ( daemon_is_file_present ( PLATFORM_SIMPLEX_MODE ) == true ) + +#define THIS_HOST \ + ( node_ptr->hostname == this->my_hostname ) + +#define NOT_THIS_HOST \ + ( node_ptr->hostname != this->my_hostname ) + +#define LARGE_SYSTEM \ + ( this->system_type == SYSTEM_TYPE__NORMAL ) + +#define CPE_SYSTEM \ + ( this->system_type != SYSTEM_TYPE__NORMAL ) + +#define SIMPLEX_CPE_SYSTEM \ + ( this->system_type == SYSTEM_TYPE__CPE_MODE__SIMPLEX ) + +/** + * @addtogroup nodeLinkClass + * @{ + * + * This class is used to maintain a linked list of nodes that + * represent currently provisioned inventory. Its member + * functions and data members along with the support files + * in maintenance and heartbeat feature directories blend + * to create a Higly Available and Reuseable Maintenance system. + */ + +class nodeLinkClass +{ +private: + + /** A single node entity within the nodeLinkClass that can + * be spliced in or out of a node linked list + */ + struct node { + + /** + * @addtogroup private_Node_variables + * @{ + * + * A set of variables that make up a node including linking members. + */ + + /** The name of the host node */ + std::string uuid ; + + /** The name of the host node */ + std::string hostname ; + + /** The IP address of the host node */ + std::string ip ; + + /** The Mac address of the host node */ + std::string mac ; + + /** The infrastructure network IP address of the host node */ + std::string infra_ip ; + + /** The Mac address of the host's infra interface */ + std::string infra_mac ; + + /** The type of node 'controller' or 'compute' node */ + std::string type ; + + /** Short text phrase indicating the operation the FSM is + * taking on this host */ + std::string task ; + + /** Administrative action from inventory */ + std::string action ; + + /** The Node Type ; compute or control or storage as a mask */ + string functions ; /* comma delimited string of host types */ + unsigned int nodetype ; /* numeric mask of functions */ + + string function_str ; /* single host type string representing + the main function of the host */ + unsigned int function ; /* numeric representing function_str */ + + string subfunction_str ; /* single host type string ie "compute" */ + unsigned int subfunction ; /* numeric representing subfunction_str */ + + /** set to true if the host specific sub function enable handler passes */ + bool subf_enabled ; + + /** set true if the BMC is provisioned */ + bool bm_provisioned ; + + + /** general retry counter */ + int retries ; + + /** number of http rest API retries since last clear */ + int http_retries_cur ; + + /* Command handler retries counter */ + int cmd_retries ; + + /* Retry counter for power actions (on/off)*/ + int power_action_retries ; + + /** Generic toggle switch */ + bool toggle ; + + /** back to back health failure counter */ + int health_threshold_counter ; + + int mtce_flags ; + + /* true if this node is patching */ + bool patching ; + + /* true if this node is patched but not reset */ + bool patched ; + + /** The node's reported uptime */ + unsigned int uptime ; + unsigned int uptime_save ; + + /** Set to true once the host's add FSM is done */ + bool add_completed ; + + int uptime_refresh_counter ; + + /** Counts the number of times this node was unlocked. + * NOTE: This value should be stored in the database. + * so that it is not reset to 0 on every swact. + */ + int node_unlocked_counter ; + + int mtcalive_timeout ; + + /* start host service retry controls */ + int start_services_retries ; + + bool start_services_running_main ; + bool start_services_running_subf ; + + bool start_services_needed ; + bool start_services_needed_subf ; /* for the add handler that defers + start to the inservice test handler. + this provides a means of telling + maintenance that the subfunction + start needs to also be run. */ + + /** Pointer to the previous node in the list */ + struct node *prev; + + /** Pointer to the next node in the list */ + struct node *next; + + /** @} private_Node_variables */ + + + /** @addtogroup private_Maintenance_variables + * @{ + * + * Finite State Machine variables and member functions + * for 'this' host/node + * + * The CGTS Maintenacne syste follows the X.731 maintenance model + * which uses the states below; For full list of states please + * refer to nodeBase.h + * + * A brief summary is (host and node are used inter-changably) + * + * Administrative Action: Actions a user may take on a host at the user + * interface ; i.e. Lock, Unlock, Reset, Reinstall + * + * Administrative State : The state a host enters into when the above + * actions are taken ; i.e. Locked or Unlocked. + * + * Operational State : The operating state of the node based on the + * administrative actions ; Enabled or Disabled. + * + * Availability State : The useability state of a host based on the + * two previous states and events that may occur + * over time ; i.e. available, failed, degraded, + * intest. + */ + mtc_nodeAdminAction_enum adminAction ; /**< Administrative Action */ + list adminAction_todo_list ; /**< Administrative Action */ + + mtc_nodeAdminState_enum adminState ; /**< Administrative State */ + mtc_nodeOperState_enum operState ; /**< Operational State */ + mtc_nodeAvailStatus_enum availStatus ; /**< Availability Status */ + mtc_nodeConfigAction_enum configAction; /**< Configuration Action */ + + mtc_nodeOperState_enum operState_subf ; /**< Subfunction Operational State */ + mtc_nodeAvailStatus_enum availStatus_subf ; /**< Subfunction Availability Status */ + + mtc_nodeOperState_enum operState_dport ; /**< Data Port Operational State */ + mtc_nodeAvailStatus_enum availStatus_dport; /**< Data Port Availability Status */ + + + /** Maintains the current handler stage. + * This is a union of all handler types such as enable, + * disable, degrade etc. See nodeBase.h for list of union members */ + mtc_stages_union handlerStage; + + /* Individual FSM handler stages */ + mtc_offlineStages_enum offlineStage ; + mtc_onlineStages_enum onlineStage ; + mtc_swactStages_enum swactStage ; + mtc_addStages_enum addStage ; + mtc_delStages_enum delStage ; + mtc_recoveryStages_enum recoveryStage ; + mtc_oosTestStages_enum oosTestStage ; + mtc_insvTestStages_enum insvTestStage ; + mtc_configStages_enum configStage ; + mtc_resetProgStages_enum resetProgStage ; + mtc_reinstallStages_enum reinstallStage ; + + /** Board management specific FSM Stages */ + mtc_powerStages_enum powerStage ; + mtc_powercycleStages_enum powercycleStage ; + mtc_subStages_enum subStage ; + mtc_resetStages_enum resetStage ; + mtc_sensorStages_enum sensorStage ; + + + /** This gate is used to block mtcAlive messages from reaching + * the state machine until its ready to receive them. + * + * Issue: The mtcClient on a slave host will continuously send the + * mtcAlive 'I'm here' messages after a reboot and until that message + * is acknowledged. This is done to make the recovery of a host more + * robust in a potentially lossy network. Without this, a single + * dropped mtcAlive message could result in an unlock-enable timeout + * which would lead to a disabled-failed state and re-recovery attempt + * after a recovery timeout (mtcTimers.h:HOST_MTCALIVE_TIMEOUT) + * period. Besides the system administrator seeing a disabled-failed + * condition the customer would realize a longer than nessary outage + * of that host. + * + * Fix: By having the mtcClient repeatedly send the mtcAlive message + * on reset recovery until it is acknowledged by active mtcAgent + * prevents the above issue. However it has a side affect on the + * maintenance FSM for that host. This mtcAlive gate prevents + * the state machine from seeing mtcAlive messages when it does not + * care about them. + */ + bool mtcAlive_gate ; + int mtcAlive_count ; + int mtcAlive_misses ; + int mtcAlive_hits ; + int mtcAlive_purge ; + + bool mtcAlive_mgmnt ; /* set true when mtcAlive is rx'd from mgmnt network */ + bool mtcAlive_infra ; /* set true when mtcAlive is rx'd from infra network */ + + /* Both of these booleans are set true upon receipt of a mtcAlive message. */ + bool mtcAlive_online ; /* this is consumed by online and offline handler */ + bool mtcAlive_offline ; /* this is consumed by reset progression handler */ + + int offline_search_count ; /* count back-2-back mtcAlive request misses */ + + bool offline_log_reported ; /* prevents offline/online log flooding when */ + bool online_log_reported ; /* availStatus switches between these states */ + /* and failed */ + + /** Host's mtc timer struct. Use to time handler stages. + * + * reset -> reset command response + * reboot -> then wait for mtcalive message + * mtcalive -> then wait for go enabled message + */ + struct mtc_timer mtcAlive_timer ; + + /* the fault handling offline handler timer */ + struct mtc_timer offline_timer ; + + /* Host level DOR recovery mode time and bools */ + int dor_recovery_time ; + bool dor_recovery_mode ; + bool was_dor_recovery_mode ; + + /** Integer code representing the host health */ + int health ; + + /** Flag indicating that the unknown health state + * has already been reported */ + bool unknown_health_reported ; + + /* Booleans indicating the main or subfunction has config failure */ + bool config_failed ; + bool config_failed_subf ; + + /* Booleans indicating the main or subfunction has passed the OOS test */ + bool goEnabled ; + bool goEnabled_subf ; + + /* Booleans indicating the main or subfunction has failed the OOS test */ + bool goEnabled_failed ; + bool goEnabled_failed_subf ; + + /* Boolean indicating the main or subfunction has start host services + * failure. */ + bool hostservices_failed ; + bool hostservices_failed_subf ; + + /* Boolean indicating the main or subfunction has inservice failure */ + bool inservice_failed ; + bool inservice_failed_subf ; + + /** node has reached enabled state this number of times */ + bool enabled_count ; + + /** Number of OOS tests run so far */ + int oos_test_count ; + + /** Number of INSV tests run so far */ + int insv_test_count ; + + /** Used to throttle inservice recovery actions */ + int insv_recovery_counter ; + + /** when true requests the task for this host be cleared at first opportunity */ + bool clear_task ; + + /** Host's mtc timer struct. Use to time handler stages. + * + * reset -> reset command response + * reboot -> then wait for mtcalive message + * mtcalive -> then wait for go enabled message + */ + struct mtc_timer mtcTimer ; + struct mtc_timer http_timer ; + struct mtc_timer mtcCmd_timer ; + struct mtc_timer oosTestTimer ; + struct mtc_timer insvTestTimer ; + struct mtc_timer mtcSwact_timer ; + struct mtc_timer mtcConfig_timer ; + struct mtc_timer power_timer ; + struct mtc_timer host_services_timer ; + + mtcCmd host_services_req ; + mtcCmd mtcAlive_req ; + mtcCmd reboot_req ; + mtcCmd general_req ; + + /* String that is used in the command handling logs which represents + * the specific command handling that is in progress */ + string cmdName ; + + /** Indicates presence of a command request */ + unsigned int cmdReq ; + + /** Indicates presence of a command response */ + unsigned int cmdRsp; + + /** Indicates acknowledgement of the initial host + * services command in execution monitoroing mode */ + unsigned int cmdAck; + + /** Command Response Status - Execution Status */ + unsigned int cmdRsp_status ; + + /** Command Response Data - typically an error details string */ + string cmdRsp_status_string ; + + bool reboot_cmd_ack_mgmnt ; + bool reboot_cmd_ack_infra ; + + /** Tracks back to back Fast Fault Recovery counts */ + int graceful_recovery_counter; + + /** Reboot acknowledge */ + mtc_client_enum activeClient ; + + /** @} private_Maintenance_variables */ + + /** + * @addtogroup private_libEvent_structs + * @{ + * + * libEvent structures used to issue libEvent + * HTTP REST API Requests to control this host + * based on each service */ + + libEvent sysinvEvent; /**< Sysinv REST API Handling for host */ + libEvent cfgEvent; /**< Sysinv REST API Handling for config changes */ + libEvent vimEvent ; /**< VIM Event REST API Handling */ + + libEvent httpReq ; /**< Http libEvent Request Handling */ + libEvent thisReq ; /**< Http libEvent Request Handling */ + + list libEvent_work_fifo ; + list::iterator libEvent_work_fifo_ptr; + list libEvent_done_fifo ; + list::iterator libEvent_done_fifo_ptr; + + // bool work_ready ; + int oper_sequence ; + int oper_failures ; + int no_work_log_throttle ; + int log_throttle ; + + /* List of queue'ed mtce commands for this host */ + mtcCmd cmd; + list mtcCmd_work_fifo ; + list::iterator mtcCmd_work_fifo_ptr; + list mtcCmd_done_fifo ; + list::iterator mtcCmd_done_fifo_ptr; + + /** @} private_libEvent_structs and utils */ + + /** + * @addtogroup private_Heartbeat_variables + * @{ + * + * A grouping a of private variables at the node level used to + * control if a node is to be monitored, the monitoring failure + * counts and next / previous pointers used to create the + * monitored node pulse linked list + */ + + /** Set 'true' when node minor threshold has exceeded */ + bool hbs_minor[MAX_IFACES] ; + + /** Set 'true' when node is degraded due to back to back heartbeat pulse + * misses tha exceed the major threshold */ + bool hbs_degrade[MAX_IFACES] ; + + /** Set 'true' when node is failed due to back to back heartbeat pulse + * misses that exceed the critical threshold */ + bool hbs_failure[MAX_IFACES] ; + + /** log throttle controls for heartbeat service */ + int stall_recovery_log_throttle ; + int stall_monitor_log_throttle ; + int lookup_mismatch_log_throttle ; + int unexpected_pulse_log_throttle ; + + /** Pulse Next and Previous Link pointers for creating + * a per-interface pulse link list */ + struct { + + /** previous pulse pointer used to create the pulse linked list for one interface */ + struct node * prev_ptr ; + + /** next pulse pointer used to create the pulse linked list for one interface */ + struct node * next_ptr ; + + } pulse_link [MAX_IFACES] ; + + /** The link index number for this node is while in an interface pulse linked list */ + int linknum [MAX_IFACES] ; + + /** true if this host is to be monitored for this indexed interface */ + bool monitor [MAX_IFACES] ; + + /** Ongoing heartbeat count cleared on HBS_START reset */ + int hbs_count [MAX_IFACES] ; + + /** Immediate running count of consecutive heartbeat misses */ + int b2b_misses_count [MAX_IFACES]; + + /** Maximum heartbeat misses since node was last brought into service */ + int max_count [MAX_IFACES]; + + /** total times minor count was exceeded */ + int hbs_minor_count [MAX_IFACES]; + + /** total times this host degraded due to heartbeat misses */ + int hbs_degrade_count [MAX_IFACES]; + + /** total times this host failed due to heartbeat loss */ + int hbs_failure_count [MAX_IFACES]; + + /** current state of heartbeat failure per interface for mtcAgent */ + bool heartbeat_failed [MAX_IFACES]; + + /** Resource reference identifier, aka resource reference array index */ + int rri ; + + /** @} private_Heartbeat_variables */ + + /** + * @addtogroup private_boad_management_variables + * @{ + * + * Various host specific board management variables. + */ + + /** The IP address of the host's board management controller */ + string bm_ip ; + + /** The password of the host's board management controller */ + string bm_pw ; + + /** A string label that represents the board management + * controller type for this host */ + string bm_type ; + + /** The operator provisioned board management hostname */ + string bm_un ; + + /* Indicates there is a board management test + * for this host in progress */ + bool bm_test_in_progress ; + + /* Indicates there is a board management operation + * in progress on this host */ + bool bm_oper_in_progress ; + + /** + * The BMC is 'accessible' once provisioning data is available + * and bmc is verified pingable. + **/ + bool bm_accessible; + + /** @} private_boad_management_variables */ + + /** + * @addtogroup private_monitoring_services_variables + * @{ + * + * A grouping a of flags, mask and degrade resource lists + * used to manage the degrade state of a host for process + * and resource monitoring services. + */ + + /* Bit mask of degrade reasons */ + unsigned int degrade_mask ; + + /** Process Monitor Daemon Flag Missing count */ + int pmon_missing_count ; + + /** Host degraded due to loss of Process Monitor running flag */ + bool pmon_degraded ; + + /** Process Monitor Ready flag and degrade list */ + bool pmond_ready ; + + /** Hardware Monitor Ready flag and degrade list */ + bool hwmond_ready ; + bool hwmond_monitor ; + + /** Heartbeat Client process ready to heartbeat flag */ + bool hbsClient_ready ; + + /** hwmon reset and powercycle recovery control structure */ + recovery_ctrl_type hwmon_reset ; + recovery_ctrl_type hwmon_powercycle ; + + /** Resource Monitor Daemon Flag Missing count */ + int rmond_missing_count ; + + /** Host degraded due to loss of Resource Monitor running flag */ + bool rmond_degraded ; + + /** Resource Monitor Ready flag and degrade list */ + bool rmond_ready ; + std::list degraded_resources_list ; + + /** process or resource list string iterator */ + std::list::iterator string_iter_ptr ; + + /** @} private_monitoring_services_variables */ + + /* List of alarms and current severity */ + EFmAlarmSeverityT alarms[MAX_ALARMS]; + + /* tracks whether the alarms for this host have been loaded already or not */ + bool alarms_loaded ; + + /** true if this host has recovered before the mnfa timeout period. + * This bool flags the graceful recovery handler that this node + * is recovering from mnfa and should manage graceful recovery + * and uptime accordingly */ + bool mnfa_graceful_recovery ; + + int stress_iteration ; + + /* for bmc ping access monitor */ + ping_info_type bm_ping_info ; + + /* the bmc info struct filled in and log printed by a + * call to ipmiUtil_mc_info_load. */ + mc_info_type mc_info ; + + bool mc_info_query_active ; + bool mc_info_query_done ; + + bool reset_cause_query_active ; + bool reset_cause_query_done ; + + bool power_status_query_active ; + bool power_status_query_done ; + bool power_on = false ; + + /* a timer used in the bm_handler to query + * the mc_info and reset cause */ + struct mtc_timer bm_timer ; + + /* timer used to manage the bmc access alarm */ + struct mtc_timer bmc_access_timer ; + + /***************************************************** + * Maintenance Thread Structs + *****************************************************/ + /* control data the parent uses to manage the thread */ + thread_ctrl_type ipmitool_thread_ctrl ; + + /*info the thread uses to execute and post results */ + thread_info_type ipmitool_thread_info ; + + /* extra thread info for board management control thread */ + thread_extra_info_type thread_extra_info ; + + }; + + struct node * head ; /**< Node Linked List Head pointer */ + struct node * tail ; /**< Node Linked List Tail pointer */ + + /** Allocate memory for a new node. + * + * Preserves the node address in the node_ptr list and increments + * the memory_allocs counter used by the inservice test audit. + * + * @return + * a pointer to the memory of the newly allocated node */ + struct nodeLinkClass::node * newNode ( void ); + + /** Build the Resource Reference Array */ + void build_rra ( void ); + + /** Free the memory used by a node. + * + * The memory to be removed is found in the node_ptr list, cleared and + * the memory_allocs counter is decremented. + * If the memory cannot be found then an error is returned. + * + * @param node_ptr + * is a pointer to the node to be freed + * @return + * a signed integer of PASS or -EINVAL + */ + int delNode ( struct nodeLinkClass::node * node_ptr ); + + /** Start heartbeating a new node. + * + * Node is added to the end of the node linked list. + * + * @param node_info_ptr + * is a pointer containing pertinent info about the physical node + * @return + * a pointer to the newly added node + */ + struct nodeLinkClass::node* addNode ( string hostname ); + struct nodeLinkClass::node* addUuid ( string uuid ); + + /** Stop heartbeating a node. + * + * Node is spliced out of the node linked list. + * + * @param node_info_ptr + * is a pointer containing info required to find the node in the node list + * @return + * an integer of PASS or -EINVAL */ + int remNode ( string hostname ); + + /** Get pointer to "hostname" node. + * + * Node list lookup by pointer from hostname. + * + * @param node_info_ptr + * is a pointer containing info required to find the node in the node list + * @return + * a pointer to the hostname's node + */ + struct nodeLinkClass::node* getNode ( string hostname ); + + /** Get the node pointer based on the service and libevent base pointer. + * + * Node list lookup by pointer service and libevent base pointer. + * + * @param libEvent_enum + * service type + * @param base_ptr + * pointer to the libEvent base + * + * @return + * a pointer to the hostname's node + */ + struct nodeLinkClass::node* getEventBaseNode ( libEvent_enum service, + struct event_base * base_ptr); + + /** Get a reference to the libEvent containing the supplied + * libEvent.base pointer. + * + * @param base_ptr + * pointer to the libEvent base + * + * @return + * reference to valid or null libEvent + */ + libEvent & getEvent ( struct event_base * base_ptr); + + int manage_dnsmasq_bmc_hosts ( struct nodeLinkClass::node * node_ptr ); + + /* run the maintenance fsm against a host */ + int fsm ( struct nodeLinkClass::node * node_ptr ); + + /* specific handlers called within the fsm */ + int enable_handler ( struct nodeLinkClass::node * node_ptr ); + int recovery_handler ( struct nodeLinkClass::node * node_ptr ); + int disable_handler ( struct nodeLinkClass::node * node_ptr ); + int add_handler ( struct nodeLinkClass::node * node_ptr ); + int delete_handler ( struct nodeLinkClass::node * node_ptr ); + int cfg_handler ( struct nodeLinkClass::node * node_ptr ); + int cmd_handler ( struct nodeLinkClass::node * node_ptr ); + int swact_handler ( struct nodeLinkClass::node * node_ptr ); + int reset_handler ( struct nodeLinkClass::node * node_ptr ); + int reboot_handler ( struct nodeLinkClass::node * node_ptr ); + int reinstall_handler ( struct nodeLinkClass::node * node_ptr ); + int power_handler ( struct nodeLinkClass::node * node_ptr ); + int powercycle_handler ( struct nodeLinkClass::node * node_ptr ); + int offline_handler ( struct nodeLinkClass::node * node_ptr ); + int online_handler ( struct nodeLinkClass::node * node_ptr ); + int oos_test_handler ( struct nodeLinkClass::node * node_ptr ); + int insv_test_handler ( struct nodeLinkClass::node * node_ptr ); + int stress_handler ( struct nodeLinkClass::node * node_ptr ); + int bm_handler ( struct nodeLinkClass::node * node_ptr ); + int uptime_handler ( void ); + + int host_services_handler ( struct nodeLinkClass::node * node_ptr ); + + /* Starts the specified 'reset or powercycle' recovery monitor */ + int hwmon_recovery_monitor ( struct nodeLinkClass::node * node_ptr, int hwmon_event ); + + /* server specific power state query handler */ + bool (*is_poweron_handler) (string hostname, string query_response ); + + /* Calculate the overall reset progression timeout */ + int calc_reset_prog_timeout ( struct nodeLinkClass::node * node_ptr, int retries ); + + /* These interfaces will start and stop the offline FSM if not already active */ + void start_offline_handler ( struct nodeLinkClass::node * node_ptr ); + void stop_offline_handler ( struct nodeLinkClass::node * node_ptr ); + + /***************************************************************************** + * + * Name : ipmi_command_send + * + * Description: This utility starts the ipmitool command handling thread + * with the specified command. + * + * Returns : PASS if all the pre-start semantic checks pass and the + * thread was started. + * + * Otherwise the thread was not started and some non zero + * FAIL_xxxx code is returned after a representative design + * log is generated. + * + *****************************************************************************/ + + int ipmi_command_send ( struct nodeLinkClass::node * node_ptr, int command ) ; + + /***************************************************************************** + * + * Name : ipmi_command_recv + * + * Description: This utility will check for ipmitool command thread completion. + * + * Returns : PASS is returned if the thread reports done. + * RETRY is returned if the thread has not completed. + * FAIL_RETRY is returned after 10 back-to-back calls return RETRY. + * + * Assumptions: The caller is expected to call ipmi_command_done once it has + * consumed the results of the thread + * + *****************************************************************************/ + + int ipmi_command_recv ( struct nodeLinkClass::node * node_ptr ); + + /***************************************************************************** + * + * Name : ipmi_command_done + * + * Description: This utility frees the ipmitool command thread for next execution. + * + *****************************************************************************/ + + void ipmi_command_done ( struct nodeLinkClass::node * node_ptr ); + + /* default all the BMC access variaables to the "no access" state */ + void bmc_access_data_init ( struct nodeLinkClass::node * node_ptr ); + + /* Combo Host enable handler */ + int enable_subf_handler ( struct nodeLinkClass::node * node_ptr ); + + /** set all service readies to false so that when the first one comes in' + * it will be logged */ + void clear_service_readies ( struct nodeLinkClass::node * node_ptr ); + + int update_dport_states ( struct nodeLinkClass::node * node_ptr, int event ); + + /* manage deciding to return or issue an immediate reboot if the + * auto recovery threshold is exceeded. */ + void manage_autorecovery ( struct nodeLinkClass::node * node_ptr ); + + /** *********************************************************************** + * + * Name : nodeLinkClass::workQueue_process + * + * Description: This is a Per Host Finite State Machine (FSM) that + * processes the work queue for the supplied host's + * node pointer. + * + * Constructs: + * + * node_ptr->libEvent_work_fifo - the current work queue/fifo + * node_ptr->libEvent_done_fifo - queue/fifo of completed requests + * + * Operations: + * + * requests are added to the libEvent_work_fifo with workQueue_enqueue. + * requests are removed from the libEvent_done_fifo with workQueue_dequeue. + * + * Behavior: + * + * In process libEvents are copied from the callers work queue to + * its thisReq. + * + * Completed events including execution status are copied to the host's + * done fifo. + * + * Failed events may be retried up to max_retries as specified by + * the callers libEvent. + * + * @param event is a reference to the callers libEvent. + * + * @return an integer with values of PASS, FAIL, RETRY + * + * Implementation: in maintenance/mtcWorkQueue.cpp + * + * ************************************************************************/ + int workQueue_process ( struct nodeLinkClass::node * node_ptr ); + + /** *********************************************************************** + * + * Name : nodeLinkClass::workQueue_del_cmd + * + * Description: To handle the pathalogical case where an event seems to + * have timed out at the callers level then this interface + * can be called to delete it from the work queue. + * + * @param node_ptr so that the hosts work queue can be found + * @param sequence to specify the specific sequence number to remove + * @return always PASS since there is nothing the caller can or needs + * to do if the command is not present. + * + * Implementation: in maintenance/mtcWorkQueue.cpp + * + */ + int workQueue_del_cmd ( struct nodeLinkClass::node * node_ptr, int sequence ); + + int doneQueue_purge ( struct nodeLinkClass::node * node_ptr ); + int workQueue_purge ( struct nodeLinkClass::node * node_ptr ); + int workQueue_done ( struct nodeLinkClass::node * node_ptr ); + void workQueue_dump ( struct nodeLinkClass::node * node_ptr ); + void doneQueue_dump ( struct nodeLinkClass::node * node_ptr ); + + int mtcCmd_workQ_purge( struct nodeLinkClass::node * node_ptr ); + int mtcCmd_doneQ_purge( struct nodeLinkClass::node * node_ptr ); + void mtcCmd_workQ_dump ( struct nodeLinkClass::node * node_ptr ); + void mtcCmd_doneQ_dump ( struct nodeLinkClass::node * node_ptr ); + + void force_full_enable ( struct nodeLinkClass::node * node_ptr ); + + int adminActionChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAdminAction_enum newActionState ); + + /** Host Administrative State Change member function */ + int adminStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAdminState_enum newAdminState ); + + /** Host Operational State Change member function */ + int operStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeOperState_enum newOperState ); + + /** Host Availability Status Change member function */ + int availStatusChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAvailStatus_enum newAvailStatus ); + + + int allStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeAdminState_enum adminState, + mtc_nodeOperState_enum operState, + mtc_nodeAvailStatus_enum availStatus ); + + int subfStateChange ( struct nodeLinkClass::node * node_ptr, + mtc_nodeOperState_enum operState_subf, + mtc_nodeAvailStatus_enum availStatus_subf ); + + /** Host Enable Handler Stage Change member function */ + int enableStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_enableStages_enum newHdlrStage ); + + /** Host Disable Handler Stage Change member function */ + int disableStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_disableStages_enum newHdlrStage ); + + /** Host configuration stage Change member function */ + int configStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_configStages_enum newHdlrStage ); + + /** Host Reset Handler Stage Change member function */ + int resetStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_resetStages_enum newHdlrStage ); + + /** Host Reinstall Handler Stage Change member function */ + int reinstallStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_reinstallStages_enum newHdlrStage ); + + /** Host Fast graceful Recovery Handler Stage Change member function */ + int recoveryStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_recoveryStages_enum newHdlrStage ); + + /** Host Power control Handler Stage Change member function */ + int powerStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_powerStages_enum newHdlrStage ); + + /** Host Powercycle control Handler Stage Change member function */ + int powercycleStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_powercycleStages_enum newHdlrStage ); + + /** Out-Of-Service Test Stage Change member function */ + int oosTestStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_oosTestStages_enum newHdlrStage ); + + /** Inservice Test Stage Change member function */ + int insvTestStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_insvTestStages_enum newHdlrStage ); + + /** Host Sensor Handler Stage Change member function */ + int sensorStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_sensorStages_enum newHdlrStage ); + + /** Generic Substage Stage change member function */ + int subStageChange ( struct nodeLinkClass::node * node_ptr, + mtc_subStages_enum newHdlrStage ); + + int failed_state_change ( struct nodeLinkClass::node * node_ptr ); + + /* issue a + * - one way lazy reboot with + * - graceful SM services shutdown and + * - failsafe backup sysreq reset + */ + int lazy_graceful_fs_reboot ( struct nodeLinkClass::node * node_ptr ); + + int alarm_enabled_clear ( struct nodeLinkClass::node * node_ptr, bool force ); + int alarm_enabled_failure ( struct nodeLinkClass::node * node_ptr ); + + int alarm_insv_clear ( struct nodeLinkClass::node * node_ptr, bool force ); + int alarm_insv_failure ( struct nodeLinkClass::node * node_ptr ); + + int alarm_config_clear ( struct nodeLinkClass::node * node_ptr ); + int alarm_config_failure ( struct nodeLinkClass::node * node_ptr ); + + int alarm_compute_clear ( struct nodeLinkClass::node * node_ptr, bool force ); + int alarm_compute_failure ( struct nodeLinkClass::node * node_ptr , EFmAlarmSeverityT sev ); + + void clear_subf_failed_bools ( struct nodeLinkClass::node * node_ptr ); + void clear_main_failed_bools ( struct nodeLinkClass::node * node_ptr ); + void clear_hostservices_ctls ( struct nodeLinkClass::node * node_ptr ); + + /** Find the node that has this timerID in its general mtc timer */ + struct nodeLinkClass::node * get_mtcTimer_timer ( timer_t tid ); + struct nodeLinkClass::node * get_mtcConfig_timer ( timer_t tid ); + struct nodeLinkClass::node * get_mtcAlive_timer ( timer_t tid ); + struct nodeLinkClass::node * get_offline_timer ( timer_t tid ); + struct nodeLinkClass::node * get_mtcSwact_timer ( timer_t tid ); + struct nodeLinkClass::node * get_mtcCmd_timer ( timer_t tid ); + struct nodeLinkClass::node * get_oosTestTimer ( timer_t tid ); + struct nodeLinkClass::node * get_insvTestTimer ( timer_t tid ); + struct nodeLinkClass::node * get_power_timer ( timer_t tid ); + struct nodeLinkClass::node * get_http_timer ( timer_t tid ); + struct nodeLinkClass::node * get_thread_timer ( timer_t tid ); + struct nodeLinkClass::node * get_ping_timer ( timer_t tid ); + struct nodeLinkClass::node * get_bm_timer ( timer_t tid ); + struct nodeLinkClass::node * get_bmc_access_timer ( timer_t tid ); + struct nodeLinkClass::node * get_host_services_timer ( timer_t tid ); + + struct nodeLinkClass::node * get_powercycle_control_timer ( timer_t tid ); + struct nodeLinkClass::node * get_powercycle_recovery_timer ( timer_t tid ); + struct nodeLinkClass::node * get_reset_control_timer ( timer_t tid ); + struct nodeLinkClass::node * get_reset_recovery_timer ( timer_t tid ); + + /* Launch the specified host services command start or stop for any host + * type into the cmd_handler. In support of AIO a subf bool is optional + * and forces the command to be COMPUTE (subfunction). + * - requires cmd_handler fsm */ + int launch_host_services_cmd ( struct nodeLinkClass::node * node_ptr, bool start , bool subf=false ); + + /* Private SYSINV API */ + int mtcInvApi_update_task ( struct nodeLinkClass::node * node_ptr, string task ); + int mtcInvApi_update_task_now ( struct nodeLinkClass::node * node_ptr, string task ); + int mtcInvApi_force_task ( struct nodeLinkClass::node * node_ptr, string task ); + int mtcInvApi_update_task ( struct nodeLinkClass::node * node_ptr, const char * task_str_ptr, int one ); + int mtcInvApi_update_task ( struct nodeLinkClass::node * node_ptr, const char * task_str_ptr, int one, int two ); + + int mtcInvApi_update_value ( struct nodeLinkClass::node * node_ptr, string key, string value ); + int mtcInvApi_update_uptime ( struct nodeLinkClass::node * node_ptr, unsigned int uptime ); + + int mtcInvApi_subf_states ( struct nodeLinkClass::node * node_ptr, string oper_subf, string avail_subf ); + int mtcInvApi_force_states ( struct nodeLinkClass::node * node_ptr, string admin, string oper, string avail ); + int mtcInvApi_update_states ( struct nodeLinkClass::node * node_ptr, string admin, string oper, string avail ); + int mtcInvApi_update_states_now ( struct nodeLinkClass::node * node_ptr, string admin, string oper, string avail, string oper_subf, string avail_subf); + int mtcInvApi_update_state ( struct nodeLinkClass::node * node_ptr, string state, string value ); + + /* Private SM API */ + int mtcSmgrApi_request ( struct nodeLinkClass::node * node_ptr, mtc_cmd_enum operation, int retries ); + + /* Private VIM API */ + int mtcVimApi_state_change ( struct nodeLinkClass::node * node_ptr, libEvent_enum operation, int retries ); + + int set_bm_prov ( struct nodeLinkClass::node * node_ptr, bool state ); + + void set_uptime ( struct nodeLinkClass::node * node_ptr, unsigned int uptime, bool force ); + + // #endif /* WANT_MTC */ + + /** Interface to asser or clear severity specific heartbeat alarms */ + void manage_heartbeat_alarm ( struct nodeLinkClass::node * node_ptr, EFmAlarmSeverityT sev, int iface ); + + /** Returns the heartbeat monitoring state for the specified interface */ + bool get_hbs_monitor_state ( string & hostname, int iface ); + + /** List of allocated node memory. + * + * An array of node pointers. + */ + nodeLinkClass::node * node_ptrs[MAX_NODES] ; + + /** A memory allocation counter. + * + * Should represent the number of nodes in the linked list. + */ + int memory_allocs ; + + /** A memory used counter + * + * A variable storing the accumulated node memory + */ + int memory_used ; + + /** Inservice memory management audit. + * + * Verifies that the node_ptr list and memory_allocs jive as well + * as all the node pointers point to a node in the linked list. + * + * @return + * an integer representing a PASS or TODO: list other error codes. + */ + int memory_audit ( void ); + + + /* Simplex mode auto recovery bools + * + * Set to true when the autorecovery threshold is reached + * and we want to avoid taking further autorecovery action + * even though it may be requested. */ + bool autorecovery_disabled ; + + /* Set to true by fault detection methods that are + * autorecoverable when in simplex mode. */ + bool autorecovery_enabled ; + + /** Tracks the number of hosts that 'are currently' in service trouble + * wrt heartbeat (above minor threshold). + * This is used in multi-host failure avoidance. + **/ + int mnfa_host_count[MAX_IFACES] ; + + /** Tracks the number of times multi failure avoidance was exited */ + int mnfa_occurances ; + + /** true when the multi node failure count exceeds the multi + * node failure avoidance threshold and until there are no more + * in service trouble hosts */ + bool mnfa_active ; + + /** Recover or exit from the muli-node failure avoidance state + * This involves restarting the heartbeat on all the nodes + * that remain hbs_minor and clearing any heartbneat degrade + * states that remain. */ + void mnfa_exit ( bool force ); + void mnfa_enter ( void ); + void mnfa_add_host ( struct nodeLinkClass::node * node_ptr, iface_enum iface ); + void mnfa_recover_host ( struct nodeLinkClass::node * node_ptr ); + void hbs_minor_clear ( struct nodeLinkClass::node * node_ptr, iface_enum iface ); + + /* Dead Office Recovery - system level controls */ + void manage_dor_recovery ( struct nodeLinkClass::node * node_ptr, EFmAlarmSeverityT severity ); + void report_dor_recovery ( struct nodeLinkClass::node * node_ptr, string node_state_log_prefix ); + + struct { + struct node * head_ptr ; /**< Pulse Linked List Head pointer */ + struct node * tail_ptr ; /**< Pulse Linked List Tail pointer */ + struct node * last_ptr ; /**< Pulse Linked List running last pointer */ + } pulse_list [MAX_IFACES] ; + + /** General Pulse Pointer used to build pulse linked list */ + struct node * pulse_ptr ; + + /** Number monitored hosts (nodes) for a specified interface */ + int pulses[MAX_IFACES] ; + + /** Resource reference Array: An array used to store + * resource references for the purpose of fast resource + * lookup making thwe heartbat service more scalable. + * + * In this case it is an array of node link pointers + * that are in the current active pulse list. */ + struct node * hbs_rra[MAX_NODES]; + + /** Pulse list node lookup pointer by hostname. + * + * Get pointer to "hostname" node located in the pulse list. + * + * @param hostname - a string containing the name of the host + * to be searched for in the pulse list. + * @param iface - iface_enum specifying which interface linked + * list to search. + * + * @return pointer to the node's control struct + */ + struct nodeLinkClass::node* getPulseNode ( string & hostname, iface_enum iface ); + + /** Manage the heartbeat pulse flags by node pointer + * + * These flags contain service information sent by the replying host. + * One example of this is the pmond flag which indicates whether the process + * monitor is running on that host. + * + * Flags that are not set are thresholded for degrade or alarm assertion + * or cleared when found to be set again. + * + * @param pulse_ptr - node's control struct pointer + * @param flags - integer containing a bit field set of flags + * + * */ + void manage_pulse_flags ( struct nodeLinkClass::node* pulse_ptr, unsigned int flags ); + + /** Remove a node from the pulse list by name, index or node pointer + * + * Deal with all the removal cases ; head, tail, full splice + * + * @return + * an integer of PASS or -FAULT, -ENXIO + */ + int remPulse_by_name ( string & hostname, iface_enum iface, bool clear_b2b_misses_count, unsigned int flags ); + int remPulse_by_index ( string hostname, int index, iface_enum iface, bool clear_b2b_misses_count, unsigned int flags ); + int remPulse ( struct node * node_ptr, iface_enum iface, bool clear_b2b_misses_count, unsigned int flags ); + + + /** Debug Dump Log Interfaces */ + void mem_log_general ( void ); + void mem_log_general_mtce_hosts ( void ); + void mem_log_mnfa ( void ); + + void mem_log_dor ( struct nodeLinkClass::node * node_ptr ); + void mem_log_identity ( struct nodeLinkClass::node * node_ptr ); + void mem_log_network ( struct nodeLinkClass::node * node_ptr ); + void mem_log_state1 ( struct nodeLinkClass::node * node_ptr ); + void mem_log_state2 ( struct nodeLinkClass::node * node_ptr ); + void mem_log_alarm1 ( struct nodeLinkClass::node * node_ptr ); + void mem_log_mtcalive ( struct nodeLinkClass::node * node_ptr ); + void mem_log_stage ( struct nodeLinkClass::node * node_ptr ); + void mem_log_test_info ( struct nodeLinkClass::node * node_ptr ); + void mem_log_bm ( struct nodeLinkClass::node * node_ptr ); + void mem_log_heartbeat ( struct nodeLinkClass::node * node_ptr ); + void mem_log_hbs_cnts ( struct nodeLinkClass::node * node_ptr ); + void mem_log_type_info ( struct nodeLinkClass::node * node_ptr ); + void mem_log_reset_info( struct nodeLinkClass::node * node_ptr ); + void mem_log_power_info( struct nodeLinkClass::node * node_ptr ); + void mem_log_thread_info ( struct nodeLinkClass::node * node_ptr ); + + void print_node_info ( struct nodeLinkClass::node * node_ptr ); + +// #endif + +/** Public Interfaces that allow hosts to be + * added or removed from maintenance. + */ +public: + + nodeLinkClass(); /**< constructor */ + ~nodeLinkClass(); /**< destructor */ + + system_type_enum system_type ; + + string functions ; /**< comma delimited string list of functions supported */ + bool maintenance ; + bool heartbeat ; + + /* offline_handler tuning controls */ + int offline_threshold ; /* number of back to back mtcAlive misses before offline */ + int offline_period ; /* offline handler mtcAlive request period */ + + /* dor mode data ; state and start time + * - start time is used to compare how long slave hosts take to come up + * after the active controller has entered dor mode */ + bool dor_mode_active ; + unsigned int dor_start_time ; + int dor_mode_active_log_throttle ; + + bool hbs_disabled ; /**< Control heartbeat service state */ + bool hbs_state_change ; /**< Flag service state change */ + int hbs_pulse_period ; /**< The curent pulse period in msec */ + int hbs_pulse_period_save ; /**< preserved copy of hbs_pulse_period */ + + /** a loop counter used to detect when the heartbeat service is silently failing */ + int hbs_silent_fault_detector ; + + /* prevents flooding FM with the silent_fault detected log */ + int hbs_silent_fault_logged ; + + /* tracks the number of pulse requests set on each interface */ + int pulse_requests[MAX_IFACES] ; + + /** The number of heartbeat misses that result in a + * minor notification to maintenance */ + int hbs_minor_threshold ; + /** The number of heartbeat misses that result in a degraded state */ + int hbs_degrade_threshold ; + /** The number of heartbeat misses that result in a failed state */ + int hbs_failure_threshold ; + + /** Running Resource Reference Identifier */ + int rrri ; + + bool active ; + bool is_active ( void ) + { return (active); } + void set_activity_state ( bool state ) + { active = state ; } + + /** Store the hostname of this controller */ + string my_hostname ; /**< */ + string my_local_ip ; /**< Primary IP address */ + string my_float_ip ; /**< Secondary (floating) IP address */ + + /********* New Public Constructs for IPMI Comamnd Handling ***********/ + + /* the main fsm entrypoint to service all hosts */ + void fsm ( void ) ; + + /** This controller's hostname set'er */ + void set_my_hostname ( string hostname ); + + /** This controller's hostname get'er */ + string get_my_hostname ( void ); + + /** This controller's local ip addr set'er */ + void set_my_local_ip ( string & hostname ); + + /** This controller's local ip addr get'er */ + string get_my_local_ip ( void ); + + /** This controller's local ip addr set'er */ + void set_my_float_ip ( string & hostname ); + + /** This controller's local ip addr get'er */ + string get_my_float_ip ( void ); + + /** get ip address for any hostname */ + string get_hostaddr ( string & hostname ); + + /** get mac address for any hostname and specified interface */ + string get_hostIfaceMac ( string & hostname, int iface ); + + /** get infrastructure network ip address for any hostname */ + string get_infra_hostaddr ( string & hostname ); + + /** set a node's ip address */ + int set_hostaddr ( string & hostname, string & ip ); + + /** set a node's infrastructure ip address */ + int set_infra_hostaddr ( string & hostname, string & ip ); + + /** get hostname for any hostname */ + string get_hostname ( string & hostaddr ); + + /******************************/ + /* NODE TYPE Member Functions */ + /******************************/ + + /** Fetch the node type (compute or controller) by hostname */ + int get_nodetype ( string & hostname ); + + /** Check if a node is a controller */ + bool is_controller ( struct nodeLinkClass::node * node_ptr ); + + /** Check if a node is a compute */ + bool is_compute ( struct nodeLinkClass::node * node_ptr ); + bool is_compute_subfunction ( struct nodeLinkClass::node * node_ptr ); + + string get_node_function_str ( string hostname ); + string get_node_subfunction_str ( string hostname ); + + /** Check if a node is a storage */ + bool is_storage ( struct nodeLinkClass::node * node_ptr ); + + /** Check if a node is a controller by hostname */ + bool is_controller ( string & hostname ); + + /** Check if a node is a compute by hostname */ +