Relocate platform-util to stx-integ/utilities/platform-util

Move content from stx-utils into stx-integ or stx-update

Packages will be relocated to

stx-update:
    enable-dev-patch
    extras

stx-integ:
    config-files/
        io-scheduler

    filesystem/
        filesystem-scripts

    grub/
        grubby

    logging/
        logmgmt

    tools/
        collector
        monitor-tools

    tools/engtools/
        hostdata-collectors
        parsers

    utilities/
        build-info
        branding   (formerly wrs-branding)
        platform-util

Change-Id: I8ee29b0511085355ebca37fd46afe087fbd00ea8
Story: 2002801
Task: 22687
Signed-off-by: Scott Little <scott.little@windriver.com>
This commit is contained in:
Scott Little 2018-08-01 12:26:18 -04:00
parent 50838ff661
commit 1ead900a8f
20 changed files with 2757 additions and 0 deletions

View File

@ -113,3 +113,4 @@ utilities/branding
config-files/io-scheduler
tools/collector
grub/grubby
utilities/platform-util

View File

@ -0,0 +1,4 @@
SRC_DIR="platform-util"
COPY_LIST_TO_TAR="scripts"
TIS_PATCH_VER=12

View File

@ -0,0 +1,87 @@
Summary: platform-util
Name: platform-util
Version: 1.0
Release: %{tis_patch_ver}%{?_tis_dist}
License: Apache-2.0
Group: base
Packager: Wind River <info@windriver.com>
URL: unknown
BuildArch: noarch
Source: %name-%version.tar.gz
BuildRequires: python-setuptools
%description
Platform utilities
%package -n platform-util-noncontroller
Summary: non controller platform utilities
%description -n platform-util-noncontroller
Platform utilities that don't get packaged on controller hosts
%define local_dir /usr/local
%define local_bindir %{local_dir}/bin
%define local_sbindir %{local_dir}/sbin
%define pythonroot /usr/lib64/python2.7/site-packages
%prep
%setup
%build
%{__python} setup.py build
%install
%{__python} setup.py install --root=$RPM_BUILD_ROOT \
--install-lib=%{pythonroot} \
--prefix=/usr \
--install-data=/usr/share \
--single-version-externally-managed
%global _buildsubdir %{_builddir}/%{name}-%{version}
install -d %{buildroot}%{local_bindir}
install %{_buildsubdir}/scripts/cgcs_tc_setup.sh %{buildroot}%{local_bindir}
install %{_buildsubdir}/scripts/remotelogging_tc_setup.sh %{buildroot}%{local_bindir}
install %{_buildsubdir}/scripts/connectivity_test %{buildroot}%{local_bindir}
install -d %{buildroot}%{local_sbindir}
install -m 700 -P -D %{_buildsubdir}/scripts/patch-restart-mtce %{buildroot}%{local_sbindir}
install -m 700 -p -D %{_buildsubdir}/scripts/patch-restart-processes %{buildroot}%{local_sbindir}
install -m 700 -p -D %{_buildsubdir}/scripts/patch-restart-haproxy %{buildroot}%{local_sbindir}
install -d %{buildroot}/etc/systemd/system
install -m 644 -p -D %{_buildsubdir}/scripts/opt-platform.mount %{buildroot}/etc/systemd/system
install -m 644 -p -D %{_buildsubdir}/scripts/opt-platform.service %{buildroot}/etc/systemd/system
# Mask the systemd ctrl-alt-delete.target, to disable reboot on ctrl-alt-del
ln -sf /dev/null %{buildroot}/etc/systemd/system/ctrl-alt-del.target
%clean
rm -rf $RPM_BUILD_ROOT
%post -n platform-util-noncontroller
mkdir -p /opt/platform
systemctl enable opt-platform.service
%files
%license LICENSE
%defattr(-,root,root,-)
/usr/bin/verify-license
%{local_bindir}/cgcs_tc_setup.sh
%{local_bindir}/remotelogging_tc_setup.sh
%{local_bindir}/connectivity_test
%{local_sbindir}/patch-restart-mtce
%{local_sbindir}/patch-restart-processes
%{local_sbindir}/patch-restart-haproxy
/etc/systemd/system/ctrl-alt-del.target
%dir %{pythonroot}/platform_util
%{pythonroot}/platform_util/*
%dir %{pythonroot}/platform_util-%{version}.0-py2.7.egg-info
%{pythonroot}/platform_util-%{version}.0-py2.7.egg-info/*
%files -n platform-util-noncontroller
%defattr(-,root,root,-)
# This is necessary to mask opt-platform.mount, so that the version generated
# from parsing the fstab is not used by systemd.
/etc/systemd/system/opt-platform.mount
/etc/systemd/system/opt-platform.service

View File

@ -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.

View File

@ -0,0 +1,5 @@
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -0,0 +1,15 @@
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import oslo_i18n
DOMAIN = 'platform-util'
_translators = oslo_i18n.TranslatorFactory(domain=DOMAIN)
_ = _translators.primary
_LI = _translators.log_info
_LW = _translators.log_warning
_LE = _translators.log_error

View File

@ -0,0 +1,5 @@
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#

View File

@ -0,0 +1,66 @@
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# coding=utf-8
#
# All available licenses
LICENSE_FEATURE_STD = "WR_TS"
LICENSE_FEATURE_STD_EVAL = "WR_TS_EVAL"
LICENSE_FEATURE_AIO = "WR_TS_CPE"
LICENSE_FEATURE_AIO_EVAL = "WR_TS_CPE_EVAL"
LICENSE_FEATURE_SIMPLEX = "WR_TS_CPE_SX"
LICENSE_FEATURE_SIMPLEX_EVAL = "WR_TS_CPE_SX_EVAL"
# All supporting license names
STD_PRODUCT_CFG = "Standard_Product_Configuration"
AIO_PRODUCT_CFG = "All-In-One_Product_Configuration"
AIO_SX_PRODUCT_CFG = "All-In-One_Simplex_Product_Configuration"
# All supporting licenses list
LICENSE_NAMES = [
STD_PRODUCT_CFG,
AIO_PRODUCT_CFG,
AIO_SX_PRODUCT_CFG
]
# License mapping
LICENSE_MAP = {
LICENSE_FEATURE_STD: STD_PRODUCT_CFG,
LICENSE_FEATURE_AIO: AIO_PRODUCT_CFG,
LICENSE_FEATURE_SIMPLEX: AIO_SX_PRODUCT_CFG,
LICENSE_FEATURE_STD_EVAL: STD_PRODUCT_CFG,
LICENSE_FEATURE_AIO_EVAL: AIO_PRODUCT_CFG,
LICENSE_FEATURE_SIMPLEX_EVAL: AIO_SX_PRODUCT_CFG,
}
# Product licenses lists
STD_SYSTEM_LICENSES = [LICENSE_FEATURE_STD, LICENSE_FEATURE_STD_EVAL]
AIO_SYSTEM_LICENSES = [LICENSE_FEATURE_AIO, LICENSE_FEATURE_AIO_EVAL]
AIO_SIMPLEX_SYSTEM_LICENSES = [LICENSE_FEATURE_SIMPLEX, LICENSE_FEATURE_SIMPLEX_EVAL]
# License check error types
NO_FEATURE_LICENSE_ERR = "No such feature exists"
EXPIRED_LICENSE_ERR = "Feature has expired"
VERSION_LICENSE_ERR = "License file does not support this version"
# License limits
LICENSE_DATE_TEXT_MAX_CHAR = 32
LICENSE_ERR_MSG_MAX_CHAR = 512
LICENSE_VENDOR_MAX_CHAR =128
# Package name prefix
PACKAGE_PREFIX = "NL_TS"
# Feature name prefix
FEATURE_PREFIX = "WR_TS"
# License status
INSTALLED = "Installed"
NOT_INSTALLED = "Not-installed"
INVALID = "Invalid"
EXPIRED = "Expired"

View File

@ -0,0 +1,40 @@
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
class ValidateError(Exception):
"""Base class for license validation exceptions."""
def __init__(self, message=None):
self.message = message
def __str__(self):
return self.message or ""
class InvalidLicense(ValidateError):
"""Generic invalid license error"""
pass
class ExpiredLicense(ValidateError):
"""Expired license error"""
pass
class InvalidLicenseVersion(ValidateError):
"""Invalid license version error"""
pass
class InvalidLicenseType(ValidateError):
"""Invalid license type error"""
pass
class LicenseNotFound(ValidateError):
"""License not found error"""
pass

View File

@ -0,0 +1,202 @@
#
# Copyright (c) 2017-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
from ctypes import cdll,util,c_bool,c_int,c_char_p,pointer,create_string_buffer
import logging
import os
from platform_util.license import constants,exception
import re
import sys
from sysinv.common import constants as sysinv_constants
from tsconfig.tsconfig import system_type,system_mode, SW_VERSION
LOG = logging.getLogger(__name__)
sm_common = cdll.LoadLibrary(util.find_library("sm_common"))
class c_char_p_sub(c_char_p):
pass
def get_licenses_info():
"""Get the license information"""
feature_list = []
sm_common.flex_lm_license_get_feature_list.restype = c_char_p_sub
features = sm_common.flex_lm_license_get_feature_list()
if features.value:
feature_list = [feature for feature in features.value.split(',')
if feature.startswith(constants.FEATURE_PREFIX)]
sm_common.flex_lm_license_free(features)
lc_attrs_list = []
licenses = [license for license in constants.LICENSE_NAMES]
for feature in feature_list:
try:
lc_attrs = verify_feature_license(feature)
except Exception as e:
# Set the license attributes for installed expired licenses
if constants.EXPIRED.lower() in e:
process_license = True
status = constants.INSTALLED
expiry_date = constants.EXPIRED
# Set the license attributes for installed invalid licenses
elif constants.INVALID or constants.VERSION_LICENSE_ERR in e:
process_license = True
status = constants.INVALID
expiry_date = '-'
# Unknown license
else:
process_license = False
LOG.warning("Feature %s is not supported." % feature)
# Send supporting licenses only
name = constants.LICENSE_MAP.get(feature)
if process_license and name:
lc_attrs = dict(name=name, status=status,
expiry_date=expiry_date)
else:
lc_attrs = dict()
if lc_attrs:
license_name = lc_attrs.get('name')
if (not any(lc.get('name') == license_name
for lc in lc_attrs_list)):
# Get the list of license attributes for all valid
# licenses and installed expired/invalid licenses
lc_attrs_list.append(lc_attrs)
if license_name in licenses:
# Get the list of not-installed license names
licenses.remove(license_name)
# Set the license attributes for all
# not-installed licenses
for license_name in licenses:
lc_attrs = dict(name=license_name,
status=constants.NOT_INSTALLED,
expiry_date='-')
lc_attrs_list.append(lc_attrs)
# Return the list of license attributes
# for all supporting licenses
return lc_attrs_list
def verify_feature_license(feature_name, feature_version=None):
"""Verify a license of a feature"""
valid = pointer(c_bool(0))
if not feature_version:
feature_version = SW_VERSION
expire_days_left = pointer(c_int(0))
expire_date_text = create_string_buffer(
constants.LICENSE_DATE_TEXT_MAX_CHAR)
vendor = create_string_buffer(
constants.LICENSE_VENDOR_MAX_CHAR)
err_msg = create_string_buffer(
constants.LICENSE_ERR_MSG_MAX_CHAR)
LOG.info("License check. License feature name=%s version=%s",
feature_name, feature_version)
feature_check = sm_common.sm_license_check(valid,
feature_name,
feature_version,
expire_days_left, expire_date_text,
vendor, err_msg)
sm_common.sm_error_str.restype = c_char_p
if (sm_common.sm_error_str(feature_check) != 'OKAY' or
(not valid.contents.value)):
LOG.error("License check error, error = %s\n", err_msg.value)
msg = "ERROR: License check failed; "
if constants.NO_FEATURE_LICENSE_ERR in err_msg.value:
msg += "the license file does not contain the required license."
raise exception.LicenseNotFound(msg)
elif constants.EXPIRED_LICENSE_ERR in err_msg.value:
msg += "the license file contains a license that is expired."
raise exception.ExpiredLicense(msg)
elif constants.VERSION_LICENSE_ERR in err_msg.value:
msg += "the license file contains a license which is NOT applicable " \
"to the current system software version."
raise exception.InvalidLicenseVersion(msg)
else:
msg += "the license file contains an invalid license."
raise exception.InvalidLicense(msg)
vendor = re.search(r'\<name\>(.*?)\<\/name\>', vendor.value)
if vendor:
license_name = vendor.group(1)
else:
license_name = constants.LICENSE_MAP.get(feature_name)
# Return license attributes of a valid license
lc_attrs = dict(name=license_name, status=constants.INSTALLED,
expiry_date=expire_date_text.value)
return lc_attrs
def verify_license(license_file):
"""Verify all features in a license file"""
os.environ["LM_LICENSE_FILE"] = license_file
os.environ["WIND_LICENSE_PROXY"] = "/usr/bin/wrlmproxy-5.0.2"
# Get all features in the license file
feature_list = []
sm_common.flex_lm_license_get_feature_list.restype = c_char_p_sub
features = sm_common.flex_lm_license_get_feature_list()
if features.value:
feature_list = [feature for feature in features.value.split(',')
if feature.startswith(constants.FEATURE_PREFIX)]
sm_common.flex_lm_license_free(features)
# Validate license of each feature in the license file
for feature in feature_list:
verify_feature_license(feature)
if system_type == sysinv_constants.TIS_AIO_BUILD:
if system_mode == sysinv_constants.SYSTEM_MODE_SIMPLEX:
product_license = constants.AIO_SIMPLEX_SYSTEM_LICENSES
elif (system_mode == sysinv_constants.SYSTEM_MODE_DUPLEX or
system_mode == sysinv_constants.SYSTEM_MODE_DUPLEX_DIRECT):
product_license = constants.AIO_SYSTEM_LICENSES
elif system_type == sysinv_constants.TIS_STD_BUILD:
product_license = constants.STD_SYSTEM_LICENSES
# Verify the right product license is installed
if not any(feature in feature_list for feature in product_license):
raise exception.InvalidLicenseType(
"ERROR: License check failed; the license file does not contain a "
"product license for the current %s/%s." % (system_type, system_mode))
# Verify the licensed tech-preview technologies(ex. baremetal container..)
# Check if magnum or ironic services are currently running
# If yes, verify the feature licenses for magnum/ironic are licensed in the
# license file.
def main():
if len(sys.argv) == 2 :
licensefile = sys.argv[1]
else:
print "Usage: verify-license <license file>"
exit(-1)
try:
verify_license(licensefile)
except exception.InvalidLicenseType:
exit(1)
except exception.LicenseNotFound:
exit(2)
except exception.ExpiredLicense:
exit(3)
except exception.InvalidLicenseVersion:
exit(4)
except exception.InvalidLicense:
exit(5)

View File

@ -0,0 +1,20 @@
#
# Copyright (c) 2017-2018 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
import setuptools
setuptools.setup(
name='platform_util',
description='Platform Util',
version='1.0.0',
license='Apache-2.0',
platforms=['any'],
packages=['platform_util', 'platform_util.license'],
entry_points={
'console_scripts': [
'verify-license = platform_util.license.license:main'
],
}
)

View File

@ -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.

View File

@ -0,0 +1,485 @@
#!/bin/sh
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# $1 - interface
# $2 - interface type [mgmt, infra]
# $3 - dummy used to determine if we're backgrounded or not
DEV=$1
NETWORKTYPE=$2
NETWORKSPEED=$3
if [ ${NETWORKTYPE} != "mgmt" -a ${NETWORKTYPE} != "infra" ]; then
exit 0
fi
# We want to be able to wait some time (typically <10 sec) for the
# network link to autonegotiate link speed. Re-run the script in
# the background so the parent can return right away and init can
# continue.
if [ $# -eq 3 ]
then
$0 $DEV $NETWORKTYPE $NETWORKSPEED dummy &
disown
exit 0
fi
function test_valid_speed
{
# After the link is enabled but before the autonegotiation is complete
# the link speed may be read as either -1 or as 4294967295 (which is
# uint(-1) in twos-complement) depending on the kernel. Neither one is valid.
if (( $1 > 0 )) && (( $1 != 4294967295 ))
then
return 0
else
return 1
fi
}
function log
{
# It seems that syslog isn't yet running, so append directly to the syslog file
echo `date +%FT%T.%3N` `hostname` CGCS_TC_SETUP: $@ >> /var/log/platform.log
}
function infra_exists
{
if [ -z "$infrastructure_interface" ]
then
return 1
else
return 0
fi
}
function is_consolidated
{
if ! infra_exists
then
return 1
else
# determine whether the management interface is a parent of the
# infrastructure interface based on name.
# eg. this matches enp0s8 to enp0s8.10 but not enp0s88
if [[ $infrastructure_interface =~ $management_interface[\.][0-9]+$ ]]
then
return 0
fi
return 1
fi
}
function is_vlan
{
if [ -f /proc/net/vlan/$DEV ]
then
return 0
else
return 1
fi
}
function is_loopback
{
# (from include/uapi/linux/if.h)
IFF_LOOPBACK=$((1<<3))
# get the interface flags
FLAGS=`cat /sys/class/net/$DEV/flags`
if ((($IFF_LOOPBACK & $FLAGS) == 0))
then
return 1
else
return 0
fi
}
function setup_tc_port_filter
{
local PORT=$1
local PORTMASK=$2
local FLOWID=$3
local PROTOCOL=$4
if [ -z $PROTOCOL ]
then
# Apply to TCP and UDP
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dport $PORT $PORTMASK flowid $FLOWID
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip sport $PORT $PORTMASK flowid $FLOWID
else
# Apply to specific protocol only
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip protocol 6 0xff match ip dport $PORT $PORTMASK flowid $FLOWID
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip protocol 6 0xff match ip sport $PORT $PORTMASK flowid $FLOWID
fi
}
function setup_tc_tos_filter
{
local TOS=$1
local TOSMASK=$2
local FLOWID=$3
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip tos $TOS $TOSMASK flowid $FLOWID
}
function setup_root_tc
{
# create new qdiscs, classes and queues
tc qdisc add dev $DEV root handle 1: htb default 40
tc class add dev $DEV parent 1: classid 1:1 htb rate ${SPEED}mbit burst 15k quantum 60000
}
function setup_default_tc
{
local RATE=$1
local CEIL=$2
local FLOWQ=40
local CLASSID=1:$FLOWQ
local FLOWID=$CLASSID
# create default qdiscs, classes
$AC $CLASSID htb rate $((${RATE}*${SPEED}/100))mbit burst 15k ceil $((${CEIL}*${SPEED}/100))mbit prio 4 quantum 60000
tc qdisc add dev $DEV parent $CLASSID handle $FLOWQ: sfq perturb 10
}
function setup_hiprio_tc
{
local RATE=$1
local CEIL=$2
local FLOWQ=10
local CLASSID=1:$FLOWQ
local FLOWID=$CLASSID
# create high priority qdiscs, classes, and queues
$AC $CLASSID htb rate $((${RATE}*${SPEED}/100))mbit burst 15k ceil $((${CEIL}*${SPEED}/100))mbit prio 3 quantum 60000
tc qdisc add dev $DEV parent $CLASSID handle $FLOWQ: sfq perturb 10
# filter for high priority traffic
setup_tc_tos_filter 0x10 0xf8 $FLOWID
}
function setup_migration_tc
{
local RATE=$1
local CEIL=$2
local FLOWQ=30
local CLASSID=1:$FLOWQ
local FLOWID=$CLASSID
# create migration qdiscs, classes, and queues
$AC $CLASSID htb rate $((${RATE}*${SPEED}/100))mbit burst 15k ceil $((${CEIL}*${SPEED}/100))mbit prio 2 quantum 60000
tc qdisc add dev $DEV parent $CLASSID handle $FLOWQ: sfq perturb 10
# Migration (TCP, ports 49152-49215)
setup_tc_port_filter 49152 0xffc0 $FLOWID $TCP
# Migration via libvirt tunnel (TCP, port 16509)
setup_tc_port_filter 16509 0xffff $FLOWID $TCP
}
function setup_storage_tc
{
local RATE=$1
local CEIL=$2
local FLOWQ=20
local CLASSID=1:$FLOWQ
local FLOWID=$CLASSID
# create storage qdiscs, classes, and queues
$AC $CLASSID htb rate $((${RATE}*${SPEED}/100))mbit burst 15k ceil $((${CEIL}*${SPEED}/100))mbit prio 1 quantum 60000
tc qdisc add dev $DEV parent $CLASSID handle $FLOWQ: sfq perturb 10
# Storage, NFS (UDP/TCP, port 2049)
setup_tc_port_filter 2049 0xffff $FLOWID
# Storage, iSCSI (UDP/TCP, port 3260)
setup_tc_port_filter 3260 0xffff $FLOWID
# Storage, CEPH (TCP, ports 6789,6800-7100)
PORTS=( 6789 6800 6816 6912 7040 7072 7088 )
PORTMASKS=( 0xffff 0xfff0 0xffa0 0xff80 0xffa0 0xfff0 0xfffa )
for idx in "${!PORTS[@]}"; do
PORT=${PORTS[$idx]}
MASK=${PORTMASKS[$idx]}
setup_tc_port_filter $PORT $MASK $FLOWID $TCP
done
}
function setup_drbd_tc
{
local RATE=$1
local CEIL=$2
local FLOWQ=50
local CLASSID=1:$FLOWQ
local FLOWID=$CLASSID
# create DRBD qdiscs, classes and queues
$AC $CLASSID htb rate $((${RATE}*${SPEED}/100))mbit burst 15k ceil $((${CEIL}*${SPEED}/100))mbit quantum 60000
tc qdisc add dev $DEV parent $CLASSID handle $FLOWQ: sfq perturb 10
# DRDB (TCP, ports 7789,7790,7791,7799)
# port 7793 is used with drdb-extension
PORTS=( 7789 7790 7791 7792 7799 7793 )
PORTMASKS=( 0xffff 0xffff 0xffff 0xffff 0xffff )
for idx in "${!PORTS[@]}"; do
PORT=${PORTS[$idx]}
MASK=${PORTMASKS[$idx]}
setup_tc_port_filter $PORT $MASK $FLOWID $TCP
done
}
function setup_mgmt_tc_individual
{
# Configure high priority and default traffic classes.
setup_root_tc
# bandwidth percentages
local HIPRIO_BW=10
local DEFAULT_BW=10
# bandwidth ceiling percentages, for borrowing bandwidth.
# the management interface is not consolidated, so set the ceiling to the
# maximum rate.
local HIPRIO_CBW=100
local DEFAULT_CBW=100
setup_hiprio_tc $HIPRIO_BW $HIPRIO_CBW
setup_default_tc $DEFAULT_BW $DEFAULT_CBW
}
function setup_mgmt_tc_vlan
{
# Configure high priority and default traffic classes.
setup_root_tc
# bandwidth percentages
local HIPRIO_BW=10
local DEFAULT_BW=10
# bandwidth ceiling percentages, for borrowing bandwidth.
# The management interface is a vlan, so reserve bandwidth
# for sibling infra vlan interfaces.
local HIPRIO_CBW=20
local DEFAULT_CBW=20
setup_hiprio_tc $HIPRIO_BW $HIPRIO_CBW
setup_default_tc $DEFAULT_BW $DEFAULT_CBW
}
function setup_mgmt_tc_consolidated
{
# Configure management classes.
# All traffic coming from the infra will get treated again by the
# management traffic classes. We need to apply the same TCs as the
# infra to prevent a management application from starving the
# upper interface.
setup_root_tc
setup_tc_all
}
function setup_mgmt_tc_infra_exists
{
if is_consolidated
then
# Infra over mgmt. In this case we want to reserve
# a small portion of the link for management.
setup_mgmt_tc_consolidated
else
# Only setup hiprio and default classes.
# The infra will handle storage, migration, DRBD.
if is_vlan
then
setup_mgmt_tc_vlan
else
setup_mgmt_tc_individual
fi
fi
}
function setup_mgmt_tc_no_infra
{
# Configure traffic classes for a management interface when
# no infrastructure interface exists. Configure the full
# set of TCs.
setup_root_tc
setup_tc_all
}
function setup_infra_tc_consolidated
{
# Configure the full set of traffic classes, but leave a small
# portion of bandwidth for the management interface.
# reserve 1% BW for management
local RESERVED=$((1*${SPEED}/100))
SPEED=$((${SPEED}-${RESERVED}))
setup_root_tc
setup_tc_all
}
function setup_infra_tc_individual
{
# Configure the full set of traffic classes.
setup_root_tc
if is_vlan
then
# reserve 1% BW for sibling vlan interfaces
local RESERVED=$((1*${SPEED}/100))
SPEED=$((${SPEED}-${RESERVED}))
fi
setup_tc_all
}
function setup_tc_all
{
# bandwidth percentages, in case of over-percentage, bandwidth is divided based
# on bandwidth ratios
local MIG_BW=30
local STOR_BW=50
local DRBD_BW=80
local HIPRIO_BW=10
local DEFAULT_BW=10
# bandwidth ceiling percentages, for borrowing bandwidth
local MIG_CBW=100
local STOR_CBW=100
local DRBD_CBW=100
local HIPRIO_CBW=20
local DEFAULT_CBW=20
setup_hiprio_tc $HIPRIO_BW $HIPRIO_CBW
setup_storage_tc $STOR_BW $STOR_CBW
setup_migration_tc $MIG_BW $MIG_CBW
setup_default_tc $DEFAULT_BW $DEFAULT_CBW
if [ $nodetype == "controller" ]
then
setup_drbd_tc $DRBD_BW $DRBD_CBW
fi
}
function get_dev_speed
{
# If the link doesn't come up we won't go enabled, so here we can
# afford to wait forever for the link.
while true
do
if [ -e /sys/class/net/$1/bonding ]
then
for VAL in `cat /sys/class/net/$1/lower_*/speed`
do
if test_valid_speed $VAL
then
log slave for bond link $1 reported speed $VAL
echo $VAL
return 0
else
log slave for bond link $1 reported invalid speed $VAL
fi
done
log all slaves for bond link $1 reported invalid speeds, will sleep 30 sec and try again
else
VAL=`cat /sys/class/net/$1/speed`
if test_valid_speed $VAL
then
log link $1 reported speed $VAL
echo $VAL
return 0
else
log link $1 returned invalid speed $VAL, will sleep 30 sec and try again
fi
fi
sleep 30
done
}
function get_speed
{
local dev=$1
local networktype=$2
local net_speed=$NETWORKSPEED
local dev_speed=$(get_dev_speed $DEV)
local speed=$dev_speed
if [ $net_speed != $dev_speed ]
then
log WARNING: $dev has a different operational speed [$dev_speed] \
than configured speed [$net_speed] for network type $networktype
if test_valid_speed $net_speed
then
# Use greater of configured net speed / recorded dev speed
if [ $net_speed -gt $dev_speed ]
then
speed=$net_speed
fi
fi
fi
log using speed $speed for tc filtering on $dev
echo $speed
}
if is_loopback
then
# mgmt/infra uses the loopback for CPE simplex
exit 0
fi
log running tc setup script for $DEV $NETWORKTYPE in background
if [ -f /etc/platform/platform.conf ]
then
source /etc/platform/platform.conf
fi
SPEED=$(get_speed $DEV $NETWORKTYPE)
# 1:10 = high priority class
# 1:20 = storage class
# 1:30 = migration class
# 1:40 = default class
# 1:50 = DRBD class
# generic class add preamble
AC="tc class add dev $DEV parent 1:1 classid"
# protocol numbers
TCP=6
UDP=17
# delete existing qdiscs
tc qdisc del dev $DEV root > /dev/null 2>&1
if [ ${NETWORKTYPE} = "mgmt" ]
then
if infra_exists
then
setup_mgmt_tc_infra_exists
else
setup_mgmt_tc_no_infra
fi
else
if is_consolidated
then
setup_infra_tc_consolidated
else
setup_infra_tc_individual
fi
fi

View File

@ -0,0 +1,58 @@
#! /bin/bash
#
# Copyright (c) 2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
usage ()
{
echo "Usage: `basename $0` [-t TIMEOUT] [-i INTERFACE] DEST"
echo "Tests connectivity to DEST (hostname or IP). Test is done with ping/ping6."
echo ""
echo "Options:"
echo " -t TIMEOUT how long to wait before failing - defaults to 70 seconds"
echo " -i INTERFACE interface to use for ping - default is to allow ping command to select interface"
exit 1
}
TIMEOUT=70
IFARG=""
while getopts t:i: opt; do
case $opt in
t)
TIMEOUT=$OPTARG
;;
i)
INTERFACE=$OPTARG
;;
*)
usage
;;
esac
done
shift $((OPTIND-1))
if [ -z $1 ]; then
usage
fi
if [ ! -z "$INTERFACE" ]; then
IFARG="-I $INTERFACE"
IFMSG="over interface $INTERFACE"
fi
DEST=$1
echo "Checking connectivity to $DEST for up to $TIMEOUT seconds $IFMSG"
while [ "$SECONDS" -le "$TIMEOUT" ]; do
ping -c 1 $IFARG $DEST > /dev/null 2>&1 || ping6 -c 1 $IFARG $DEST > /dev/null 2>&1
if [ $? -eq 0 ]
then
exit 0
fi
sleep 1
done
exit 1

View File

@ -0,0 +1,15 @@
[Unit]
Description=Titanium Cloud opt-platform mounter
After=sw-patch.service
[Service]
Type=oneshot
User=root
ExecStart=/usr/bin/nfs-mount controller-platform-nfs:/opt/platform /opt/platform
ExecStop=/usr/bin/umount /opt/platform
RemainAfterExit=yes
StandardOutput=syslog+console
StandardError=syslog+console
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,94 @@
#!/bin/bash
#
# Copyright (c) 2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# This script provides in-service patching restart for haproxy
#
# The patching subsystem provides a patch-functions bash source file
# with useful function and variable definitions.
#
if [ -e "/etc/patching/patch-functions" ] ; then
. /etc/patching/patch-functions
fi
loginfo "----------------------------------------------"
loginfo "Haproxy No-Reboot Patching Restart Request"
#
# Declare an overall script return code
#
declare -i GLOBAL_RC=$PATCH_STATUS_OK
SM_RESTART_CMD="sm-restart-safe"
SM_QUERY_CMD="sm-query"
SM_ENABLED_ACTIVE="enabled-active"
DAEMON_NAME=haproxy
NEUTRON_RESTART_CMD="/bin/neutron-restart"
# check if SM managed haproxy process is running on the controllers
if is_controller
then
if [ ! -f $PATCH_FLAGDIR/$DAEMON_NAME.restarted ]
then
${SM_QUERY_CMD} service ${DAEMON_NAME} | grep -q ${SM_ENABLED_ACTIVE}
if [ $? -eq 0 ]
then
# The daemon is running, so restart it
loginfo "$0: Restarting ${DAEMON_NAME}"
${SM_RESTART_CMD} service "${DAEMON_NAME}"
touch $PATCH_FLAGDIR/$DAEMON_NAME.restarted
# Wait up to 10 seconds for service to recover
let -i UNTIL=$SECONDS+10
while [ $UNTIL -ge $SECONDS ]
do
# Check to make sure it's running
${SM_QUERY_CMD} service ${DAEMON_NAME} | grep -q ${SM_ENABLED_ACTIVE}
if [ $? -eq 0 ]
then
break
fi
# Not running Let's wait a couple of seconds and check again
loginfo "$0: ${DAEMON_NAME} is not running, wait for 2 seconds"
sleep 2
done
${SM_QUERY_CMD} service ${DAEMON_NAME} | grep -q ${SM_ENABLED_ACTIVE}
if [ $? -ne 0 ]
then
# Still not running! Clear the flag and mark the RC as failed
GLOBAL_RC=$PATCH_STATUS_FAILED
loginfo "$0: Failed to restart ${DAEMON_NAME}"
fi
fi
fi
fi
# check if it is a CPE system or a compute node
if is_cpe || is_compute
then
# restart neutron-agent managed haproxy processes
if [ ! -f $NEUTRON_RESTART_CMD ]
then
loginfo "$0: ${NEUTRON_RESTART_CMD} is not available for restarting ${DAEMON_NAME}"
GLOBAL_RC=$PATCH_STATUS_FAILED
else
loginfo "$0: Restarting neutron agent managed ${DAEMON_NAME}"
${NEUTRON_RESTART_CMD} --agents-using-haproxy
if [ $? -ne $PATCH_STATUS_OK ]
then
loginfo "$0: Failed to restart neutron agent managed ${DAEMON_NAME}"
GLOBAL_RC=$PATCH_STATUS_FAILED
fi
fi
fi
# Exit the script with the overall return code
#
exit $GLOBAL_RC

View File

@ -0,0 +1,476 @@
#!/bin/bash
#
# Copyright (c) 2016 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# This script supports no-reboot patching of any single or
# combination of maintenance processes specified on the command line.
#
# Calling sequence:
#
# rc=mtce-restart process1 process2 process3 ...
# if [ $? != 0 ] ; then
# restart action failed
#
#
###############################################################################
#
# The patching subsystem provides a patch-functions bash source file
# with useful function and variable definitions.
#
if [ -e "/etc/patching/patch-functions" ] ; then
. /etc/patching/patch-functions
fi
loginfo "----------------------------------------------"
loginfo "Maintenance No-Reboot Patching Restart Request"
#
# Declare an overall script return code
#
declare -i GLOBAL_RC=$PATCH_STATUS_FAILED
#if [ ! -e $PATCH_FLAGDIR ] ; then
# mkdir -p $PATCH_FLAGDIR
#fi
# if set with -c or --clean options then the flag files for
# each process are removed at the start.
CLEAN=false
#
# Completion status ; stored in PID index
#
DISABLED="disabled"
NOPID="not-running"
SKIPPED="skipped"
RESTARTED="restarted"
#
# process query and restart executables
#
SM_RESTART_EXEC="sm-restart-safe"
SM_QUERY_EXEC="sm-query"
PMON_RESTART_EXEC="pmon-restart"
#
# Struct indexes
#
PROCESS_INDEX=0
PID_INDEX=1
ALIAS_INDEX=2
#
# Process Struct and List [ name ] [ alias ] [ pid | status ]
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# NOTE TO PATCH WRITERS: Simply Un-Comment processes you want no-reboot patch restarted.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
# The process restart control structure
declare sm_managed_processes=""
declare pmon_managed_processes=""
# Build the process list.
# All arguements should be a valid maintenance process name.
# The name of the binary, not the SM alias.
# See the list below for supported process names.
while [[ ${#} > 0 ]]
do
process="${1}"
case $process in
-c|--clean)
CLEAN=true
;;
# Maintenance Processes - SM managed
"mtcAgent")
sm_managed_processes=( ${sm_managed_processes[@]} "mtcAgent:0:mtc-agent")
;;
"hbsAgent")
sm_managed_processes=( ${sm_managed_processes[@]} "hbsAgent:0:hbs-agent")
;;
"guestAgent")
sm_managed_processes=( ${sm_managed_processes[@]} "guestAgent:0:guest-agent")
;;
"hwmond")
sm_managed_processes=( ${sm_managed_processes[@]} "hwmond:0:hw-mon")
;;
# Maintenance Processes - PMON managed
"pmond")
pmon_managed_processes=(${pmon_managed_processes[@]} "pmond:0")
;;
"guestServer")
pmon_managed_processes=(${pmon_managed_processes[@]} "guestServer:0")
;;
"mtcClient")
pmon_managed_processes=(${pmon_managed_processes[@]} "mtcClient:0")
;;
"hbsClient")
pmon_managed_processes=(${pmon_managed_processes[@]} "hbsClient:0")
;;
"rmond")
pmon_managed_processes=(${pmon_managed_processes[@]} "rmond:0")
;;
"hostwd")
pmon_managed_processes=(${pmon_managed_processes[@]} "hostwd:0")
;;
"fsmond")
pmon_managed_processes=(${pmon_managed_processes[@]} "fsmond:0")
;;
"mtclogd")
pmon_managed_processes=(${pmon_managed_processes[@]} "mtclogd:0")
;;
"mtcalarmd")
pmon_managed_processes=(${pmon_managed_processes[@]} "mtcalarmd:0")
;;
*)
loginfo "Unknown process:${process}"
;;
esac
shift
done
# Assume both groupings are done until we know there are not
sm_done=true
pmon_done=true
#if [ ${#sm_managed_processes[@]} -ne 0 -a is_controller ] ; then
if [ -n "${sm_managed_processes}" -a is_controller ] ; then
# Record current process IDs
index=0
for DAEMON in "${sm_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ "${CLEAN}" = true ] ; then
rm -f $PATCH_FLAGDIR/${info[${PROCESS_INDEX}]}.restarted
fi
info[${PID_INDEX}]=`pidof ${info[${PROCESS_INDEX}]}`
if [ -z "${info[${PID_INDEX}]}" ] ; then
loginfo "${info[${PROCESS_INDEX}]} is not running"
info[${PID_INDEX}]="${NOPID}"
fi
# Save the PID or NOPID status to the process line
sm_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}:${info[${ALIAS_INDEX}]}"
((index++))
done
# Restart the processes
index=0
for DAEMON in "${sm_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ -e $PATCH_FLAGDIR/${info[${PROCESS_INDEX}]}.restarted ] ; then
info[${PID_INDEX}]="${SKIPPED}"
# Add the PID to the process line
sm_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}:${info[${ALIAS_INDEX}]}"
((index++))
continue
fi
sm_query_result=`${SM_QUERY_EXEC} service ${info[${ALIAS_INDEX}]}`
if [[ "${sm_query_result}" == *"enabled-active"* ]] ; then
# Save the original PID
info[${PID_INDEX}]=`pidof ${info[${PROCESS_INDEX}]}`
if [ -n "${info[${PID_INDEX}]}" ] ; then
loginfo "sm-restart of ${info[${PROCESS_INDEX}]} [pid:${info[${PID_INDEX}]}]"
touch $PATCH_FLAGDIR/${info[${PROCESS_INDEX}]}.restarted
${SM_RESTART_EXEC} service "${info[${ALIAS_INDEX}]}"
sm_done=false
sleep 5
else
loginfo "${info[${PROCESS_INDEX}]} is not running ; must be on inactive controller"
info[${PID_INDEX}]="${NOPID}"
fi
elif [[ ${sm_query_result} == *"is enabling"* ]] ; then
info[${PID_INDEX}]="${NOPID}"
loginfo "sm-restart ${info[${PROCESS_INDEX}]} ; [in progress] ; [pid:${info[${PID_INDEX}]}]"
else
info[${PID_INDEX}]="${DISABLED}"
loginfo "${info[${PROCESS_INDEX}]} is not active"
fi
# Add the PID to the process line
sm_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}:${info[${ALIAS_INDEX}]}"
((index++))
done
fi
if [ -n "${pmon_managed_processes}" ] ; then
echo "DEBUG: pmon_managed_processes:${pmon_managed_processes}"
# Restart the pmond processes
index=0
for DAEMON in "${pmon_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ "${CLEAN}" = true ] ; then
rm -f $PATCH_FLAGDIR/${info[${PROCESS_INDEX}]}.restarted
fi
if [ -e $PATCH_FLAGDIR/${info[${PROCESS_INDEX}]}.restarted ] ; then
info[${PID_INDEX}]="${SKIPPED}"
pmon_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}"
((index++))
continue
fi
# Save the original PID
info[${PID_INDEX}]=`pidof ${info[${PROCESS_INDEX}]}`
if [ -n "${info[${PID_INDEX}]}" ] ; then
loginfo "pmon-restart of ${info[${PROCESS_INDEX}]} [pid:${info[${PID_INDEX}]}]"
touch $PATCH_FLAGDIR/${info[${PROCESS_INDEX}]}.restarted
${PMON_RESTART_EXEC} ${info[${PROCESS_INDEX}]}
pmon_done=false
sleep 2
####################################################################
# Special Handling Section
#
# - pmond needs 30 seconds to restart before it will start
# monitoring processes.We can maybe remove that in the daemon
# config file but for now its there and we have to wait.
####################################################################
if [ "${info[${PROCESS_INDEX}]}" == "pmond" ] ; then
sleep 30
fi
else
info[${PID_INDEX}]="${DISABLED}"
loginfo "${info[${PROCESS_INDEX}]} is not active"
fi
# Save the updated PID or other status to the process line
pmon_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}"
((index++))
done
fi
# check for done. If this is not met in timeout then fail is returned
if [ "$sm_done" = true -a "$pmon_done" = true ] ; then
GLOBAL_RC=$PATCH_STATUS_OK
loginfo " SM Processes: ${sm_managed_processes[@]}"
loginfo "PMON Processes: ${pmon_managed_processes[@]}"
loginfo "Maintenance No-Reboot Patching Status: ${GLOBAL_RC} - nothing to do."
exit ${GLOBAL_RC}
fi
# Monitor the restart of SM processes
#
# Don't want to start from the beginning of the shell
# Want time zero now plus 20 seconds.
#
SECONDS=0
TIMEOUT=120
let UNTIL=${SECONDS}+${TIMEOUT}
loginfo "restart timeout is ${TIMEOUT}"
while [ ${UNTIL} -ge ${SECONDS} ]
do
if [ "$sm_done" = false ] ; then
if [ is_controller -o is_cpe ] ; then
sm_not_done=false
index=0
for DAEMON in "${sm_managed_processes[@]}"
do
info=(${DAEMON//:/ })
# Don't wast time on processes that are being skipped due to past restart
if [ "${info[${PID_INDEX}]}" == "${SKIPPED}" ] ; then
((index++))
continue
# Don't wast time on processes that have already restarted
elif [ "${info[${PID_INDEX}]}" == "${RESTARTED}" ] ; then
((index++))
continue
# Don't look for disabled processes
elif [ "${info[${PID_INDEX}]}" == "${DISABLED}" ] ; then
((index++))
continue
# Don't look at not running processes
elif [ "${info[${PID_INDEX}]}" == "${NOPID}" ] ; then
((index++))
continue
elif [[ `sm-query service ${info[${ALIAS_INDEX}]}` == *"enabled-active"* ]] ; then
# Save the original PID
new_pid=`pidof ${info[${PROCESS_INDEX}]}`
if [ $? -eq 0 -a -n ${new_pid} ] ; then
if [ "${info[${PID_INDEX}]}" != "${new_pid}" ] ; then
loginfo "${info[${PROCESS_INDEX}]} ${RESTARTED} ok [pid:${info[${PID_INDEX}]} -> ${new_pid}]"
info[${PID_INDEX}]="${RESTARTED}"
fi
fi
fi
if [ "${info[${PID_INDEX}]}" != "${RESTARTED}" ] ; then
sm_not_done=true
fi
# Add the PID to the process line
sm_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}:${info[${ALIAS_INDEX}]}"
((index++))
done
fi
# log when SM restarts are done print a summary only once
if [ "${sm_not_done}" = false -a "${sm_done}" = false ] ; then
sm_done=true
logged=false
for DAEMON in "${sm_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ "${info[${PID_INDEX}]}" == "${RESTARTED}" ] ; then
if [ "${logged}" = false ] ; then
loginfo "The following 'sm managed' processes have been 'restarted'"
logged=true
fi
loginfo "... process: ${info[${PROCESS_INDEX}]}"
fi
done
logged=false
for DAEMON in "${sm_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ "${info[${PID_INDEX}]}" == "${SKIPPED}" ] ; then
if [ "${logged}" = false ] ; then
loginfo "The following 'sm managed' processes have been 'skipped' ; due to previous restart"
logged=true
fi
loginfo "... process: ${info[${PROCESS_INDEX}]}"
fi
done
fi
fi
#########################################################################
# For all nodes ....
#########################################################################
# Loop over all PMON proceses looking for complete restarts.
# Update process struct PID field as status is learned.
if [ "$pmon_done" = false ] ; then
# Start assuming we are not done
pmon_not_done=false
index=0
for DAEMON in "${pmon_managed_processes[@]}"
do
info=(${DAEMON//:/ })
# Don't wast time on processes that are being skipped due to past restart
if [ "${info[${PID_INDEX}]}" == "${SKIPPED}" ] ; then
((index++))
continue
# Don't wast time on processes that have already restarted
elif [ "${info[${PID_INDEX}]}" == "${RESTARTED}" ] ; then
((index++))
continue
# Don't look for disabled processes
elif [ "${info[${PID_INDEX}]}" == "${DISABLED}" ] ; then
((index++))
continue
# Don't look at not running processes
elif [ "${info[${PID_INDEX}]}" == "${NOPID}" ] ; then
((index++))
continue
fi
# Save the original PID
new_pid=`pidof ${info[${PROCESS_INDEX}]}`
if [ $? -eq 0 -a "${new_pid}" != "" ] ; then
# set the process as restarted as soon as we have a new pid
if [ "${info[${PID_INDEX}]}" != "${RESTARTED}" ] ; then
loginfo "${info[${PROCESS_INDEX}]} ${RESTARTED} ok [PID: ${info[${PID_INDEX}]} -> ${new_pid}]"
info[${PID_INDEX}]=${RESTARTED}
fi
fi
# Set not done as long as there is one process not restarted
if [ "${info[${PID_INDEX}]}" != "${RESTARTED}" ] ; then
pmon_not_done=true
fi
# Add the PID to the process line
pmon_managed_processes[${index}]="${info[${PROCESS_INDEX}]}:${info[${PID_INDEX}]}"
((index++))
done
fi
# log when all pmond restarts are done
if [ "${pmon_not_done}" = false -a "${pmon_done}" = false ] ; then
pmon_done=true
logged=false
for DAEMON in "${pmon_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ "${info[${PID_INDEX}]}" == "${RESTARTED}" ] ; then
if [ "${logged}" = false ] ; then
loginfo "The following 'pmon managed' processes have been 'restarted'"
logged=true
fi
loginfo "... process: ${info[${PROCESS_INDEX}]}"
fi
done
logged=false
for DAEMON in "${pmon_managed_processes[@]}"
do
info=(${DAEMON//:/ })
if [ "${info[${PID_INDEX}]}" == "${SKIPPED}" ] ; then
if [ "${logged}" = false ] ; then
loginfo "The following 'pmon managed' processes have been 'skipped' ; due to previous restart"
logged=true
fi
loginfo "... process: ${info[${PROCESS_INDEX}]}"
fi
done
fi
# check for done. If this is not met in timeout then fail is returned
if [ "$sm_done" = true -a "$pmon_done" = true ] ; then
GLOBAL_RC=$PATCH_STATUS_OK
break
fi
sleep 1
done
loginfo "Maintenance No-Reboot Patching Status: ${GLOBAL_RC}"
exit ${GLOBAL_RC}

View File

@ -0,0 +1,637 @@
#!/bin/bash
#
# Copyright (c) 2016-18 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
script=`basename "$0"`
##############################################################################
#
# For Patch Writers
# -----------------
#
# This script supports no-reboot process restart from command line list.
# Must be run as root or y sudo
# Calling sequence:
#
# /usr/sbin/process-restart process1 process2 ... processN
# if [ $? != 0 ] ; then
# restart action failed
#
###############################################################################
#
# For Developers
# --------------
#
# Process restart support can be added to this script by adding your process to the
# command line parser as a new case based on the process's name in the following form.
#
# "[process-name]")
# process_list =(${process_list[@]} "[monitor] [process-name] [process-alias] [hosttype] [pidfile] [status]
# ;;
#
# Field Descriptions: all fields are manditory
#
# monitor : sm or pmon
# process-name : the name of the process
# - for sm monitored processes, this must be unique, but does
# not need to match the actual binary name
# - for pmon monitored processes, this must be unique and
# must match the actual binary name
# process-alias: the alias name that SM uses instead of the actual process name
# - valid for sm only
# - if its the same as the process name then make it the same
# hosttype : the supported hosttypes are ; stack with commas
# - all ...... all nodetypes
# - controller . controllers
# - storage .... storage nodes
# - compute .... compute nodes
# pidfile : the path to and name of the process's pidfile
# status : set as 0
#
# Example: based on sysinv-api which is monitored by sm, only runs on the controller
# and has an sm alias.
#
# "sysinv-api")
# process_list =(${process_list[@] } "sm:sysinv-api:sysinv-inv:controller:/var/run/sysinv-api.pid:0")
# ;;
#
# start with empty process restart control structure
declare process_list=""
declare pids=""
# pull in loginfo and nodetype
. /etc/patching/patch-functions
. /etc/platform/platform.conf
#
# Declare an overall script return code
#
declare -i GLOBAL_RC=$PATCH_STATUS_FAILED
# if set with -c or --clean options then the flag files for
# each process are removed at the start.
CLEAN=false
#
# if set with -p or --parallel options then restart each process in parallel
PARALLEL=false
#
# Completion status ; stored in PID index
#
DISABLED="disabled"
NOPID="not-running"
SKIPPED="skipped"
RESTARTED="restarted"
#
# process query and restart executables
#
SM_RESTART_EXEC="sm-restart-safe"
SM_QUERY_EXEC="sm-query"
PMON_RESTART_EXEC="pmon-restart"
#
# sleep delays (seconds)
#
SM_SLEEP=5
PMON_SLEEP=2
MONITOR_SLEEP=2
#
# Struct indexes
#
MONITOR_INDEX=0
PROCESS_INDEX=1
ALIAS_INDEX=2
HOSTTYPE_INDEX=3
PIDFILE_INDEX=4
STATUS_INDEX=5
#
# update_status: update the specified process index's status field
#
# ${1} = process list index
# ${2} = status
#
function update_status {
DAEMON=${process_list[${1}]}
info=(${DAEMON//:/ })
process_list[${1}]="${info[${MONITOR_INDEX}]}:${info[${PROCESS_INDEX}]}:${info[${ALIAS_INDEX}]}:${info[${HOSTTYPE_INDEX}]}:${info[${PIDFILE_INDEX}]}:${2}"
}
#
# print the list of processes that this script supports restart of
#
function print_list {
printf "\nThis restart script supports post patching restart the following processes ...\n\n"
list=$(fgrep "process_list=(${process_list[@]}" ${0} | grep -v grep | cut -f 2 -d ':')
printf "${list}\n\n"
}
#
# print the command and option syntax as well as the list of processes supported by this script
#
function print_help {
printf "\nTiS patching process restart script.\n"
printf "\n%s {-options} [processes ...]\n" "${script}"
printf "\noptions: -l or --list prints a list of supported processes\n"
print_list
}
#
# patching.log banner for this script
#
loginfo "------------------------------------------"
loginfo "No-Reboot Patching Process Restart Request"
#
# Option and process list parser
# Build the process list.
# All arguements should be a valid process name, not the SM alias.
# See the list below for supported process names.
#
while [[ ${#} > 0 ]]
do
process="${1}"
case $process in
-h|--help)
print_help
exit 0
;;
-l|--list)
print_list
exit 0
;;
-c|--clean)
CLEAN=true
;;
-p|--parallel)
PARALLEL=true
;;
# Sysinv processes
"sysinv-conductor")
process_list=(${process_list[@]} "sm:sysinv-conductor:sysinv-conductor:controller:/var/run/sysinv-conductor.pid:0")
;;
"sysinv-api")
process_list=(${process_list[@]} "sm:sysinv-api:sysinv-inv:controller:/var/run/sysinv-api.pid:0")
;;
"sysinv-agent")
process_list=(${process_list[@]} "pmon:sysinv-agent:sysinv-agent:all:/var/run/sysinv-agent.pid:0")
;;
"ceilometer-polling")
process_list=(${process_list[@]} "pmon:ceilometer-polling:ceilometer-polling:all:/var/run/ceilometer-polling.pid:0")
;;
"ceilometer-agent-notification")
process_list=(${process_list[@]} "sm:ceilometer-agent-notification:ceilometer-agent-notification:controller:/var/run/resource-agents/ceilometer-agent-notification.pid:0")
;;
"ceilometer-collector")
process_list=(${process_list[@]} "sm:ceilometer-collector:ceilometer-collector:controller:/var/run/resource-agents/ceilometer-collector.pid:0")
;;
"ceilometer-api")
process_list=(${process_list[@]} "sm:ceilometer-api:ceilometer-api:controller:/var/run/resource-agents/ceilometer-api.pid:0")
;;
"keystone")
process_list=(${process_list[@]} "sm:keystone:keystone:controller:/var/run/openstack-keystone.pid:0")
;;
# AODH processes
"aodh-api")
process_list=(${process_list[@]} "sm:aodh-api:aodh-api:controller:/var/run/resource-agents/aodh-api.pid:0")
;;
"aodh-evaluator")
process_list=(${process_list[@]} "sm:aodh-evaluator:aodh-evaluator:controller:/var/run/resource-agents/aodh-evaluator.pid:0")
;;
"aodh-listener")
process_list=(${process_list[@]} "sm:aodh-listener:aodh-listener:controller:/var/run/resource-agents/aodh-listener.pid:0")
;;
"aodh-notifier")
process_list=(${process_list[@]} "sm:aodh-notifier:aodh-notifier:controller:/var/run/resource-agents/aodh-notifier.pid:0")
;;
# Panko process
"panko-api")
process_list=(${process_list[@]} "sm:panko-api:panko-api:controller:/var/run/resource-agents/panko-api.pid:0")
;;
# Murano processes
"murano-engine")
process_list=(${process_list[@]} "sm:murano-engine:murano-engine:controller:/var/run/resource-agents/murano-engine.pid:0")
;;
"murano-api")
process_list=(${process_list[@]} "sm:murano-api:murano-api:controller:/var/run/resource-agents/murano-api.pid:0")
;;
# Magnum processes
"magnum-conductor")
process_list=(${process_list[@]} "sm:magnum-conductor:magnum-conductor:controller:/var/run/resource-agent/magnum-conductor.pid:0")
;;
"magnum-api")
process_list=(${process_list[@]} "sm:magnum-api:magnum-api:controller:/var/run/resource-agents/magnum-api.pid:0")
;;
# Ironic processes
"ironic-conductor")
process_list=(${process_list[@]} "sm:ironic-conductor:ironic-conductor:controller:/var/run/resource-agents/ironic-conductor.pid:0")
;;
"ironic-api")
process_list=(${process_list[@]} "sm:ironic-api:ironic-api:controller:/var/run/resource-agents/ironic-api.pid:0")
;;
# IO-Monitor process
"io-monitor-manager")
process_list=(${process_list[@]} "pmon:io-monitor-manager:io-monitor-manager:controller:/var/run/io-monitor/io-monitor-manager.pid:0")
;;
# HEAT processes
"heat-engine")
process_list=(${process_list[@]} "sm:heat-engine:heat-engine:controller:/var/run/resource-agents/heat-engine.pid:0")
;;
"heat-api")
process_list=(${process_list[@]} "sm:heat-api:heat-api:controller:/var/run/resource-agents/heat-api.pid:0")
;;
"heat-api-cfn")
process_list=(${process_list[@]} "sm:heat-api-cfn:heat-api-cfn:controller:/var/run/resource-agents/heat-api-cfn.pid:0")
;;
"heat-api-cloudwatch")
process_list=(${process_list[@]} "sm:heat-api-cloudwatch:heat-api-cloudwatch:controller:/var/run/resource-agents/heat-api-cloudwatch.pid:0")
;;
# Vim processes
"nfv-vim")
process_list=(${process_list[@]} "sm:nfv-vim:vim:controller:/var/run/nfv-vim.pid:0")
;;
"nfv-vim-api")
process_list=(${process_list[@]} "sm:nfv-vim-api:vim-api:controller:/var/run/nfv-vim-api.pid:0")
;;
"nfv-vim-webserver")
process_list=(${process_list[@]} "sm:nfv-vim-webserver:vim-webserver:controller:/var/run/nfv-vim-webserver.pid:0")
;;
# NOVA processes
"nova-api")
process_list=(${process_list[@]} "sm:nova-api:nova-api:controller:/var/run/resource-agents/nova-api.pid:0")
;;
"nova-placement-api")
process_list=(${process_list[@]} "sm:nova-placement-api:nova-placement-api:controller:/var/run/resource-agents/nova-placement-api.pid:0")
;;
"nova-conductor")
process_list=(${process_list[@]} "sm:nova-conductor:nova-conductor:controller:/var/run/resource-agents/nova-conductor.pid:0")
;;
"nova-console-auth")
process_list=(${process_list[@]} "sm:nova-console-auth:nova-console-auth:controller:/var/run/resource-agents/nova-console-auth.pid:0")
;;
"nova-novnc")
process_list=(${process_list[@]} "sm:nova-novnc:nova-novnc:controller:/var/run/resource-agents/nova-novnc.pid:0")
;;
"nova-scheduler")
process_list=(${process_list[@]} "sm:nova-scheduler:nova-scheduler:controller:/var/run/resource-agents/nova-scheduler.pid:0")
;;
"nova-compute")
process_list=(${process_list[@]} "pmon:nova-compute:nova-compute:compute:/var/run/nova/nova-compute.pid:0" "sm:nova-compute:nova-compute:controller:/var/run/resource-agents/nova-compute.pid:0")
;;
"nova-serialproxy")
process_list=(${process_list[@]} "sm:nova-serialproxy:nova-serialproxy:controller:/var/run/resource-agents/nova-serialproxy.pid:0")
;;
# NOVA proxy
"nova-api-proxy")
process_list=(${process_list[@]} "sm:nova-api-proxy:nova-api-proxy:controller:/var/run/nova-api-proxy.pid:0")
;;
# Distributed Cloud processes
"dcmanager-manager")
process_list=(${process_list[@]} "sm:dcmanager-manager:dcmanager-manager:controller:/var/run/resource-agents/dcmanager-manager.pid:0")
;;
"dcmanager-api")
process_list=(${process_list[@]} "sm:dcmanager-api:dcmanager-api:controller:/var/run/resource-agents/dcmanager-api.pid:0")
;;
"dcorch-engine")
process_list=(${process_list[@]} "sm:dcorch-engine:dcorch-engine:controller:/var/run/resource-agents/dcorch-engine.pid:0")
;;
"dcorch-snmp")
process_list=(${process_list[@]} "sm:dcorch-snmp:dcorch-snmp:controller:/var/run/resource-agents/dcorch-snmp.pid:0")
;;
"dcorch-sysinv-api-proxy")
process_list=(${process_list[@]} "sm:dcorch-sysinv-api-proxy:dcorch-sysinv-api-proxy:controller:/var/run/resource-agents/dcorch-sysinv-api-proxy.pid:0")
;;
"dcorch-nova-api-proxy")
process_list=(${process_list[@]} "sm:dcorch-nova-api-proxy:dcorch-nova-api-proxy:controller:/var/run/resource-agents/dcorch-nova-api-proxy.pid:0")
;;
"dcorch-neutron-api-proxy")
process_list=(${process_list[@]} "sm:dcorch-neutron-api-proxy:dcorch-neutron-api-proxy:controller:/var/run/resource-agents/dcorch-neutron-api-proxy.pid:0")
;;
"dcorch-patch-api-proxy")
process_list=(${process_list[@]} "sm:dcorch-patch-api-proxy:dcorch-patch-api-proxy:controller:/var/run/resource-agents/dcorch-patch-api-proxy.pid:0")
;;
*)
echo "Unknown process:${process}"
loginfo "Unknown process:${process}"
;;
esac
shift
done
# Assume we are done until we know we are not
__done=true
if [ -n "${process_list}" ] ; then
# Record current process IDs
index=0
for DAEMON in "${process_list[@]}"
do
info=(${DAEMON//:/ })
monitor="${info[${MONITOR_INDEX}]}"
pidfile="${info[${PIDFILE_INDEX}]}"
hosttype="${info[${HOSTTYPE_INDEX}]}"
process="${info[${PROCESS_INDEX}]}"
alias="${info[${ALIAS_INDEX}]}"
stat="${info[${STATUS_INDEX}]}"
if [ "${CLEAN}" = true ] ; then
rm -f $PATCH_FLAGDIR/${process}.restarted
fi
# default to not skipping this process
skip=true
# filter out based on current nodetype and specified hosttype
if [ "${hosttype}" == "all" ] ; then
skip=false
else
# check for controller function
if [[ ${hosttype} == *"controller"* ]] ; then
if [[ ${nodetype} == *"controller"* ]] ; then
skip=false
fi
fi
# Check for compute as subfunction
if [[ "${subfunction}" == *"compute"* ]] ; then
if [[ $hosttype} == *"compute"* ]] ; then
skip=false
fi
fi
# check for compute as main function
if [[ ${hosttype} == *"compute"* ]] ; then
if [[ ${nodetype} == *"compute"* ]] ; then
skip=false
fi
fi
# check for storage type
if [[ ${hosttype} == *"storage"* ]] ; then
if [[ "${nodetype}" == *"storage"* ]] ; then
skip=false
fi
fi
fi
if [ "${skip}" = true ] ; then
loginfo "${process} skipped for '${nodetype}' nodetype"
stat="${SKIPPED}"
update_status $index "$stat"
((index++))
continue
fi
if [ -e ${PATCH_FLAGDIR}/${process}.restarted ] ; then
loginfo "${process} restart skipped - already done"
stat="${SKIPPED}"
update_status ${index} "${stat}"
((index++))
continue
else
# record the existing PID for log purposes
if [ -e ${pidfile} ] ; then
stat=$(head -1 ${pidfile} 2>/dev/null)
# check if the pid is running
kill -0 ${stat} 2>/dev/null
rc=$?
if [ ${rc} -ne 0 ] ; then
loginfo "${process} is not running"
stat="${NOPID}"
update_status ${index} "${stat}"
((index++))
continue
fi
else
loginfo "${process} is not running ; missing pidfile"
stat="${NOPID}"
update_status ${index} "${stat}"
((index++))
continue
fi
#
# If we get here then we want to restart this process
# for this node type and the process is running
#
#
# Now manage restart of that process based on what its monitor method is
#
if [ "${monitor}" == "sm" ] ; then
# Managed/Monitored by SM
sm_query_result=$(${SM_QUERY_EXEC} service ${alias})
echo "sm_query_result:${sm_query_result} - alias:${alias}"
if [[ "${sm_query_result}" == *"enabled-active"* ]] ; then
echo "${SM_RESTART_EXEC} of ${process} [pid:${stat}]"
loginfo "${SM_RESTART_EXEC} of ${process} [pid:${stat}]"
touch $PATCH_FLAGDIR/${process}.restarted 2>/dev/null
${SM_RESTART_EXEC} service "${alias}"
__done=false
if [ "${PARALLEL}" = true ] ; then
sleep ${SM_SLEEP} &
pids="$pids $!"
else
sleep ${SM_SLEEP}
fi
elif [[ ${sm_query_result} == *"is enabling"* ]] ; then
loginfo "sm-restart ${process} ; [in progress] ; [pid:${info[${STATUS_INDEX}]}]"
stat="${NOPID}"
else
loginfo "${process} is not active"
stat="${DISABLED}"
fi
else
# Managed/Monitored by PMON
echo "${PMON_RESTART_EXEC} of ${process} [pid:${stat}]"
loginfo "${PMON_RESTART_EXEC} of ${process} [pid:${stat}]"
touch $PATCH_FLAGDIR/${process}.restarted 2>/dev/null
${PMON_RESTART_EXEC} ${process}
__done=false
if [ "${PARALLEL}" = true ] ; then
sleep ${PMON_SLEEP} &
pids="$pids $!"
else
sleep ${PMON_SLEEP}
fi
fi
fi
# echo "Monitor:${monitor} Process:${process} Alias:${alias} Node:${hosttype} Pidfile:${pidfile} Status:${stat}"
# Save the PID or NOPID status to the process line
update_status ${index} "${stat}"
((index++))
done
# wait for background sleeps
wait ${pids}
fi
#
# Now Loop over the process list waiting for all the processes to restart.
# There is an overall timout of 20 seconds for all the processes to be restarted
#
if [ "${__done}" = true ] ; then
GLOBAL_RC=$PATCH_STATUS_OK
loginfo "No-Reboot Patching Process Restart Status: ${GLOBAL_RC} - nothing to do."
exit ${GLOBAL_RC}
fi
# Monitor the restart of processes
#
# Don't want to start from the beginning of the shell
# Want time zero now plus 30 seconds.
#
SECONDS=0
TIMEOUT=120
let UNTIL=${SECONDS}+${TIMEOUT}
loginfo "restart timeout is ${TIMEOUT}"
while [ ${UNTIL} -ge ${SECONDS} ]
do
if [ "${__done}" = false ] ; then
index=0
for DAEMON in "${process_list[@]}"
do
info=(${DAEMON//:/ })
pidfile="${info[${PIDFILE_INDEX}]}"
process="${info[${PROCESS_INDEX}]}"
alias="${info[${ALIAS_INDEX}]}"
stat="${info[${STATUS_INDEX}]}"
if [ "${stat}" != "${SKIPPED}" -a "${stat}" != "${RESTARTED}" -a "${stat}" != "${DISABLED}" -a "${stat}" != "${NOPID}" ] ; then
if [ -e ${pidfile} ] ; then
# Get the new PID
new_pid=$(head -1 ${pidfile} 2>/dev/null)
# check if the pid is running
kill -0 ${new_pid} 2>/dev/null
if [ $? -eq 0 -a -n ${new_pid} ] ; then
# verify the pid is different
if [ "${stat}" != "${new_pid}" ] ; then
loginfo "${process} ${RESTARTED} ok [pid:${stat} -> ${new_pid}]"
stat="${RESTARTED}"
update_status ${index} "${stat}"
fi
fi
fi
fi
((index++))
done
sleep ${MONITOR_SLEEP}
# Loop over all proceses looking for complete restarts.
# Update process struct PID field as status is learned.
index=0
__not_done=false
for DAEMON in "${process_list[@]}"
do
info=(${DAEMON//:/ })
stat="${info[${STATUS_INDEX}]}"
if [ "${stat}" != "${SKIPPED}" -a "${stat}" != "${RESTARTED}" -a "${stat}" != "${DISABLED}" -a "${stat}" != "${NOPID}" ] ; then
__not_done=true
fi
((index++))
done
# Exit if done
if [ "${__not_done}" = false ] ; then
__done=true
GLOBAL_RC=${PATCH_STATUS_OK}
break
fi
else
# should not get here but handle anyway
GLOBAL_RC=${PATCH_STATUS_OK}
break
fi
done
logged=false
for DAEMON in "${process_list[@]}"
do
info=(${DAEMON//:/ })
if [ "${info[${STATUS_INDEX}]}" == "${RESTARTED}" ] ; then
if [ "${logged}" = false ] ; then
loginfo "The following processes have been 'restarted'"
logged=true
fi
loginfo "... process: ${info[${PROCESS_INDEX}]}"
fi
done
logged=false
for DAEMON in "${process_list[@]}"
do
info=(${DAEMON//:/ })
if [ "${info[${STATUS_INDEX}]}" == "${SKIPPED}" ] ; then
if [ "${logged}" = false ] ; then
loginfo "The following processes have been 'skipped'"
logged=true
fi
loginfo "... process: ${info[${PROCESS_INDEX}]}"
fi
done
if [ "${__done}" = false ] ; then
loginfo "Process Restart Timeout ; waiting on "
for DAEMON in "${process_list[@]}"
do
info=(${DAEMON//:/ })
stat="${info[${STATUS_INDEX}]}"
if [ "${stat}" == "${SKIPPED}" ] ; then
((index++))
elif [ "${stat}" == "${RESTARTED}" ] ; then
((index++))
elif [ "${stat}" == "${DISABLED}" ] ; then
((index++))
elif [ "${stat}" == "${NOPID}" ] ; then
((index++))
else
loginfo "... process: ${stat}"
fi
((index++))
done
fi
loginfo "No-Reboot Patching Process Restart Status: ${GLOBAL_RC}"
exit ${GLOBAL_RC}

View File

@ -0,0 +1,143 @@
#!/bin/sh
#
# Copyright (c) 2017 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
# $1 - listening port of remote log server
PORT=$1
function is_loopback
{
# (from include/uapi/linux/if.h)
IFF_LOOPBACK=$((1<<3))
# get the interface flags
FLAGS=`cat /sys/class/net/$DEV/flags`
if ((($IFF_LOOPBACK & $FLAGS) == 0))
then
return 1
else
return 0
fi
}
function log
{
# It seems that syslog isn't yet running, so append directly to the syslog file
echo `date +%FT%T.%3N` `hostname` CGCS_TC_SETUP: $@ >> /var/log/platform.log
}
function test_valid_speed
{
# After the link is enabled but before the autonegotiation is complete
# the link speed may be read as either -1 or as 4294967295 (which is
# uint(-1) in twos-complement) depending on the kernel. Neither one is valid.
if (( $1 > 0 )) && (( $1 != 4294967295 ))
then
return 0
else
return 1
fi
}
function get_dev_speed
{
# If the link doesn't come up we won't go enabled, so here we can
# afford to wait forever for the link.
while true
do
if [ -e /sys/class/net/$1/bonding ]
then
for VAL in `cat /sys/class/net/$1/lower_*/speed`
do
if test_valid_speed $VAL
then
log slave for bond link $1 reported speed $VAL
echo $VAL
return 0
else
log slave for bond link $1 reported invalid speed $VAL
fi
done
log all slaves for bond link $1 reported invalid speeds, will sleep 30 sec and try again
else
VAL=`cat /sys/class/net/$1/speed`
if test_valid_speed $VAL
then
log link $1 reported speed $VAL
echo $VAL
return 0
else
log link $1 returned invalid speed $VAL, will sleep 30 sec and try again
fi
fi
sleep 30
done
}
if [ -f /etc/platform/platform.conf ]
then
source /etc/platform/platform.conf
else
exit 0
fi
# bandwitdh percentages, in case of over-percentage, bandwidth is divided based
# on bandwidth ratios
DEFAULT_BW=10
LOG_BW=9
# bandwitdh ceiling percentages, for borrowing bandwidth
DEFAULT_CBW=20
LOG_CBW=20
# 1:40 = default class from cgcs_tc_setup.sh
# 1:60 = LOG class
if [ $nodetype == "controller" ]
then
# Add class and filters to the oam interface
DEV=$oam_interface
SPEED=$(get_dev_speed $DEV)
# delete existing qdiscs
tc qdisc del dev $DEV root > /dev/null 2>&1
# create new qdiscs, classes and LOG filters
tc qdisc add dev $DEV root handle 1: htb default 40
tc class add dev $DEV parent 1: classid 1:1 htb rate ${SPEED}mbit burst 15k quantum 60000
AC="tc class add dev $DEV parent 1:1 classid"
$AC 1:40 htb rate $((${DEFAULT_BW}*${SPEED}/100))mbit burst 15k ceil $((${DEFAULT_CBW}*${SPEED}/100))mbit quantum 60000
$AC 1:60 htb rate $((${LOG_BW}*${SPEED}/100))mbit burst 15k ceil $((${LOG_CBW}*${SPEED}/100))mbit quantum 60000
tc qdisc add dev $DEV parent 1:40 handle 40: sfq perturb 10
tc qdisc add dev $DEV parent 1:60 handle 60: sfq perturb 10
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dport ${PORT} 0xffff flowid 1:60
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip sport ${PORT} 0xffff flowid 1:60
fi
# On all node types, add LOG class 1:60 and filters to the mgmt interface
DEV=$management_interface
if is_loopback
then
# mgmt/infra uses the loopback for CPE simplex
exit 0
fi
SPEED=$(get_dev_speed $DEV)
AC="tc class add dev $DEV parent 1:1 classid"
$AC 1:60 htb rate $((${LOG_BW}*${SPEED}/100))mbit burst 15k ceil $((${LOG_CBW}*${SPEED}/100))mbit quantum 60000
tc qdisc add dev $DEV parent 1:60 handle 60: sfq perturb 10
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip dport ${PORT} 0xffff flowid 1:60
tc filter add dev $DEV protocol ip parent 1:0 prio 1 u32 match ip sport ${PORT} 0xffff flowid 1:60