StarlingX open source release updates
Signed-off-by: Dean Troyer <dtroyer@gmail.com>
This commit is contained in:
parent
9e5dab7ca9
commit
527e098821
7
CONTRIBUTORS.wrs
Normal file
7
CONTRIBUTORS.wrs
Normal file
@ -0,0 +1,7 @@
|
||||
The following contributors from Wind River have developed the seed code in this
|
||||
repository. We look forward to community collaboration and contributions for
|
||||
additional features, enhancements and refactoring.
|
||||
|
||||
Contributors:
|
||||
=============
|
||||
Don Penney <Don.Penney@windriver.com>
|
202
LICENSE
Normal file
202
LICENSE
Normal 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.
|
5
README.rst
Normal file
5
README.rst
Normal file
@ -0,0 +1,5 @@
|
||||
==========
|
||||
stx-update
|
||||
==========
|
||||
|
||||
StarlingX Software Management
|
202
cgcs-patch/LICENSE
Normal file
202
cgcs-patch/LICENSE
Normal 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.
|
13
cgcs-patch/PKG-INFO
Normal file
13
cgcs-patch/PKG-INFO
Normal file
@ -0,0 +1,13 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: cgcs-patch
|
||||
Version: 1.0
|
||||
Summary: TIS Platform Patching
|
||||
Home-page:
|
||||
Author: Windriver
|
||||
Author-email: info@windriver.com
|
||||
License: Apache-2.0
|
||||
|
||||
Description: TIS Platform Patching
|
||||
|
||||
|
||||
Platform: UNKNOWN
|
15
cgcs-patch/bin/make_patch
Executable file
15
cgcs-patch/bin/make_patch
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_make_patch.make_patch_functions import make_patch
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(make_patch())
|
15
cgcs-patch/bin/modify_patch
Executable file
15
cgcs-patch/bin/modify_patch
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_make_patch.make_patch_functions import modify_patch
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(modify_patch())
|
52
cgcs-patch/bin/patch-functions
Normal file
52
cgcs-patch/bin/patch-functions
Normal file
@ -0,0 +1,52 @@
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#
|
||||
# This bash source file provides variables and functions that
|
||||
# may be used by in-service patching scripts.
|
||||
#
|
||||
|
||||
# Source platform.conf, for nodetype and subfunctions
|
||||
. /etc/platform/platform.conf
|
||||
|
||||
declare PATCH_SCRIPTDIR=/run/patching/patch-scripts
|
||||
declare PATCH_FLAGDIR=/run/patching/patch-flags
|
||||
declare -i PATCH_STATUS_OK=0
|
||||
declare -i PATCH_STATUS_FAILED=1
|
||||
|
||||
declare logfile=/var/log/patching.log
|
||||
declare NAME=$(basename $0)
|
||||
|
||||
function loginfo()
|
||||
{
|
||||
echo "`date "+%FT%T.%3N"`: $NAME: $*" >> $logfile
|
||||
}
|
||||
|
||||
function is_controller()
|
||||
{
|
||||
[[ $nodetype == "controller" ]]
|
||||
}
|
||||
|
||||
function is_compute()
|
||||
{
|
||||
[[ $nodetype == "compute" ]]
|
||||
}
|
||||
|
||||
function is_storage()
|
||||
{
|
||||
[[ $nodetype == "storage" ]]
|
||||
}
|
||||
|
||||
function is_cpe()
|
||||
{
|
||||
[[ $nodetype == "controller" && $subfunction =~ compute ]]
|
||||
}
|
||||
|
||||
function is_locked()
|
||||
{
|
||||
test -f /var/run/.node_locked
|
||||
}
|
||||
|
2
cgcs-patch/bin/patch-tmpdirs.conf
Normal file
2
cgcs-patch/bin/patch-tmpdirs.conf
Normal file
@ -0,0 +1,2 @@
|
||||
d /run/patching 0700 root root -
|
||||
|
16
cgcs-patch/bin/patch_build
Executable file
16
cgcs-patch/bin/patch_build
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_patch.patch_functions import patch_build
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(patch_build())
|
||||
|
29
cgcs-patch/bin/patch_check_goenabled.sh
Normal file
29
cgcs-patch/bin/patch_check_goenabled.sh
Normal file
@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# Patching "goenabled" check.
|
||||
# If a patch has been applied on this node, it is now out-of-date and should be rebooted.
|
||||
|
||||
NAME=$(basename $0)
|
||||
SYSTEM_CHANGED_FLAG=/var/run/node_is_patched
|
||||
|
||||
logfile=/var/log/patching.log
|
||||
|
||||
function LOG()
|
||||
{
|
||||
logger "$NAME: $*"
|
||||
echo "`date "+%FT%T.%3N"`: $NAME: $*" >> $logfile
|
||||
}
|
||||
|
||||
if [ -f $SYSTEM_CHANGED_FLAG ]
|
||||
then
|
||||
LOG "Node has been patched. Failing goenabled check."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
7
cgcs-patch/bin/patching.conf
Normal file
7
cgcs-patch/bin/patching.conf
Normal file
@ -0,0 +1,7 @@
|
||||
[runtime]
|
||||
controller_multicast = 239.1.1.3
|
||||
agent_multicast = 239.1.1.4
|
||||
api_port = 5487
|
||||
controller_port = 5488
|
||||
agent_port = 5489
|
||||
|
15
cgcs-patch/bin/patching.logrotate
Normal file
15
cgcs-patch/bin/patching.logrotate
Normal file
@ -0,0 +1,15 @@
|
||||
/var/log/patching.log
|
||||
/var/log/patching-api.log
|
||||
/var/log/patching-insvc.log
|
||||
{
|
||||
nodateext
|
||||
size 10M
|
||||
start 1
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
compress
|
||||
delaycompress
|
||||
copytruncate
|
||||
}
|
||||
|
19
cgcs-patch/bin/pmon-sw-patch-agent.conf
Normal file
19
cgcs-patch/bin/pmon-sw-patch-agent.conf
Normal file
@ -0,0 +1,19 @@
|
||||
[process]
|
||||
process = sw-patch-agent
|
||||
pidfile = /var/run/sw-patch-agent.pid
|
||||
script = /etc/init.d/sw-patch-agent
|
||||
style = lsb ; ocf or lsb
|
||||
severity = major ; Process failure severity
|
||||
; critical : host is failed
|
||||
; major : host is degraded
|
||||
; minor : log is generated
|
||||
restarts = 3 ; Number of back to back unsuccessful restarts before severity assertion
|
||||
interval = 5 ; Number of seconds to wait between back-to-back unsuccessful restarts
|
||||
debounce = 20 ; Number of seconds the process needs to run before declaring
|
||||
; it as running O.K. after a restart.
|
||||
; Time after which back-to-back restart count is cleared.
|
||||
startuptime = 10 ; 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
|
||||
|
19
cgcs-patch/bin/pmon-sw-patch-controller-daemon.conf
Normal file
19
cgcs-patch/bin/pmon-sw-patch-controller-daemon.conf
Normal file
@ -0,0 +1,19 @@
|
||||
[process]
|
||||
process = sw-patch-controller-daemon
|
||||
pidfile = /var/run/sw-patch-controller-daemon.pid
|
||||
script = /etc/init.d/sw-patch-controller-daemon
|
||||
style = lsb ; ocf or lsb
|
||||
severity = major ; Process failure severity
|
||||
; critical : host is failed
|
||||
; major : host is degraded
|
||||
; minor : log is generated
|
||||
restarts = 3 ; Number of back to back unsuccessful restarts before severity assertion
|
||||
interval = 5 ; Number of seconds to wait between back-to-back unsuccessful restarts
|
||||
debounce = 20 ; Number of seconds the process needs to run before declaring
|
||||
; it as running O.K. after a restart.
|
||||
; Time after which back-to-back restart count is cleared.
|
||||
startuptime = 10 ; 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
|
||||
|
5
cgcs-patch/bin/policy.json
Normal file
5
cgcs-patch/bin/policy.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"admin": "role:admin or role:administrator",
|
||||
"admin_api": "is_admin:True",
|
||||
"default": "rule:admin_api"
|
||||
}
|
15
cgcs-patch/bin/query_patch
Executable file
15
cgcs-patch/bin/query_patch
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_make_patch.make_patch_functions import query_patch
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(query_patch())
|
175
cgcs-patch/bin/rpm-audit
Executable file
175
cgcs-patch/bin/rpm-audit
Executable file
@ -0,0 +1,175 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "This utility must be run as root." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function show_usage()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage: [ --include-pyc ] [ --include-cfg ] --skip-multi [ pkg ... ]
|
||||
|
||||
This utility scans the installed RPMs to compare checksums of files.
|
||||
By default, files flagged as config are skipped, as are python pyc files.
|
||||
|
||||
Optional arguments:
|
||||
--include-pyc : Include pyc files in check
|
||||
--include-cfg : Include config files in check
|
||||
--skip-links : Skip symlink check
|
||||
--skip-multi : Skip the search for files with multiple owners
|
||||
pkg : Specify one or more packages to limit the scan
|
||||
(implies --skip-multi)
|
||||
|
||||
EOF
|
||||
|
||||
exit 1
|
||||
}
|
||||
|
||||
declare INCLUDE_PYTHON_FILES="no"
|
||||
declare INCLUDE_CFG_FILES="no"
|
||||
declare CHECK_FOR_MULTI="yes"
|
||||
declare CHECK_LINKS="yes"
|
||||
declare TIS_ONLY="yes"
|
||||
|
||||
declare CHECK_RPM=
|
||||
|
||||
for arg in "$@"
|
||||
do
|
||||
case $arg in
|
||||
-h|--help)
|
||||
show_usage
|
||||
;;
|
||||
--include-pyc)
|
||||
INCLUDE_PYTHON_FILES="yes"
|
||||
;;
|
||||
--include-cfg)
|
||||
INCLUDE_CFG_FILES="yes"
|
||||
;;
|
||||
--skip-links)
|
||||
CHECK_LINKS="no"
|
||||
;;
|
||||
--skip-multi)
|
||||
CHECK_FOR_MULTI="no"
|
||||
;;
|
||||
--all-rpms)
|
||||
TIS_ONLY="no"
|
||||
;;
|
||||
*)
|
||||
CHECK_RPM="$CHECK_RPM $arg"
|
||||
CHECK_FOR_MULTI="no"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
function rpm_list()
|
||||
{
|
||||
if [ -n "$CHECK_RPM" ]
|
||||
then
|
||||
for pkg in $CHECK_RPM
|
||||
do
|
||||
echo $pkg
|
||||
done
|
||||
elif [ "$TIS_ONLY" = "yes" ]
|
||||
then
|
||||
rpm -qa | grep '\.tis\.' | sort
|
||||
else
|
||||
rpm -qa | sort
|
||||
fi
|
||||
}
|
||||
|
||||
rpm_list | while read pkg
|
||||
do
|
||||
# Get the --dump from the pkg
|
||||
rpm -q --queryformat "[%{FILENAMES}|%{FILEMD5S}|%{FILEFLAGS:fflags}|%{FILELINKTOS}\n]" $pkg | \
|
||||
while IFS='|' read pname psum pflags plinkto
|
||||
do
|
||||
if [[ $pname == "(contains" ]]
|
||||
then
|
||||
# (contains no files)
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ $INCLUDE_CFG_FILES == "no" && $pflags =~ c ]]
|
||||
then
|
||||
# Skip file already flagged as config
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ $INCLUDE_PYTHON_FILES == "no" && $pname =~ \.py[co]?$ ]]
|
||||
then
|
||||
# Skip python .py or .pyc file
|
||||
continue
|
||||
fi
|
||||
|
||||
# Directories and symlinks will have no checksum
|
||||
if [[ -z $psum ]]
|
||||
then
|
||||
if [[ -n $plinkto && $CHECK_LINKS == "yes" ]]
|
||||
then
|
||||
# Check the symlink pointer
|
||||
flinkto=$(readlink $pname)
|
||||
if [[ "$flinkto" != "$plinkto" ]]
|
||||
then
|
||||
echo "Link Mismatch: $pname ($pkg)"
|
||||
fi
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
|
||||
# Does the file exist?
|
||||
if [ ! -e "$pname" ]
|
||||
then
|
||||
echo "Missing: $pname ($pkg)"
|
||||
continue
|
||||
fi
|
||||
|
||||
# Has the file been replaced by a symlink? ie. update-alternatives
|
||||
if [ -L "$pname" ]
|
||||
then
|
||||
continue
|
||||
fi
|
||||
|
||||
echo $psum $pname | sha256sum --check --status
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Mismatch: $pname ($pkg)"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
function check_for_multi_master()
|
||||
{
|
||||
# Search for files owned by multiple packages
|
||||
prev=
|
||||
rpm_list | xargs rpm -q --queryformat "[%{FILENAMES}|%{=NAME}\n]" | sort | while IFS='|' read f p
|
||||
do
|
||||
if [ "$f" = "$prev" ]
|
||||
then
|
||||
echo $f
|
||||
fi
|
||||
prev=$f
|
||||
done | sort -u | while read f
|
||||
do
|
||||
if [ ! -d "$f" ]
|
||||
then
|
||||
echo $f
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
if [ $CHECK_FOR_MULTI = "yes" ]
|
||||
then
|
||||
echo
|
||||
echo
|
||||
echo "The following files belong to multiple packages:"
|
||||
echo
|
||||
check_for_multi_master
|
||||
fi
|
||||
|
60
cgcs-patch/bin/run-patch-scripts
Normal file
60
cgcs-patch/bin/run-patch-scripts
Normal file
@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
. /etc/patching/patch-functions
|
||||
|
||||
declare SCRIPTS=$(find $PATCH_SCRIPTDIR -type f -executable | sort)
|
||||
declare -i NUM_SCRIPTS=$(echo "$SCRIPTS" | wc -l)
|
||||
|
||||
if [ $NUM_SCRIPTS -eq 0 ]
|
||||
then
|
||||
loginfo "No in-service patch scripts found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
loginfo "Running $NUM_SCRIPTS in-service patch scripts"
|
||||
|
||||
declare SCRIPTLOG=/var/log/patching-insvc.log
|
||||
cat <<EOF >>$SCRIPTLOG
|
||||
############################################################
|
||||
`date "+%FT%T.%3N"`: Running $NUM_SCRIPTS in-service patch scripts:
|
||||
|
||||
$SCRIPTS
|
||||
|
||||
############################################################
|
||||
EOF
|
||||
|
||||
declare -i FAILURES=0
|
||||
for cmd in $SCRIPTS
|
||||
do
|
||||
cat <<EOF >>$SCRIPTLOG
|
||||
############################################################
|
||||
`date "+%FT%T.%3N"`: Running $cmd
|
||||
|
||||
EOF
|
||||
|
||||
bash -x $cmd >>$SCRIPTLOG 2>&1
|
||||
rc=$?
|
||||
if [ $rc -ne $PATCH_STATUS_OK ]
|
||||
then
|
||||
let -i FAILURES++
|
||||
fi
|
||||
cat <<EOF >>$SCRIPTLOG
|
||||
`date "+%FT%T.%3N"`: Completed running $cmd (rc=$rc)
|
||||
############################################################
|
||||
|
||||
EOF
|
||||
done
|
||||
|
||||
cat <<EOF >>$SCRIPTLOG
|
||||
|
||||
`date "+%FT%T.%3N"`: Completed running scripts with $FAILURES failures
|
||||
############################################################
|
||||
EOF
|
||||
|
||||
exit $FAILURES
|
||||
|
182
cgcs-patch/bin/setup_patch_repo
Executable file
182
cgcs-patch/bin/setup_patch_repo
Executable file
@ -0,0 +1,182 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2018 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import getopt
|
||||
import os
|
||||
import platform
|
||||
import rpm
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import cgcs_patch.patch_functions as pf
|
||||
import cgcs_patch.patch_verify as pv
|
||||
import cgcs_patch.constants as constants
|
||||
|
||||
import logging
|
||||
logging.getLogger('main_logger')
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# Override the pv.dev_certificate_marker so we can verify signatures off-box
|
||||
cgcs_patch_bindir = os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||
dev_cert_path = os.path.abspath(os.path.join(cgcs_patch_bindir, '../../enable-dev-patch/enable-dev-patch/dev_certificate_enable.bin'))
|
||||
|
||||
pv.dev_certificate_marker = dev_cert_path
|
||||
|
||||
def usage():
|
||||
print "Usage: %s -o <repodir> <patch> ..." \
|
||||
% os.path.basename(sys.argv[0])
|
||||
exit(1)
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
opts, remainder = getopt.getopt(sys.argv[1:],
|
||||
'o:',
|
||||
['output='])
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
|
||||
output = None
|
||||
|
||||
for opt, arg in opts:
|
||||
if opt == "--output" or opt == '-o':
|
||||
output = arg
|
||||
|
||||
if output is None:
|
||||
usage()
|
||||
|
||||
sw_version = os.environ['PLATFORM_RELEASE']
|
||||
|
||||
allpatches = pf.PatchData()
|
||||
|
||||
output = os.path.abspath(output)
|
||||
|
||||
pkgdir = os.path.join(output, 'Packages')
|
||||
datadir = os.path.join(output, 'metadata')
|
||||
committed_dir = os.path.join(datadir, 'committed')
|
||||
|
||||
if os.path.exists(output):
|
||||
# Check to see if the expected structure already exists,
|
||||
# maybe we're appending a patch.
|
||||
if not os.path.exists(committed_dir) or not os.path.exists(pkgdir):
|
||||
print "Packages or metadata dir missing from existing %s. Aborting..." % output
|
||||
exit(1)
|
||||
|
||||
# Load the existing metadata
|
||||
allpatches.load_all_metadata(committed_dir, constants.COMMITTED)
|
||||
else:
|
||||
os.mkdir(output, 0755)
|
||||
os.mkdir(datadir, 0755)
|
||||
os.mkdir(committed_dir, 0755)
|
||||
os.mkdir(pkgdir, 0755)
|
||||
|
||||
# Save the current directory, so we can chdir back after
|
||||
orig_wd = os.getcwd()
|
||||
|
||||
tmpdir = None
|
||||
try:
|
||||
for p in remainder:
|
||||
fpath = os.path.abspath(p)
|
||||
|
||||
# Create a temporary working directory
|
||||
tmpdir = tempfile.mkdtemp(prefix="patchrepo_")
|
||||
|
||||
# Change to the tmpdir
|
||||
os.chdir(tmpdir)
|
||||
|
||||
print "Parsing %s" % fpath
|
||||
pf.PatchFile.read_patch(fpath)
|
||||
|
||||
thispatch = pf.PatchData()
|
||||
patch_id = thispatch.parse_metadata("metadata.xml", constants.COMMITTED)
|
||||
|
||||
if patch_id in allpatches.metadata:
|
||||
print "Skipping %s as it's already in the repo" % patch_id
|
||||
# Change back to original working dir
|
||||
os.chdir(orig_wd)
|
||||
|
||||
shutil.rmtree(tmpdir)
|
||||
tmpdir = None
|
||||
|
||||
continue
|
||||
|
||||
patch_sw_version = thispatch.query_line(patch_id, 'sw_version')
|
||||
if patch_sw_version != sw_version:
|
||||
print "%s is for release %s, not %s" % (patch_sw_version, sw_version)
|
||||
|
||||
# Move the metadata to the "committed" dir, and the rpms to the Packages dir
|
||||
shutil.move('metadata.xml', os.path.join(committed_dir, "%s-metadata.xml" % patch_id))
|
||||
for f in thispatch.query_line(patch_id, 'contents'):
|
||||
shutil.move(f, pkgdir)
|
||||
|
||||
allpatches.add_patch(patch_id, thispatch)
|
||||
|
||||
# Change back to original working dir
|
||||
os.chdir(orig_wd)
|
||||
|
||||
shutil.rmtree(tmpdir)
|
||||
tmpdir = None
|
||||
except:
|
||||
if tmpdir is not None:
|
||||
# Change back to original working dir
|
||||
os.chdir(orig_wd)
|
||||
|
||||
shutil.rmtree(tmpdir)
|
||||
tmpdir = None
|
||||
raise
|
||||
|
||||
allpatches.gen_release_groups_xml(sw_version, output)
|
||||
|
||||
# Purge unneeded RPMs
|
||||
keep = {}
|
||||
for patch_id in allpatches.metadata.keys():
|
||||
for rpmname in allpatches.contents[patch_id]:
|
||||
try:
|
||||
pkgname, arch, pkgver = pf.parse_rpm_filename(rpmname)
|
||||
except ValueError as e:
|
||||
raise e
|
||||
|
||||
if pkgname not in keep:
|
||||
keep[pkgname] = { arch: pkgver }
|
||||
continue
|
||||
elif arch not in keep[pkgname]:
|
||||
keep[pkgname][arch] = pkgver
|
||||
continue
|
||||
|
||||
# Compare versions
|
||||
keep_pkgver = keep[pkgname][arch]
|
||||
if pkgver > keep_pkgver:
|
||||
# Find the rpmname
|
||||
keep_rpmname = keep_pkgver.generate_rpm_filename(pkgname, arch)
|
||||
|
||||
filename = os.path.join(pkgdir, keep_rpmname)
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
|
||||
# Keep the new pkgver
|
||||
keep[pkgname][arch] = pkgver
|
||||
else:
|
||||
filename = os.path.join(pkgdir, rpmname)
|
||||
if os.path.exists(filename):
|
||||
os.remove(filename)
|
||||
|
||||
# Create the repo metadata
|
||||
if os.path.exists('/usr/bin/createrepo_c'):
|
||||
createrepo = '/usr/bin/createrepo_c'
|
||||
else:
|
||||
createrepo = 'createrepo'
|
||||
|
||||
os.chdir(output)
|
||||
subprocess.check_call([createrepo, '-g', 'comps.xml', '.'])
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
|
16
cgcs-patch/bin/sw-patch
Executable file
16
cgcs-patch/bin/sw-patch
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_patch.patch_client import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
16
cgcs-patch/bin/sw-patch-agent
Executable file
16
cgcs-patch/bin/sw-patch-agent
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_patch.patch_agent import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
97
cgcs-patch/bin/sw-patch-agent-init.sh
Executable file
97
cgcs-patch/bin/sw-patch-agent-init.sh
Executable file
@ -0,0 +1,97 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# chkconfig: 345 26 30
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: sw-patch-agent
|
||||
# Required-Start: $syslog
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: sw-patch-agent
|
||||
# Description: Provides the CGCS Patch Agent Daemon
|
||||
### END INIT INFO
|
||||
|
||||
DESC="sw-patch-agent"
|
||||
DAEMON="/usr/sbin/sw-patch-agent"
|
||||
PIDFILE="/var/run/sw-patch-agent.pid"
|
||||
PATCH_INSTALLING_FILE="/var/run/patch_installing"
|
||||
|
||||
start()
|
||||
{
|
||||
if [ -e $PIDFILE ]; then
|
||||
PIDDIR=/proc/$(cat $PIDFILE)
|
||||
if [ -d ${PIDDIR} ]; then
|
||||
echo "$DESC already running."
|
||||
exit 1
|
||||
else
|
||||
echo "Removing stale PID file $PIDFILE"
|
||||
rm -f $PIDFILE
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -n "Starting $DESC..."
|
||||
|
||||
start-stop-daemon --start --quiet --background \
|
||||
--pidfile ${PIDFILE} --make-pidfile --exec ${DAEMON}
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "failed."
|
||||
fi
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
if [ -f $PATCH_INSTALLING_FILE ]
|
||||
then
|
||||
echo "Patches are installing. Waiting for install to complete."
|
||||
while [ -f $PATCH_INSTALLING_FILE ]
|
||||
do
|
||||
# Verify the agent is still running
|
||||
pid=$(cat $PATCH_INSTALLING_FILE)
|
||||
cat /proc/$pid/cmdline 2>/dev/null | grep -q $DAEMON
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "Patch agent not running."
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "Continuing with shutdown."
|
||||
fi
|
||||
|
||||
echo -n "Stopping $DESC..."
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "failed."
|
||||
fi
|
||||
rm -f $PIDFILE
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart|force-reload)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|force-reload|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
20
cgcs-patch/bin/sw-patch-agent-restart
Normal file
20
cgcs-patch/bin/sw-patch-agent-restart
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
. /etc/patching/patch-functions
|
||||
|
||||
#
|
||||
# Triggering a restart of the patching daemons is done by
|
||||
# creating a flag file and letting the daemon handle the restart.
|
||||
#
|
||||
loginfo "Requesting restart of patch-agent"
|
||||
|
||||
restart_patch_agent_flag="/run/patching/.restart.patch-agent"
|
||||
touch $restart_patch_agent_flag
|
||||
|
||||
exit 0
|
||||
|
16
cgcs-patch/bin/sw-patch-agent.service
Normal file
16
cgcs-patch/bin/sw-patch-agent.service
Normal file
@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=TIS Patching Agent
|
||||
After=syslog.target network.target sw-patch.service
|
||||
Before=pmon.service
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
User=root
|
||||
ExecStart=/etc/init.d/sw-patch-agent start
|
||||
ExecStop=/etc/init.d/sw-patch-agent stop
|
||||
ExecReload=/etc/init.d/sw-patch-agent restart
|
||||
PIDFile=/var/run/sw-patch-agent.pid
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
16
cgcs-patch/bin/sw-patch-controller-daemon
Executable file
16
cgcs-patch/bin/sw-patch-controller-daemon
Executable file
@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from cgcs_patch.patch_controller import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
78
cgcs-patch/bin/sw-patch-controller-daemon-init.sh
Executable file
78
cgcs-patch/bin/sw-patch-controller-daemon-init.sh
Executable file
@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
# chkconfig: 345 25 30
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: sw-patch-controller-daemon
|
||||
# Required-Start: $syslog
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: sw-patch-controller-daemon
|
||||
# Description: Provides the CGCS Patch Controller Daemon
|
||||
### END INIT INFO
|
||||
|
||||
DESC="sw-patch-controller-daemon"
|
||||
DAEMON="/usr/sbin/sw-patch-controller-daemon"
|
||||
PIDFILE="/var/run/sw-patch-controller-daemon.pid"
|
||||
|
||||
start()
|
||||
{
|
||||
if [ -e $PIDFILE ]; then
|
||||
PIDDIR=/proc/$(cat $PIDFILE)
|
||||
if [ -d ${PIDDIR} ]; then
|
||||
echo "$DESC already running."
|
||||
exit 1
|
||||
else
|
||||
echo "Removing stale PID file $PIDFILE"
|
||||
rm -f $PIDFILE
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -n "Starting $DESC..."
|
||||
|
||||
start-stop-daemon --start --quiet --background \
|
||||
--pidfile ${PIDFILE} --make-pidfile --exec ${DAEMON}
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "failed."
|
||||
fi
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
echo -n "Stopping $DESC..."
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "failed."
|
||||
fi
|
||||
rm -f $PIDFILE
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart|force-reload)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|force-reload|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
20
cgcs-patch/bin/sw-patch-controller-daemon-restart
Normal file
20
cgcs-patch/bin/sw-patch-controller-daemon-restart
Normal file
@ -0,0 +1,20 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
. /etc/patching/patch-functions
|
||||
|
||||
#
|
||||
# Triggering a restart of the patching daemons is done by
|
||||
# creating a flag file and letting the daemon handle the restart.
|
||||
#
|
||||
loginfo "Requesting restart of patch-controller"
|
||||
|
||||
restart_patch_controller_flag="/run/patching/.restart.patch-controller"
|
||||
touch $restart_patch_controller_flag
|
||||
|
||||
exit 0
|
||||
|
16
cgcs-patch/bin/sw-patch-controller-daemon.service
Normal file
16
cgcs-patch/bin/sw-patch-controller-daemon.service
Normal file
@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=TIS Patching Controller Daemon
|
||||
After=syslog.target network.target sw-patch.service sw-patch-controller.service
|
||||
Before=pmon.service
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
User=root
|
||||
ExecStart=/etc/init.d/sw-patch-controller-daemon start
|
||||
ExecStop=/etc/init.d/sw-patch-controller-daemon stop
|
||||
ExecReload=/etc/init.d/sw-patch-controller-daemon restart
|
||||
PIDFile=/var/run/sw-patch-controller-daemon.pid
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
104
cgcs-patch/bin/sw-patch-controller-init.sh
Normal file
104
cgcs-patch/bin/sw-patch-controller-init.sh
Normal file
@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# CGCS Patching Controller setup
|
||||
# chkconfig: 345 20 24
|
||||
# description: CGCS Patching Controller init script
|
||||
|
||||
. /usr/bin/tsconfig
|
||||
|
||||
NAME=$(basename $0)
|
||||
|
||||
REPO_ID=updates
|
||||
REPO_ROOT=/www/pages/${REPO_ID}
|
||||
REPO_DIR=${REPO_ROOT}/rel-${SW_VERSION}
|
||||
GROUPS_FILE=$REPO_DIR/comps.xml
|
||||
PATCHING_DIR=/opt/patching
|
||||
|
||||
logfile=/var/log/patching.log
|
||||
|
||||
function LOG()
|
||||
{
|
||||
logger "$NAME: $*"
|
||||
echo "`date "+%FT%T.%3N"`: $NAME: $*" >> $logfile
|
||||
}
|
||||
|
||||
function LOG_TO_FILE()
|
||||
{
|
||||
echo "`date "+%FT%T.%3N"`: $NAME: $*" >> $logfile
|
||||
}
|
||||
|
||||
function create_groups()
|
||||
{
|
||||
if [ -f $GROUPS_FILE ]
|
||||
then
|
||||
return 0
|
||||
fi
|
||||
|
||||
cat >$GROUPS_FILE <<EOF
|
||||
<comps>
|
||||
</comps>
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function do_setup()
|
||||
{
|
||||
# Does the repo exist?
|
||||
if [ ! -d $REPO_DIR ]
|
||||
then
|
||||
LOG "Creating repo"
|
||||
mkdir -p $REPO_DIR
|
||||
|
||||
# Setup the groups file
|
||||
create_groups
|
||||
|
||||
createrepo -g $GROUPS_FILE $REPO_DIR >> $logfile 2>&1
|
||||
fi
|
||||
|
||||
if [ ! -d $PATCHING_DIR ]
|
||||
then
|
||||
LOG "Creating $PATCHING_DIR"
|
||||
mkdir -p $PATCHING_DIR
|
||||
fi
|
||||
|
||||
# If we can ping the active controller, sync the repos
|
||||
LOG_TO_FILE "ping -c 1 -w 1 controller"
|
||||
ping -c 1 -w 1 controller >> $logfile 2>&1 || ping6 -c 1 -w 1 controller >> $logfile 2>&1
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
LOG "Cannot ping controller. Nothing to do"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Sync the patching dir
|
||||
LOG_TO_FILE "rsync -acv --delete rsync://controller/patching/ ${PATCHING_DIR}/"
|
||||
rsync -acv --delete rsync://controller/patching/ ${PATCHING_DIR}/ >> $logfile 2>&1
|
||||
|
||||
# Sync the patching dir
|
||||
LOG_TO_FILE "rsync -acv --delete rsync://controller/repo/ ${REPO_ROOT}/"
|
||||
rsync -acv --delete rsync://controller/repo/ ${REPO_ROOT}/ >> $logfile 2>&1
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
do_setup
|
||||
;;
|
||||
status)
|
||||
;;
|
||||
stop)
|
||||
# Nothing to do here
|
||||
;;
|
||||
restart)
|
||||
do_setup
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {status|start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
14
cgcs-patch/bin/sw-patch-controller.service
Normal file
14
cgcs-patch/bin/sw-patch-controller.service
Normal file
@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=TIS Patching Controller
|
||||
After=syslog.service network.target sw-patch.service
|
||||
Before=sw-patch-agent.service sw-patch-controller-daemon.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
ExecStart=/etc/init.d/sw-patch-controller start
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
147
cgcs-patch/bin/sw-patch-init.sh
Normal file
147
cgcs-patch/bin/sw-patch-init.sh
Normal file
@ -0,0 +1,147 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# CGCS Patching
|
||||
# chkconfig: 345 20 23
|
||||
# description: CGCS Patching init script
|
||||
|
||||
NAME=$(basename $0)
|
||||
|
||||
. /usr/bin/tsconfig
|
||||
. /etc/platform/platform.conf
|
||||
|
||||
logfile=/var/log/patching.log
|
||||
|
||||
function LOG_TO_FILE()
|
||||
{
|
||||
echo "`date "+%FT%T.%3N"`: $NAME: $*" >> $logfile
|
||||
}
|
||||
|
||||
function check_for_rr_patch()
|
||||
{
|
||||
if [ -f /var/run/node_is_patched_rr ]
|
||||
then
|
||||
echo
|
||||
echo "Node has been patched and requires an immediate reboot."
|
||||
echo
|
||||
LOG_TO_FILE "Node has been patched, with reboot-required flag set. Rebooting"
|
||||
/sbin/reboot
|
||||
fi
|
||||
}
|
||||
|
||||
function check_install_uuid()
|
||||
{
|
||||
# Check whether our installed load matches the active controller
|
||||
CONTROLLER_UUID=`curl -sf http://controller/feed/rel-${SW_VERSION}/install_uuid`
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
if [ "$HOSTNAME" = "controller-1" ]
|
||||
then
|
||||
# If we're on controller-1, controller-0 may not have the install_uuid
|
||||
# matching this release, if we're in an upgrade. If the file doesn't exist,
|
||||
# bypass this check
|
||||
return 0
|
||||
fi
|
||||
|
||||
LOG_TO_FILE "Unable to retrieve installation uuid from active controller"
|
||||
echo "Unable to retrieve installation uuid from active controller"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$INSTALL_UUID" != "$CONTROLLER_UUID" ]
|
||||
then
|
||||
LOG_TO_FILE "This node is running a different load than the active controller and must be reinstalled"
|
||||
echo "This node is running a different load than the active controller and must be reinstalled"
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
# Check for installation failure
|
||||
if [ -f /etc/platform/installation_failed ] ; then
|
||||
LOG_TO_FILE "/etc/platform/installation_failed flag is set. Aborting."
|
||||
echo "$(basename $0): Detected installation failure. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up the RPM DB
|
||||
if [ ! -f /var/run/.rpmdb_cleaned ]
|
||||
then
|
||||
LOG_TO_FILE "Cleaning RPM DB"
|
||||
rm -f /var/lib/rpm/__db*
|
||||
touch /var/run/.rpmdb_cleaned
|
||||
fi
|
||||
|
||||
# If the management interface is bonded, it may take some time
|
||||
# before communications can be properly setup.
|
||||
# Allow up to $DELAY_SEC seconds to reach controller.
|
||||
DELAY_SEC=120
|
||||
START=`date +%s`
|
||||
FOUND=0
|
||||
while [ $(date +%s) -lt $(( ${START} + ${DELAY_SEC} )) ]
|
||||
do
|
||||
ping -c 1 controller > /dev/null 2>&1 || ping6 -c 1 controller > /dev/null 2>&1
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
FOUND=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if [ ${FOUND} -eq 0 ]
|
||||
then
|
||||
# 'controller' is not available, just exit
|
||||
LOG_TO_FILE "Unable to contact active controller (controller). Boot will continue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ "${system_mode}" = "simplex" ]
|
||||
then
|
||||
# On a simplex CPE, we need to launch the http server first,
|
||||
# before we can do the patch installation
|
||||
LOG_TO_FILE "***** Launching lighttpd *****"
|
||||
/etc/init.d/lighttpd start
|
||||
|
||||
LOG_TO_FILE "***** Starting patch operation *****"
|
||||
/usr/sbin/sw-patch-agent --install 2>>$logfile
|
||||
LOG_TO_FILE "***** Finished patch operation *****"
|
||||
|
||||
LOG_TO_FILE "***** Shutting down lighttpd *****"
|
||||
/etc/init.d/lighttpd stop
|
||||
else
|
||||
check_install_uuid
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# The INSTALL_UUID doesn't match the active controller, so exit
|
||||
exit 1
|
||||
fi
|
||||
|
||||
LOG_TO_FILE "***** Starting patch operation *****"
|
||||
/usr/sbin/sw-patch-agent --install 2>>$logfile
|
||||
LOG_TO_FILE "***** Finished patch operation *****"
|
||||
fi
|
||||
|
||||
check_for_rr_patch
|
||||
;;
|
||||
stop)
|
||||
# Nothing to do here
|
||||
;;
|
||||
restart)
|
||||
LOG_TO_FILE "***** Starting patch operation *****"
|
||||
/usr/sbin/sw-patch-agent --install 2>>$logfile
|
||||
LOG_TO_FILE "***** Finished patch operation *****"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
124
cgcs-patch/bin/sw-patch.completion
Normal file
124
cgcs-patch/bin/sw-patch.completion
Normal file
@ -0,0 +1,124 @@
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#
|
||||
# This file provides bash-completion functionality for the sw-patch CLI
|
||||
#
|
||||
|
||||
function _swpatch()
|
||||
{
|
||||
COMPREPLY=()
|
||||
local cur="${COMP_WORDS[COMP_CWORD]}"
|
||||
local prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||
local subcommand=${COMP_WORDS[1]}
|
||||
|
||||
#
|
||||
# The available sw-patch subcommands
|
||||
#
|
||||
local subcommands="
|
||||
apply
|
||||
commit
|
||||
delete
|
||||
query
|
||||
query-dependencies
|
||||
query-hosts
|
||||
remove
|
||||
show
|
||||
upload
|
||||
upload-dir
|
||||
what-requires
|
||||
drop-host
|
||||
"
|
||||
if [ -f /etc/platform/.initial_config_complete ]; then
|
||||
# Post-config, so the host-install commands are accessible
|
||||
subcommands="${subcommands} host-install host-install-async"
|
||||
else
|
||||
# Pre-config, so the install-local command is accessible
|
||||
subcommands="${subcommands} install-local"
|
||||
fi
|
||||
|
||||
# Appends the '/' when completing dir names
|
||||
set mark-directories on
|
||||
|
||||
if [ $COMP_CWORD -gt 1 ]; then
|
||||
#
|
||||
# Complete the arguments to the subcommands.
|
||||
#
|
||||
case "$subcommand" in
|
||||
apply|remove|delete|show|what-requires)
|
||||
# Query the list of known patches
|
||||
local patches=$(sw-patch completion patches 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "${patches}" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
host-install|host-install-async|drop-host)
|
||||
if [ "${prev}" = "${subcommand}" -o "${prev}" = "--force" ]; then
|
||||
# Query the list of known hosts
|
||||
local names=$(sw-patch completion hosts 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "${names}" -- ${cur}) )
|
||||
else
|
||||
# Only one host can be specified, so no more completion
|
||||
COMPREPLY=( $(compgen -- ${cur}) )
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
upload)
|
||||
# Allow dirs and files with .patch extension for completion
|
||||
COMPREPLY=( $(compgen -f -o plusdirs -X '!*.patch' -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
upload-dir)
|
||||
# Allow dirs only for completion
|
||||
COMPREPLY=( $(compgen -d -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
query)
|
||||
if [ "${prev}" = "--release" ]; then
|
||||
# If --release has been specified, provide installed releases for completion
|
||||
local releases=$(/bin/ls -d /www/pages/feed/rel-* 2>/dev/null | sed 's#/www/pages/feed/rel-##')
|
||||
COMPREPLY=( $(compgen -W "${releases}" -- ${cur}) )
|
||||
else
|
||||
# --release is only completion option for query
|
||||
COMPREPLY=( $(compgen -W "--release" -- ${cur}) )
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
query-hosts|install-local)
|
||||
# These subcommands have no options/arguments
|
||||
COMPREPLY=( $(compgen -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
query-dependencies)
|
||||
# Query the list of known patches
|
||||
local patches=$(sw-patch completion patches 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "--recursive ${patches}" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
commit)
|
||||
if [ "${prev}" = "--release" ]; then
|
||||
# If --release has been specified, provide installed releases for completion
|
||||
local releases=$(/bin/ls -d /www/pages/feed/rel-* 2>/dev/null | sed 's#/www/pages/feed/rel-##')
|
||||
COMPREPLY=( $(compgen -W "${releases}" -- ${cur}) )
|
||||
else
|
||||
# Query the list of known patches
|
||||
local patches=$(sw-patch completion patches 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "--all --dry-run --release ${patches}" -- ${cur}) )
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Provide subcommands for completion
|
||||
COMPREPLY=($(compgen -W "${subcommands}" -- ${cur}))
|
||||
return 0
|
||||
}
|
||||
|
||||
# Bind the above function to the sw-patch CLI
|
||||
complete -F _swpatch -o filenames sw-patch
|
||||
|
16
cgcs-patch/bin/sw-patch.service
Normal file
16
cgcs-patch/bin/sw-patch.service
Normal file
@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=TIS Patching
|
||||
After=syslog.target network.target
|
||||
Before=sw-patch-agent.service
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
User=root
|
||||
ExecStart=/etc/init.d/sw-patch start
|
||||
RemainAfterExit=yes
|
||||
StandardOutput=syslog+console
|
||||
StandardError=syslog+console
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
135
cgcs-patch/bin/upgrade-start-pkg-extract
Normal file
135
cgcs-patch/bin/upgrade-start-pkg-extract
Normal file
@ -0,0 +1,135 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2018 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
function show_usage()
|
||||
{
|
||||
cat >&2 <<EOF
|
||||
$(basename $0): -r <release>
|
||||
|
||||
This tool will extract required packages to support upgrade-start
|
||||
|
||||
Options:
|
||||
-r <release> : Release ID for target release.
|
||||
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
. /etc/build.info
|
||||
if [ -z "${SW_VERSION}" ]; then
|
||||
logger -t $0 "Unable to identify running release ID"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
declare TGT_RELEASE=
|
||||
|
||||
while getopts "r:h" opt; do
|
||||
case $opt in
|
||||
r)
|
||||
TGT_RELEASE=$OPTARG
|
||||
;;
|
||||
h)
|
||||
show_usage
|
||||
;;
|
||||
*)
|
||||
logger -t $0 "Unsupported option"
|
||||
show_usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "${TGT_RELEASE}" ]; then
|
||||
logger -t $0 "You must specify the target release."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${TGT_RELEASE}" = "${SW_VERSION}" ]; then
|
||||
logger -t $0 "Target release cannot be running release."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
declare TGT_BASE_REPO=/www/pages/feed/rel-${TGT_RELEASE}
|
||||
declare TGT_PATCHES_REPO=/www/pages/updates/rel-${TGT_RELEASE}
|
||||
|
||||
if [ ! -d ${TGT_BASE_REPO} ]; then
|
||||
logger -t $0 "Target release ${TGT_RELEASE} is not installed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
declare TGT_PATCHES_REPO_OPT=""
|
||||
if [ -d ${TGT_PATCHES_REPO} ]; then
|
||||
TGT_PATCHES_REPO_OPT="--repofrompath updates,${TGT_PATCHES_REPO}"
|
||||
fi
|
||||
|
||||
declare WORKDIR=
|
||||
|
||||
function cleanup() {
|
||||
if [ -n "${WORKDIR}" -a -d "${WORKDIR}" ]; then
|
||||
rm -rf ${WORKDIR}
|
||||
fi
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
function extract_pkg() {
|
||||
local pkgname=$1
|
||||
|
||||
ORIG_PWD=$PWD
|
||||
cd $WORKDIR
|
||||
|
||||
# Find the RPM
|
||||
local pkgfile=$(repoquery --repofrompath base,${TGT_BASE_REPO} ${TGT_PATCHES_REPO_OPT} --location -q ${pkgname})
|
||||
if [ -z "${pkgfile}" ]; then
|
||||
logger -t $0 "Could not find ${pkgname}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Chop off the file: from the start of the file location
|
||||
local rpmfile=${pkgfile/file://}
|
||||
|
||||
rpm2cpio ${rpmfile} | cpio -idm
|
||||
if [ $? -ne 0 ]; then
|
||||
logger -t $0 "Failed to extract $pkgname files from ${pkgfile/file://}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd ${ORIG_PWD}
|
||||
}
|
||||
|
||||
# Extract files from pxe-network-installer
|
||||
WORKDIR=$(mktemp -d --tmpdir=/scratch pkgextract_XXXX)
|
||||
if [ -z "${WORKDIR}" -o ! -d "${WORKDIR}" ]; then
|
||||
logger -t $0 "Failed to create workdir"
|
||||
exit 1
|
||||
fi
|
||||
extract_pkg pxe-network-installer
|
||||
rsync -ac ${WORKDIR}/usr/ /usr/ &&
|
||||
rsync -ac ${WORKDIR}/pxeboot/rel-${TGT_RELEASE}/ /pxeboot/rel-${TGT_RELEASE}/ &&
|
||||
rsync -c ${WORKDIR}/pxeboot/pxelinux.cfg.files/*-${TGT_RELEASE} /pxeboot/pxelinux.cfg.files/ &&
|
||||
rsync -ac ${WORKDIR}/www/pages/feed/rel-${TGT_RELEASE}/ /www/pages/feed/rel-${TGT_RELEASE}/
|
||||
if [ $? -ne 0 ]; then
|
||||
logger -t $0 "rsync command failed, extracting pxe-network-installer"
|
||||
exit 1
|
||||
fi
|
||||
rm -rf ${WORKDIR}
|
||||
|
||||
# Extract files from platform-kickstarts
|
||||
WORKDIR=$(mktemp -d --tmpdir=/scratch pkgextract_XXXX)
|
||||
if [ -z "${WORKDIR}" -o ! -d "${WORKDIR}" ]; then
|
||||
logger -t $0 "Failed to create workdir"
|
||||
exit 1
|
||||
fi
|
||||
extract_pkg platform-kickstarts
|
||||
rsync -ac ${WORKDIR}/www/pages/feed/rel-${TGT_RELEASE}/ /www/pages/feed/rel-${TGT_RELEASE}/
|
||||
if [ $? -ne 0 ]; then
|
||||
logger -t $0 "rsync command failed, extracting platform-kickstarts"
|
||||
exit 1
|
||||
fi
|
||||
rm -rf ${WORKDIR}
|
||||
|
||||
exit 0
|
||||
|
101
cgcs-patch/centos/build_srpm
Executable file
101
cgcs-patch/centos/build_srpm
Executable file
@ -0,0 +1,101 @@
|
||||
source "$SRC_BASE/build-tools/spec-utils"
|
||||
|
||||
if [ "x$DATA" == "x" ]; then
|
||||
echo "ERROR: Environment variable 'DATA' not defined."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$DATA" ]; then
|
||||
echo "ERROR: Couldn't find '$PWD/$DATA'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
unset TIS_PATCH_VER # Ensure there's nothing in the env already
|
||||
|
||||
source $DATA
|
||||
|
||||
if [ -z "$TIS_PATCH_VER" ]; then
|
||||
echo "ERROR: TIS_PATCH_VER must be defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_DIR="cgcs-patch"
|
||||
EXTRA_DIR="bin"
|
||||
|
||||
VERSION=$(grep '^Version:' PKG-INFO | awk -F ': ' '{print $2}' | sed -e 's/^[[:space:]]*//')
|
||||
TAR_NAME=$(grep '^Name:' PKG-INFO | awk -F ': ' '{print $2}' | sed -e 's/^[[:space:]]*//')
|
||||
CUR_DIR=`pwd`
|
||||
BUILD_DIR="$RPMBUILD_BASE"
|
||||
|
||||
mkdir -p $BUILD_DIR/SRPMS
|
||||
|
||||
TAR="$TAR_NAME-$VERSION.tar.gz"
|
||||
TAR_PATH="$BUILD_DIR/SOURCES/$TAR"
|
||||
|
||||
# copy the LICENSE for rpm spec %license directive
|
||||
cp $SRC_DIR/LICENSE $BUILD_DIR/SOURCES/
|
||||
|
||||
TAR_NEEDED=0
|
||||
if [ -f $TAR_PATH ]; then
|
||||
n=`find . -cnewer $TAR_PATH -and ! -path './.git*' \
|
||||
-and ! -path './build/*' \
|
||||
-and ! -path './.pc/*' \
|
||||
-and ! -path './patches/*' \
|
||||
-and ! -path "./$DISTRO/*" \
|
||||
-and ! -path './pbr-*.egg/*' \
|
||||
| wc -l`
|
||||
if [ $n -gt 0 ]; then
|
||||
TAR_NEEDED=1
|
||||
fi
|
||||
else
|
||||
TAR_NEEDED=1
|
||||
fi
|
||||
|
||||
if [ $TAR_NEEDED -gt 0 ]; then
|
||||
tar czvf $TAR_PATH $SRC_DIR $EXTRA_DIR \
|
||||
--exclude='cgcs-patch/cgcs_patch_id' \
|
||||
--exclude='cgcs-patch/cgcs_make_patch' \
|
||||
--exclude='.git*' \
|
||||
--exclude='build' \
|
||||
--exclude='.pc' \
|
||||
--exclude='patches' \
|
||||
--exclude="$DISTRO" \
|
||||
--exclude='pbr-*.egg' \
|
||||
--transform "s,^$SRC_DIR/LICENSE,LICENSE," \
|
||||
--transform "s,^$SRC_DIR,$TAR_NAME-$VERSION,"
|
||||
fi
|
||||
|
||||
|
||||
for SPEC in `ls $BUILD_DIR/SPECS`; do
|
||||
SPEC_PATH="$BUILD_DIR/SPECS/$SPEC"
|
||||
RELEASE=`spec_find_tag Release "$SPEC_PATH" 2>> /dev/null`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: 'Release' not found in '$SPEC_PATH'"
|
||||
fi
|
||||
NAME=`spec_find_tag Name "$SPEC_PATH" 2>> /dev/null`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: 'Name' not found in '$SPEC_PATH'"
|
||||
fi
|
||||
SRPM="$NAME-$VERSION-$RELEASE.src.rpm"
|
||||
SRPM_PATH="$BUILD_DIR/SRPMS/$SRPM"
|
||||
|
||||
BUILD_NEEDED=0
|
||||
if [ -f $SRPM_PATH ]; then
|
||||
n=`find . -cnewer $SRPM_PATH | wc -l`
|
||||
if [ $n -gt 0 ]; then
|
||||
BUILD_NEEDED=1
|
||||
fi
|
||||
else
|
||||
BUILD_NEEDED=1
|
||||
fi
|
||||
|
||||
if [ $BUILD_NEEDED -gt 0 ]; then
|
||||
echo "SPEC file: $SPEC_PATH"
|
||||
echo "SRPM build directory: $BUILD_DIR"
|
||||
echo "TIS_PATCH_VER: $TIS_PATCH_VER"
|
||||
|
||||
sed -i -e "1 i%define tis_patch_ver $TIS_PATCH_VER" $SPEC_PATH
|
||||
rpmbuild -bs $SPEC_PATH --define="%_topdir $BUILD_DIR" --define="_tis_dist .tis"
|
||||
fi
|
||||
done
|
||||
|
1
cgcs-patch/centos/build_srpm.data
Normal file
1
cgcs-patch/centos/build_srpm.data
Normal file
@ -0,0 +1 @@
|
||||
TIS_PATCH_VER=25
|
180
cgcs-patch/centos/cgcs-patch.spec
Normal file
180
cgcs-patch/centos/cgcs-patch.spec
Normal file
@ -0,0 +1,180 @@
|
||||
Summary: TIS Platform Patching
|
||||
Name: cgcs-patch
|
||||
Version: 1.0
|
||||
Release: %{tis_patch_ver}%{?_tis_dist}
|
||||
License: Apache-2.0
|
||||
Group: base
|
||||
Packager: Wind River <info@windriver.com>
|
||||
URL: unknown
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
Source1: LICENSE
|
||||
|
||||
BuildRequires: python-setuptools
|
||||
BuildRequires: systemd-units
|
||||
BuildRequires: systemd-devel
|
||||
Requires: python-devel
|
||||
Requires: /bin/bash
|
||||
|
||||
%description
|
||||
TIS Platform Patching
|
||||
|
||||
%define pythonroot /usr/lib64/python2.7/site-packages
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
%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
|
||||
|
||||
install -m 755 -d %{buildroot}%{_sbindir}
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/bash_completion.d
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/goenabled.d
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/init.d
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/logrotate.d
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/patching
|
||||
install -m 700 -d %{buildroot}%{_sysconfdir}/patching/patch-scripts
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/pmon.d
|
||||
install -m 755 -d %{buildroot}%{_unitdir}
|
||||
|
||||
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-agent \
|
||||
%{buildroot}%{_sbindir}/sw-patch-agent
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-controller-daemon \
|
||||
%{buildroot}%{_sbindir}/sw-patch-controller-daemon
|
||||
install -m 555 ${RPM_BUILD_DIR}/bin/sw-patch \
|
||||
%{buildroot}%{_sbindir}/sw-patch
|
||||
|
||||
install -m 555 ${RPM_BUILD_DIR}/bin/rpm-audit \
|
||||
%{buildroot}%{_sbindir}/rpm-audit
|
||||
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-controller-daemon-init.sh \
|
||||
%{buildroot}%{_sysconfdir}/init.d/sw-patch-controller-daemon
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-agent-init.sh \
|
||||
%{buildroot}%{_sysconfdir}/init.d/sw-patch-agent
|
||||
|
||||
install -m 600 ${RPM_BUILD_DIR}/bin/patching.conf \
|
||||
%{buildroot}%{_sysconfdir}/patching/patching.conf
|
||||
install -m 644 ${RPM_BUILD_DIR}/bin/policy.json \
|
||||
%{buildroot}%{_sysconfdir}/patching/policy.json
|
||||
|
||||
install -m 444 ${RPM_BUILD_DIR}/bin/pmon-sw-patch-controller-daemon.conf \
|
||||
%{buildroot}%{_sysconfdir}/pmon.d/sw-patch-controller-daemon.conf
|
||||
install -m 444 ${RPM_BUILD_DIR}/bin/pmon-sw-patch-agent.conf \
|
||||
%{buildroot}%{_sysconfdir}/pmon.d/sw-patch-agent.conf
|
||||
|
||||
install -m 444 ${RPM_BUILD_DIR}/bin/*.service %{buildroot}%{_unitdir}
|
||||
|
||||
install -m 444 ${RPM_BUILD_DIR}/bin/sw-patch.completion %{buildroot}%{_sysconfdir}/bash_completion.d/sw-patch
|
||||
|
||||
install -m 400 ${RPM_BUILD_DIR}/bin/patch-functions \
|
||||
%{buildroot}%{_sysconfdir}/patching/patch-functions
|
||||
|
||||
install -D -m 444 ${RPM_BUILD_DIR}/bin/patch-tmpdirs.conf \
|
||||
%{buildroot}%{_tmpfilesdir}/patch-tmpdirs.conf
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/run-patch-scripts \
|
||||
%{buildroot}%{_sbindir}/run-patch-scripts
|
||||
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-controller-daemon-restart \
|
||||
%{buildroot}%{_sbindir}/sw-patch-controller-daemon-restart
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-agent-restart \
|
||||
%{buildroot}%{_sbindir}/sw-patch-agent-restart
|
||||
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-init.sh \
|
||||
%{buildroot}%{_sysconfdir}/init.d/sw-patch
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/sw-patch-controller-init.sh \
|
||||
%{buildroot}%{_sysconfdir}/init.d/sw-patch-controller
|
||||
|
||||
install -m 555 ${RPM_BUILD_DIR}/bin/patch_check_goenabled.sh \
|
||||
%{buildroot}%{_sysconfdir}/goenabled.d/patch_check_goenabled.sh
|
||||
|
||||
install -m 444 ${RPM_BUILD_DIR}/bin/patching.logrotate \
|
||||
%{buildroot}%{_sysconfdir}/logrotate.d/patching
|
||||
|
||||
install -m 500 ${RPM_BUILD_DIR}/bin/upgrade-start-pkg-extract \
|
||||
%{buildroot}%{_sbindir}/upgrade-start-pkg-extract
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%package -n cgcs-patch-controller
|
||||
Summary: TIS Platform Patching
|
||||
Group: base
|
||||
Requires: /usr/bin/env
|
||||
Requires: /bin/sh
|
||||
Requires: requests-toolbelt
|
||||
Requires: createrepo
|
||||
Requires(post): /usr/bin/env
|
||||
Requires(post): /bin/sh
|
||||
|
||||
%description -n cgcs-patch-controller
|
||||
TIS Platform Patching
|
||||
|
||||
%post -n cgcs-patch-controller
|
||||
/usr/bin/systemctl enable sw-patch-controller.service
|
||||
/usr/bin/systemctl enable sw-patch-controller-daemon.service
|
||||
|
||||
|
||||
%package -n cgcs-patch-agent
|
||||
Summary: TIS Platform Patching
|
||||
Group: base
|
||||
Requires: /usr/bin/env
|
||||
Requires: /bin/sh
|
||||
Requires(post): /usr/bin/env
|
||||
Requires(post): /bin/sh
|
||||
|
||||
%description -n cgcs-patch-agent
|
||||
TIS Platform Patching
|
||||
|
||||
%post -n cgcs-patch-agent
|
||||
/usr/bin/systemctl enable sw-patch-agent.service
|
||||
|
||||
%post
|
||||
/usr/bin/systemctl enable sw-patch.service
|
||||
|
||||
%files
|
||||
%license ../LICENSE
|
||||
%defattr(-,root,root,-)
|
||||
%{pythonroot}/cgcs_patch
|
||||
%{pythonroot}/cgcs_patch-*.egg-info
|
||||
%{_sbindir}/rpm-audit
|
||||
%config(noreplace) %{_sysconfdir}/patching/policy.json
|
||||
%config(noreplace) %{_sysconfdir}/patching/patching.conf
|
||||
%dir %{_sysconfdir}/patching/patch-scripts
|
||||
%{_sysconfdir}/patching/patch-functions
|
||||
%{_tmpfilesdir}/patch-tmpdirs.conf
|
||||
%{_sbindir}/run-patch-scripts
|
||||
%{_sysconfdir}/init.d/sw-patch
|
||||
%{_unitdir}/sw-patch.service
|
||||
%{_sysconfdir}/goenabled.d/patch_check_goenabled.sh
|
||||
%{_sysconfdir}/logrotate.d/patching
|
||||
|
||||
%files -n cgcs-patch-controller
|
||||
%defattr(-,root,root,-)
|
||||
%{_sbindir}/sw-patch
|
||||
%{_sbindir}/sw-patch-controller-daemon
|
||||
%{_sbindir}/sw-patch-controller-daemon-restart
|
||||
%{_sbindir}/upgrade-start-pkg-extract
|
||||
%{_sysconfdir}/pmon.d/sw-patch-controller-daemon.conf
|
||||
%{_sysconfdir}/init.d/sw-patch-controller-daemon
|
||||
%{_unitdir}/sw-patch-controller-daemon.service
|
||||
%{_sysconfdir}/bash_completion.d/sw-patch
|
||||
%{_sysconfdir}/init.d/sw-patch-controller
|
||||
%{_unitdir}/sw-patch-controller.service
|
||||
|
||||
%files -n cgcs-patch-agent
|
||||
%defattr(-,root,root,-)
|
||||
%{_sbindir}/sw-patch-agent
|
||||
%{_sbindir}/sw-patch-agent-restart
|
||||
%{_sysconfdir}/pmon.d/sw-patch-agent.conf
|
||||
%{_sysconfdir}/init.d/sw-patch-agent
|
||||
%{_unitdir}/sw-patch-agent.service
|
||||
|
202
cgcs-patch/cgcs-patch/LICENSE
Normal file
202
cgcs-patch/cgcs-patch/LICENSE
Normal 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.
|
0
cgcs-patch/cgcs-patch/cgcs_make_patch/__init__.py
Normal file
0
cgcs-patch/cgcs-patch/cgcs_make_patch/__init__.py
Normal file
1988
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patch_functions.py
Normal file
1988
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patch_functions.py
Normal file
File diff suppressed because it is too large
Load Diff
226
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patching_branch
Executable file
226
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patching_branch
Executable file
@ -0,0 +1,226 @@
|
||||
#!/bin/bash
|
||||
|
||||
# repos
|
||||
UPSTREAM_CLONE="git://vxgit.wrs.com/git"
|
||||
# UPSTREAM_PUSH="ssh://vxgit.wrs.com/git"
|
||||
ROOT_REPO=cgcs-root
|
||||
|
||||
JENKINS_HOST=yow-cgts3-lx.wrs.com
|
||||
|
||||
# SOURCE_CONTEXT=TC_17.06
|
||||
# SOURCE_JENKINS_BUILD=TC_17.06_Pull
|
||||
# PREFIX=TC
|
||||
# SW_VERSION=18.03
|
||||
# JOB=patching
|
||||
USAGE=0
|
||||
|
||||
if [ x"$1" = x ] ; then
|
||||
echo "ERROR: You must specify a source context"
|
||||
USAGE=1
|
||||
fi
|
||||
SOURCE_CONTEXT=$1
|
||||
|
||||
if [ x"$2" = x ] ; then
|
||||
echo "ERROR: You must specify a source context"
|
||||
USAGE=1
|
||||
fi
|
||||
SOURCE_JENKINS_BUILD=$2
|
||||
|
||||
if [ x"$3" = x ] ; then
|
||||
echo "ERROR: You must specify a prefix for patch and patch branch names"
|
||||
USAGE=1
|
||||
fi
|
||||
PREFIX=$3
|
||||
|
||||
if [ x"$4" = x ] ; then
|
||||
echo "ERROR: You must specify a sw_version"
|
||||
USAGE=1
|
||||
fi
|
||||
SW_VERSION=$4
|
||||
|
||||
if [ x"$5" = x ] ; then
|
||||
echo "ERROR: You must specify a job directory"
|
||||
USAGE=1
|
||||
fi
|
||||
JOB=$5
|
||||
|
||||
if [ $USAGE -ne 0 ] ; then
|
||||
echo "USAGE: make_patching_branch <source_context> <jenkins_src_job> <prefix> <sw_version> <repo_dir>"
|
||||
echo " e.g. make_patching_branch CGCS_DEV_0007 Secure_Src_Pull_CGCS_DEV_0007 CGCS 14.10 testpatch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PATCH_BRANCH=$PREFIX"_"$SW_VERSION"_PATCHING"
|
||||
PATCH_TAG0=v$PREFIX"_"$SW_VERSION"_PATCH_0000"
|
||||
MY_LOCAL_DISK=/localdisk/designer/$USER/$JOB
|
||||
MY_REPO=$MY_LOCAL_DISK
|
||||
|
||||
if [[ "$JOB" = /* ]]
|
||||
then
|
||||
MY_LOCAL_DISK=$JOB
|
||||
MY_REPO=$JOB
|
||||
fi
|
||||
|
||||
|
||||
echo "PREFIX=$PREFIX"
|
||||
echo "SW_VERSION=$SW_VERSION"
|
||||
echo "JOB=$JOB"
|
||||
echo "SOURCE_CONTEXT=$SOURCE_CONTEXT"
|
||||
echo "MY_LOCAL_DISK=$MY_LOCAL_DISK"
|
||||
echo "MY_REPO=$MY_REPO"
|
||||
echo "SOURCE_JENKINS_BUILD=$SOURCE_JENKINS_BUILD"
|
||||
echo "PATCH_BRANCH=$PATCH_BRANCH"
|
||||
echo "UPSTREAM_CLONE=$UPSTREAM_CLONE"
|
||||
|
||||
mkdir -p $MY_LOCAL_DISK
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to create directory '$MY_LOCAL_DISK'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd $MY_LOCAL_DISK
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_LOCAL_DISK'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get latest tools
|
||||
if [ ! -d bin ] ; then
|
||||
echo "clone bin"
|
||||
git clone git://git.wrs.com/git/bin
|
||||
else
|
||||
echo "pull bin"
|
||||
cd bin
|
||||
git pull
|
||||
cd $MY_LOCAL_DISK
|
||||
fi
|
||||
|
||||
|
||||
export PATH=$MY_REPO/build-tools/branching:$PATH
|
||||
|
||||
|
||||
# Create repo
|
||||
mkdir -p $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to create directory '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chgrp cgts $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed chgrp '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
chmod 750 $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to chmod '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_LOCAL_DISK'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d $ROOT_REPO ] ; then
|
||||
WRGIT_ALL_ADDONS=1 wrgit clone $UPSTREAM_CLONE/$ROOT_REPO $ROOT_REPO $SOURCE_CONTEXT
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to clone from repo '$UPSTREAM_CLONE' with context '$SOURCE_CONTEXT'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
MY_REPO=$MY_REPO/$ROOT_REPO
|
||||
else
|
||||
MY_REPO=$MY_REPO/$ROOT_REPO
|
||||
cd $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wrgit checkout $SOURCE_CONTEXT
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: wrgit checkout '$SOURCE_CONTEXT' failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
wrgit pull
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: wrgit pull failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
cd $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
git branch | grep $PATCH_BRANCH
|
||||
if [ $? -ne 0 ] ; then
|
||||
# Set context
|
||||
CONTEXT_PATH="/localdisk/designer/jenkins/$SOURCE_JENKINS_BUILD/$ROOT_REPO/CONTEXT"
|
||||
if [ -f $CONTEXT_PATH ]; then
|
||||
cp $CONTEXT_PATH ../
|
||||
else
|
||||
CONTEXT_PROVIDER=$JENKINS_HOST:$CONTEXT_PATH
|
||||
scp $CONTEXT_PROVIDER ../
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to obtain context from '$CONTEXT_PROVIDER'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
source ../CONTEXT
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to set context"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
git branch | grep $PATCH_BRANCH
|
||||
if [ $? -ne 0 ] ; then
|
||||
# create patching branch and tag
|
||||
create_branches_and_tags.sh $PATCH_BRANCH .
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to create branch '$PATCH_BRANCH'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
push_branches_tags.sh $PATCH_BRANCH
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to push branch '$PATCH_BRANCH' to '$UPSTREAM_PUSH'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
wrgit checkout $PATCH_BRANCH
|
||||
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: wrgit checkout '$PATCH_BRANCH' failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
git tag | grep $PATCH_TAG0
|
||||
if [ $? -ne 0 ] ; then
|
||||
create_tags.sh $PATCH_TAG0
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to create tag '$PATCH_TAG0'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
push_tags.sh $PATCH_TAG0
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to push branch '$PATCH_BRANCH' to '$UPSTREAM_PUSH'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
98
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patching_tag
Executable file
98
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patching_tag
Executable file
@ -0,0 +1,98 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Real upstream repo
|
||||
# UPSTREAM="git://vxgit.wrs.com/git/cgcs-root"
|
||||
# Testing upstream repo
|
||||
UPSTREAM="git://vxgit.wrs.com/git/users/cgcs/cgcs-root"
|
||||
|
||||
JENKINS_HOST=yow-cgts4-lx.wrs.com
|
||||
|
||||
# TAG=GCGS_14.10_PATCH_0001
|
||||
# JOB=playground
|
||||
USAGE=0
|
||||
|
||||
|
||||
if [ x"$1" = x ] ; then
|
||||
echo "ERROR: You must specify a PATCH_ID"
|
||||
USAGE=1
|
||||
fi
|
||||
PATCH_ID=$1
|
||||
|
||||
if [ x"$2" = x ] ; then
|
||||
echo "ERROR: You must specify a job directory"
|
||||
USAGE=1
|
||||
fi
|
||||
JOB=$2
|
||||
|
||||
if [ $USAGE -ne 0 ] ; then
|
||||
echo "USAGE: make_patching_tag <patch_id> <repo_dir>"
|
||||
echo "USAGE: make_patching_tag CGCS_14.10_PATCH_0001 testpatch"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TAG="v$PATCH_ID"
|
||||
MY_LOCAL_DISK=/localdisk/designer/$USER/$JOB
|
||||
MY_REPO=$MY_LOCAL_DISK
|
||||
|
||||
if [[ "$JOB" = /* ]]
|
||||
then
|
||||
MY_LOCAL_DISK=$JOB
|
||||
MY_REPO=$JOB
|
||||
fi
|
||||
|
||||
|
||||
echo "TAG=$TAG"
|
||||
echo "JOB=$JOB"
|
||||
echo "MY_LOCAL_DISK=$MY_LOCAL_DISK"
|
||||
echo "MY_REPO=$MY_REPO"
|
||||
|
||||
# Get latest tools
|
||||
if [ ! -d bin ] ; then
|
||||
echo "clone bin"
|
||||
git clone git://git.wrs.com/git/bin
|
||||
else
|
||||
echo "pull bin"
|
||||
cd bin
|
||||
git pull
|
||||
cd $MY_LOCAL_DISK
|
||||
fi
|
||||
|
||||
|
||||
export PATH=$MY_REPO/build-tools/branching:$PATH
|
||||
|
||||
|
||||
MY_REPO=$MY_REPO/cgcs-root
|
||||
cd $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
### wrgit pull
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: wrgit pull failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# create patching tag
|
||||
create_tags.sh $TAG .
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to create tag '$TAG'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$USER" = "jenkins" ] ; then
|
||||
sh /localdisk/designer/slittle1/proxy/push_tags.sh $TAG
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to push branch '$TAG' to '$UPSTREAM'"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
push_tags.sh $TAG
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to push branch '$TAG' to '$UPSTREAM'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
|
181
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patching_workspace
Executable file
181
cgcs-patch/cgcs-patch/cgcs_make_patch/make_patching_workspace
Executable file
@ -0,0 +1,181 @@
|
||||
#!/bin/bash
|
||||
|
||||
USAGE=0
|
||||
|
||||
if [ x"$1" = x ] ; then
|
||||
echo "ERROR: You must specify a prefix for patch and patch branch names"
|
||||
USAGE=1
|
||||
fi
|
||||
PREFIX=$1
|
||||
|
||||
if [ x"$2" = x ] ; then
|
||||
echo "ERROR: You must specify a sw_version"
|
||||
USAGE=1
|
||||
fi
|
||||
SW_VERSION=$2
|
||||
|
||||
if [ x"$3" = x ] ; then
|
||||
echo "ERROR: You must specify a job directory"
|
||||
USAGE=1
|
||||
fi
|
||||
JOB=$3
|
||||
|
||||
PATCH_BRANCH=$PREFIX"_"$SW_VERSION"_PATCHING"
|
||||
PATCH_ID0=$PREFIX"_"$SW_VERSION"_PATCH_0000"
|
||||
PATCH_TAG0=v$PATCH_ID0
|
||||
MY_LOCAL_DISK=/localdisk/designer/$USER/$JOB
|
||||
MY_REPO=$MY_LOCAL_DISK/cgcs-root
|
||||
MY_WORKSPACE=/localdisk/loadbuild/$USER/$JOB
|
||||
|
||||
if [[ "$JOB" = /* ]]
|
||||
then
|
||||
MY_LOCAL_DISK=$JOB
|
||||
MY_REPO=$JOB/cgcs-root
|
||||
MY_WORKSPACE=$JOB
|
||||
fi
|
||||
|
||||
if [ x"$4" != x ] ; then
|
||||
MY_WORKSPACE=$4
|
||||
fi
|
||||
|
||||
if [ x"$5" != x ] ; then
|
||||
MY_LOCAL_DISK=$(realpath $5/..)
|
||||
fi
|
||||
MY_REPO=$MY_LOCAL_DISK/cgcs-root
|
||||
|
||||
if [ $USAGE -ne 0 ] ; then
|
||||
echo "USAGE: make_patching_workspace <prefix> <sw_version> <repo_dir> [<workspace> [<sscache> [<repo>]]]"
|
||||
echo " e.g. make_patching_workspace TC 18.03 testpatch"
|
||||
echo " e.g. make_patching_workspace TC 18.03 mypatch $MY_WORKSPACE $MY_REPO"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RPM_DB_DIR=$MY_WORKSPACE/export/patch_data
|
||||
RPM_DB=$RPM_DB_DIR/$PATCH_ID0.rpm_db
|
||||
|
||||
echo "PREFIX=$PREFIX"
|
||||
echo "SW_VERSION=$SW_VERSION"
|
||||
echo "JOB=$JOB"
|
||||
echo "MY_LOCAL_DISK=$MY_LOCAL_DISK"
|
||||
echo "MY_REPO=$MY_REPO"
|
||||
echo "MY_WORKSPACE=$MY_WORKSPACE"
|
||||
echo "PATCH_BRANCH=$PATCH_BRANCH"
|
||||
echo "PATCH_TAG0=$PATCH_TAG0"
|
||||
echo "RPM_DB_DIR=$RPM_DB_DIR"
|
||||
echo "RPM_DB=$RPM_DB"
|
||||
|
||||
|
||||
cd $MY_LOCAL_DISK/bin
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_LOCAL_DISK/bin'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export PATH=`pwd`:$PATH
|
||||
|
||||
cd $MY_REPO
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_REPO'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure gits are free of changes that would prevent checkout or pull
|
||||
for d in $(find . -type d -name .git | xargs --max-args=1 dirname)
|
||||
do
|
||||
(cd $d
|
||||
echo $d
|
||||
git clean -df
|
||||
git reset --hard
|
||||
git ls-files --others --exclude-standard | xargs --no-run-if-empty rm
|
||||
if [ ! -f .subgits ]; then
|
||||
if [ -f .gitignore ]; then
|
||||
git ls-files --others --ignored --exclude-from=.gitignore | xargs --no-run-if-empty rm
|
||||
fi
|
||||
fi
|
||||
)
|
||||
done
|
||||
|
||||
wrgit checkout $PATCH_TAG0
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: wrgit checkout '$PATCH_TAG0' failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create workspace
|
||||
echo "01: mkdir $MY_WORKSPACE"
|
||||
if [ ! -d $MY_WORKSPACE ] ; then
|
||||
mkdir -p $MY_WORKSPACE
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to create directory '$MY_WORKSPACE'"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "02: cd $MY_WORKSPACE"
|
||||
cd $MY_WORKSPACE
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$MY_WORKSPACE'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "03: build"
|
||||
if [ ! -f export/bootimage.iso ] ; then
|
||||
echo "04: build pkgs"
|
||||
nice -n 20 ionice -c Idle build-pkgs
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: build-pkgs failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "05: build iso"
|
||||
nice -n 20 ionice -c Idle build-iso
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: build-iso failed "
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "06: rpm db"
|
||||
mkdir -p $RPM_DB_DIR
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to make directory '$RPM_DB_DIR'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "" > $RPM_DB
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to write file '$RPM_DB'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for build_type in std rt; do
|
||||
RPM_ROOT_DIR=$MY_WORKSPACE/$build_type/rpmbuild/RPMS
|
||||
echo "RPM_ROOT_DIR=$RPM_ROOT_DIR"
|
||||
cd $RPM_ROOT_DIR
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$RPM_ROOT_DIR'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for d in `find * -type d`; do
|
||||
pushd $d > /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: failed to change to directory '$d'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rpm -qp --queryformat "$d %{NAME} %{RELEASE}\n" *rpm >> $RPM_DB 2> /dev/null
|
||||
if [ $? -ne 0 ] ; then
|
||||
echo "ERROR: rpm query failed in directory '$d'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
popd > /dev/null
|
||||
done
|
||||
done
|
||||
|
||||
|
||||
echo 'Build is complete'
|
||||
|
||||
|
||||
|
7
cgcs-patch/cgcs-patch/cgcs_patch/__init__.py
Normal file
7
cgcs-patch/cgcs-patch/cgcs_patch/__init__.py
Normal file
@ -0,0 +1,7 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
30
cgcs-patch/cgcs-patch/cgcs_patch/api/__init__.py
Normal file
30
cgcs-patch/cgcs-patch/cgcs_patch/api/__init__.py
Normal file
@ -0,0 +1,30 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
|
||||
API_SERVICE_OPTS = [
|
||||
cfg.StrOpt('api_bind_ip',
|
||||
default='127.0.0.1',
|
||||
help='IP for the Patching controller API server to bind to',
|
||||
),
|
||||
cfg.IntOpt('api_port',
|
||||
default=5487,
|
||||
help='The port for the Patching controller API server',
|
||||
),
|
||||
cfg.IntOpt('api_limit_max',
|
||||
default=1000,
|
||||
help='the maximum number of items returned in a single '
|
||||
'response from a collection resource'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
opt_group = cfg.OptGroup(name='api',
|
||||
title='Options for the Patching controller api service')
|
||||
CONF.register_group(opt_group)
|
||||
CONF.register_opts(API_SERVICE_OPTS)
|
45
cgcs-patch/cgcs-patch/cgcs_patch/api/app.py
Normal file
45
cgcs-patch/cgcs-patch/cgcs_patch/api/app.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
#from oslo.config import cfg
|
||||
import pecan
|
||||
|
||||
from cgcs_patch.api import config
|
||||
|
||||
#CONF = cfg.CONF
|
||||
|
||||
def get_pecan_config():
|
||||
# Set up the pecan configuration
|
||||
filename = config.__file__.replace('.pyc', '.py')
|
||||
return pecan.configuration.conf_from_file(filename)
|
||||
|
||||
|
||||
def setup_app(pecan_config=None):
|
||||
if not pecan_config:
|
||||
pecan_config = get_pecan_config()
|
||||
|
||||
pecan.configuration.set_config(dict(pecan_config), overwrite=True)
|
||||
|
||||
app = pecan.make_app(
|
||||
pecan_config.app.root,
|
||||
static_root=pecan_config.app.static_root,
|
||||
template_path=pecan_config.app.template_path,
|
||||
debug=False,
|
||||
force_canonical=getattr(pecan_config.app, 'force_canonical', True),
|
||||
guess_content_type_from_ext=False, # Avoid mime-type lookup
|
||||
)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
class VersionSelectorApplication(object):
|
||||
def __init__(self):
|
||||
pc = get_pecan_config()
|
||||
self.v1 = setup_app(pecan_config=pc)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
return self.v1(environ, start_response)
|
23
cgcs-patch/cgcs-patch/cgcs_patch/api/config.py
Normal file
23
cgcs-patch/cgcs-patch/cgcs_patch/api/config.py
Normal file
@ -0,0 +1,23 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
# Server Specific Configurations
|
||||
server = {
|
||||
'port': '5487',
|
||||
'host': '127.0.0.1'
|
||||
}
|
||||
|
||||
# Pecan Application Configurations
|
||||
app = {
|
||||
'root': 'cgcs_patch.api.controllers.root.RootController',
|
||||
'modules': ['cgcs_patch.authapi'],
|
||||
'static_root': '%(confdir)s/public',
|
||||
'template_path': '%(confdir)s/../templates',
|
||||
'debug': False,
|
||||
'enable_acl': True,
|
||||
'acl_public_routes': [],
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
266
cgcs-patch/cgcs-patch/cgcs_patch/api/controllers/root.py
Normal file
266
cgcs-patch/cgcs-patch/cgcs_patch/api/controllers/root.py
Normal file
@ -0,0 +1,266 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from pecan import expose, request
|
||||
import cgi
|
||||
import glob
|
||||
|
||||
from cgcs_patch.exceptions import PatchError
|
||||
from cgcs_patch.patch_controller import pc
|
||||
|
||||
import logging
|
||||
from cgcs_patch.patch_functions import LOG
|
||||
|
||||
class PatchAPIController(object):
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def index(self):
|
||||
return self.query()
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def query(self, **kwargs):
|
||||
try:
|
||||
pd = pc.patch_query_cached(**kwargs)
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
return dict(pd=pd)
|
||||
|
||||
@expose('json')
|
||||
@expose('show.xml', content_type='application/xml')
|
||||
def show(self, *args):
|
||||
try:
|
||||
result = pc.patch_query_specific_cached(list(args))
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def apply(self, *args):
|
||||
if pc.any_patch_host_installing():
|
||||
return dict(error="Rejected: One or more nodes are installing patches.")
|
||||
|
||||
try:
|
||||
result = pc.patch_apply_api(list(args))
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def remove(self, *args, **kwargs):
|
||||
if pc.any_patch_host_installing():
|
||||
return dict(error="Rejected: One or more nodes are installing patches.")
|
||||
|
||||
try:
|
||||
result = pc.patch_remove_api(list(args), **kwargs)
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def delete(self, *args):
|
||||
try:
|
||||
result = pc.patch_delete_api(list(args))
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def upload(self):
|
||||
assert isinstance(request.POST['file'], cgi.FieldStorage)
|
||||
fileitem = request.POST['file']
|
||||
|
||||
if not fileitem.filename:
|
||||
return dict(error="Error: No file uploaded")
|
||||
|
||||
fn = '/scratch/' + os.path.basename(fileitem.filename)
|
||||
# This technique cannot copy a very large file. It
|
||||
# requires a lot of memory as all data from the
|
||||
# source file is read into memory then written to
|
||||
# the destination file one chunk
|
||||
# open(fn, 'wb').write(fileitem.file.read())
|
||||
|
||||
# Copying file by chunks using OS system calls
|
||||
# requires much less memory. A larger chunk
|
||||
# size can be used to improve the copy speed;
|
||||
# currently 64K chunk size is selected
|
||||
dst = os.open(fn, os.O_WRONLY | os.O_CREAT)
|
||||
src = fileitem.file.fileno()
|
||||
size = 64*1024
|
||||
n = size
|
||||
while n >= size:
|
||||
s = os.read(src, size)
|
||||
n = os.write(dst, s)
|
||||
os.close(dst)
|
||||
|
||||
try:
|
||||
result = pc.patch_import_api([fn])
|
||||
except PatchError as e:
|
||||
os.remove(fn)
|
||||
return dict(error=e.message)
|
||||
|
||||
os.remove(fn)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def upload_dir(self, **kwargs):
|
||||
files = []
|
||||
for key, path in kwargs.iteritems():
|
||||
LOG.info("upload-dir: Retrieving patches from %s" % path)
|
||||
for f in glob.glob(path + '/*.patch'):
|
||||
if os.path.isfile(f):
|
||||
files.append(f)
|
||||
|
||||
if len(files) == 0:
|
||||
return dict(error="No patches found")
|
||||
|
||||
try:
|
||||
result = pc.patch_import_api(sorted(files))
|
||||
except PatchError as e:
|
||||
return dict(error=e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def init_release(self, *args):
|
||||
if len(list(args)) == 0:
|
||||
return dict(error="Release must be specified")
|
||||
|
||||
try:
|
||||
result = pc.patch_init_release_api(list(args)[0])
|
||||
except PatchError as e:
|
||||
return dict(error=e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def del_release(self, *args):
|
||||
if len(list(args)) == 0:
|
||||
return dict(error="Release must be specified")
|
||||
|
||||
try:
|
||||
result = pc.patch_del_release_api(list(args)[0])
|
||||
except PatchError as e:
|
||||
return dict(error=e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query_hosts.xml', content_type='application/xml')
|
||||
def query_hosts(self, *args):
|
||||
return dict(data=pc.query_host_cache())
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def what_requires(self, *args):
|
||||
try:
|
||||
result = pc.patch_query_what_requires(list(args))
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def host_install(self, *args):
|
||||
return dict(error="Deprecated: Use host_install_async")
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def host_install_async(self, *args):
|
||||
if len(list(args)) == 0:
|
||||
return dict(error="Host must be specified for install")
|
||||
force = False
|
||||
if len(list(args)) > 1 and 'force' in list(args)[1:]:
|
||||
force = True
|
||||
|
||||
try:
|
||||
result = pc.patch_host_install(list(args)[0], force, async=True)
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
@expose('query.xml', content_type='application/xml')
|
||||
def drop_host(self, *args):
|
||||
if len(list(args)) == 0:
|
||||
return dict(error="Host must be specified")
|
||||
|
||||
try:
|
||||
result = pc.drop_host(list(args)[0])
|
||||
except PatchError as e:
|
||||
return dict(error="Error: %s" % e.message)
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def query_dependencies(self, *args, **kwargs):
|
||||
try:
|
||||
result = pc.patch_query_dependencies(list(args), **kwargs)
|
||||
except PatchError as e:
|
||||
return dict(error=e.message)
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def commit(self, *args):
|
||||
try:
|
||||
result = pc.patch_commit(list(args))
|
||||
except PatchError as e:
|
||||
return dict(error=e.message)
|
||||
|
||||
pc.patch_sync()
|
||||
|
||||
return result
|
||||
|
||||
@expose('json')
|
||||
def commit_dry_run(self, *args):
|
||||
try:
|
||||
result = pc.patch_commit(list(args), dry_run=True)
|
||||
except PatchError as e:
|
||||
return dict(error=e.message)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
class RootController(object):
|
||||
|
||||
@expose()
|
||||
@expose('json')
|
||||
def index(self):
|
||||
return "Titanium Cloud Patching API, Available versions: /v1"
|
||||
|
||||
patch = PatchAPIController()
|
||||
v1 = PatchAPIController()
|
||||
|
27
cgcs-patch/cgcs-patch/cgcs_patch/app.py
Normal file
27
cgcs-patch/cgcs-patch/cgcs_patch/app.py
Normal file
@ -0,0 +1,27 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
from pecan import make_app
|
||||
from cgcs_patch import model
|
||||
|
||||
|
||||
def setup_app(config):
|
||||
|
||||
model.init_model()
|
||||
|
||||
return make_app(
|
||||
config.app.root,
|
||||
static_root=config.app.static_root,
|
||||
template_path=config.app.template_path,
|
||||
logging=getattr(config, 'logging', {}),
|
||||
debug=getattr(config.app, 'debug', False),
|
||||
force_canonical=getattr(config.app, 'force_canonical', True),
|
||||
guess_content_type_from_ext=getattr(
|
||||
config.app,
|
||||
'guess_content_type_from_ext',
|
||||
True),
|
||||
)
|
25
cgcs-patch/cgcs-patch/cgcs_patch/authapi/__init__.py
Executable file
25
cgcs-patch/cgcs-patch/cgcs_patch/authapi/__init__.py
Executable file
@ -0,0 +1,25 @@
|
||||
# Copyright (c) 2013-2017 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
from oslo_config import cfg
|
||||
|
||||
API_SERVICE_OPTS = [
|
||||
cfg.StrOpt('auth_api_bind_ip',
|
||||
default=None,
|
||||
help='IP for the authenticated Patching API server to bind to'),
|
||||
cfg.IntOpt('auth_api_port',
|
||||
default=5491,
|
||||
help='The port for the authenticated Patching API server'),
|
||||
cfg.IntOpt('api_limit_max',
|
||||
default=1000,
|
||||
help='the maximum number of items returned in a single '
|
||||
'response from a collection resource')
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
opt_group = cfg.OptGroup(name='api',
|
||||
title='Options for the patch-api service')
|
||||
CONF.register_group(opt_group)
|
||||
CONF.register_opts(API_SERVICE_OPTS)
|
28
cgcs-patch/cgcs-patch/cgcs_patch/authapi/acl.py
Executable file
28
cgcs-patch/cgcs-patch/cgcs_patch/authapi/acl.py
Executable file
@ -0,0 +1,28 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
"""Access Control Lists (ACL's) control access the API server."""
|
||||
|
||||
from cgcs_patch.authapi import auth_token
|
||||
|
||||
OPT_GROUP_NAME = 'keystone_authtoken'
|
||||
|
||||
|
||||
def install(app, conf, public_routes):
|
||||
"""Install ACL check on application.
|
||||
|
||||
:param app: A WSGI application.
|
||||
:param conf: Settings. Must include OPT_GROUP_NAME section.
|
||||
:param public_routes: The list of the routes which will be allowed
|
||||
access without authentication.
|
||||
:return: The same WSGI application with ACL installed.
|
||||
|
||||
"""
|
||||
|
||||
keystone_config = dict(conf.items(OPT_GROUP_NAME))
|
||||
return auth_token.AuthTokenMiddleware(app,
|
||||
conf=keystone_config,
|
||||
public_api_routes=public_routes)
|
77
cgcs-patch/cgcs-patch/cgcs_patch/authapi/app.py
Executable file
77
cgcs-patch/cgcs-patch/cgcs_patch/authapi/app.py
Executable file
@ -0,0 +1,77 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
from oslo_config import cfg
|
||||
import pecan
|
||||
|
||||
from cgcs_patch.authapi import acl
|
||||
from cgcs_patch.authapi import config
|
||||
from cgcs_patch.authapi import hooks
|
||||
from cgcs_patch.authapi import policy
|
||||
|
||||
import ConfigParser
|
||||
|
||||
auth_opts = [
|
||||
cfg.StrOpt('auth_strategy',
|
||||
default='keystone',
|
||||
help='Method to use for auth: noauth or keystone.'),
|
||||
]
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(auth_opts)
|
||||
|
||||
|
||||
def get_pecan_config():
|
||||
# Set up the pecan configuration
|
||||
filename = config.__file__.replace('.pyc', '.py')
|
||||
return pecan.configuration.conf_from_file(filename)
|
||||
|
||||
|
||||
def setup_app(pecan_config=None, extra_hooks=None):
|
||||
config = ConfigParser.RawConfigParser()
|
||||
config.read('/etc/patching/patching.conf')
|
||||
|
||||
policy.init()
|
||||
|
||||
app_hooks = [hooks.ConfigHook(),
|
||||
hooks.ContextHook(pecan_config.app.acl_public_routes),
|
||||
]
|
||||
if extra_hooks:
|
||||
app_hooks.extend(extra_hooks)
|
||||
|
||||
if not pecan_config:
|
||||
pecan_config = get_pecan_config()
|
||||
|
||||
if pecan_config.app.enable_acl:
|
||||
app_hooks.append(hooks.AdminAuthHook())
|
||||
|
||||
pecan.configuration.set_config(dict(pecan_config), overwrite=True)
|
||||
|
||||
app = pecan.make_app(
|
||||
pecan_config.app.root,
|
||||
static_root=pecan_config.app.static_root,
|
||||
template_path=pecan_config.app.template_path,
|
||||
debug=False,
|
||||
force_canonical=getattr(pecan_config.app, 'force_canonical', True),
|
||||
hooks=app_hooks,
|
||||
guess_content_type_from_ext=False, # Avoid mime-type lookup
|
||||
)
|
||||
|
||||
if pecan_config.app.enable_acl:
|
||||
return acl.install(app, config, pecan_config.app.acl_public_routes)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
class VersionSelectorApplication(object):
|
||||
def __init__(self):
|
||||
pc = get_pecan_config()
|
||||
pc.app.enable_acl = (CONF.auth_strategy == 'keystone')
|
||||
self.v1 = setup_app(pecan_config=pc)
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
return self.v1(environ, start_response)
|
38
cgcs-patch/cgcs-patch/cgcs_patch/authapi/auth_token.py
Executable file
38
cgcs-patch/cgcs-patch/cgcs_patch/authapi/auth_token.py
Executable file
@ -0,0 +1,38 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# 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.
|
||||
|
||||
from keystonemiddleware import auth_token
|
||||
from sysinv.common import utils
|
||||
|
||||
|
||||
class AuthTokenMiddleware(auth_token.AuthProtocol):
|
||||
"""A wrapper on Keystone auth_token middleware.
|
||||
|
||||
Does not perform verification of authentication tokens
|
||||
for public routes in the API.
|
||||
|
||||
"""
|
||||
def __init__(self, app, conf, public_api_routes=[]):
|
||||
self.public_api_routes = set(public_api_routes)
|
||||
|
||||
super(AuthTokenMiddleware, self).__init__(app, conf)
|
||||
|
||||
def __call__(self, env, start_response):
|
||||
path = utils.safe_rstrip(env.get('PATH_INFO'), '/')
|
||||
|
||||
if path in self.public_api_routes:
|
||||
return self.app(env, start_response)
|
||||
|
||||
return super(AuthTokenMiddleware, self).__call__(env, start_response)
|
23
cgcs-patch/cgcs-patch/cgcs_patch/authapi/config.py
Executable file
23
cgcs-patch/cgcs-patch/cgcs_patch/authapi/config.py
Executable file
@ -0,0 +1,23 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
# Server Specific Configurations
|
||||
server = {
|
||||
'port': '5491',
|
||||
'host': '0.0.0.0'
|
||||
}
|
||||
|
||||
# Pecan Application Configurations
|
||||
app = {
|
||||
'root': 'cgcs_patch.api.controllers.root.RootController',
|
||||
'modules': ['cgcs_patch.api'],
|
||||
'static_root': '%(confdir)s/public',
|
||||
'template_path': '%(confdir)s/../templates',
|
||||
'debug': False,
|
||||
'enable_acl': True,
|
||||
'acl_public_routes': [],
|
||||
}
|
100
cgcs-patch/cgcs-patch/cgcs_patch/authapi/hooks.py
Executable file
100
cgcs-patch/cgcs-patch/cgcs_patch/authapi/hooks.py
Executable file
@ -0,0 +1,100 @@
|
||||
# -*- encoding: utf-8 -*-
|
||||
#
|
||||
# Copyright © 2012 New Dream Network, LLC (DreamHost)
|
||||
#
|
||||
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2013-2017 Wind River Systems, Inc.
|
||||
#
|
||||
|
||||
|
||||
from oslo_config import cfg
|
||||
from pecan import hooks
|
||||
|
||||
from sysinv.common import context
|
||||
from sysinv.common import utils
|
||||
from sysinv.openstack.common import policy
|
||||
from webob import exc
|
||||
|
||||
|
||||
class ConfigHook(hooks.PecanHook):
|
||||
"""Attach the config object to the request so controllers can get to it."""
|
||||
|
||||
def before(self, state):
|
||||
state.request.cfg = cfg.CONF
|
||||
|
||||
|
||||
class ContextHook(hooks.PecanHook):
|
||||
"""Configures a request context and attaches it to the request.
|
||||
|
||||
The following HTTP request headers are used:
|
||||
|
||||
X-User-Id or X-User:
|
||||
Used for context.user_id.
|
||||
|
||||
X-Tenant-Id or X-Tenant:
|
||||
Used for context.tenant.
|
||||
|
||||
X-Auth-Token:
|
||||
Used for context.auth_token.
|
||||
|
||||
X-Roles:
|
||||
Used for setting context.is_admin flag to either True or False.
|
||||
The flag is set to True, if X-Roles contains either an administrator
|
||||
or admin substring. Otherwise it is set to False.
|
||||
|
||||
"""
|
||||
def __init__(self, public_api_routes):
|
||||
self.public_api_routes = public_api_routes
|
||||
super(ContextHook, self).__init__()
|
||||
|
||||
def before(self, state):
|
||||
user_id = state.request.headers.get('X-User-Id')
|
||||
user_id = state.request.headers.get('X-User', user_id)
|
||||
tenant = state.request.headers.get('X-Tenant-Id')
|
||||
tenant = state.request.headers.get('X-Tenant', tenant)
|
||||
domain_id = state.request.headers.get('X-User-Domain-Id')
|
||||
domain_name = state.request.headers.get('X-User-Domain-Name')
|
||||
auth_token = state.request.headers.get('X-Auth-Token', None)
|
||||
creds = {'roles': state.request.headers.get('X-Roles', '').split(',')}
|
||||
|
||||
is_admin = policy.check('admin', state.request.headers, creds)
|
||||
|
||||
path = utils.safe_rstrip(state.request.path, '/')
|
||||
is_public_api = path in self.public_api_routes
|
||||
|
||||
state.request.context = context.RequestContext(
|
||||
auth_token=auth_token,
|
||||
user=user_id,
|
||||
tenant=tenant,
|
||||
domain_id=domain_id,
|
||||
domain_name=domain_name,
|
||||
is_admin=is_admin,
|
||||
is_public_api=is_public_api)
|
||||
|
||||
|
||||
class AdminAuthHook(hooks.PecanHook):
|
||||
"""Verify that the user has admin rights.
|
||||
|
||||
Checks whether the request context is an admin context and
|
||||
rejects the request otherwise.
|
||||
|
||||
"""
|
||||
def before(self, state):
|
||||
ctx = state.request.context
|
||||
is_admin_api = policy.check('admin_api', {}, ctx.to_dict())
|
||||
|
||||
if not is_admin_api and not ctx.is_public_api:
|
||||
raise exc.HTTPForbidden()
|
117
cgcs-patch/cgcs-patch/cgcs_patch/authapi/policy.py
Executable file
117
cgcs-patch/cgcs-patch/cgcs_patch/authapi/policy.py
Executable file
@ -0,0 +1,117 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2011 OpenStack Foundation
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
#
|
||||
|
||||
"""Policy Engine For Patching."""
|
||||
|
||||
import os.path
|
||||
|
||||
from sysinv.common import exception
|
||||
from sysinv.common import utils
|
||||
from sysinv.openstack.common import policy
|
||||
|
||||
|
||||
_POLICY_PATH = None
|
||||
_POLICY_CACHE = {}
|
||||
|
||||
def reset():
|
||||
global _POLICY_PATH
|
||||
global _POLICY_CACHE
|
||||
_POLICY_PATH = None
|
||||
_POLICY_CACHE = {}
|
||||
policy.reset()
|
||||
|
||||
|
||||
def init():
|
||||
global _POLICY_PATH
|
||||
global _POLICY_CACHE
|
||||
if not _POLICY_PATH:
|
||||
_POLICY_PATH = '/etc/patching/policy.json'
|
||||
if not os.path.exists(_POLICY_PATH):
|
||||
raise exception.ConfigNotFound(message='/etc/patching/policy.json')
|
||||
utils.read_cached_file(_POLICY_PATH, _POLICY_CACHE,
|
||||
reload_func=_set_rules)
|
||||
|
||||
|
||||
def _set_rules(data):
|
||||
default_rule = "rule:admin_api"
|
||||
policy.set_rules(policy.Rules.load_json(data, default_rule))
|
||||
|
||||
|
||||
def enforce(context, action, target, do_raise=True):
|
||||
"""Verifies that the action is valid on the target in this context.
|
||||
|
||||
:param context: sysinv context
|
||||
:param action: string representing the action to be checked
|
||||
this should be colon separated for clarity.
|
||||
i.e. ``compute:create_instance``,
|
||||
``compute:attach_volume``,
|
||||
``volume:attach_volume``
|
||||
:param target: dictionary representing the object of the action
|
||||
for object creation this should be a dictionary representing the
|
||||
location of the object e.g. ``{'project_id': context.project_id}``
|
||||
:param do_raise: if True (the default), raises PolicyNotAuthorized;
|
||||
if False, returns False
|
||||
|
||||
:raises sysinv.exception.PolicyNotAuthorized: if verification fails
|
||||
and do_raise is True.
|
||||
|
||||
:return: returns a non-False value (not necessarily "True") if
|
||||
authorized, and the exact value False if not authorized and
|
||||
do_raise is False.
|
||||
"""
|
||||
init()
|
||||
|
||||
credentials = context.to_dict()
|
||||
|
||||
# Add the exception arguments if asked to do a raise
|
||||
extra = {}
|
||||
if do_raise:
|
||||
extra.update(exc=exception.PolicyNotAuthorized, action=action)
|
||||
|
||||
return policy.check(action, target, credentials, **extra)
|
||||
|
||||
|
||||
def check_is_admin(context):
|
||||
"""Whether or not role contains 'admin' role according to policy setting.
|
||||
|
||||
"""
|
||||
init()
|
||||
|
||||
credentials = context.to_dict()
|
||||
target = credentials
|
||||
|
||||
return policy.check('context_is_admin', target, credentials)
|
||||
|
||||
|
||||
@policy.register('context_is_admin')
|
||||
class IsAdminCheck(policy.Check):
|
||||
"""An explicit check for is_admin."""
|
||||
|
||||
def __init__(self, kind, match):
|
||||
"""Initialize the check."""
|
||||
|
||||
self.expected = (match.lower() == 'true')
|
||||
|
||||
super(IsAdminCheck, self).__init__(kind, str(self.expected))
|
||||
|
||||
def __call__(self, target, creds):
|
||||
"""Determine whether is_admin matches the requested value."""
|
||||
|
||||
return creds['is_admin'] == self.expected
|
166
cgcs-patch/cgcs-patch/cgcs_patch/base.py
Normal file
166
cgcs-patch/cgcs-patch/cgcs_patch/base.py
Normal file
@ -0,0 +1,166 @@
|
||||
"""
|
||||
Copyright (c) 2017-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import socket
|
||||
import struct
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
import cgcs_patch.utils as utils
|
||||
import cgcs_patch.config as cfg
|
||||
import cgcs_patch.constants as constants
|
||||
from cgcs_patch.patch_functions import LOG
|
||||
|
||||
|
||||
class PatchService:
|
||||
def __init__(self):
|
||||
self.sock_out = None
|
||||
self.sock_in = None
|
||||
self.service_type = None
|
||||
self.port = None
|
||||
self.mcast_addr = None
|
||||
self.socket_lock = None
|
||||
|
||||
def update_config(self):
|
||||
# Implemented in subclass
|
||||
pass
|
||||
|
||||
def socket_lock_acquire(self):
|
||||
pass
|
||||
|
||||
def socket_lock_release(self):
|
||||
pass
|
||||
|
||||
def setup_socket_ipv4(self):
|
||||
mgmt_ip = cfg.get_mgmt_ip()
|
||||
if mgmt_ip is None:
|
||||
# Don't setup socket unless we have a mgmt ip
|
||||
return None
|
||||
|
||||
self.update_config()
|
||||
|
||||
interface_addr = socket.inet_pton(socket.AF_INET, mgmt_ip)
|
||||
|
||||
# Close sockets, if necessary
|
||||
for s in [self.sock_out, self.sock_in]:
|
||||
if s is not None:
|
||||
s.close()
|
||||
|
||||
self.sock_out = socket.socket(socket.AF_INET,
|
||||
socket.SOCK_DGRAM)
|
||||
self.sock_in = socket.socket(socket.AF_INET,
|
||||
socket.SOCK_DGRAM)
|
||||
|
||||
self.sock_out.setblocking(0)
|
||||
self.sock_in.setblocking(0)
|
||||
|
||||
self.sock_out.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.sock_in.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
self.sock_out.bind((mgmt_ip, 0))
|
||||
self.sock_in.bind(('', self.port))
|
||||
|
||||
# These options are for outgoing multicast messages
|
||||
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF, interface_addr)
|
||||
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 1)
|
||||
# Since only the controllers are sending to this address,
|
||||
# we want the loopback so the local agent can receive it
|
||||
self.sock_out.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_LOOP, 1)
|
||||
|
||||
# Register the multicast group
|
||||
group = socket.inet_pton(socket.AF_INET, self.mcast_addr)
|
||||
mreq = struct.pack('=4s4s', group, interface_addr)
|
||||
|
||||
self.sock_in.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
|
||||
|
||||
return self.sock_in
|
||||
|
||||
def setup_socket_ipv6(self):
|
||||
mgmt_ip = cfg.get_mgmt_ip()
|
||||
if mgmt_ip is None:
|
||||
# Don't setup socket unless we have a mgmt ip
|
||||
return None
|
||||
|
||||
self.update_config()
|
||||
|
||||
# Close sockets, if necessary
|
||||
for s in [self.sock_out, self.sock_in]:
|
||||
if s is not None:
|
||||
s.close()
|
||||
|
||||
self.sock_out = socket.socket(socket.AF_INET6,
|
||||
socket.SOCK_DGRAM)
|
||||
self.sock_in = socket.socket(socket.AF_INET6,
|
||||
socket.SOCK_DGRAM)
|
||||
|
||||
self.sock_out.setblocking(0)
|
||||
self.sock_in.setblocking(0)
|
||||
|
||||
self.sock_out.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.sock_in.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
|
||||
self.sock_out.bind((mgmt_ip, 0))
|
||||
self.sock_in.bind(('', self.port))
|
||||
|
||||
# These options are for outgoing multicast messages
|
||||
mgmt_ifindex = utils.if_nametoindex(cfg.get_mgmt_iface())
|
||||
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_IF, mgmt_ifindex)
|
||||
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, 1)
|
||||
# Since only the controllers are sending to this address,
|
||||
# we want the loopback so the local agent can receive it
|
||||
self.sock_out.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, 1)
|
||||
|
||||
# Register the multicast group
|
||||
if_index_packed = struct.pack('I', mgmt_ifindex)
|
||||
group = socket.inet_pton(socket.AF_INET6, self.mcast_addr) + if_index_packed
|
||||
self.sock_in.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, group)
|
||||
|
||||
return self.sock_in
|
||||
|
||||
def setup_socket(self):
|
||||
self.socket_lock_acquire()
|
||||
|
||||
try:
|
||||
sock_in = None
|
||||
if utils.get_management_version() == constants.ADDRESS_VERSION_IPV6:
|
||||
sock_in = self.setup_socket_ipv6()
|
||||
else:
|
||||
sock_in = self.setup_socket_ipv4()
|
||||
self.socket_lock_release()
|
||||
return sock_in
|
||||
except:
|
||||
LOG.exception("Failed to setup socket")
|
||||
|
||||
# Close sockets, if necessary
|
||||
for s in [self.sock_out, self.sock_in]:
|
||||
if s is not None:
|
||||
s.close()
|
||||
|
||||
self.socket_lock_release()
|
||||
|
||||
return None
|
||||
|
||||
def audit_socket(self):
|
||||
# Ensure multicast address is still allocated
|
||||
cmd = "ip maddr show %s | awk 'BEGIN { ORS=\"\" }; {if ($2 == \"%s\") print $2}'" % \
|
||||
(cfg.get_mgmt_iface(), self.mcast_addr)
|
||||
try:
|
||||
result = subprocess.check_output(cmd, shell=True)
|
||||
|
||||
if result == self.mcast_addr:
|
||||
return
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOG.error("Command output: %s" % e.output)
|
||||
return
|
||||
|
||||
# Close the socket and set it up again
|
||||
LOG.info("Detected missing multicast addr (%s). Reconfiguring" % self.mcast_addr)
|
||||
while self.setup_socket() is None:
|
||||
LOG.info("Unable to setup sockets. Waiting to retry")
|
||||
time.sleep(5)
|
||||
LOG.info("Multicast address reconfigured")
|
||||
|
51
cgcs-patch/cgcs-patch/cgcs_patch/certificates.py
Normal file
51
cgcs-patch/cgcs-patch/cgcs_patch/certificates.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""
|
||||
Copyright (c) 2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
dev_certificate = b"""-----BEGIN CERTIFICATE-----
|
||||
MIIDejCCAmKgAwIBAgICEAQwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCQ0Ex
|
||||
EDAOBgNVBAgMB09udGFyaW8xITAfBgNVBAoMGFdpbmQgUml2ZXIgU3lzdGVtcywg
|
||||
SW5jLjAeFw0xNzA4MTgxNDM3MjlaFw0yNzA4MTYxNDM3MjlaMEExCzAJBgNVBAYT
|
||||
AkNBMRAwDgYDVQQIDAdPbnRhcmlvMSAwHgYDVQQKDBdXaW5kIFJpdmVyIFN5c3Rl
|
||||
bXMsIEluYzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALcs0/Te6x69
|
||||
lxQOxudrF+uSC5F9r5bKUnZNWUKHyXKlN4SzZgWGs+fb/DqXIm7piuoQ6GH7GEQd
|
||||
BEN1j/bwp30LZlv0Ur+8jhCvEdqsIP3vUXfv7pv0bomVs0Q8ZRI/FYZhjxYlyFKr
|
||||
gZFV9WPP8S9SwfClHjaYRUudvwvjHHnnnkZ9blVFbXU0Xe83A8fWd0HNqAU1TlmK
|
||||
4CeSi4FI4aRKiXJnOvgv2UoJMI57rBIVKYRUH8uuFpPofOwjOM/Rd6r3Ir+4/CX6
|
||||
+/NALOBIEN6M05ZzoiyiH8NHELknQBqzNs0cXObJWpaSinAOcBnPCc7DNRwgQzjR
|
||||
SdcE9FG1+LcCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3Bl
|
||||
blNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFDRbal2KxU0hQyv4
|
||||
MVnWrW96+aWoMB8GA1UdIwQYMBaAFJaLO1x8+jti7V6pLGbUyqpy0M36MA0GCSqG
|
||||
SIb3DQEBCwUAA4IBAQBmcPFZzEoPtuMPCFvJ/0cmngp8yvCGxWz3JEDkdGYSCVGs
|
||||
TG5e9DeltaHOk6yLvZSRY1so30GQnyB9q8v4DwEGVslKg8u9w/WEU81wl6Q2FZ5s
|
||||
XRP6TASQ0Lbg9e4b3bnTITJJ8jT/zF29NaohgC2fg0UwVuldZLfa7FihJB4//OC1
|
||||
UdNEcmdqTVRqN2oco1n3ZUWKXvG2AvGsoiqu+lsWX1MXacoFvJexSACLrUvOoXMW
|
||||
i38Ofp7XMCAm3rM0cXv7Uc9WCrgnTWbEvDgjGfRAmcM9moWGoWX6E46Xkojpkfle
|
||||
Ss6CHAMK42aZ/+MWQlZEzNK49PtomGMjn5SuoK8u
|
||||
-----END CERTIFICATE-----"""
|
||||
|
||||
formal_certificate=b"""-----BEGIN CERTIFICATE-----
|
||||
MIIDezCCAmOgAwIBAgICEAMwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCQ0Ex
|
||||
EDAOBgNVBAgMB09udGFyaW8xITAfBgNVBAoMGFdpbmQgUml2ZXIgU3lzdGVtcywg
|
||||
SW5jLjAeFw0xNzA4MTgxNDM1MTJaFw0yNzA4MTYxNDM1MTJaMEIxCzAJBgNVBAYT
|
||||
AkNBMRAwDgYDVQQIDAdPbnRhcmlvMSEwHwYDVQQKDBhXaW5kIFJpdmVyIFN5c3Rl
|
||||
bXMsIEluYy4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC+0fS8ybg8
|
||||
M37lW+lcR9LmQAR2zUJdbnl2L0fj3W/7W+PMm3mJWeQDTf19wf+qHHrgEkjxGp10
|
||||
BSXWZYdPyCdOjAay/Ew1s/waFeAQZpf4vv/9D1Y/4sVkqct9ibo5NVgvVsjqKVnX
|
||||
IVhyzHlhBSUqYhZlS/SOx8JcLQWSUMJoP2XR4Tv28xIXi0Fuyp8QBwUmSwmvfPy4
|
||||
0yxzfON/b8kHld5aTY353KLXh/5YWsn1zRlOYfS1OuJk4LGjm6HvmZtxPNUZk4vI
|
||||
NA24rH4FKkuxyM3x8aPi3LE4G6GSrJDuNi28xzOj864rlFoyLODy/mov1YMR/g4k
|
||||
d3mG6UbRckPxAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w
|
||||
ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTjyMN/AX07rEmB
|
||||
6sz6pnyt/m+eSzAfBgNVHSMEGDAWgBSWiztcfPo7Yu1eqSxm1MqqctDN+jANBgkq
|
||||
hkiG9w0BAQsFAAOCAQEASpyCu/adGTvNjyy/tV+sL/kaVEKLA7q36HUrzQkTjMPX
|
||||
y8L8PVZoeWprkz7cvYTyHmVTPLBvFkGEFVn8LWi9fTTp/UrHnxw6fvb+V78mOypi
|
||||
4A1aU9+dh3L6arpd4jZ4hDiLhEClesGCYVTVBdsrh3zSOc51nT4hosyBVpRd/VgQ
|
||||
jhGJBBMEXASZceady4ajK5jnR3wF8oW/he4NYF97qh8WWKVsIYbwgLS0rT58q7qq
|
||||
vpjPxMOahUdACkyPyt/XJICTlkanVD7KgG3oLWpc+3FWPHGr+F7mspPLZqUcEFDV
|
||||
bGF+oDJ7p/tqHsNvPlRDVGqh0QdiAkKeS/SJC9jmAw==
|
||||
-----END CERTIFICATE-----
|
||||
"""
|
126
cgcs-patch/cgcs-patch/cgcs_patch/config.py
Normal file
126
cgcs-patch/cgcs-patch/cgcs_patch/config.py
Normal file
@ -0,0 +1,126 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import ConfigParser
|
||||
import StringIO
|
||||
import subprocess
|
||||
import logging
|
||||
import socket
|
||||
import cgcs_patch.utils as utils
|
||||
import cgcs_patch.constants as constants
|
||||
import tsconfig.tsconfig as tsc
|
||||
|
||||
controller_mcast_group = None
|
||||
agent_mcast_group = None
|
||||
controller_port = 0
|
||||
agent_port = 0
|
||||
api_port = 0
|
||||
mgmt_if = None
|
||||
nodetype = None
|
||||
platform_conf_mtime = 0
|
||||
patching_conf_mtime = 0
|
||||
patching_conf = '/etc/patching/patching.conf'
|
||||
|
||||
def read_config():
|
||||
global patching_conf_mtime
|
||||
global patching_conf
|
||||
|
||||
if patching_conf_mtime == os.stat(patching_conf).st_mtime:
|
||||
# The file has not changed since it was last read
|
||||
return
|
||||
|
||||
defaults = {
|
||||
'controller_mcast_group': "239.1.1.3",
|
||||
'agent_mcast_group': "239.1.1.4",
|
||||
'api_port': "5487",
|
||||
'controller_port': "5488",
|
||||
'agent_port': "5489",
|
||||
}
|
||||
|
||||
global controller_mcast_group
|
||||
global agent_mcast_group
|
||||
global api_port
|
||||
global controller_port
|
||||
global agent_port
|
||||
|
||||
config = ConfigParser.SafeConfigParser(defaults)
|
||||
config.read(patching_conf)
|
||||
patching_conf_mtime = os.stat(patching_conf).st_mtime
|
||||
|
||||
controller_mcast_group = config.get('runtime',
|
||||
'controller_multicast')
|
||||
agent_mcast_group = config.get('runtime', 'agent_multicast')
|
||||
|
||||
api_port = config.getint('runtime', 'api_port')
|
||||
controller_port = config.getint('runtime', 'controller_port')
|
||||
agent_port = config.getint('runtime', 'agent_port')
|
||||
|
||||
# The platform.conf file has no section headers, which causes problems
|
||||
# for ConfigParser. So we'll fake it out.
|
||||
ini_str = '[platform_conf]\n' + open(tsc.PLATFORM_CONF_FILE, 'r').read()
|
||||
ini_fp = StringIO.StringIO(ini_str)
|
||||
config.readfp(ini_fp)
|
||||
|
||||
try:
|
||||
value = config.get('platform_conf', 'nodetype')
|
||||
|
||||
global nodetype
|
||||
nodetype = value
|
||||
except ConfigParser.Error:
|
||||
logging.exception("Failed to read nodetype from config")
|
||||
return False
|
||||
|
||||
|
||||
def get_mgmt_ip():
|
||||
# Check if initial config is complete
|
||||
if not os.path.exists('/etc/platform/.initial_config_complete'):
|
||||
return None
|
||||
mgmt_hostname = socket.gethostname()
|
||||
return utils.gethostbyname(mgmt_hostname)
|
||||
|
||||
|
||||
# Because the patching daemons are launched before manifests are
|
||||
# applied, the content of some settings in platform.conf can change,
|
||||
# such as the management interface. As such, we can't just directly
|
||||
# use tsc.management_interface
|
||||
#
|
||||
def get_mgmt_iface():
|
||||
# Check if initial config is complete
|
||||
if not os.path.exists(constants.INITIAL_CONFIG_COMPLETE_FLAG):
|
||||
return None
|
||||
|
||||
global mgmt_if
|
||||
global platform_conf_mtime
|
||||
|
||||
if mgmt_if is not None and \
|
||||
platform_conf_mtime == os.stat(tsc.PLATFORM_CONF_FILE).st_mtime:
|
||||
# The platform.conf file hasn't been modified since we read it,
|
||||
# so return the cached value.
|
||||
return mgmt_if
|
||||
|
||||
config = ConfigParser.SafeConfigParser()
|
||||
|
||||
# The platform.conf file has no section headers, which causes problems
|
||||
# for ConfigParser. So we'll fake it out.
|
||||
ini_str = '[platform_conf]\n' + open(tsc.PLATFORM_CONF_FILE, 'r').read()
|
||||
ini_fp = StringIO.StringIO(ini_str)
|
||||
config.readfp(ini_fp)
|
||||
|
||||
try:
|
||||
value = config.get('platform_conf', 'management_interface')
|
||||
|
||||
global nodetype
|
||||
mgmt_if = value
|
||||
|
||||
platform_conf_mtime = os.stat(tsc.PLATFORM_CONF_FILE).st_mtime
|
||||
except ConfigParser.Error:
|
||||
logging.exception("Failed to read management_interface from config")
|
||||
return None
|
||||
return mgmt_if
|
||||
|
||||
|
43
cgcs-patch/cgcs-patch/cgcs_patch/constants.py
Normal file
43
cgcs-patch/cgcs-patch/cgcs_patch/constants.py
Normal file
@ -0,0 +1,43 @@
|
||||
"""
|
||||
Copyright (c) 2015-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
try:
|
||||
# The tsconfig module is only available at runtime
|
||||
import tsconfig.tsconfig as tsc
|
||||
|
||||
INITIAL_CONFIG_COMPLETE_FLAG = os.path.join(
|
||||
tsc.PLATFORM_CONF_PATH, ".initial_config_complete")
|
||||
except:
|
||||
pass
|
||||
|
||||
PATCH_AGENT_STATE_IDLE = "idle"
|
||||
PATCH_AGENT_STATE_INSTALLING = "installing"
|
||||
PATCH_AGENT_STATE_INSTALL_FAILED = "install-failed"
|
||||
PATCH_AGENT_STATE_INSTALL_REJECTED = "install-rejected"
|
||||
|
||||
ADDRESS_VERSION_IPV4 = 4
|
||||
ADDRESS_VERSION_IPV6 = 6
|
||||
CONTROLLER_FLOATING_HOSTNAME = "controller"
|
||||
|
||||
AVAILABLE = 'Available'
|
||||
APPLIED = 'Applied'
|
||||
PARTIAL_APPLY = 'Partial-Apply'
|
||||
PARTIAL_REMOVE = 'Partial-Remove'
|
||||
COMMITTED = 'Committed'
|
||||
UNKNOWN = 'n/a'
|
||||
|
||||
STATUS_OBSOLETE = 'OBS'
|
||||
STATUS_RELEASED = 'REL'
|
||||
STATUS_DEVELOPEMENT = 'DEV'
|
||||
|
||||
CLI_OPT_ALL = '--all'
|
||||
CLI_OPT_DRY_RUN = '--dry-run'
|
||||
CLI_OPT_RECURSIVE = '--recursive'
|
||||
CLI_OPT_RELEASE = '--release'
|
||||
|
||||
ENABLE_DEV_CERTIFICATE_PATCH_IDENTIFIER = 'ENABLE_DEV_CERTIFICATE'
|
45
cgcs-patch/cgcs-patch/cgcs_patch/exceptions.py
Normal file
45
cgcs-patch/cgcs-patch/cgcs_patch/exceptions.py
Normal file
@ -0,0 +1,45 @@
|
||||
"""
|
||||
Copyright (c) 2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
class PatchError(Exception):
|
||||
"""Base class for patching exceptions."""
|
||||
|
||||
def __init__(self, message=None):
|
||||
self.message = message
|
||||
|
||||
def __str__(self):
|
||||
return self.message or ""
|
||||
|
||||
|
||||
class MetadataFail(PatchError):
|
||||
"""Metadata error."""
|
||||
pass
|
||||
|
||||
|
||||
class RpmFail(PatchError):
|
||||
"""RPM error."""
|
||||
pass
|
||||
|
||||
|
||||
class RepoFail(PatchError):
|
||||
"""Repo error."""
|
||||
pass
|
||||
|
||||
|
||||
class PatchFail(PatchError):
|
||||
"""General patching error."""
|
||||
pass
|
||||
|
||||
|
||||
class PatchValidationFailure(PatchError):
|
||||
"""Patch validation error."""
|
||||
pass
|
||||
|
||||
|
||||
class PatchMismatchFailure(PatchError):
|
||||
"""Patch validation error."""
|
||||
pass
|
64
cgcs-patch/cgcs-patch/cgcs_patch/messages.py
Normal file
64
cgcs-patch/cgcs-patch/cgcs_patch/messages.py
Normal file
@ -0,0 +1,64 @@
|
||||
"""
|
||||
Copyright (c) 2014-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
from cgcs_patch.patch_functions import LOG
|
||||
|
||||
PATCHMSG_UNKNOWN = 0
|
||||
PATCHMSG_HELLO = 1
|
||||
PATCHMSG_HELLO_ACK = 2
|
||||
PATCHMSG_SYNC_REQ = 3
|
||||
PATCHMSG_SYNC_COMPLETE = 4
|
||||
PATCHMSG_HELLO_AGENT = 5
|
||||
PATCHMSG_HELLO_AGENT_ACK = 6
|
||||
PATCHMSG_QUERY_DETAILED = 7
|
||||
PATCHMSG_QUERY_DETAILED_RESP = 8
|
||||
PATCHMSG_AGENT_INSTALL_REQ = 9
|
||||
PATCHMSG_AGENT_INSTALL_RESP = 10
|
||||
PATCHMSG_DROP_HOST_REQ = 11
|
||||
|
||||
PATCHMSG_STR = {
|
||||
PATCHMSG_UNKNOWN: "unknown",
|
||||
PATCHMSG_HELLO: "hello",
|
||||
PATCHMSG_HELLO_ACK: "hello-ack",
|
||||
PATCHMSG_SYNC_REQ: "sync-req",
|
||||
PATCHMSG_SYNC_COMPLETE: "sync-complete",
|
||||
PATCHMSG_HELLO_AGENT: "hello-agent",
|
||||
PATCHMSG_HELLO_AGENT_ACK: "hello-agent-ack",
|
||||
PATCHMSG_QUERY_DETAILED: "query-detailed",
|
||||
PATCHMSG_QUERY_DETAILED_RESP: "query-detailed-resp",
|
||||
PATCHMSG_AGENT_INSTALL_REQ: "agent-install-req",
|
||||
PATCHMSG_AGENT_INSTALL_RESP: "agent-install-resp",
|
||||
PATCHMSG_DROP_HOST_REQ: "drop-host-req",
|
||||
}
|
||||
|
||||
|
||||
class PatchMessage(object):
|
||||
def __init__(self, msgtype=PATCHMSG_UNKNOWN):
|
||||
self.msgtype = msgtype
|
||||
self.msgversion = 1
|
||||
self.message = {}
|
||||
|
||||
def decode(self, data):
|
||||
if 'msgtype' in data:
|
||||
self.msgtype = data['msgtype']
|
||||
if 'msgversion' in data:
|
||||
self.msgversion = data['msgversion']
|
||||
|
||||
def encode(self):
|
||||
self.message['msgtype'] = self.msgtype
|
||||
self.message['msgversion'] = self.msgversion
|
||||
|
||||
def data(self):
|
||||
return {'msgtype': self.msgtype}
|
||||
|
||||
def msgtype_str(self):
|
||||
if self.msgtype in PATCHMSG_STR:
|
||||
return PATCHMSG_STR[self.msgtype]
|
||||
return "invalid-type"
|
||||
|
||||
def handle(self, sock, addr):
|
||||
LOG.info("Unhandled message type: %s" % self.msgtype)
|
1060
cgcs-patch/cgcs-patch/cgcs_patch/patch_agent.py
Normal file
1060
cgcs-patch/cgcs-patch/cgcs_patch/patch_agent.py
Normal file
File diff suppressed because it is too large
Load Diff
1308
cgcs-patch/cgcs-patch/cgcs_patch/patch_client.py
Normal file
1308
cgcs-patch/cgcs-patch/cgcs_patch/patch_client.py
Normal file
File diff suppressed because it is too large
Load Diff
2468
cgcs-patch/cgcs-patch/cgcs_patch/patch_controller.py
Normal file
2468
cgcs-patch/cgcs-patch/cgcs_patch/patch_controller.py
Normal file
File diff suppressed because it is too large
Load Diff
1205
cgcs-patch/cgcs-patch/cgcs_patch/patch_functions.py
Normal file
1205
cgcs-patch/cgcs-patch/cgcs_patch/patch_functions.py
Normal file
File diff suppressed because it is too large
Load Diff
66
cgcs-patch/cgcs-patch/cgcs_patch/patch_signing.py
Normal file
66
cgcs-patch/cgcs-patch/cgcs_patch/patch_signing.py
Normal file
@ -0,0 +1,66 @@
|
||||
"""
|
||||
Copyright (c) 2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
from Crypto.Signature import PKCS1_PSS
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Util.asn1 import DerSequence
|
||||
from binascii import a2b_base64
|
||||
from cgcs_patch.patch_verify import read_RSA_key
|
||||
|
||||
# To save memory, read and hash 1M of files at a time
|
||||
default_blocksize=1*1024*1024
|
||||
|
||||
# When we sign patches, look for private keys in the following paths
|
||||
#
|
||||
# The (currently hardcoded) path on the signing server will be replaced
|
||||
# by the capability to specify filename from calling function.
|
||||
private_key_files=['/signing/keys/formal-private-key.pem',
|
||||
os.path.expandvars('$MY_REPO/build-tools/signing/dev-private-key.pem')
|
||||
]
|
||||
|
||||
|
||||
def sign_files(filenames, signature_file, private_key=None):
|
||||
"""
|
||||
Utility function for signing data in files.
|
||||
:param filenames: A list of files containing the data to be signed
|
||||
:param signature_file: The name of the file to which the signature will be
|
||||
stored
|
||||
:param private_key: If specified, sign with this private key. Otherwise,
|
||||
the files in private_key_files will be searched for
|
||||
and used, if found.
|
||||
"""
|
||||
|
||||
# Hash the data across all files
|
||||
blocksize=default_blocksize
|
||||
data_hash = SHA256.new()
|
||||
for filename in filenames:
|
||||
with open(filename, 'rb') as infile:
|
||||
data=infile.read(blocksize)
|
||||
while len(data) > 0:
|
||||
data_hash.update(data)
|
||||
data=infile.read(blocksize)
|
||||
|
||||
# Find a private key to use, if not already provided
|
||||
if private_key is None:
|
||||
for filename in private_key_files:
|
||||
# print 'Checking to see if ' + filename + ' exists\n'
|
||||
if os.path.exists(filename):
|
||||
# print 'Getting private key from ' + filename + '\n'
|
||||
private_key = read_RSA_key(open(filename, 'rb').read())
|
||||
|
||||
assert (private_key is not None),"Could not find private signing key"
|
||||
|
||||
# Encrypt the hash (sign the data) with the key we find
|
||||
signer = PKCS1_PSS.new(private_key)
|
||||
signature = signer.sign(data_hash)
|
||||
|
||||
# Save it
|
||||
with open(signature_file, 'wb') as outfile:
|
||||
outfile.write(signature)
|
||||
|
147
cgcs-patch/cgcs-patch/cgcs_patch/patch_verify.py
Normal file
147
cgcs-patch/cgcs-patch/cgcs_patch/patch_verify.py
Normal file
@ -0,0 +1,147 @@
|
||||
"""
|
||||
Copyright (c) 2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import logging
|
||||
|
||||
from Crypto.Signature import PKCS1_v1_5
|
||||
from Crypto.Signature import PKCS1_PSS
|
||||
from Crypto.Hash import SHA256
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto.Util.asn1 import DerSequence
|
||||
from binascii import a2b_base64
|
||||
|
||||
from cgcs_patch.certificates import dev_certificate, formal_certificate
|
||||
|
||||
# To save memory, read and hash 1M of files at a time
|
||||
default_blocksize=1*1024*1024
|
||||
|
||||
dev_certificate_marker='/etc/pki/wrs/dev_certificate_enable.bin'
|
||||
LOG = logging.getLogger('main_logger')
|
||||
|
||||
|
||||
def verify_hash(data_hash, signature_bytes, certificate_list):
|
||||
"""
|
||||
Checkes that a hash's signature can be validates against an approved
|
||||
certificate
|
||||
:param data_hash: A hash of the data to be validated
|
||||
:param signature_bytes: A pre-generated signature (typically, the hash
|
||||
encrypted with a private key)
|
||||
:param certifcate_list: A list of approved certificates or public keys
|
||||
which the signature is validated against
|
||||
:return: True if the signature was validated against a certificate
|
||||
"""
|
||||
verified = False
|
||||
for cert in certificate_list:
|
||||
if verified:
|
||||
break
|
||||
pub_key = read_RSA_key(cert)
|
||||
x = pub_key.exportKey()
|
||||
|
||||
# PSS is the recommended signature scheme, but some tools (like OpenSSL)
|
||||
# use the older v1_5 scheme. We try to validate against both.
|
||||
#
|
||||
# We use PSS for patch validation, but use v1_5 for ISO validation
|
||||
# since we want to generate detached sigs that a customer can validate
|
||||
# OpenSSL
|
||||
verifier = PKCS1_PSS.new(pub_key)
|
||||
verified = verifier.verify(data_hash, signature_bytes)
|
||||
if not verified:
|
||||
verifier = PKCS1_v1_5.new(pub_key)
|
||||
verified = verifier.verify(data_hash, signature_bytes)
|
||||
return verified
|
||||
|
||||
|
||||
def get_public_certificates():
|
||||
"""
|
||||
Builds a list of accepted certificates which can be used to validate
|
||||
further things. This list may contain multiple certificates depending on
|
||||
the configuration of the system (for instance, should we include the
|
||||
developer certificate in the list).
|
||||
:return: A list of certificates in PEM format
|
||||
"""
|
||||
cert_list = [formal_certificate]
|
||||
|
||||
# We enable the dev certificate based on the presence of a file. This file
|
||||
# contains a hash of an arbitrary string ('Titanum patching') which has been
|
||||
# encrypted with our formal private key. If the file is present (and valid)
|
||||
# then we add the developer key to the approved certificates list
|
||||
if os.path.exists(dev_certificate_marker):
|
||||
with open(dev_certificate_marker) as infile:
|
||||
signature = infile.read()
|
||||
data_hash = SHA256.new()
|
||||
data_hash.update('Titanium patching')
|
||||
if verify_hash(data_hash, signature, cert_list):
|
||||
cert_list.append(dev_certificate)
|
||||
else:
|
||||
msg = "Invalid data found in " + dev_certificate_marker
|
||||
LOG.error(msg)
|
||||
|
||||
return cert_list
|
||||
|
||||
|
||||
def read_RSA_key(key_data):
|
||||
"""
|
||||
Utility function for reading an RSA key half from encoded data
|
||||
:param key_data: PEM data containing raw key or X.509 certificate
|
||||
:return: An RSA key object
|
||||
"""
|
||||
try:
|
||||
# Handle data that is just a raw key
|
||||
key = RSA.importKey(key_data)
|
||||
except ValueError:
|
||||
# The RSA.importKey function cannot read X.509 certificates directly
|
||||
# (depending on the version of the Crypto library). Instead, we
|
||||
# may need to extract the key from the certificate before building
|
||||
# the key object
|
||||
#
|
||||
# We need to strip the BEGIN and END lines from PEM first
|
||||
x509lines = key_data.replace(' ','').split()
|
||||
x509text = ''.join(x509lines[1:-1])
|
||||
x509data = DerSequence()
|
||||
x509data.decode(a2b_base64(x509text))
|
||||
|
||||
# X.509 contains a few parts. The first part (index 0) is the
|
||||
# certificate itself, (TBS or "to be signed" cert) and the 7th field
|
||||
# of that cert is subjectPublicKeyInfo, which can be imported.
|
||||
# RFC3280
|
||||
tbsCert = DerSequence()
|
||||
tbsCert.decode(x509data[0])
|
||||
|
||||
# Initialize RSA key from the subjectPublicKeyInfo field
|
||||
key = RSA.importKey(tbsCert[6])
|
||||
return key
|
||||
|
||||
|
||||
def verify_files(filenames, signature_file):
|
||||
"""
|
||||
Verify data files against a detached signature.
|
||||
:param filenames: A list of files containing the data which was signed
|
||||
:param public_key_file: A file containing the public key or certificate
|
||||
corresponding to the key which signed the data
|
||||
:param signature_file: The name of the file containing the signature
|
||||
:return: True if the signature was verified, False otherwise
|
||||
"""
|
||||
|
||||
# Hash the data across all files
|
||||
blocksize=default_blocksize
|
||||
data_hash = SHA256.new()
|
||||
for filename in filenames:
|
||||
with open(filename, 'rb') as infile:
|
||||
data=infile.read(blocksize)
|
||||
while len(data) > 0:
|
||||
data_hash.update(data)
|
||||
data=infile.read(blocksize)
|
||||
|
||||
# Get the signature
|
||||
with open(signature_file, 'rb') as sig_file:
|
||||
signature_bytes = sig_file.read()
|
||||
|
||||
# Verify the signature
|
||||
certificate_list = get_public_certificates()
|
||||
return verify_hash(data_hash, signature_bytes, certificate_list)
|
||||
|
92
cgcs-patch/cgcs-patch/cgcs_patch/templates/query.html
Normal file
92
cgcs-patch/cgcs-patch/cgcs_patch/templates/query.html
Normal file
@ -0,0 +1,92 @@
|
||||
|
||||
<br>
|
||||
% if not pd is UNDEFINED and len(pd) > 0:
|
||||
<table border="2" style="width:300px">
|
||||
<tr>
|
||||
<th>Patch ID</th>
|
||||
<th>Patch Data</th>
|
||||
</tr>
|
||||
|
||||
% for patch_id in sorted(pd.keys()):
|
||||
${patchrow(patch_id)}
|
||||
% endfor
|
||||
</table>
|
||||
% endif
|
||||
|
||||
% if not info is UNDEFINED and len(info) > 0:
|
||||
<p>${info}</p>
|
||||
% endif
|
||||
|
||||
% if not warning is UNDEFINED and len(warning) > 0:
|
||||
<p>Warning:<br>${warning}</p>
|
||||
% endif
|
||||
|
||||
% if not error is UNDEFINED and len(error) > 0:
|
||||
<p>Error:<br>${error}</p>
|
||||
% endif
|
||||
|
||||
<br><br>
|
||||
<a href="/patch/query">Show all</a><br>
|
||||
<a href="/patch/query?show=applied">Show applied</a><br>
|
||||
<a href="/patch/query?show=available">Show available</a><br>
|
||||
<a href="/patch/query_hosts">Query Hosts</a><br>
|
||||
|
||||
<br><br>
|
||||
<form action="/patch/upload" method="POST" enctype="multipart/form-data">
|
||||
<input type="file" name="file"/>
|
||||
<button type="submit">Upload Patch</button>
|
||||
</form>
|
||||
|
||||
<%def name="patchrow(patch_id)">
|
||||
<%
|
||||
p = pd[patch_id]
|
||||
%>
|
||||
<tr>
|
||||
<td valign="top"><a href="/patch/show/${patch_id}">${patch_id}</a></td>
|
||||
<td valign="top">
|
||||
<table border="1" width=100%>
|
||||
% if p["repostate"] != "":
|
||||
<tr><td valign="top">Repo State:</td><td valign="top">${p["repostate"]}</td></tr>
|
||||
% endif
|
||||
% if p["patchstate"] != "":
|
||||
<tr><td valign="top">Patch State:</td><td valign="top">${p["patchstate"]}</td></tr>
|
||||
% endif
|
||||
% if p["status"] != "":
|
||||
<tr><td valign="top">Status:</td><td valign="top">${p["status"]}</td></tr>
|
||||
% endif
|
||||
% if p["unremovable" != ""]:
|
||||
<tr><td valign="top">Unremovable:</td><td valign="top">${p["unremovable"]}</td></tr>
|
||||
% endif
|
||||
% if p["reboot_required" != ""]:
|
||||
<tr><td valign="top">Reboot-Required:</td><td valign="top">${p["reboot_required"]}</td></tr>
|
||||
% endif
|
||||
% if p["summary"] != "":
|
||||
<tr><td valign="top">Summary:</td><td valign="top">${p["summary"]}</td></tr>
|
||||
% endif
|
||||
% if p["description"] != "":
|
||||
<tr><td valign="top">Description:</td><td valign="top">${p["description"]}</td></tr>
|
||||
% endif
|
||||
% if p["install_instructions"] != "":
|
||||
<tr><td valign="top">Install Instructions:</td><td valign="top">${p["install_instructions"]}</td></tr>
|
||||
% endif
|
||||
% if p["warnings"] != "":
|
||||
<tr><td valign="top">Warnings:</td><td valign="top">${p["warnings"]}</td></tr>
|
||||
% endif
|
||||
% if p["repostate"] == "Applied":
|
||||
<tr>
|
||||
<td valign="top">Actions:</td>
|
||||
<td valign="top"><a href="/patch/remove/${patch_id}">Remove</a></td>
|
||||
</tr>
|
||||
% endif
|
||||
% if p["repostate"] == "Available":
|
||||
<tr>
|
||||
<td valign="top">Actions:</td>
|
||||
<td valign="top"><a href="/patch/apply/${patch_id}">Apply</a><br>
|
||||
<a href="/patch/delete/${patch_id}">Delete</a></td>
|
||||
</tr>
|
||||
% endif
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</%def>
|
||||
|
95
cgcs-patch/cgcs-patch/cgcs_patch/templates/query.xml
Executable file
95
cgcs-patch/cgcs-patch/cgcs_patch/templates/query.xml
Executable file
@ -0,0 +1,95 @@
|
||||
% if not pd is UNDEFINED:
|
||||
<pd>
|
||||
% if len(pd) > 0:
|
||||
% for patch_id in sorted(pd.keys()):
|
||||
${patchelem(patch_id)}
|
||||
% endfor
|
||||
% endif
|
||||
</pd>
|
||||
% endif
|
||||
% if not info is UNDEFINED or not warning is UNDEFINED or not error is UNDEFINED:
|
||||
<info>
|
||||
% if not info is UNDEFINED and len(info) > 0:
|
||||
${info}
|
||||
% endif
|
||||
</info>
|
||||
<warning>
|
||||
% if not warning is UNDEFINED and len(warning) > 0:
|
||||
${warning}
|
||||
% endif
|
||||
</warning>
|
||||
<error>
|
||||
% if not error is UNDEFINED and len(error) > 0:
|
||||
${error}
|
||||
% endif
|
||||
</error>
|
||||
% endif
|
||||
<%def name="patchelem(patch_id)">\
|
||||
<%p = pd[patch_id] %>\
|
||||
<patch>
|
||||
<patch_id>
|
||||
${patch_id}
|
||||
</patch_id>
|
||||
<status>
|
||||
% if p["status"] != "":
|
||||
${p["status"]}
|
||||
% endif
|
||||
</status>
|
||||
<sw_version>
|
||||
% if p["sw_version"] != "":
|
||||
${p["sw_version"]}
|
||||
% endif
|
||||
</sw_version>
|
||||
<repostate>
|
||||
% if p["repostate"] != "":
|
||||
${p["repostate"]}
|
||||
% endif
|
||||
</repostate>
|
||||
<patchstate>
|
||||
% if p["patchstate"] != "":
|
||||
${p["patchstate"]}
|
||||
% endif
|
||||
</patchstate>
|
||||
<status>
|
||||
% if p["status"] != "":
|
||||
${p["status"]}
|
||||
% endif
|
||||
</status>
|
||||
<unremovable>
|
||||
% if p["unremovable"] != "":
|
||||
${p["unremovable"]}
|
||||
% endif
|
||||
</unremovable>
|
||||
<reboot_required>
|
||||
% if p["reboot_required"] != "":
|
||||
${p["reboot_required"]}
|
||||
% endif
|
||||
</reboot_required>
|
||||
<summary>
|
||||
% if p["summary"] != "":
|
||||
${p["summary"]}
|
||||
% endif
|
||||
</summary>
|
||||
<description>
|
||||
% if p["description"] != "":
|
||||
${p["description"]}
|
||||
% endif
|
||||
</description>
|
||||
<install_instructions>
|
||||
% if p["install_instructions"] != "":
|
||||
${p["install_instructions"]}
|
||||
% endif
|
||||
</install_instructions>
|
||||
<warnings>
|
||||
% if p["warnings"] != "":
|
||||
${p["warnings"]}
|
||||
% endif
|
||||
</warnings>
|
||||
<requires>
|
||||
% if "requires" in p and len(p["requires"]) > 0:
|
||||
% for req in sorted(p["requires"]):
|
||||
<patch>${req}</patch>
|
||||
% endfor
|
||||
% endif
|
||||
</requires>
|
||||
</patch></%def>
|
32
cgcs-patch/cgcs-patch/cgcs_patch/templates/query_agents.html
Normal file
32
cgcs-patch/cgcs-patch/cgcs_patch/templates/query_agents.html
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
<br>
|
||||
<table border="2" style="width:300px">
|
||||
<tr>
|
||||
<th>Hostname</th>
|
||||
<th>IP</th>
|
||||
<th>Patch Patch?</th>
|
||||
<th>Requires Reboot</th>
|
||||
<th>Time since last ack</th>
|
||||
</tr>
|
||||
|
||||
% for agent in data:
|
||||
${agentrow(agent)}
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
<br><br>
|
||||
<a href="/patch/query">Show all</a><br>
|
||||
<a href="/patch/query?show=applied">Show applied</a><br>
|
||||
<a href="/patch/query?show=available">Show available</a><br>
|
||||
|
||||
|
||||
<%def name="agentrow(agent)">
|
||||
<tr>
|
||||
<td>${agent["ip"]}</td>
|
||||
<td>${agent["hostname"]}</td>
|
||||
<td>${agent["patch_current"]}</td>
|
||||
<td>${agent["requires_reboot"]}</td>
|
||||
<td>${agent["secs_since_ack"]}</td>
|
||||
</tr>
|
||||
</%def>
|
||||
|
75
cgcs-patch/cgcs-patch/cgcs_patch/templates/query_hosts.xml
Executable file
75
cgcs-patch/cgcs-patch/cgcs_patch/templates/query_hosts.xml
Executable file
@ -0,0 +1,75 @@
|
||||
% if not data is UNDEFINED and len(data) > 0:
|
||||
<data>
|
||||
% for host in data:
|
||||
${hostelem(host)}
|
||||
% endfor
|
||||
</data>
|
||||
% endif
|
||||
<%def name="hostelem(host)">\
|
||||
<%h = host %>\
|
||||
<host>
|
||||
<hostname>
|
||||
% if h["hostname"] != "":
|
||||
${h["hostname"]}
|
||||
% endif
|
||||
</hostname>
|
||||
<requires_reboot>
|
||||
% if h["requires_reboot"] != "":
|
||||
${h["requires_reboot"]}
|
||||
% endif
|
||||
</requires_reboot>
|
||||
<nodetype>
|
||||
% if h["nodetype"] != "":
|
||||
${h["nodetype"]}
|
||||
% endif
|
||||
</nodetype>
|
||||
<ip>
|
||||
% if h["ip"] != "":
|
||||
${h["ip"]}
|
||||
% endif
|
||||
</ip>
|
||||
<missing_pkgs>
|
||||
% if "missing_pkgs" in h and len(h["missing_pkgs"]) > 0:
|
||||
% for pkg in sorted(h["missing_pkgs"]):
|
||||
<pkg>${pkg}</pkg>
|
||||
% endfor
|
||||
% endif
|
||||
</missing_pkgs>
|
||||
<installed>
|
||||
% if "installed" in h and len(h["installed"]) > 0:
|
||||
% for pkg in sorted(h["installed"]):
|
||||
<pkg>
|
||||
<name>${pkg}</name>
|
||||
<pkgname>${h["installed"][pkg]}</pkgname>
|
||||
</pkg>
|
||||
% endfor
|
||||
% endif
|
||||
</installed>
|
||||
<to_remove>
|
||||
% if "to_remove" in h and len(h["to_remove"]) > 0:
|
||||
% for pkg in sorted(h["to_remove"]):
|
||||
<pkg>${pkg}</pkg>
|
||||
% endfor
|
||||
% endif
|
||||
</to_remove>
|
||||
<secs_since_ack>
|
||||
% if h["secs_since_ack"] != "":
|
||||
${h["secs_since_ack"]}
|
||||
% endif
|
||||
</secs_since_ack>
|
||||
<patch_failed>
|
||||
% if h["patch_failed"] != "":
|
||||
${h["patch_failed"]}
|
||||
% endif
|
||||
</patch_failed>
|
||||
<stale_details>
|
||||
% if h["stale_details"] != "":
|
||||
${h["stale_details"]}
|
||||
% endif
|
||||
</stale_details>
|
||||
<patch_current>
|
||||
% if h["patch_current"] != "":
|
||||
${h["patch_current"]}
|
||||
% endif
|
||||
</patch_current>
|
||||
</host></%def>
|
83
cgcs-patch/cgcs-patch/cgcs_patch/templates/show.html
Normal file
83
cgcs-patch/cgcs-patch/cgcs_patch/templates/show.html
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
<br>
|
||||
% if not metadata is UNDEFINED and len(metadata) > 0:
|
||||
% for patch_id in sorted(metadata.keys()):
|
||||
${showpatch(patch_id)}
|
||||
% endfor
|
||||
% endif
|
||||
|
||||
% if not info is UNDEFINED and len(info) > 0:
|
||||
<p>${info}</p>
|
||||
% endif
|
||||
|
||||
% if not warning is UNDEFINED and len(warning) > 0:
|
||||
<p>Warning:<br>${warning}</p>
|
||||
% endif
|
||||
|
||||
% if not error is UNDEFINED and len(error) > 0:
|
||||
<p>Error:<br>${error}</p>
|
||||
% endif
|
||||
|
||||
<br><br>
|
||||
<a href="/patch/query">Show all</a><br>
|
||||
<a href="/patch/query?show=applied">Show applied</a><br>
|
||||
<a href="/patch/query?show=available">Show available</a><br>
|
||||
<a href="/patch/query_hosts">Query Hosts</a><br>
|
||||
|
||||
<br><br>
|
||||
<form action="/patch/upload" method="POST" enctype="multipart/form-data">
|
||||
<input type="file" name="file"/>
|
||||
<button type="submit">Upload Patch</button>
|
||||
</form>
|
||||
|
||||
<%def name="showpatch(patch_id)">
|
||||
<%
|
||||
p = metadata[patch_id]
|
||||
%>
|
||||
<h2>${patch_id}</h2>
|
||||
<table border="2">
|
||||
% if p["repostate"] != "":
|
||||
<tr><td valign="top">Repo State:</td><td valign="top">${p["repostate"]}</td></tr>
|
||||
% endif
|
||||
% if p["patchstate"] != "":
|
||||
<tr><td valign="top">Patch State:</td><td valign="top">${p["patchstate"]}</td></tr>
|
||||
% endif
|
||||
% if p["status"] != "":
|
||||
<tr><td valign="top">Status:</td><td valign="top">${p["status"]}</td></tr>
|
||||
% endif
|
||||
% if p["unremovable"] != "":
|
||||
<tr><td valign="top">Unremovable:</td><td valign="top">${p["unremovable"]}</td></tr>
|
||||
% endif
|
||||
% if p["reboot_required"] != "":
|
||||
<tr><td valign="top">Reboot-Required:</td><td valign="top">${p["reboot_required"]}</td></tr>
|
||||
% endif
|
||||
% if p["summary"] != "":
|
||||
<tr><td valign="top">Summary:</td><td valign="top">${p["summary"]}</td></tr>
|
||||
% endif
|
||||
% if p["description"] != "":
|
||||
<tr><td valign="top">Description:</td><td valign="top">${p["description"]}</td></tr>
|
||||
% endif
|
||||
% if p["install_instructions"] != "":
|
||||
<tr><td valign="top">Install Instructions:</td><td valign="top">${p["install_instructions"]}</td></tr>
|
||||
% endif
|
||||
% if p["warnings"] != "":
|
||||
<tr><td valign="top">Warnings:</td><td valign="top">${p["warnings"]}</td></tr>
|
||||
% endif
|
||||
% if "requires" in p and len(p["requires"]) > 0:
|
||||
<tr><td valign="top">Requires:</td><td valign="top">
|
||||
% for req in sorted(p["requires"]):
|
||||
${req}<br>
|
||||
% endfor
|
||||
</td></tr>
|
||||
% endif
|
||||
% if not contents is UNDEFINED and patch_id in contents:
|
||||
<tr><td valign="top">Contents:</td><td valign="top">
|
||||
% for pkg in sorted(contents[patch_id]):
|
||||
${pkg}<br>
|
||||
% endfor
|
||||
</td></tr>
|
||||
% endif
|
||||
|
||||
</table>
|
||||
</%def>
|
||||
|
92
cgcs-patch/cgcs-patch/cgcs_patch/templates/show.xml
Executable file
92
cgcs-patch/cgcs-patch/cgcs_patch/templates/show.xml
Executable file
@ -0,0 +1,92 @@
|
||||
<contents>
|
||||
% if not contents is UNDEFINED and len(contents) > 0:
|
||||
% for patch_id in sorted(contents.keys()):
|
||||
<patch id=${patch_id}>
|
||||
% for pkg in sorted(contents[patch_id]):
|
||||
<pkg>${pkg}</pkg>
|
||||
% endfor
|
||||
</patch>
|
||||
% endfor
|
||||
% endif
|
||||
</contents>
|
||||
<error>
|
||||
% if not error is UNDEFINED and len(error) > 0:
|
||||
${error}
|
||||
% endif
|
||||
</error>
|
||||
<metadata>
|
||||
% if not metadata is UNDEFINED and len(metadata) > 0:
|
||||
% for patch_id in sorted(metadata.keys()):
|
||||
${showpatch(patch_id)}
|
||||
% endfor
|
||||
% endif
|
||||
</metadata>
|
||||
<%def name="showpatch(patch_id)">\
|
||||
<% p = metadata[patch_id] %>\
|
||||
<patch>
|
||||
<patch_id>
|
||||
${patch_id}
|
||||
</patch_id>
|
||||
<status>
|
||||
% if p["status"] != "":
|
||||
${p["status"]}
|
||||
% endif
|
||||
</status>
|
||||
<unremovable>
|
||||
% if p["unremovable"] != "":
|
||||
${p["unremovable"]}
|
||||
% endif
|
||||
</unremovable>
|
||||
<reboot_required>
|
||||
% if p["reboot_required"] != "":
|
||||
${p["reboot_required"]}
|
||||
% endif
|
||||
</reboot_required>
|
||||
<sw_version>
|
||||
% if p["sw_version"] != "":
|
||||
${p["sw_version"]}
|
||||
% endif
|
||||
</sw_version>
|
||||
<repostate>
|
||||
% if p["repostate"] != "":
|
||||
${p["repostate"]}
|
||||
% endif
|
||||
</repostate>
|
||||
<patchstate>
|
||||
% if p["patchstate"] != "":
|
||||
${p["patchstate"]}
|
||||
% endif
|
||||
</patchstate>
|
||||
<status>
|
||||
% if p["status"] != "":
|
||||
${p["status"]}
|
||||
% endif
|
||||
</status>
|
||||
<summary>
|
||||
% if p["summary"] != "":
|
||||
${p["summary"]}
|
||||
% endif
|
||||
</summary>
|
||||
<description>
|
||||
% if p["description"] != "":
|
||||
${p["description"]}
|
||||
% endif
|
||||
</description>
|
||||
<install_instructions>
|
||||
% if p["install_instructions"] != "":
|
||||
${p["install_instructions"]}
|
||||
% endif
|
||||
</install_instructions>
|
||||
<warnings>
|
||||
% if p["warnings"] != "":
|
||||
${p["warnings"]}
|
||||
% endif
|
||||
</warnings>
|
||||
<requires>
|
||||
% if "requires" in p and len(p["requires"]) > 0:
|
||||
% for req in sorted(p["requires"]):
|
||||
<patch>${req}</patch>
|
||||
% endfor
|
||||
% endif
|
||||
</requires>
|
||||
</patch></%def>
|
74
cgcs-patch/cgcs-patch/cgcs_patch/utils.py
Normal file
74
cgcs-patch/cgcs-patch/cgcs_patch/utils.py
Normal file
@ -0,0 +1,74 @@
|
||||
"""
|
||||
Copyright (c) 2016-2017 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
from netaddr import IPAddress
|
||||
import cgcs_patch.constants as constants
|
||||
import socket
|
||||
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
|
||||
libc = ctypes.CDLL(ctypes.util.find_library('c'))
|
||||
|
||||
|
||||
def if_nametoindex(name):
|
||||
return libc.if_nametoindex(name)
|
||||
|
||||
|
||||
def gethostbyname(hostname):
|
||||
""" gethostbyname with IPv6 support """
|
||||
try:
|
||||
return socket.getaddrinfo(hostname, None)[0][4][0]
|
||||
except:
|
||||
return None
|
||||
|
||||
|
||||
def get_management_version():
|
||||
""" Determine whether management is IPv4 or IPv6 """
|
||||
controller_ip_string = gethostbyname(constants.CONTROLLER_FLOATING_HOSTNAME)
|
||||
if controller_ip_string:
|
||||
controller_ip_address = IPAddress(controller_ip_string)
|
||||
return controller_ip_address.version
|
||||
else:
|
||||
return constants.ADDRESS_VERSION_IPV4
|
||||
|
||||
|
||||
def get_management_family():
|
||||
ip_version = get_management_version()
|
||||
if ip_version == constants.ADDRESS_VERSION_IPV6:
|
||||
return socket.AF_INET6
|
||||
else:
|
||||
return socket.AF_INET
|
||||
|
||||
|
||||
def get_versioned_address_all():
|
||||
ip_version = get_management_version()
|
||||
if ip_version == constants.ADDRESS_VERSION_IPV6:
|
||||
return "::"
|
||||
else:
|
||||
return "0.0.0.0"
|
||||
|
||||
|
||||
def ip_to_url(ip_address_string):
|
||||
""" Add brackets if an IPv6 address """
|
||||
try:
|
||||
ip_address = IPAddress(ip_address_string)
|
||||
if ip_address.version == constants.ADDRESS_VERSION_IPV6:
|
||||
return "[%s]" % ip_address_string
|
||||
else:
|
||||
return ip_address_string
|
||||
except:
|
||||
return ip_address_string
|
||||
|
||||
|
||||
def ip_to_versioned_localhost(ip_address_string):
|
||||
""" Add brackets if an IPv6 address """
|
||||
ip_address = IPAddress(ip_address_string)
|
||||
if ip_address.version == constants.ADDRESS_VERSION_IPV6:
|
||||
return "::1"
|
||||
else:
|
||||
return "localhost"
|
34
cgcs-patch/cgcs-patch/cgcs_patch_id/README.txt
Normal file
34
cgcs-patch/cgcs-patch/cgcs_patch_id/README.txt
Normal file
@ -0,0 +1,34 @@
|
||||
Intended to run on a single build server. Currently yow-cgts2-lx
|
||||
|
||||
# On other build servers
|
||||
mkdir -p /localdisk/designer/jenkins/bin
|
||||
cp patch_id_allocator_client.py /localdisk/designer/jenkins/bin
|
||||
|
||||
|
||||
# On the intended server: e.g. yow-cgts2-lx
|
||||
mkdir -p /localdisk/designer/jenkins/bin
|
||||
cp *py /localdisk/designer/jenkins/bin/
|
||||
mkdir -p /localdisk/designer/jenkins/patch_ids
|
||||
sudo cp patch_id_allocator_server.conf /etc/init
|
||||
sudo initctl reload-configuration
|
||||
sudo start script
|
||||
|
||||
# Change to a different server
|
||||
edit patch_id_allocator_client.py
|
||||
change the line ...
|
||||
server = 'yow-cgts2-lx.wrs.com'
|
||||
|
||||
# TODO:
|
||||
Need to back up the /localdisk/designer/jenkins/patch_ids directory
|
||||
|
||||
# Quick test
|
||||
Point your browser at this url:
|
||||
http://yow-cgts2-lx:8888/get_patch_id
|
||||
|
||||
expected result is:
|
||||
CGCS_None_PATCH_0000
|
||||
|
||||
on each reload of the page, the number increments:
|
||||
CGCS_None_PATCH_0001
|
||||
CGCS_None_PATCH_0002
|
||||
....
|
49
cgcs-patch/cgcs-patch/cgcs_patch_id/patch_id_allocator.py
Executable file
49
cgcs-patch/cgcs-patch/cgcs_patch_id/patch_id_allocator.py
Executable file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
import posixfile
|
||||
import string
|
||||
import time
|
||||
|
||||
directory="/localdisk/designer/jenkins/patch_ids"
|
||||
|
||||
def get_unique_id(filename, digits=4):
|
||||
counter = 1
|
||||
path = "%s/%s" % (directory, filename)
|
||||
try:
|
||||
# open for update
|
||||
file = posixfile.open(path, "r+")
|
||||
file.lock("w|", digits)
|
||||
counter = int(file.read(digits)) + 1
|
||||
except IOError:
|
||||
# create it
|
||||
try:
|
||||
file = posixfile.open(path, "w")
|
||||
file.lock("w|", digits)
|
||||
except IOError:
|
||||
print "creation of file '%s' failed" % path
|
||||
return -1
|
||||
|
||||
file.seek(0) # rewind
|
||||
format = "%%0%dd" % digits
|
||||
file.write(format % counter)
|
||||
|
||||
# Note: close releases lock
|
||||
file.close()
|
||||
|
||||
return counter
|
||||
|
||||
def get_patch_id(version, prefix="CGCS", digits=4):
|
||||
filename = "%s_%s_patchid" % (prefix, version)
|
||||
id = get_unique_id(filename)
|
||||
if id < 0:
|
||||
return None
|
||||
patch_id_format = "%%s_%%s_PATCH_%%0%dd" % digits
|
||||
patch_id = patch_id_format % (prefix, version, id)
|
||||
return patch_id
|
||||
|
57
cgcs-patch/cgcs-patch/cgcs_patch_id/patch_id_allocator_client.py
Executable file
57
cgcs-patch/cgcs-patch/cgcs_patch_id/patch_id_allocator_client.py
Executable file
@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import urllib
|
||||
import urllib2
|
||||
import getopt
|
||||
import sys
|
||||
|
||||
|
||||
opts = ['sw_version=', 'prefix=' ]
|
||||
|
||||
server = 'yow-cgts2-lx.wrs.com'
|
||||
port = 8888
|
||||
|
||||
def request_patch_id(sw_version="1.01", prefix="CGCS"):
|
||||
raw_parms = {}
|
||||
raw_parms['sw_version'] = sw_version
|
||||
raw_parms['prefix'] = prefix
|
||||
print "raw_parms = %s" % str(raw_parms)
|
||||
|
||||
url = "http://%s:%d/get_patch_id" % (server, port)
|
||||
params = urllib.urlencode(raw_parms)
|
||||
response = urllib2.urlopen(url, params).read()
|
||||
return response
|
||||
|
||||
def main():
|
||||
optlist, remainder = getopt.getopt(sys.argv[1:], '', opts)
|
||||
|
||||
sw_version = None
|
||||
prefix = None
|
||||
raw_parms = {}
|
||||
|
||||
print "optlist = %s" % str(optlist)
|
||||
print "remainder = %s" % str(remainder)
|
||||
for key, val in optlist:
|
||||
print "key = %s, val = %s" % (key, val)
|
||||
if key == '--sw_version':
|
||||
sw_version = val
|
||||
print "sw_version = %s" % sw_version
|
||||
raw_parms['sw_version'] = sw_version
|
||||
|
||||
if key == '--prefix':
|
||||
prefix = val
|
||||
print "prefix = %s" % prefix
|
||||
raw_parms['prefix'] = prefix
|
||||
|
||||
# response = request_patch_id(sw_version=sw_version, prefix=prefix)
|
||||
response = request_patch_id(**raw_parms)
|
||||
print "response = %s" % str(response)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -0,0 +1,16 @@
|
||||
# upstart script for patch_id_allocator_server
|
||||
#
|
||||
# Intallation
|
||||
# sudo cp patch_id_allocator_server.conf /etc/init
|
||||
# sudo initctl reload-configuration
|
||||
# sudo start script
|
||||
|
||||
description "patch_id service"
|
||||
author "Scott Little <scott.little@windriver.com>"
|
||||
|
||||
start on runlevel [234]
|
||||
stop on runlevel [0156]
|
||||
|
||||
chdir /tmp
|
||||
exec /localdisk/designer/jenkins/bin/patch_id_allocator_server.py
|
||||
respawn
|
43
cgcs-patch/cgcs-patch/cgcs_patch_id/patch_id_allocator_server.py
Executable file
43
cgcs-patch/cgcs-patch/cgcs_patch_id/patch_id_allocator_server.py
Executable file
@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013-2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import web
|
||||
import patch_id_allocator as pida
|
||||
|
||||
|
||||
|
||||
port = 8888
|
||||
|
||||
urls = (
|
||||
'/get_patch_id', 'get_patch_id',
|
||||
)
|
||||
|
||||
class get_patch_id:
|
||||
def GET(self):
|
||||
data = web.input(sw_version=None, prefix="CGCS")
|
||||
output = pida.get_patch_id(data.sw_version, data.prefix)
|
||||
return output
|
||||
|
||||
def POST(self):
|
||||
data = web.input(sw_version=None, prefix="CGCS")
|
||||
output = pida.get_patch_id(data.sw_version, data.prefix)
|
||||
return output
|
||||
|
||||
class MyApplication(web.application):
|
||||
def run(self, port=8080, *middleware):
|
||||
func = self.wsgifunc(*middleware)
|
||||
return web.httpserver.runsimple(func, ('0.0.0.0', port))
|
||||
|
||||
def main():
|
||||
app = MyApplication(urls, globals())
|
||||
app.run(port=port)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
20
cgcs-patch/cgcs-patch/setup.py
Normal file
20
cgcs-patch/cgcs-patch/setup.py
Normal file
@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2013-2015 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(name='cgcs_patch',
|
||||
version='1.0',
|
||||
description='CGCS Patch',
|
||||
packages=setuptools.find_packages(),
|
||||
package_data = {
|
||||
# Include templates
|
||||
'': ['templates/*'],
|
||||
}
|
||||
)
|
||||
|
712
cgcs-patch/restart-info.html
Executable file
712
cgcs-patch/restart-info.html
Executable file
@ -0,0 +1,712 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
table, th, td {
|
||||
border: 1px solid black;
|
||||
border-collapse: collapse;
|
||||
padding: 10px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<caption>
|
||||
<font size=10>Process restart information</font>
|
||||
</caption>
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Process/Service</th>
|
||||
<th>Function</th>
|
||||
<th>In service patchable</th>
|
||||
<th>Managed by</th>
|
||||
<th>Restart command</th>
|
||||
<th>Patch Restart command</th>
|
||||
<th>Restart dependency</th>
|
||||
<th>Impact(if restarted while in operation)</th>
|
||||
<th>Special handling required</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tr>
|
||||
<td><font color="blue">ceilometer-polling</font></td>
|
||||
<td>Daemon that polls Openstack services and build meters</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/init.d/openstack-ceilometer-polling restart</b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>As batch_polled_samples is set to True, may lose some samples that
|
||||
are in the pollsters memory if the process is restarted exactly
|
||||
when they have just finished polling for samples and are about to
|
||||
publish these samples to RabbitMQ. This is about 10 millisecond
|
||||
window for cpu_source and 0.03 millisecond 1 second window for
|
||||
meter related sources.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">ceilometer-agent-notification</font></td>
|
||||
<td>Daemon that listens to notifications on message queue, converts
|
||||
them to Events and Samples and applies pipeline actions
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service ceilometer-agent-notification</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/ceilometer-agent-notification stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/ceilometer-agent-notification start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>May lose some samples/events if the process is restarted while they
|
||||
are being transformed or converted.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">ceilometer-collector</font></td>
|
||||
<td>Daemon that gathers and records event and metering data created by
|
||||
notification and polling agents
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service ceilometer-collector</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/ceilometer-collector stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/ceilometer-collector
|
||||
start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>May lose some samples/events if the process is restarted while they
|
||||
are being persisted in Postgres DB. This is a tiny window
|
||||
especially with recent optimization work (no message signature
|
||||
verification, one single call to create_sample stored proc).<br>
|
||||
Note: Making sure that child processes and their database
|
||||
connections are released when a parent process is stopped is part
|
||||
of collector functionality. It is not specific to in-service
|
||||
patching.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">ceilometer-api</font></td>
|
||||
<td>Service to query and view data recorded by the collector</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service ceilometer-api</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/ceilometer-api stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/ceilometer-api start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, horizon or CLI ceilometer request
|
||||
will fail. Horizon request will be re-established automatically in
|
||||
its next polling interval. CLI command needs to be re-issued.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">ceilometer-expirer-active</font></td>
|
||||
<td>Cron job that purges expired samples and events as well as related
|
||||
meter and resource data
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>CRON</td>
|
||||
<td><b>N/A</b><br><br>
|
||||
To run the expirer manually: /usr/bin/ceilometer-expirer-active
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>There is no need to restart after patch. The change will take
|
||||
effect next time the expirer cron job is run.<br>
|
||||
Unless there are new features specifically planned for expirer,
|
||||
this code is very stable.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">haproxy</font></td>
|
||||
<td>A Proxy service that is responsible for forwarding external REST
|
||||
API requests to Open Stack and Titanium Cloud services that listening on the
|
||||
internal interfaces.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service haproxy</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /etc/init.d/haproxy stop<br>
|
||||
/bin/sh /etc/init.d/haproxy start
|
||||
</td>
|
||||
<td><b>/usr/local/sbin/patch-restart-haproxy</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will fail
|
||||
and new requests will get connection error until the service is
|
||||
re-enabled.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">sm</font></td>
|
||||
<td>Service management daemon</td>
|
||||
<td>N</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/init.d/sm restart</b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>Will cause all services disabled on the active controller before
|
||||
the standby controller takes over the control.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">sm-api</font></td>
|
||||
<td>Daemon that provides sm api</td>
|
||||
<td>N</td>
|
||||
<td>PMON</td>
|
||||
<td><b></b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td></td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">sm-eru</font></td>
|
||||
<td>Daemon that records sm eru data</td>
|
||||
<td>N</td>
|
||||
<td></td>
|
||||
<td><b></b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td></td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">sm-watchdog</font></td>
|
||||
<td>Daemon that loads NFS watchdog module to look for and handle
|
||||
stalled NFS threads
|
||||
</td>
|
||||
<td>N</td>
|
||||
<td></td>
|
||||
<td><b></b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td></td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">neutron-server</font></td>
|
||||
<td>Service that manages network functions</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service neutron-server</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/neutron-server stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/neutron-server start
|
||||
</td>
|
||||
<td><b>/bin/neutron-restart neutron-server</b><br/>or<br/><b>/bin/neutron-restart --all</b></td>
|
||||
<td>N</td>
|
||||
<td>Will cause neutron services to not be available while restarting,
|
||||
which will prevent instances from being created while it is down.
|
||||
Could cause RPCs from computes to fail while it is restarting.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">neutron-dhcp-agent</font></td>
|
||||
<td>Agent on compute node that manages DHCP servers for tenant
|
||||
networks
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/init.d/neutron-dhcp-agent restart</b></td>
|
||||
<td><b>/bin/neutron-restart neutron-dhcp-agent</b><br/>or<br/><b>/bin/neutron-restart --all</b></td>
|
||||
<td>N</td>
|
||||
<td>Will prevent binding new DHCP servers while it is down. Requires
|
||||
special handling to kill metadata haproxy processes for networks.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">neutron-metadata-agent</font></td>
|
||||
<td>Agent on compute node serving metadata to nodes</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/init.d/neutron-metadata-agent restart</b></td>
|
||||
<td><b>/bin/neutron-restart neutron-metadata-agent</b><br/>or<br/><b>/bin/neutron-restart --all</b></td>
|
||||
<td>N</td>
|
||||
<td>Nodes will not be able to receive metadata while it is down</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">neutron-sriov-nic-agent</font></td>
|
||||
<td>Agent on compute node responsible for setting SR-IOV port
|
||||
information
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/init.d/neutron-sriov-nic-agent restart</b></td>
|
||||
<td><b>/bin/neutron-restart neutron-sriov-nic-agent</b><br/>or<br/><b>/bin/neutron-restart --all</b></td>
|
||||
<td>N</td>
|
||||
<td>Will not be able to set device parameters while restarting</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">neutron-bgp-dragent</font></td>
|
||||
<td>BGP dynamic routing agent on controller node
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/init.d/neutron-bgp-dragent restart</b></td>
|
||||
<td><b>/bin/neutron-restart neutron-bgp-dragent</b><br/>or<br/><b>/bin/neutron-restart --all</b></td>
|
||||
<td>N</td>
|
||||
<td>Will not be able to set device parameters while restarting</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">keystone-all</font></td>
|
||||
<td>Keystone provides services that support an identity, token
|
||||
management, and service catalog and policy functionality.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service keystone</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/keystone stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/keystone start
|
||||
</td>
|
||||
<td><b>/usr/local/sbin/patch-restart-processes keystone-all</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will fail
|
||||
and new requests will get connection error until the service is
|
||||
re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">aodh-api</font></td>
|
||||
<td>Aodh service that handles API requests for openstack alarming.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service aodh-api</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-api stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-api start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will fail
|
||||
and new requests will get connection error until the service is
|
||||
re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">aodh-evaluator</font></td>
|
||||
<td>Aodh service that performs threshold evaluation for openstack
|
||||
alarming.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service aodh-evaluator</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-evaluator stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-evaluator start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted no openstack alarm threshold
|
||||
evaluations will be executed until the service is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">aodh-listener</font></td>
|
||||
<td>Aodh service that generates alarms based on events.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service aodh-listener</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-listener stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-listener start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted no openstack event based alarms will
|
||||
be generated until the service is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">aodh-notifier</font></td>
|
||||
<td>Aodh service that sends openstack alarm notifications.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service aodh-notifier</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-notifier stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/aodh-notifier start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted no openstack alarm threshold
|
||||
notifications will be issued until the service is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">aodh-expirer-active</font></td>
|
||||
<td>Cron job that purges expired openstack alarms</td>
|
||||
<td>Y</td>
|
||||
<td>CRON</td>
|
||||
<td><b>N/A</b><br><br>
|
||||
To run the expirer manually: /usr/bin/aodh-expirer-active
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>There is no need to restart after patch. The change will take
|
||||
effect next time the expirer cron job is run.<br>
|
||||
Unless there are new features specifically planned for expirer,
|
||||
this code is very stable.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">heat-api</font></td>
|
||||
<td>Heat service for API requests for openstack orchestration.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service heat-api</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-api stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-api start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, horizon or CLI heat requests will
|
||||
fail. Horizon will re-established automatically. CLI commands needs
|
||||
to be re-issued. Heat stack updates in progress may fail.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">heat-api-cfn</font></td>
|
||||
<td>Heat service for AWS Cloudformation API requests.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service heat-api-cfn</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-api-cfn stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-api-cfn start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, cloudformation API requests such as
|
||||
autoscaling will not be processed.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">heat-api-cloudwatch</font></td>
|
||||
<td>Heat service for AWS Cloudwatch metric collection.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service heat-api-cloudwatch</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-api-cloudwatch stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-api-cloudwatch start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, stats sent from VMs will not be
|
||||
processed.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">heat-engine</font></td>
|
||||
<td>Heat service for AWS Cloudwatch metric collection.</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service heat-engine</b><br>
|
||||
which runs the following:<br><br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-engine stop<br>
|
||||
/bin/sh /usr/lib/ocf/resource.d/openstack/heat-engine start
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, openstrack heat orchestration
|
||||
commands will not be processed. Stacks being created, deleted or
|
||||
updated will fail and need to be re-initiated.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">heat-purge-deleted-active</font></td>
|
||||
<td>Cron job that purges deleted openstack heat stacks from the
|
||||
database
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>CRON</td>
|
||||
<td><b>N/A</b><br><br>
|
||||
To run the expirer manually: /usr/bin/heat-purge-deleted-active
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>There is no need to restart after patch. The change will take
|
||||
effect next time the cron job is run.<br>
|
||||
Unless there are new features specifically planned, this code is
|
||||
very stable.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">Glance</font></td>
|
||||
<td>Glance imaging service - a single script restarts both glance-api
|
||||
and glance-registry.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>/usr/bin/restart-glance</b><br>
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
continue and new requests will get connection error until the
|
||||
service is re-enabled. The graceful restart takes more than 30
|
||||
secs the process is killed. Timers are configurable from the
|
||||
restart script
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">Cinder</font></td>
|
||||
<td>Cinder volume service - a single script restarts cinder-volume,
|
||||
cinder-scheduler and cinder-api.
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>/usr/bin/restart-cinder</b><br>
|
||||
</td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
continue and new requests will get connection error until the
|
||||
service is re-enabled. Timers are configurable from the restart
|
||||
script
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">Horizon</font></td>
|
||||
<td>Horizon - Openstack Dashboard GUI used to control openstack and Titanium Cloud
|
||||
operations
|
||||
</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart service horizon</b><br>
|
||||
</td>
|
||||
<td><b>/usr/bin/horizon-patching-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>When horizon is restarted via the patch restart command all users
|
||||
will be logged out. If they try to log back in before the server is
|
||||
up again they will see an internal server error. It usually takes
|
||||
less than a minute for the service to restart
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">IO-Monitor</font></td>
|
||||
<td>Daemon which monitors cinder devices and raises alarms for excessive storage IO load.</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>pmon-restart io-monitor-manager</b></td>
|
||||
<td><b>/usr/local/sbin/patch-restart-processes io-monitor-manager</b></td>
|
||||
<td>N</td>
|
||||
<td>Generally there should be no impact. It is very unlikely for
|
||||
the system to encounter an excessive storage IO load which will
|
||||
only last a couple of seconds until the io-monitor process is restarted,
|
||||
such that it will not be detected.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">vim</font></td>
|
||||
<td>Virtual Infrastructure Manager</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service vim</b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarting, requests through the VIM API or
|
||||
through the Nova API Proxy will fail. Any instance actions normally
|
||||
triggered due to instance state changes (from nova) will not occur
|
||||
until the process starts up again and audits the instance states.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">vim-api</font></td>
|
||||
<td>Virtual Infrastructure Manager API</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service vim-api</b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarting, requests through the external VIM
|
||||
API will fail.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">vim-webserver</font></td>
|
||||
<td>Virtual Infrastructure Manager Web Server</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service vim-webserver</b></td>
|
||||
<td><b></b></td>
|
||||
<td>N</td>
|
||||
<td>No impact. This service is for design use only.</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-api</font></td>
|
||||
<td>Nova API Service</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service nova-api</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-placement-api</font></td>
|
||||
<td>Nova Placement API Service</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service nova-placement-api</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-conductor</font></td>
|
||||
<td>Nova Conductor Service</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service nova-conductor</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-scheduler</font></td>
|
||||
<td>Nova Scheduler Service</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service nova-scheduler</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-console-auth</font></td>
|
||||
<td>Nova Console Auth Service</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service nova-console-auth</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-novnc</font></td>
|
||||
<td>Nova VNC Service</td>
|
||||
<td>Y</td>
|
||||
<td>SM</td>
|
||||
<td><b>sm-restart-safe service nova-novnc</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the service is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">nova-compute</font></td>
|
||||
<td>Nova Compute Service</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/usr/local/sbin/pmon-restart nova-compute</b><br></td>
|
||||
<td><b>/bin/nova-restart</b></td>
|
||||
<td>N</td>
|
||||
<td>While the services is restarted, the outstanding requests will
|
||||
fail and new requests will get connection error until the service
|
||||
is re-enabled.
|
||||
</td>
|
||||
<td>N</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><font color="blue">ceph-osd & ceph-mon</font></td>
|
||||
<td>Ceph OSD and Monitor processes</td>
|
||||
<td>Y</td>
|
||||
<td>PMON</td>
|
||||
<td><b>/etc/ceph/ceph_pmon_wrapper.sh restart</b><br></td>
|
||||
<td><b>/etc/ceph/ceph_pmon_wrapper.sh restart</b></td>
|
||||
<td>N</td>
|
||||
<td>Ceph processes on a node will restart (ceph-mon and ceph-osd). The restart
|
||||
will take at most 30s and functionality should not be affected. Note that this
|
||||
command should not be executed at the same time on storage-0 and any of the
|
||||
controller nodes as we do not support restarting two of the three ceph-mon at
|
||||
the same time.
|
||||
</td>
|
||||
<td>Restarting it on controller-0, controller-1 & storage-0,
|
||||
at the same time with glance, cinder, nova, ceph-rest-api, sysinv or ceph-manager
|
||||
on the active controller should be avoided due to ~30 secs delay to ceph APIs.
|
||||
This delay happens when any of the ceph-mon changes state and may cause timeouts
|
||||
when dependent services restart. Recommendations: (1) On the active controller,
|
||||
restart Ceph before the other service; (2) updating ctrl-0,ctrl-1 & storage-0
|
||||
at the same time should be avoided.</td>
|
||||
</tr>
|
||||
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th>Process/Service</th>
|
||||
<th>Function</th>
|
||||
<th>In service patchable</th>
|
||||
<th>Managed by</th>
|
||||
<th>Restart command</th>
|
||||
<th>Patch Restart command</th>
|
||||
<th>Restart dependency</th>
|
||||
<th>Impact(if restarted while in operation)</th>
|
||||
<th>Special handling required</th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
10
mwa-chilon.map
Normal file
10
mwa-chilon.map
Normal file
@ -0,0 +1,10 @@
|
||||
cgcs/middleware/sysinv/recipes-common|sysinv
|
||||
cgcs/middleware/patching/recipes-common/cgcs-patch|cgcs-patch
|
||||
cgcs/middleware/patching/recipes-common/patch-alarm|patch-alarm
|
||||
cgcs/middleware/patching/recipes-common/patch-boot-args|patch-boot-args
|
||||
cgcs/middleware/patching/recipes-common/patch-scripts|patch-scripts
|
||||
cgcs/middleware/patching/recipes-common/requests-toolbelt|requests-toolbelt
|
||||
cgcs/middleware/patching/recipes-common/smart-helper|smart-helper
|
||||
cgcs/middleware/config/recipes-compute/computeconfig/computeconfig|computeconfig
|
||||
cgcs/middleware/config/recipes-control/controllerconfig/controllerconfig|controllerconfig
|
||||
cgcs/middleware/config/recipes-common/tsconfig|tsconfig
|
202
patch-alarm/LICENSE
Normal file
202
patch-alarm/LICENSE
Normal 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.
|
13
patch-alarm/PKG-INFO
Normal file
13
patch-alarm/PKG-INFO
Normal file
@ -0,0 +1,13 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: patch-alarm
|
||||
Version: 1.0
|
||||
Summary: Patch alarm management
|
||||
Home-page:
|
||||
Author: Windriver
|
||||
Author-email: info@windriver.com
|
||||
License: Apache-2.0
|
||||
|
||||
Description: Patch alarm management
|
||||
|
||||
|
||||
Platform: UNKNOWN
|
95
patch-alarm/centos/build_srpm
Executable file
95
patch-alarm/centos/build_srpm
Executable file
@ -0,0 +1,95 @@
|
||||
source "$SRC_BASE/build-tools/spec-utils"
|
||||
|
||||
if [ "x$DATA" == "x" ]; then
|
||||
echo "ERROR: Environment variable 'DATA' not defined."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$DATA" ]; then
|
||||
echo "ERROR: Couldn't find '$PWD/$DATA'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
unset TIS_PATCH_VER # Ensure there's nothing in the env already
|
||||
|
||||
source $DATA
|
||||
|
||||
if [ -z "$TIS_PATCH_VER" ]; then
|
||||
echo "ERROR: TIS_PATCH_VER must be defined"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SRC_DIR="patch-alarm"
|
||||
EXTRA_DIR="scripts"
|
||||
|
||||
VERSION=$(grep '^Version:' PKG-INFO | awk -F ': ' '{print $2}' | sed -e 's/^[[:space:]]*//')
|
||||
TAR_NAME=$(grep '^Name:' PKG-INFO | awk -F ': ' '{print $2}' | sed -e 's/^[[:space:]]*//')
|
||||
CUR_DIR=`pwd`
|
||||
BUILD_DIR="$RPMBUILD_BASE"
|
||||
|
||||
mkdir -p $BUILD_DIR/SRPMS
|
||||
|
||||
TAR="$TAR_NAME-$VERSION.tar.gz"
|
||||
TAR_PATH="$BUILD_DIR/SOURCES/$TAR"
|
||||
|
||||
TAR_NEEDED=0
|
||||
if [ -f $TAR_PATH ]; then
|
||||
n=`find . -cnewer $TAR_PATH -and ! -path './.git*' \
|
||||
-and ! -path './build/*' \
|
||||
-and ! -path './.pc/*' \
|
||||
-and ! -path './patches/*' \
|
||||
-and ! -path "./$DISTRO/*" \
|
||||
-and ! -path './pbr-*.egg/*' \
|
||||
| wc -l`
|
||||
if [ $n -gt 0 ]; then
|
||||
TAR_NEEDED=1
|
||||
fi
|
||||
else
|
||||
TAR_NEEDED=1
|
||||
fi
|
||||
|
||||
if [ $TAR_NEEDED -gt 0 ]; then
|
||||
tar czvf $TAR_PATH $SRC_DIR $EXTRA_DIR \
|
||||
--exclude='.git*' \
|
||||
--exclude='build' \
|
||||
--exclude='.pc' \
|
||||
--exclude='patches' \
|
||||
--exclude="$DISTRO" \
|
||||
--exclude='pbr-*.egg' \
|
||||
--transform "s,^$SRC_DIR,$TAR_NAME-$VERSION,"
|
||||
fi
|
||||
|
||||
|
||||
for SPEC in `ls $BUILD_DIR/SPECS`; do
|
||||
SPEC_PATH="$BUILD_DIR/SPECS/$SPEC"
|
||||
RELEASE=`spec_find_tag Release "$SPEC_PATH" 2>> /dev/null`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: 'Release' not found in '$SPEC_PATH'"
|
||||
fi
|
||||
NAME=`spec_find_tag Name "$SPEC_PATH" 2>> /dev/null`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: 'Name' not found in '$SPEC_PATH'"
|
||||
fi
|
||||
SRPM="$NAME-$VERSION-$RELEASE.src.rpm"
|
||||
SRPM_PATH="$BUILD_DIR/SRPMS/$SRPM"
|
||||
|
||||
BUILD_NEEDED=0
|
||||
if [ -f $SRPM_PATH ]; then
|
||||
n=`find . -cnewer $SRPM_PATH | wc -l`
|
||||
if [ $n -gt 0 ]; then
|
||||
BUILD_NEEDED=1
|
||||
fi
|
||||
else
|
||||
BUILD_NEEDED=1
|
||||
fi
|
||||
|
||||
if [ $BUILD_NEEDED -gt 0 ]; then
|
||||
echo "SPEC file: $SPEC_PATH"
|
||||
echo "SRPM build directory: $BUILD_DIR"
|
||||
echo "TIS_PATCH_VER: $TIS_PATCH_VER"
|
||||
|
||||
sed -i -e "1 i%define tis_patch_ver $TIS_PATCH_VER" $SPEC_PATH
|
||||
rpmbuild -bs $SPEC_PATH --define="%_topdir $BUILD_DIR" --define="_tis_dist .tis"
|
||||
fi
|
||||
done
|
||||
|
1
patch-alarm/centos/build_srpm.data
Normal file
1
patch-alarm/centos/build_srpm.data
Normal file
@ -0,0 +1 @@
|
||||
TIS_PATCH_VER=2
|
55
patch-alarm/centos/patch-alarm.spec
Normal file
55
patch-alarm/centos/patch-alarm.spec
Normal file
@ -0,0 +1,55 @@
|
||||
Summary: Patch alarm management
|
||||
Name: patch-alarm
|
||||
Version: 1.0
|
||||
Release: %{tis_patch_ver}%{?_tis_dist}
|
||||
License: Apache-2.0
|
||||
Group: base
|
||||
Packager: Wind River <info@windriver.com>
|
||||
URL: unknown
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
|
||||
%define debug_package %{nil}
|
||||
|
||||
BuildRequires: python-setuptools
|
||||
Requires: python-devel
|
||||
Requires: /bin/bash
|
||||
|
||||
%description
|
||||
TIS Platform Patching
|
||||
|
||||
%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
|
||||
|
||||
install -m 755 -d %{buildroot}%{_bindir}
|
||||
install -m 755 -d %{buildroot}%{_sysconfdir}/init.d
|
||||
|
||||
install -m 700 ${RPM_BUILD_DIR}/scripts/bin/patch-alarm-manager \
|
||||
%{buildroot}%{_bindir}/patch-alarm-manager
|
||||
|
||||
install -m 700 ${RPM_BUILD_DIR}/scripts/init.d/patch-alarm-manager \
|
||||
%{buildroot}%{_sysconfdir}/init.d/patch-alarm-manager
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc LICENSE
|
||||
%{pythonroot}/patch_alarm
|
||||
%{pythonroot}/patch_alarm-*.egg-info
|
||||
"%{_bindir}/patch-alarm-manager"
|
||||
"%{_sysconfdir}/init.d/patch-alarm-manager"
|
||||
|
202
patch-alarm/patch-alarm/LICENSE
Normal file
202
patch-alarm/patch-alarm/LICENSE
Normal 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.
|
6
patch-alarm/patch-alarm/patch_alarm/__init__.py
Normal file
6
patch-alarm/patch-alarm/patch_alarm/__init__.py
Normal file
@ -0,0 +1,6 @@
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
223
patch-alarm/patch-alarm/patch_alarm/patch_alarm_manager.py
Normal file
223
patch-alarm/patch-alarm/patch_alarm/patch_alarm_manager.py
Normal file
@ -0,0 +1,223 @@
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
###################
|
||||
# IMPORTS
|
||||
###################
|
||||
import logging
|
||||
import time
|
||||
import requests
|
||||
import json
|
||||
import os
|
||||
|
||||
from daemon import runner
|
||||
from fm_api import fm_api
|
||||
from fm_api import constants as fm_constants
|
||||
|
||||
import cgcs_patch.config as cfg
|
||||
from cgcs_patch.patch_functions import configure_logging
|
||||
from cgcs_patch.constants import ENABLE_DEV_CERTIFICATE_PATCH_IDENTIFIER
|
||||
|
||||
###################
|
||||
# CONSTANTS
|
||||
###################
|
||||
LOG_FILE = '/var/log/patch-alarms.log'
|
||||
PID_FILE = '/var/run/patch-alarm-manager.pid'
|
||||
|
||||
#logging.basicConfig(filename=LOG_FILE, level=logging.DEBUG)
|
||||
|
||||
|
||||
###################
|
||||
# METHODS
|
||||
###################
|
||||
def start_polling():
|
||||
cfg.read_config()
|
||||
patch_alarm_daemon = PatchAlarmDaemon()
|
||||
alarm_runner = runner.DaemonRunner(patch_alarm_daemon)
|
||||
alarm_runner.daemon_context.umask = 0o022
|
||||
alarm_runner.do_action()
|
||||
|
||||
|
||||
###################
|
||||
# CLASSES
|
||||
###################
|
||||
class PatchAlarmDaemon():
|
||||
""" Daemon process representation of
|
||||
the patch monitoring program
|
||||
"""
|
||||
def __init__(self):
|
||||
# Daemon-specific init
|
||||
self.stdin_path = '/dev/null'
|
||||
self.stdout_path = '/dev/null'
|
||||
self.stderr_path = '/dev/null'
|
||||
self.pidfile_path = PID_FILE
|
||||
self.pidfile_timeout = 5
|
||||
|
||||
self.api_addr = "127.0.0.1:%d" % cfg.api_port
|
||||
|
||||
self.fm_api = fm_api.FaultAPIs()
|
||||
|
||||
def run(self):
|
||||
configure_logging()
|
||||
|
||||
requests_logger = logging.getLogger('requests')
|
||||
requests_logger.setLevel(logging.CRITICAL)
|
||||
|
||||
while True:
|
||||
# start monitoring patch status
|
||||
self.check_patch_alarms()
|
||||
|
||||
# run/poll every 1 min
|
||||
time.sleep(60)
|
||||
|
||||
def check_patch_alarms(self):
|
||||
self._handle_patch_alarms()
|
||||
self._get_handle_failed_hosts()
|
||||
|
||||
def _handle_patch_alarms(self):
|
||||
url = "http://%s/patch/query" % self.api_addr
|
||||
|
||||
try:
|
||||
req = requests.get(url)
|
||||
except:
|
||||
return
|
||||
|
||||
entity_instance_id = "%s=%s" % (fm_constants.FM_ENTITY_TYPE_HOST, "controller")
|
||||
|
||||
raise_pip_alarm = False
|
||||
raise_obs_alarm = False
|
||||
raise_cert_alarm = False
|
||||
if req.status_code == 200:
|
||||
data = json.loads(req.text)
|
||||
|
||||
if 'pd' in data:
|
||||
for patch_id, metadata in data['pd'].iteritems():
|
||||
if 'patchstate' in metadata and \
|
||||
(metadata['patchstate'] == 'Partial-Apply' or metadata['patchstate'] == 'Partial-Remove'):
|
||||
raise_pip_alarm = True
|
||||
if 'status' in metadata and \
|
||||
(metadata['status'] == 'OBS' or metadata['status'] == 'Obsolete'):
|
||||
raise_obs_alarm = True
|
||||
# If there is a patch in the system (in any state) that is
|
||||
# named some variation of "enable-dev-certificate", raise
|
||||
# the 'developer certificate could allow for untrusted
|
||||
# patches' alarm
|
||||
if ENABLE_DEV_CERTIFICATE_PATCH_IDENTIFIER in patch_id:
|
||||
raise_cert_alarm = True
|
||||
|
||||
pip_alarm = self.fm_api.get_fault(fm_constants.FM_ALARM_ID_PATCH_IN_PROGRESS,
|
||||
entity_instance_id)
|
||||
if raise_pip_alarm and pip_alarm is None:
|
||||
logging.info("Raising patch-in-progress alarm")
|
||||
fault = fm_api.Fault(alarm_id = fm_constants.FM_ALARM_ID_PATCH_IN_PROGRESS,
|
||||
alarm_type = fm_constants.FM_ALARM_TYPE_5,
|
||||
alarm_state = fm_constants.FM_ALARM_STATE_SET,
|
||||
entity_type_id = fm_constants.FM_ENTITY_TYPE_HOST,
|
||||
entity_instance_id = entity_instance_id,
|
||||
severity = fm_constants.FM_ALARM_SEVERITY_MINOR,
|
||||
reason_text = 'Patching operation in progress',
|
||||
probable_cause = fm_constants.ALARM_PROBABLE_CAUSE_65,
|
||||
proposed_repair_action = 'Complete reboots of affected hosts',
|
||||
service_affecting = False)
|
||||
|
||||
self.fm_api.set_fault(fault)
|
||||
elif not raise_pip_alarm and pip_alarm is not None:
|
||||
logging.info("Clearing patch-in-progress alarm")
|
||||
self.fm_api.clear_fault(fm_constants.FM_ALARM_ID_PATCH_IN_PROGRESS,
|
||||
entity_instance_id)
|
||||
|
||||
obs_alarm = self.fm_api.get_fault(fm_constants.FM_ALARM_ID_PATCH_OBS_IN_SYSTEM,
|
||||
entity_instance_id)
|
||||
if raise_obs_alarm and obs_alarm is None:
|
||||
logging.info("Raising obsolete-patch-in-system alarm")
|
||||
fault = fm_api.Fault(alarm_id = fm_constants.FM_ALARM_ID_PATCH_OBS_IN_SYSTEM,
|
||||
alarm_type = fm_constants.FM_ALARM_TYPE_5,
|
||||
alarm_state = fm_constants.FM_ALARM_STATE_SET,
|
||||
entity_type_id = fm_constants.FM_ENTITY_TYPE_HOST,
|
||||
entity_instance_id = entity_instance_id,
|
||||
severity = fm_constants.FM_ALARM_SEVERITY_WARNING,
|
||||
reason_text = 'Obsolete patch in system',
|
||||
probable_cause = fm_constants.ALARM_PROBABLE_CAUSE_65,
|
||||
proposed_repair_action = 'Remove and delete obsolete patches',
|
||||
service_affecting = False)
|
||||
|
||||
self.fm_api.set_fault(fault)
|
||||
elif not raise_obs_alarm and obs_alarm is not None:
|
||||
logging.info("Clearing obsolete-patch-in-system alarm")
|
||||
self.fm_api.clear_fault(fm_constants.FM_ALARM_ID_PATCH_OBS_IN_SYSTEM,
|
||||
entity_instance_id)
|
||||
|
||||
cert_alarm = self.fm_api.get_fault(fm_constants.FM_ALARM_ID_NONSTANDARD_CERT_PATCH,
|
||||
entity_instance_id)
|
||||
if raise_cert_alarm and cert_alarm is None:
|
||||
logging.info("Raising developer-certificate-enabled alarm")
|
||||
fault = fm_api.Fault(alarm_id = fm_constants.FM_ALARM_ID_NONSTANDARD_CERT_PATCH,
|
||||
alarm_type = fm_constants.FM_ALARM_TYPE_9,
|
||||
alarm_state = fm_constants.FM_ALARM_STATE_SET,
|
||||
entity_type_id = fm_constants.FM_ENTITY_TYPE_HOST,
|
||||
entity_instance_id = entity_instance_id,
|
||||
severity = fm_constants.FM_ALARM_SEVERITY_CRITICAL,
|
||||
reason_text = 'Developer patch certificate is enabled',
|
||||
probable_cause = fm_constants.ALARM_PROBABLE_CAUSE_65,
|
||||
proposed_repair_action = 'Reinstall system to disable certificate and remove untrusted patches',
|
||||
suppression = False,
|
||||
service_affecting = False)
|
||||
|
||||
self.fm_api.set_fault(fault)
|
||||
|
||||
|
||||
def _get_handle_failed_hosts(self):
|
||||
url = "http://%s/patch/query_hosts" % self.api_addr
|
||||
|
||||
try:
|
||||
req = requests.get(url)
|
||||
except:
|
||||
return
|
||||
|
||||
entity_instance_id = "%s=%s" % (fm_constants.FM_ENTITY_TYPE_HOST, "controller")
|
||||
|
||||
failed_hosts = []
|
||||
if req.status_code == 200:
|
||||
data = json.loads(req.text)
|
||||
|
||||
if 'data' in data:
|
||||
for host in data['data']:
|
||||
if 'hostname' in host and 'patch_failed' in host and host['patch_failed']:
|
||||
failed_hosts.append(host['hostname'])
|
||||
|
||||
# Query existing alarms
|
||||
patch_failed_alarm = self.fm_api.get_fault(fm_constants.FM_ALARM_ID_PATCH_HOST_INSTALL_FAILED,
|
||||
entity_instance_id)
|
||||
|
||||
if len(failed_hosts) > 0:
|
||||
reason_text = "Patch installation failed on the following hosts: %s" % ", ".join(sorted(failed_hosts))
|
||||
|
||||
if patch_failed_alarm is None or reason_text != patch_failed_alarm.reason_text:
|
||||
if patch_failed_alarm is None:
|
||||
logging.info("Raising patch-host-install-failure alarm")
|
||||
else:
|
||||
logging.info("Updating patch-host-install-failure alarm")
|
||||
|
||||
fault = fm_api.Fault(alarm_id = fm_constants.FM_ALARM_ID_PATCH_HOST_INSTALL_FAILED,
|
||||
alarm_type = fm_constants.FM_ALARM_TYPE_5,
|
||||
alarm_state = fm_constants.FM_ALARM_STATE_SET,
|
||||
entity_type_id = fm_constants.FM_ENTITY_TYPE_HOST,
|
||||
entity_instance_id = entity_instance_id,
|
||||
severity = fm_constants.FM_ALARM_SEVERITY_MAJOR,
|
||||
reason_text = reason_text,
|
||||
probable_cause = fm_constants.ALARM_PROBABLE_CAUSE_65,
|
||||
proposed_repair_action = 'Undo patching operation',
|
||||
service_affecting = False)
|
||||
self.fm_api.set_fault(fault)
|
||||
|
||||
elif patch_failed_alarm is not None:
|
||||
logging.info("Clearing patch-host-install-failure alarm")
|
||||
self.fm_api.clear_fault(fm_constants.FM_ALARM_ID_PATCH_HOST_INSTALL_FAILED,
|
||||
entity_instance_id)
|
||||
|
||||
return False
|
||||
|
19
patch-alarm/patch-alarm/setup.py
Normal file
19
patch-alarm/patch-alarm/setup.py
Normal file
@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import setuptools
|
||||
|
||||
setuptools.setup(name='patch_alarm',
|
||||
version='1.0.0',
|
||||
description='CEPH alarm',
|
||||
license='Apache-2.0',
|
||||
packages=['patch_alarm'],
|
||||
entry_points={
|
||||
}
|
||||
)
|
18
patch-alarm/scripts/bin/patch-alarm-manager
Normal file
18
patch-alarm/scripts/bin/patch-alarm-manager
Normal file
@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2014 Wind River Systems, Inc.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
try:
|
||||
from patch_alarm import patch_alarm_manager
|
||||
except EnvironmentError as e:
|
||||
print >> sys.stderr, "Error importing patch_alarm_manager: ", str(e)
|
||||
sys.exit(1)
|
||||
|
||||
patch_alarm_manager.start_polling()
|
98
patch-alarm/scripts/init.d/patch-alarm-manager
Normal file
98
patch-alarm/scripts/init.d/patch-alarm-manager
Normal file
@ -0,0 +1,98 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
### BEGIN INIT INFO
|
||||
# Provides: patch-alarm-manager
|
||||
# Required-Start: $patch
|
||||
# Required-Stop: $patch
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Daemon for polling patch status
|
||||
# Description: Daemon for polling patch status
|
||||
### END INIT INFO
|
||||
|
||||
DESC="patch-alarm-manager"
|
||||
DAEMON="/usr/bin/patch-alarm-manager"
|
||||
RUNDIR="/var/run"
|
||||
PIDFILE=$RUNDIR/$DESC.pid
|
||||
|
||||
start()
|
||||
{
|
||||
if [ -e $PIDFILE ]; then
|
||||
PIDDIR=/prod/$(cat $PIDFILE)
|
||||
if [ -d ${PIDFILE} ]; then
|
||||
echo "$DESC already running."
|
||||
exit 0
|
||||
else
|
||||
echo "Removing stale PID file $PIDFILE"
|
||||
rm -f $PIDFILE
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -n "Starting $DESC..."
|
||||
mkdir -p $RUNDIR
|
||||
start-stop-daemon --start --quiet \
|
||||
--pidfile ${PIDFILE} --exec ${DAEMON} start
|
||||
|
||||
#--make-pidfile
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "failed."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
echo -n "Stopping $DESC..."
|
||||
start-stop-daemon --stop --quiet --pidfile $PIDFILE
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "done."
|
||||
else
|
||||
echo "failed."
|
||||
fi
|
||||
rm -f $PIDFILE
|
||||
}
|
||||
|
||||
status()
|
||||
{
|
||||
pid=`cat $PIDFILE 2>/dev/null`
|
||||
if [ -n "$pid" ]; then
|
||||
if ps -p $pid &>/dev/null ; then
|
||||
echo "$DESC is running"
|
||||
exit 0
|
||||
else
|
||||
echo "$DESC is not running but has pid file"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "$DESC is not running"
|
||||
exit 3
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart|force-reload|reload)
|
||||
stop
|
||||
start
|
||||
;;
|
||||
status)
|
||||
status
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|force-reload|restart|reload|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
202
patch-boot-args/LICENSE
Normal file
202
patch-boot-args/LICENSE
Normal 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.
|
27
patch-scripts/EXAMPLE_0001/centos/EXAMPLE_0001.spec
Normal file
27
patch-scripts/EXAMPLE_0001/centos/EXAMPLE_0001.spec
Normal file
@ -0,0 +1,27 @@
|
||||
Name: EXAMPLE_0001
|
||||
Summary: TIS In-Service Patch Scripts Example
|
||||
Version: 1.0
|
||||
Release: %{tis_patch_ver}%{?_tis_dist}
|
||||
License: Apache-2.0
|
||||
Group: base
|
||||
Packager: Wind River <info@windriver.com>
|
||||
Source0: example-restart
|
||||
|
||||
%install
|
||||
install -Dp -m 700 %{S:0} %{buildroot}%{_patch_scripts}/%{name}
|
||||
|
||||
%description
|
||||
%{summary}
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%{_patch_scripts}/*
|
||||
|
||||
%post
|
||||
cp -f %{_patch_scripts}/%{name} %{_runtime_patch_scripts}/
|
||||
exit 0
|
||||
|
||||
%preun
|
||||
cp -f %{_patch_scripts}/%{name} %{_runtime_patch_scripts}/
|
||||
exit 0
|
||||
|
2
patch-scripts/EXAMPLE_0001/centos/build_srpm.data
Normal file
2
patch-scripts/EXAMPLE_0001/centos/build_srpm.data
Normal file
@ -0,0 +1,2 @@
|
||||
COPY_LIST="scripts/*"
|
||||
TIS_PATCH_VER=0
|
128
patch-scripts/EXAMPLE_0001/scripts/example-restart
Normal file
128
patch-scripts/EXAMPLE_0001/scripts/example-restart
Normal file
@ -0,0 +1,128 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2016 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
#
|
||||
# This script provides an example in-service patching restart
|
||||
#
|
||||
|
||||
#
|
||||
# The patching subsystem provides a patch-functions bash source file
|
||||
# with useful function and variable definitions.
|
||||
#
|
||||
. /etc/patching/patch-functions
|
||||
|
||||
#
|
||||
# We can now check to see what type of node we're on, if it's locked, etc,
|
||||
# and act accordingly
|
||||
#
|
||||
|
||||
#
|
||||
# Declare an overall script return code
|
||||
#
|
||||
declare -i GLOBAL_RC=$PATCH_STATUS_OK
|
||||
|
||||
# NOTE: The following restart example code could be implemented in scripts
|
||||
# owned by the various domains, with a single high-level call in the patch-script.
|
||||
# This would be the preferred method, in fact, to ensure the patch-scripts
|
||||
# themselves are simple and clean.
|
||||
#
|
||||
|
||||
#
|
||||
# First up, we'll handle restarting the sysinv-agent, which runs on all nodes
|
||||
#
|
||||
if [ ! -f $PATCH_FLAGDIR/sysinv-agent.restarted ]
|
||||
then
|
||||
# The sysinv-agent has not yet been restarted in this patch operation
|
||||
systemctl status sysinv-agent.service
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
# The daemon is running, so restart it
|
||||
loginfo "$0: Restarting sysinv-agent"
|
||||
pmon-restart sysinv-agent
|
||||
touch $PATCH_FLAGDIR/sysinv-agent.restarted
|
||||
|
||||
# Wait up to 15 seconds for service to recover
|
||||
let -i UNTIL=$SECONDS+15
|
||||
while [ $UNTIL -ge $SECONDS ]
|
||||
do
|
||||
# Check to make sure it's running
|
||||
systemctl status sysinv-agent.service
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
|
||||
# Not running... Let's wait a couple of seconds and check again
|
||||
sleep 2
|
||||
done
|
||||
|
||||
systemctl status sysinv-agent.service
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# Still not running! Clear the flag and mark the RC as failed
|
||||
rm -f $PATCH_FLAGDIR/sysinv-agent.restarted
|
||||
GLOBAL_RC=$PATCH_STATUS_FAILED
|
||||
loginfo "$0: Failed to restart sysinv-agent"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Next, handle restarting horizon.
|
||||
# TODO: There will be some SM enhancements coming to provide
|
||||
# utilities we can use to facilitate in-service patching.
|
||||
# For now, we'll do this a slightly uglier fashion
|
||||
#
|
||||
if is_controller
|
||||
then
|
||||
# Horizon only runs on the controller
|
||||
|
||||
if [ ! -f $PATCH_FLAGDIR/horizon.restarted ]
|
||||
then
|
||||
# Check SM to see if Horizon is running
|
||||
sm-query service horizon | grep -q 'enabled-active'
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
loginfo "$0: Restarting horizon"
|
||||
|
||||
# Ask SM to restart Horizon
|
||||
sm-restart service horizon
|
||||
touch $PATCH_FLAGDIR/horizon.restarted
|
||||
|
||||
# Wait up to 30 seconds for service to recover
|
||||
let -i UNTIL=$SECONDS+30
|
||||
while [ $UNTIL -ge $SECONDS ]
|
||||
do
|
||||
# Check to see if it's running
|
||||
sm-query service horizon | grep -q 'enabled-active'
|
||||
if [ $? -eq 0 ]
|
||||
then
|
||||
break
|
||||
fi
|
||||
|
||||
# Still not running? Let's wait 5 seconds and check again
|
||||
sleep 5
|
||||
done
|
||||
|
||||
sm-query service horizon | grep -q 'enabled-active'
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# Still not running! Clear the flag and mark the RC as failed
|
||||
loginfo "$0: Failed to restart horizon"
|
||||
rm -f $PATCH_FLAGDIR/horizon.restarted
|
||||
GLOBAL_RC=$PATCH_STATUS_FAILED
|
||||
sm-query service horizon
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Exit the script with the overall return code
|
||||
#
|
||||
exit $GLOBAL_RC
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user