Debian: Minor sw-patch cleanup

- Adding missing requirements for sw-patch
- Cleaning up redundant dependencies
- Invoke clean as part of debian build
- Rename Starlingx to StarlingX
- Display error details for failed sw-patch commands
- Fix a python3 string comparison affecting duplex
- Fix report-app-dependencies
- Remove 'six' from sw-patch since the code is py3 only
- Fix a KeyError if restart_script not found in metadata.
- Allow bandit to ignore 'input' checks on python3 since
it is considered safe

Test Plan:
  PASS: Build/Bootstrap/Unlock AIO-SX Debian
  PASS: sw-patch report-app-dependencies --app foo
  PASS: Upload/Apply/Remove/Delete a patch on AIO-DX system
       host-install was not tested on AIO-DX as that
       capability is still under active developement.

Closes-Bug: #1976535
Signed-off-by: Al Bailey <al.bailey@windriver.com>
Change-Id: I94ec47e2f2087989da26ebab0e05c3b0d8f303e6
This commit is contained in:
Al Bailey 2022-07-11 18:49:51 +00:00
parent def5e22b27
commit abaea457e5
12 changed files with 61 additions and 56 deletions

View File

@ -5,6 +5,7 @@ SPDX-License-Identifier: Apache-2.0
""" """
import configparser
from oslo_config import cfg from oslo_config import cfg
import pecan import pecan
@ -13,7 +14,6 @@ from cgcs_patch.authapi import config
from cgcs_patch.authapi import hooks from cgcs_patch.authapi import hooks
from cgcs_patch.authapi import policy from cgcs_patch.authapi import policy
from six.moves import configparser
auth_opts = [ auth_opts = [
cfg.StrOpt('auth_strategy', cfg.StrOpt('auth_strategy',

View File

@ -8,6 +8,7 @@ SPDX-License-Identifier: Apache-2.0
import socket import socket
import struct import struct
import subprocess import subprocess
import sys
import time import time
import cgcs_patch.utils as utils import cgcs_patch.utils as utils
@ -154,7 +155,7 @@ class PatchService(object):
cmd = "ip maddr show %s | awk 'BEGIN {ORS=\"\"}; {if ($2 == \"%s\") print $2}'" % \ cmd = "ip maddr show %s | awk 'BEGIN {ORS=\"\"}; {if ($2 == \"%s\") print $2}'" % \
(cfg.get_mgmt_iface(), self.mcast_addr) (cfg.get_mgmt_iface(), self.mcast_addr)
try: try:
result = subprocess.check_output(cmd, shell=True) result = subprocess.check_output(cmd, shell=True).decode(sys.stdout.encoding)
if result == self.mcast_addr: if result == self.mcast_addr:
return return

View File

@ -4,10 +4,10 @@ Copyright (c) 2014-2022 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
""" """
import configparser
import io import io
import logging import logging
import os import os
from six.moves import configparser
import socket import socket
import tsconfig.tsconfig as tsc import tsconfig.tsconfig as tsc

View File

@ -4,21 +4,17 @@ Copyright (c) 2014-2022 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
""" """
from __future__ import print_function
from six.moves import input
import requests
import json import json
import os import os
import sys
import shutil
import re import re
import time import requests
import shutil
import signal import signal
import subprocess import subprocess
import sys
import textwrap import textwrap
import time
# noinspection PyUnresolvedReferences
from requests_toolbelt import MultipartEncoder from requests_toolbelt import MultipartEncoder
import cgcs_patch.constants as constants import cgcs_patch.constants as constants
@ -878,6 +874,8 @@ def query_dependencies(debug, args):
if 'patches' in data: if 'patches' in data:
for patch_id in sorted(data['patches']): for patch_id in sorted(data['patches']):
print(patch_id) print(patch_id)
if 'error' in data and data["error"] != "":
print("Error: %s" % data.get("error"))
elif req.status_code == 500: elif req.status_code == 500:
print("An internal error has occurred. Please check /var/log/patching.log for details") print("An internal error has occurred. Please check /var/log/patching.log for details")
@ -1259,6 +1257,7 @@ def patch_report_app_dependencies_req(debug, args): # pylint: disable=unused-ar
if req.status_code == 200: if req.status_code == 200:
return 0 return 0
else: else:
print("An internal error has occurred. Please check /var/log/patching.log for details")
return 1 return 1

View File

@ -4,13 +4,12 @@ Copyright (c) 2014-2022 Wind River Systems, Inc.
SPDX-License-Identifier: Apache-2.0 SPDX-License-Identifier: Apache-2.0
""" """
import configparser
import gc import gc
import json import json
import os import os
import select import select
import shutil import shutil
import six
from six.moves import configparser
import socket import socket
import subprocess import subprocess
import tarfile import tarfile
@ -55,7 +54,6 @@ from cgcs_patch.base import PatchService
import cgcs_patch.config as cfg import cgcs_patch.config as cfg
import cgcs_patch.utils as utils import cgcs_patch.utils as utils
import cgcs_patch.messages as messages import cgcs_patch.messages as messages
import cgcs_patch.constants as constants import cgcs_patch.constants as constants
@ -653,10 +651,7 @@ class PatchController(PatchService):
pass pass
def write_state_file(self): def write_state_file(self):
if six.PY2: config = configparser.ConfigParser(strict=False)
config = configparser.ConfigParser()
elif six.PY3:
config = configparser.ConfigParser(strict=False)
cfgfile = open(state_file, 'w') cfgfile = open(state_file, 'w')
@ -666,10 +661,7 @@ class PatchController(PatchService):
cfgfile.close() cfgfile.close()
def read_state_file(self): def read_state_file(self):
if six.PY2: config = configparser.ConfigParser(strict=False)
config = configparser.ConfigParser()
elif six.PY3:
config = configparser.ConfigParser(strict=False)
config.read(state_file) config.read(state_file)
@ -839,7 +831,7 @@ class PatchController(PatchService):
Deletes the restart script (if any) associated with the patch Deletes the restart script (if any) associated with the patch
:param patch_id: The patch ID :param patch_id: The patch ID
''' '''
if not self.patch_data.metadata[patch_id]["restart_script"]: if not self.patch_data.metadata[patch_id].get("restart_script"):
return return
restart_script_path = "%s/%s" % (root_scripts_dir, self.patch_data.metadata[patch_id]["restart_script"]) restart_script_path = "%s/%s" % (root_scripts_dir, self.patch_data.metadata[patch_id]["restart_script"])
@ -1965,7 +1957,7 @@ class PatchController(PatchService):
for patch_id in self.patch_data.metadata: for patch_id in self.patch_data.metadata:
if (self.patch_data.metadata[patch_id]["patchstate"] in if (self.patch_data.metadata[patch_id]["patchstate"] in
[constants.PARTIAL_APPLY, constants.PARTIAL_REMOVE]) \ [constants.PARTIAL_APPLY, constants.PARTIAL_REMOVE]) \
and self.patch_data.metadata[patch_id]["restart_script"]: and self.patch_data.metadata[patch_id].get("restart_script"):
try: try:
restart_script_name = self.patch_data.metadata[patch_id]["restart_script"] restart_script_name = self.patch_data.metadata[patch_id]["restart_script"]
restart_script_path = "%s/%s" \ restart_script_path = "%s/%s" \
@ -1983,7 +1975,7 @@ class PatchController(PatchService):
msg = "Failed to copy the restart script for %s" % patch_id msg = "Failed to copy the restart script for %s" % patch_id
LOG.exception(msg) LOG.exception(msg)
raise PatchError(msg) raise PatchError(msg)
elif self.patch_data.metadata[patch_id]["restart_script"]: elif self.patch_data.metadata[patch_id].get("restart_script"):
try: try:
restart_script_name = self.patch_data.metadata[patch_id]["restart_script"] restart_script_name = self.patch_data.metadata[patch_id]["restart_script"]
restart_script_path = "%s/%s" \ restart_script_path = "%s/%s" \
@ -2205,7 +2197,7 @@ class PatchController(PatchService):
prefix=app_dependency_basename, prefix=app_dependency_basename,
dir=constants.PATCH_STORAGE_DIR) dir=constants.PATCH_STORAGE_DIR)
os.write(tmpfile, json.dumps(self.app_dependencies)) os.write(tmpfile, json.dumps(self.app_dependencies).encode())
os.close(tmpfile) os.close(tmpfile)
os.rename(tmpfname, app_dependency_filename) os.rename(tmpfname, app_dependency_filename)

View File

@ -854,7 +854,8 @@ class PatchFile(object):
shutil.move("software.tar", shutil.move("software.tar",
"%s/%s-software.tar" % (abs_ostree_tar_dir, patch_id)) "%s/%s-software.tar" % (abs_ostree_tar_dir, patch_id))
if thispatch.metadata[patch_id]["restart_script"]: # restart_script may not exist in metadata.
if thispatch.metadata[patch_id].get("restart_script"):
if not os.path.exists(root_scripts_dir): if not os.path.exists(root_scripts_dir):
os.makedirs(root_scripts_dir) os.makedirs(root_scripts_dir)
restart_script_name = thispatch.metadata[patch_id]["restart_script"] restart_script_name = thispatch.metadata[patch_id]["restart_script"]

View File

@ -12,7 +12,7 @@ from cgcs_patch.patch_controller import PatchController
class CgcsPatchControllerTestCase(testtools.TestCase): class CgcsPatchControllerTestCase(testtools.TestCase):
@mock.patch('six.moves.builtins.open') @mock.patch('builtins.open')
def test_cgcs_patch_controller_instantiate(self, _mock_open): def test_cgcs_patch_controller_instantiate(self, _mock_open):
pc = PatchController() pc = PatchController()
self.assertIsNotNone(pc) self.assertIsNotNone(pc)

View File

@ -3,9 +3,10 @@
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
keystonemiddleware keystonemiddleware
oslo_config lxml
oslo.config
netaddr
pecan pecan
pycryptodomex pycryptodomex
lxml
requests_toolbelt requests_toolbelt
sh sh

View File

@ -5,7 +5,7 @@
# #
[tox] [tox]
envlist = pep8,py36,py39,pylint,bandit,cover envlist = pep8,py39,pylint,bandit,cover
minversion = 2.3.2 minversion = 2.3.2
skipsdist = True skipsdist = True

View File

@ -2,51 +2,58 @@ Source: cgcs-patch
Section: admin Section: admin
Priority: optional Priority: optional
Maintainer: StarlingX Developers <StarlingX-discuss@lists.StarlingX.io> Maintainer: StarlingX Developers <StarlingX-discuss@lists.StarlingX.io>
Build-Depends: debhelper-compat (= 13), dh-python, python3-setuptools, python3-all Build-Depends: debhelper-compat (= 13),
Build-Depends-Indep: python3-keystonemiddleware, dh-python,
python3-all,
python3-setuptools
Build-Depends-Indep:
python3-keystonemiddleware,
python3-lxml,
python3-mock,
python3-netaddr,
python3-oslo.config, python3-oslo.config,
python3-pecan, python3-pecan,
python3-pycryptodome, python3-pycryptodome,
python3-lxml,
python3-requests-toolbelt, python3-requests-toolbelt,
python3-mock, python3-sh,
python3-stestr, python3-stestr,
python3-testtools, python3-testtools,
python3-six, tsconfig
tsconfig, Standards-Version: 4.5.1
python3-sh Homepage: https://www.starlingx.io
Standards-Version: 4.4.1 Rules-Requires-Root: no
Package: cgcs-patch Package: cgcs-patch
Architecture: all Architecture: all
Depends: ${misc:Depends}, ${python3:Depends}, python3-cgcs-patch Depends: python3-cgcs-patch
Description: Starlingx platform patching Description: StarlingX platform patching
Starlingx platform patching system StarlingX platform patching system
Package: cgcs-patch-controller Package: cgcs-patch-controller
Architecture: all Architecture: all
Depends: ${misc:Depends}, ${python3:Depends}, python3-cgcs-patch, cgcs-patch Depends: cgcs-patch
Description: Starlingx platform patching Description: StarlingX platform patching controller
Starlingx platform patching system StarlingX platform patching system controller
Package: cgcs-patch-agent Package: cgcs-patch-agent
Architecture: all Architecture: all
Depends: ${misc:Depends}, ${python3:Depends}, python3-cgcs-patch, cgcs-patch Depends: cgcs-patch
Description: Starlingx platform patching Description: StarlingX platform patching agent
Starlingx platform patching system StarlingX platform patching system agent
Package: python3-cgcs-patch Package: python3-cgcs-patch
Architecture: all Architecture: all
Depends: ${python3:Depends}, Depends:
${misc:Depends}, ${misc:Depends},
${python3:Depends},
python3-keystonemiddleware, python3-keystonemiddleware,
python3-lxml,
python3-oslo.config, python3-oslo.config,
python3-netaddr,
python3-pecan, python3-pecan,
python3-pycryptodome, python3-pycryptodome,
python3-lxml,
python3-requests-toolbelt, python3-requests-toolbelt,
python3-six, python3-sh,
tsconfig, tsconfig
python3-sh Description: StarlingX platfom patching (python3)
Description: Starlingx platfom patching (python3) StarlingX platform patching system python libraries
Starlingx platform patching system python libraries

View File

@ -13,6 +13,9 @@ override_dh_auto_test:
override_dh_auto_install: override_dh_auto_install:
echo echo
override_dh_auto_clean:
python3 setup.py clean
override_dh_install: override_dh_install:
python3 setup.py install -f --install-layout=deb --root=${DEBIAN_DESTDIR} python3 setup.py install -f --install-layout=deb --root=${DEBIAN_DESTDIR}

View File

@ -147,6 +147,7 @@ commands = {[testenv]commands}
# B311: Standard pseudo-random generators are not suitable for security/cryptographic purposes # B311: Standard pseudo-random generators are not suitable for security/cryptographic purposes
# B314: Blacklisted calls to xml.etree.ElementTree # B314: Blacklisted calls to xml.etree.ElementTree
# B318: Blacklisted calls to xml.dom.minidom # B318: Blacklisted calls to xml.dom.minidom
# B322: Blacklist call to input (this is safe on python3)
# B404: Import of subprocess module # B404: Import of subprocess module
# B405: import xml.etree # B405: import xml.etree
# B408: import xml.minidom # B408: import xml.minidom
@ -155,7 +156,7 @@ commands = {[testenv]commands}
# B602: Test for use of popen with shell equals true # B602: Test for use of popen with shell equals true
# B603: Test for use of subprocess without shell equals true # B603: Test for use of subprocess without shell equals true
# B607: Test for starting a process with a partial path # B607: Test for starting a process with a partial path
skips = B101,B104,B110,B303,B311,B314,B318,B404,B405,B408,B413,B506,B602,B603,B607 skips = B101,B104,B110,B303,B311,B314,B318,B322,B404,B405,B408,B413,B506,B602,B603,B607
exclude = tests exclude = tests
[testenv:bandit] [testenv:bandit]