Patch extraction and validation enhancements
This commit updates patch extraction process to read and untar specific files. Additionally, it updates the process used to extract sw_version from deeply nested tar archives of a patch file. Test Plan: [PASS] Ran below command in DC env that invokes this code path sw-patch --os-region-name SystemController upload <patch>.patch [PASS] Uploaded an in-service and RR patch Story: 2010993 Task: 49289 Change-Id: I7ada7b55f458c50ed3bf51e66841cc49592f2f71 Signed-off-by: Jessica Castelino <jessica.castelino@windriver.com>
This commit is contained in:
parent
8aed4785a3
commit
00575b6dc2
@ -202,8 +202,7 @@ def parse_pkgver(pkgver):
|
|||||||
def get_release_from_patch(patchfile):
|
def get_release_from_patch(patchfile):
|
||||||
rel = ""
|
rel = ""
|
||||||
try:
|
try:
|
||||||
cmd = "tar xf %s -O metadata.tar | tar x -O" % patchfile
|
metadata_str = subprocess.check_output(['tar', '--to-command=tar -xO', '-xf', patchfile, 'metadata.tar'])
|
||||||
metadata_str = subprocess.check_output(cmd, shell=True)
|
|
||||||
root = ElementTree.fromstring(metadata_str)
|
root = ElementTree.fromstring(metadata_str)
|
||||||
# Extract release version
|
# Extract release version
|
||||||
rel = root.findtext('sw_version')
|
rel = root.findtext('sw_version')
|
||||||
|
@ -157,8 +157,7 @@ def write_xml_file(top,
|
|||||||
def get_release_from_patch(patchfile):
|
def get_release_from_patch(patchfile):
|
||||||
rel = ""
|
rel = ""
|
||||||
try:
|
try:
|
||||||
cmd = "tar xf %s -O metadata.tar | tar x -O" % patchfile
|
metadata_str = subprocess.check_output(['tar', '--to-command=tar -xO', '-xf', patchfile, 'metadata.tar'])
|
||||||
metadata_str = subprocess.check_output(cmd, shell=True)
|
|
||||||
root = ElementTree.fromstring(metadata_str)
|
root = ElementTree.fromstring(metadata_str)
|
||||||
# Extract release version
|
# Extract release version
|
||||||
rel = root.findtext('sw_version')
|
rel = root.findtext('sw_version')
|
||||||
@ -625,22 +624,21 @@ class PatchFile(object):
|
|||||||
# Open the patch file and extract the contents to the current dir
|
# Open the patch file and extract the contents to the current dir
|
||||||
tar = tarfile.open(path, "r:gz")
|
tar = tarfile.open(path, "r:gz")
|
||||||
|
|
||||||
filelist = []
|
tar.extract("signature")
|
||||||
for f in tar.getmembers():
|
try:
|
||||||
filelist.append(f.name)
|
tar.extract(detached_signature_file)
|
||||||
|
except KeyError:
|
||||||
if detached_signature_file not in filelist:
|
msg = "Patch has not been signed"
|
||||||
msg = "Patch not signed"
|
|
||||||
LOG.warning(msg)
|
LOG.warning(msg)
|
||||||
|
|
||||||
for f in filelist:
|
|
||||||
tar.extract(f)
|
|
||||||
|
|
||||||
# Filelist used for signature validation and verification
|
# Filelist used for signature validation and verification
|
||||||
sig_filelist = ["metadata.tar", "software.tar"]
|
sig_filelist = ["metadata.tar", "software.tar"]
|
||||||
if "semantics.tar" in filelist:
|
if "semantics.tar" in [f.name for f in tar.getmembers()]:
|
||||||
sig_filelist.append("semantics.tar")
|
sig_filelist.append("semantics.tar")
|
||||||
|
|
||||||
|
for f in sig_filelist:
|
||||||
|
tar.extract(f)
|
||||||
|
|
||||||
# Verify the data integrity signature first
|
# Verify the data integrity signature first
|
||||||
sigfile = open("signature", "r")
|
sigfile = open("signature", "r")
|
||||||
sig = int(sigfile.read(), 16)
|
sig = int(sigfile.read(), 16)
|
||||||
@ -676,6 +674,11 @@ class PatchFile(object):
|
|||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise ReleaseValidationFailure(msg)
|
raise ReleaseValidationFailure(msg)
|
||||||
|
|
||||||
|
# Restart script
|
||||||
|
for f in tar.getmembers():
|
||||||
|
if f.name not in sig_filelist:
|
||||||
|
tar.extract(f)
|
||||||
|
|
||||||
tar = tarfile.open("metadata.tar")
|
tar = tarfile.open("metadata.tar")
|
||||||
tar.extractall()
|
tar.extractall()
|
||||||
|
|
||||||
|
@ -157,8 +157,7 @@ def write_xml_file(top,
|
|||||||
def get_release_from_patch(patchfile):
|
def get_release_from_patch(patchfile):
|
||||||
rel = ""
|
rel = ""
|
||||||
try:
|
try:
|
||||||
cmd = "tar xf %s -O metadata.tar | tar x -O" % patchfile
|
metadata_str = subprocess.check_output(['tar', '--to-command=tar -xO', '-xf', patchfile, 'metadata.tar'])
|
||||||
metadata_str = subprocess.check_output(cmd, shell=True)
|
|
||||||
root = ElementTree.fromstring(metadata_str)
|
root = ElementTree.fromstring(metadata_str)
|
||||||
# Extract release version
|
# Extract release version
|
||||||
rel = root.findtext('sw_version')
|
rel = root.findtext('sw_version')
|
||||||
@ -618,22 +617,21 @@ class PatchFile(object):
|
|||||||
# Open the patch file and extract the contents to the current dir
|
# Open the patch file and extract the contents to the current dir
|
||||||
tar = tarfile.open(path, "r:gz")
|
tar = tarfile.open(path, "r:gz")
|
||||||
|
|
||||||
filelist = []
|
tar.extract("signature")
|
||||||
for f in tar.getmembers():
|
try:
|
||||||
filelist.append(f.name)
|
tar.extract(detached_signature_file)
|
||||||
|
except KeyError:
|
||||||
if detached_signature_file not in filelist:
|
msg = "Patch has not been signed"
|
||||||
msg = "Patch not signed"
|
|
||||||
LOG.warning(msg)
|
LOG.warning(msg)
|
||||||
|
|
||||||
for f in filelist:
|
|
||||||
tar.extract(f)
|
|
||||||
|
|
||||||
# Filelist used for signature validation and verification
|
# Filelist used for signature validation and verification
|
||||||
sig_filelist = ["metadata.tar", "software.tar"]
|
sig_filelist = ["metadata.tar", "software.tar"]
|
||||||
if "semantics.tar" in filelist:
|
if "semantics.tar" in [f.name for f in tar.getmembers()]:
|
||||||
sig_filelist.append("semantics.tar")
|
sig_filelist.append("semantics.tar")
|
||||||
|
|
||||||
|
for f in sig_filelist:
|
||||||
|
tar.extract(f)
|
||||||
|
|
||||||
# Verify the data integrity signature first
|
# Verify the data integrity signature first
|
||||||
sigfile = open("signature", "r")
|
sigfile = open("signature", "r")
|
||||||
sig = int(sigfile.read(), 16)
|
sig = int(sigfile.read(), 16)
|
||||||
@ -669,6 +667,11 @@ class PatchFile(object):
|
|||||||
LOG.error(msg)
|
LOG.error(msg)
|
||||||
raise PatchValidationFailure(msg)
|
raise PatchValidationFailure(msg)
|
||||||
|
|
||||||
|
# Restart script
|
||||||
|
for f in tar.getmembers():
|
||||||
|
if f.name not in sig_filelist:
|
||||||
|
tar.extract(f)
|
||||||
|
|
||||||
tar = tarfile.open("metadata.tar")
|
tar = tarfile.open("metadata.tar")
|
||||||
tar.extractall()
|
tar.extractall()
|
||||||
|
|
||||||
|
@ -106,6 +106,14 @@ class FakeTar(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class NoSignatureTar(FakeTar):
|
||||||
|
def extract(self, filename):
|
||||||
|
if filename == "signature.v2": # pylint: disable=no-else-raise
|
||||||
|
raise KeyError("Signature doesn't exist")
|
||||||
|
else:
|
||||||
|
return filename
|
||||||
|
|
||||||
|
|
||||||
class CgcsPatchFunctionsTestCase(testtools.TestCase):
|
class CgcsPatchFunctionsTestCase(testtools.TestCase):
|
||||||
|
|
||||||
def create_element_tree_from_dict(self, tree_root, dict_obj):
|
def create_element_tree_from_dict(self, tree_root, dict_obj):
|
||||||
@ -208,9 +216,9 @@ class CgcsPatchFunctionsTestCase(testtools.TestCase):
|
|||||||
_mock_log_warning,
|
_mock_log_warning,
|
||||||
_mock_open):
|
_mock_open):
|
||||||
test_obj = PatchFile()
|
test_obj = PatchFile()
|
||||||
_mock_open.return_value = FakeTar(["file1"])
|
_mock_open.return_value = NoSignatureTar(["file1"])
|
||||||
self.assertRaises(PatchValidationFailure, test_obj.read_patch, "fake_path")
|
self.assertRaises(PatchValidationFailure, test_obj.read_patch, "fake_path")
|
||||||
_mock_log_warning.assert_any_call('Patch not signed')
|
_mock_log_warning.assert_any_call('Patch has not been signed')
|
||||||
_mock_log_error.assert_any_call('Patch failed verification')
|
_mock_log_error.assert_any_call('Patch failed verification')
|
||||||
|
|
||||||
@mock.patch.object(tarfile, "open")
|
@mock.patch.object(tarfile, "open")
|
||||||
|
Loading…
Reference in New Issue
Block a user