diff --git a/common/src/stack/report-system/command/report/system/tests/test_sles_patch.py b/common/src/stack/report-system/command/report/system/tests/test_sles_patch.py new file mode 100644 index 000000000..49d8091b2 --- /dev/null +++ b/common/src/stack/report-system/command/report/system/tests/test_sles_patch.py @@ -0,0 +1,114 @@ +import pytest +import os +import stack.api +import hashlib +import json + + +# Returns a hash of filename +def Get_A_Hash(filename): + hasher = hashlib.md5() + with open(filename, 'rb') as f: + buf = f.read() + hasher.update(buf) + + return hasher.hexdigest() + +# Compare 2 hashes and return boolean +def Hashes_Match(hash1, hash2, filename): + if hash1 == hash2: + return True + else: + print('%s hash did NOT match' % filename) + return False + +# Grab all found SLES versions and returns a list +def Get_SLES_Flavors(): + base_dir = '/export/stack/pallets/SLES/' + sles_flavors = os.listdir(base_dir) + return sles_flavors + + +# Verify SLES patches are installed +def test_sles_pallet_patched(host): + # Only run on SLES + if not os.path.exists('/etc/SuSE-release'): + print('OS is not SLES, skipping test') + return 0 + + error_occurred = False + base_dir = '/export/stack/pallets/SLES/' + sles_flavors = Get_SLES_Flavors() + assert sles_flavors + # Just need a new line for readability + print('') + + # Test every sles flavor found + for sles_flavor in sles_flavors: + # Make sure installed patches match what's under /opt/stack/pallet-patches + patch_dir = '/opt/stack/pallet-patches' + patch_dir_files = [] + for (dir_path, dir_names, filenames) in os.walk(patch_dir): + # Only want particular SLES version + if sles_flavor in dir_path: + patch_dir_files += [os.path.join(dir_path, file) for file in filenames if file == 'content'] + + # We should have non-empty list here + assert patch_dir_files + + # Find img file from patch directory in SLES pallet + result = host.run(f'grep .img {patch_dir_files[0]}\n') + + # Last item is the partial image path + part_img_file = result.stdout.split()[-1] + + # Find full path to /export/stack/pallets/SLES/? + result = host.run(f'probepal {base_dir}') + assert result.rc == 0 + palinfo = json.loads(result.stdout) + + # It shouldn't be empty + assert palinfo[base_dir] + + sles_pallet_root = None + for pallet in palinfo[base_dir]: + # Grab the right sles sp level + if pallet['name'] == 'SLES' and pallet['version'] == sles_flavor: + assert host.file(f"{pallet['pallet_root']}").is_directory + sles_pallet_root = pallet['pallet_root'] + break + + # .img file should exist in sles pallet directory in relative path + assert os.path.exists(sles_pallet_root + '/' + part_img_file) + + # Find out where is stack-sles*images*.rpm file + result = host.run('find / -name "*stack-sles-*.rpm" -print\n') + RPM = result.stdout.splitlines()[0] + + # Make sure we found pm file + assert '.rpm' in RPM + + result = host.run(f'rpm -qp --dump {RPM}\n') + # We don't want file under /opt/stack/images to be included in this list + patch_files = [line.split() for line in result.stdout.splitlines() if sles_flavor in line and '/images/' not in line] + + # Verify file(s) from images RPM actually exist + for this_list in patch_files: + file_to_check = this_list[0] + assert os.path.exists(file_to_check) + hash_value = this_list[3] + # Grab hash for this file in patch directory and compare against hash from img file. They should match + hash_value1 = Get_A_Hash(file_to_check) + if Hashes_Match(hash_value, hash_value1, file_to_check) == False: + error_occurred = True + + # Grab hash for this file in SLES pallet directory and compare against hash from img file. They should match + # Need to build the equivalent path first + temp_path_list = file_to_check.split('add-stacki-squashfs') + temp_path = sles_pallet_root + temp_path_list[1] + hash_value1 = Get_A_Hash(temp_path) + if Hashes_Match(hash_value, hash_value1, temp_path) == False: + error_occurred = True + + # Overall result for hash check + assert error_occurred == False