Fork cgcs-patch package as sw-patch for Debian
The original cgcs-patch is rpm based which requires a complete re-write to work on ostree/dpkg systems like Debian. The code has been forked, since the older Centos env and python2.7 are end-of-life. Forking the code allows all new development to not require re-testing on Centos. The debian folder under cgcs-patch has been moved under sw-patch Renaming and refactoring will be done in later commits. pylint is un-clamped in order to work on python3.9 Some minor pylint suppressions have been added. Test Plan: Verify that this builds on Debian Verify that the ISO installs the new content on Debian without breaking packages that import cgcs_patch. Verify patching service runs on Debian Co-Authored-By: Jessica Castelino <jessica.castelino@windriver.com> Story: 2009101 Task: 43076 Signed-off-by: Al Bailey <al.bailey@windriver.com> Change-Id: I3f1bca749404053bae63d4bcc9fb2477cf909fcdchanges/84/835484/18
parent
0f682de55f
commit
be09ccc584
34
.zuul.yaml
34
.zuul.yaml
|
@ -15,6 +15,8 @@
|
|||
- patch-alarm-tox-pylint
|
||||
- patch-alarm-tox-py27
|
||||
- patch-alarm-tox-py39
|
||||
- sw-patch-tox-pylint
|
||||
- sw-patch-tox-py39
|
||||
gate:
|
||||
jobs:
|
||||
- openstack-tox-linters
|
||||
|
@ -26,6 +28,8 @@
|
|||
- patch-alarm-tox-pylint
|
||||
- patch-alarm-tox-py27
|
||||
- patch-alarm-tox-py39
|
||||
- sw-patch-tox-pylint
|
||||
- sw-patch-tox-py39
|
||||
post:
|
||||
jobs:
|
||||
- stx-update-upload-git-mirror
|
||||
|
@ -79,7 +83,6 @@
|
|||
required-projects:
|
||||
- starlingx/config
|
||||
- starlingx/fault
|
||||
- starlingx/root
|
||||
files:
|
||||
- cgcs-patch/cgcs-patch/*
|
||||
vars:
|
||||
|
@ -87,6 +90,34 @@
|
|||
python_version: 3.9
|
||||
tox_extra_args: -c cgcs-patch/cgcs-patch/tox.ini
|
||||
|
||||
- job:
|
||||
name: sw-patch-tox-py39
|
||||
parent: tox-py39
|
||||
nodeset: debian-bullseye
|
||||
required-projects:
|
||||
- starlingx/config
|
||||
- starlingx/fault
|
||||
files:
|
||||
- sw-patch/cgcs-patch/*
|
||||
vars:
|
||||
tox_envlist: py39
|
||||
python_version: 3.9
|
||||
tox_extra_args: -c sw-patch/cgcs-patch/tox.ini
|
||||
|
||||
- job:
|
||||
name: sw-patch-tox-pylint
|
||||
parent: tox
|
||||
nodeset: debian-bullseye
|
||||
required-projects:
|
||||
- starlingx/config
|
||||
- starlingx/fault
|
||||
files:
|
||||
- sw-patch/cgcs-patch/*
|
||||
vars:
|
||||
tox_envlist: pylint
|
||||
python_version: 3.9
|
||||
tox_extra_args: -c sw-patch/cgcs-patch/tox.ini
|
||||
|
||||
|
||||
- job:
|
||||
name: patch-alarm-tox-pylint
|
||||
|
@ -121,7 +152,6 @@
|
|||
required-projects:
|
||||
- starlingx/config
|
||||
- starlingx/fault
|
||||
- starlingx/root
|
||||
files:
|
||||
- patch-alarm/patch-alarm/*
|
||||
vars:
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
# This is a cross-platform list tracking distribution packages needed for install and tests;
|
||||
# see https://docs.openstack.org/infra/bindep/ for additional information.
|
||||
# Do not install python2 rpms in a python3 only environment such as debian-bullseye
|
||||
|
||||
python-rpm [platform:dpkg !platform:debian-bullseye]
|
||||
python3-rpm [platform:dpkg]
|
||||
rpm-python [platform:rpm]
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
cgcs-patch
|
||||
enable-dev-patch
|
||||
patch-alarm
|
||||
sw-patch
|
||||
|
|
|
@ -3,9 +3,12 @@
|
|||
# process, which may cause wedges in the gate later.
|
||||
|
||||
hacking>=1.1.0,<=2.0.0 # Apache-2.0
|
||||
|
||||
astroid <= 2.2.5
|
||||
coverage!=4.4,>=4.0 # Apache-2.0
|
||||
mock>=2.0.0 # BSD
|
||||
stestr>=1.0.0 # Apache-2.0
|
||||
testtools>=2.2.0 # MIT
|
||||
pycryptodomex
|
||||
isort<5;python_version>="3.0"
|
||||
pylint<2.1.0;python_version<"3.0" # GPLv2
|
||||
pylint<2.4.0;python_version>="3.0" # GPLv2
|
||||
|
|
|
@ -28,7 +28,7 @@ setenv = VIRTUAL_ENV={envdir}
|
|||
passenv =
|
||||
XDG_CACHE_HOME
|
||||
|
||||
sitepackages = False
|
||||
sitepackages = True
|
||||
install_command = pip install \
|
||||
-v -v -v \
|
||||
-c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/stable/stein/upper-constraints.txt} \
|
||||
|
@ -64,7 +64,6 @@ install_command = pip install \
|
|||
-v -v -v \
|
||||
-c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/starlingx/root/raw/branch/master/build-tools/requirements/debian/upper-constraints.txt} \
|
||||
{opts} {packages}
|
||||
{opts} {packages}
|
||||
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
|
@ -110,17 +109,13 @@ basepython = python3
|
|||
deps = {[testenv]deps}
|
||||
flake8-bugbear
|
||||
usedevelop = False
|
||||
#skip_install = True
|
||||
commands =
|
||||
flake8 {posargs} .
|
||||
|
||||
[testenv:pylint]
|
||||
basepython = python3
|
||||
deps = {[testenv]deps}
|
||||
pylint
|
||||
|
||||
basepython = python2.7
|
||||
sitepackages = False
|
||||
|
||||
commands = pylint patch_alarm --rcfile=./pylint.rc
|
||||
|
||||
[testenv:cover]
|
||||
|
|
|
@ -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())
|
|
@ -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())
|
|
@ -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_worker()
|
||||
{
|
||||
[[ $nodetype == "worker" ]]
|
||||
}
|
||||
|
||||
function is_storage()
|
||||
{
|
||||
[[ $nodetype == "storage" ]]
|
||||
}
|
||||
|
||||
function is_cpe()
|
||||
{
|
||||
[[ $nodetype == "controller" && $subfunction =~ worker ]]
|
||||
}
|
||||
|
||||
function is_locked()
|
||||
{
|
||||
test -f /var/run/.node_locked
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
d /run/patching 0700 root root -
|
||||
|
|
@ -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())
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#!/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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"admin": "role:admin or role:administrator",
|
||||
"admin_api": "is_admin:True",
|
||||
"default": "rule:admin_api"
|
||||
}
|
|
@ -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())
|
|
@ -0,0 +1,183 @@
|
|||
#!/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 .pyo 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
|
||||
|
||||
let -i sumlen=$(echo -n $psum | wc -c)
|
||||
if [ $sumlen = 64 ]
|
||||
then
|
||||
sumcmd=sha256sum
|
||||
else
|
||||
sumcmd=md5sum
|
||||
fi
|
||||
|
||||
echo $psum $pname | $sumcmd --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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Copyright (c) 2018-2020 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, 0o755)
|
||||
os.mkdir(datadir, 0o755)
|
||||
os.mkdir(committed_dir, 0o755)
|
||||
os.mkdir(pkgdir, 0o755)
|
||||
|
||||
# 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:
|
||||
raise Exception("%s is for release %s, not %s" % (patch_id, 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())
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/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()
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/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()
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
#!/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
|
|
@ -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
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[Unit]
|
||||
Description=StarlingX Patching Agent
|
||||
After=syslog.target network-online.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
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/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()
|
||||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[Unit]
|
||||
Description=StarlingX Patching Controller Daemon
|
||||
After=syslog.target network-online.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
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# StarlingX Patching Controller setup
|
||||
# chkconfig: 345 20 24
|
||||
# description: CGCS Patching Controller init script
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: sw-patch-controller
|
||||
# Required-Start: $syslog
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: sw-patch-controller
|
||||
# Description: Provides the StarlingX Patch Controller Daemon
|
||||
### END INIT INFO
|
||||
|
||||
. /usr/bin/tsconfig
|
||||
|
||||
NAME=$(basename $0)
|
||||
|
||||
REPO_ID=updates
|
||||
REPO_ROOT=/var/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
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=StarlingX Patching Controller
|
||||
After=syslog.service network-online.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
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2014-2020 Wind River Systems, Inc.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# StarlingX Patching
|
||||
# chkconfig: 345 20 23
|
||||
# description: StarlingX Patching init script
|
||||
|
||||
### BEGIN INIT INFO
|
||||
# Provides: sw-patch
|
||||
# Required-Start: $syslog
|
||||
# Required-Stop: $syslog
|
||||
# Default-Start: 2 3 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: sw-patch
|
||||
# Description: Provides the StarlingX Patching
|
||||
### END INIT INFO
|
||||
|
||||
NAME=$(basename $0)
|
||||
|
||||
. /usr/bin/tsconfig
|
||||
. /etc/platform/platform.conf
|
||||
|
||||
logfile=/var/log/patching.log
|
||||
patch_failed_file=/var/run/patch_install_failed
|
||||
patched_during_init=/etc/patching/.patched_during_init
|
||||
|
||||
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
|
||||
if [ ! -f ${patched_during_init} ]; 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"
|
||||
touch ${patched_during_init}
|
||||
/sbin/reboot
|
||||
else
|
||||
echo
|
||||
echo "Node has been patched during init a second consecutive time. Skipping reboot due to possible error"
|
||||
echo
|
||||
LOG_TO_FILE "Node has been patched during init a second consecutive time. Skipping reboot due to possible error"
|
||||
touch ${patch_failed_file}
|
||||
rm -f ${patched_during_init}
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
rm -f ${patched_during_init}
|
||||
fi
|
||||
}
|
||||
|
||||
function check_install_uuid {
|
||||
# Check whether our installed load matches the active controller
|
||||
CONTROLLER_UUID=`curl -sf http://controller:${http_port}/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
|
||||
|
||||
# For AIO-SX, abort if config is not yet applied and this is running in init
|
||||
if [ "${system_mode}" = "simplex" -a ! -f ${INITIAL_CONTROLLER_CONFIG_COMPLETE} -a "$1" = "start" ]; then
|
||||
LOG_TO_FILE "Config is not yet applied. Skipping init patching"
|
||||
exit 0
|
||||
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
|
||||
|
||||
RC=0
|
||||
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
|
||||
if [ -f ${patch_failed_file} ]; then
|
||||
RC=1
|
||||
LOG_TO_FILE "***** Patch operation failed *****"
|
||||
fi
|
||||
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
|
||||
if [ -f ${patch_failed_file} ]; then
|
||||
RC=1
|
||||
LOG_TO_FILE "***** Patch operation failed *****"
|
||||
fi
|
||||
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
|
||||
if [ -f ${patch_failed_file} ]; then
|
||||
RC=1
|
||||
LOG_TO_FILE "***** Patch operation failed *****"
|
||||
fi
|
||||
LOG_TO_FILE "***** Finished patch operation *****"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit $RC
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
#
|
||||
# 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
|
||||
is-applied
|
||||
is-available
|
||||
report-app-dependencies
|
||||
query-app-dependencies
|
||||
"
|
||||
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|delete|show|what-requires|is-applied|is-available)
|
||||
# Query the list of known patches
|
||||
local patches=$(sw-patch completion patches 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "${patches}" -- ${cur}) )
|
||||
return 0
|
||||
;;
|
||||
remove)
|
||||
# Query the list of known patches
|
||||
local patches=$(sw-patch completion patches 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "--skipappcheck ${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 /var/www/pages/feed/rel-* 2>/dev/null | sed 's#/var/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 /var/www/pages/feed/rel-* 2>/dev/null | sed 's#/var/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
|
||||
;;
|
||||
report-app-dependencies)
|
||||
if [ "${prev}" = "${subcommand}" ]; then
|
||||
COMPREPLY=( $(compgen -W "--app" -- ${cur}) )
|
||||
elif [ "${prev}" = "--app" ]; then
|
||||
COMPREPLY=
|
||||
else
|
||||
local patches=$(sw-patch completion patches 2>/dev/null)
|
||||
COMPREPLY=( $(compgen -W "${patches}" -- ${cur}) )
|
||||
fi
|
||||
return 0
|
||||
;;
|
||||
query-app-dependencies)
|
||||
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
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
[Unit]
|
||||
Description=StarlingX Patching
|
||||
After=syslog.target network-online.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
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright (c) 2018-2021 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=/var/www/pages/feed/rel-${TGT_RELEASE}
|
||||
declare TGT_PATCHES_REPO=/var/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
|
||||
}
|
||||