264 lines
15 KiB
Python
264 lines
15 KiB
Python
|
# Copyright (C) 2015 Intel Corporation
|
||
|
#
|
||
|
# Released under the MIT license (see COPYING.MIT)
|
||
|
|
||
|
# Provides functions to help with exporting binaries obtained from built targets
|
||
|
|
||
|
import os, re, glob as g, shutil as sh,sys
|
||
|
from time import sleep
|
||
|
from .commands import runCmd
|
||
|
from difflib import SequenceMatcher as SM
|
||
|
|
||
|
try:
|
||
|
import bb
|
||
|
except ImportError:
|
||
|
class my_log():
|
||
|
def __init__(self):
|
||
|
pass
|
||
|
def plain(self, msg):
|
||
|
if msg:
|
||
|
print(msg)
|
||
|
def warn(self, msg):
|
||
|
if msg:
|
||
|
print("WARNING: " + msg)
|
||
|
def fatal(self, msg):
|
||
|
if msg:
|
||
|
print("FATAL:" + msg)
|
||
|
sys.exit(1)
|
||
|
bb = my_log()
|
||
|
|
||
|
|
||
|
def determine_if_poky_env():
|
||
|
"""
|
||
|
used to determine if we are inside the poky env or not. Usefull for remote machine where poky is not present
|
||
|
"""
|
||
|
check_env = True if ("/scripts" and "/bitbake/bin") in os.getenv("PATH") else False
|
||
|
return check_env
|
||
|
|
||
|
|
||
|
def get_dest_folder(tune_features, folder_list):
|
||
|
"""
|
||
|
Function to determine what rpm deploy dir to choose for a given architecture based on TUNE_FEATURES
|
||
|
"""
|
||
|
features_list = tune_features.split(" ")
|
||
|
features_list.reverse()
|
||
|
features_list = "_".join(features_list)
|
||
|
match_rate = 0
|
||
|
best_match = None
|
||
|
for folder in folder_list:
|
||
|
curr_match_rate = SM(None, folder, features_list).ratio()
|
||
|
if curr_match_rate > match_rate:
|
||
|
match_rate = curr_match_rate
|
||
|
best_match = folder
|
||
|
return best_match
|
||
|
|
||
|
|
||
|
def process_binaries(d, params):
|
||
|
param_list = params
|
||
|
export_env = d.getVar("TEST_EXPORT_ONLY")
|
||
|
|
||
|
def extract_binary(pth_to_pkg, dest_pth=None):
|
||
|
cpio_command = runCmd("which cpio")
|
||
|
rpm2cpio_command = runCmd("ls /usr/bin/rpm2cpio")
|
||
|
if (cpio_command.status != 0) and (rpm2cpio_command.status != 0):
|
||
|
bb.fatal("Either \"rpm2cpio\" or \"cpio\" tools are not available on your system."
|
||
|
"All binaries extraction processes will not be available, crashing all related tests."
|
||
|
"Please install them according to your OS recommendations") # will exit here
|
||
|
if dest_pth:
|
||
|
os.chdir(dest_pth)
|
||
|
else:
|
||
|
os.chdir("%s" % os.sep)# this is for native package
|
||
|
extract_bin_command = runCmd("%s %s | %s -idm" % (rpm2cpio_command.output, pth_to_pkg, cpio_command.output)) # semi-hardcoded because of a bug on poky's rpm2cpio
|
||
|
return extract_bin_command
|
||
|
|
||
|
if determine_if_poky_env(): # machine with poky environment
|
||
|
exportpath = d.getVar("TEST_EXPORT_DIR") if export_env else d.getVar("DEPLOY_DIR")
|
||
|
rpm_deploy_dir = d.getVar("DEPLOY_DIR_RPM")
|
||
|
arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(rpm_deploy_dir))
|
||
|
arch_rpm_dir = os.path.join(rpm_deploy_dir, arch)
|
||
|
extracted_bin_dir = os.path.join(exportpath,"binaries", arch, "extracted_binaries")
|
||
|
packaged_bin_dir = os.path.join(exportpath,"binaries", arch, "packaged_binaries")
|
||
|
# creating necessary directory structure in case testing is done in poky env.
|
||
|
if export_env == "0":
|
||
|
if not os.path.exists(extracted_bin_dir): bb.utils.mkdirhier(extracted_bin_dir)
|
||
|
if not os.path.exists(packaged_bin_dir): bb.utils.mkdirhier(packaged_bin_dir)
|
||
|
|
||
|
if param_list[3] == "native":
|
||
|
if export_env == "1": #this is a native package and we only need to copy it. no need for extraction
|
||
|
native_rpm_dir = os.path.join(rpm_deploy_dir, get_dest_folder("{} nativesdk".format(d.getVar("BUILD_SYS")), os.listdir(rpm_deploy_dir)))
|
||
|
native_rpm_file_list = [item for item in os.listdir(native_rpm_dir) if re.search("nativesdk-" + param_list[0] + "-([0-9]+\.*)", item)]
|
||
|
if not native_rpm_file_list:
|
||
|
bb.warn("Couldn't find any version of {} native package. Related tests will most probably fail.".format(param_list[0]))
|
||
|
return ""
|
||
|
for item in native_rpm_file_list:# will copy all versions of package. Used version will be selected on remote machine
|
||
|
bb.plain("Copying native package file: %s" % item)
|
||
|
sh.copy(os.path.join(rpm_deploy_dir, native_rpm_dir, item), os.path.join(d.getVar("TEST_EXPORT_DIR"), "binaries", "native"))
|
||
|
else: # nothing to do here; running tests under bitbake, so we asume native binaries are in sysroots dir.
|
||
|
if param_list[1] or param_list[4]:
|
||
|
bb.warn("Native binary %s %s%s. Running tests under bitbake environment. Version can't be checked except when the test itself does it"
|
||
|
" and binary can't be removed."%(param_list[0],"has assigned ver. " + param_list[1] if param_list[1] else "",
|
||
|
", is marked for removal" if param_list[4] else ""))
|
||
|
else:# the package is target aka DUT intended and it is either required to be delivered in an extracted form or in a packaged version
|
||
|
target_rpm_file_list = [item for item in os.listdir(arch_rpm_dir) if re.search(param_list[0] + "-([0-9]+\.*)", item)]
|
||
|
if not target_rpm_file_list:
|
||
|
bb.warn("Couldn't find any version of target package %s. Please ensure it was built. "
|
||
|
"Related tests will probably fail." % param_list[0])
|
||
|
return ""
|
||
|
if param_list[2] == "rpm": # binary should be deployed as rpm; (other, .deb, .ipk? ; in the near future)
|
||
|
for item in target_rpm_file_list: # copying all related rpm packages. "Intuition" reasons, someone may need other versions too. Deciding later on version
|
||
|
bb.plain("Copying target specific packaged file: %s" % item)
|
||
|
sh.copy(os.path.join(arch_rpm_dir, item), packaged_bin_dir)
|
||
|
return "copied"
|
||
|
else: # it is required to extract the binary
|
||
|
if param_list[1]: # the package is versioned
|
||
|
for item in target_rpm_file_list:
|
||
|
if re.match(".*-{}-.*\.rpm".format(param_list[1]), item):
|
||
|
destination = os.path.join(extracted_bin_dir,param_list[0], param_list[1])
|
||
|
bb.utils.mkdirhier(destination)
|
||
|
extract_binary(os.path.join(arch_rpm_dir, item), destination)
|
||
|
break
|
||
|
else:
|
||
|
bb.warn("Couldn't find the desired version %s for target binary %s. Related test cases will probably fail." % (param_list[1], param_list[0]))
|
||
|
return ""
|
||
|
return "extracted"
|
||
|
else: # no version provided, just extract one binary
|
||
|
destination = os.path.join(extracted_bin_dir,param_list[0],
|
||
|
re.search(".*-([0-9]+\.[0-9]+)-.*rpm", target_rpm_file_list[0]).group(1))
|
||
|
bb.utils.mkdirhier(destination)
|
||
|
extract_binary(os.path.join(arch_rpm_dir, target_rpm_file_list[0]), destination)
|
||
|
return "extracted"
|
||
|
else: # remote machine
|
||
|
binaries_path = os.getenv("bin_dir")# in order to know where the binaries are, bin_dir is set as env. variable
|
||
|
if param_list[3] == "native": #need to extract the native pkg here
|
||
|
native_rpm_dir = os.path.join(binaries_path, "native")
|
||
|
native_rpm_file_list = os.listdir(native_rpm_dir)
|
||
|
for item in native_rpm_file_list:
|
||
|
if param_list[1] and re.match("nativesdk-{}-{}-.*\.rpm".format(param_list[0], param_list[1]), item): # native package has version
|
||
|
extract_binary(os.path.join(native_rpm_dir, item))
|
||
|
break
|
||
|
else:# just copy any related native binary
|
||
|
found_version = re.match("nativesdk-{}-([0-9]+\.[0-9]+)-".format(param_list[0]), item).group(1)
|
||
|
if found_version:
|
||
|
extract_binary(os.path.join(native_rpm_dir, item))
|
||
|
else:
|
||
|
bb.warn("Couldn't find native package %s%s. Related test cases will be influenced." %
|
||
|
(param_list[0], " with version " + param_list[1] if param_list[1] else ""))
|
||
|
return
|
||
|
|
||
|
else: # this is for target device
|
||
|
if param_list[2] == "rpm":
|
||
|
return "No need to extract, this is an .rpm file"
|
||
|
arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(binaries_path))
|
||
|
extracted_bin_path = os.path.join(binaries_path, arch, "extracted_binaries")
|
||
|
extracted_bin_list = [item for item in os.listdir(extracted_bin_path)]
|
||
|
packaged_bin_path = os.path.join(binaries_path, arch, "packaged_binaries")
|
||
|
packaged_bin_file_list = os.listdir(packaged_bin_path)
|
||
|
# see if the package is already in the extracted ones; maybe it was deployed when exported the env.
|
||
|
if os.path.exists(os.path.join(extracted_bin_path, param_list[0], param_list[1] if param_list[1] else "")):
|
||
|
return "binary %s is already extracted" % param_list[0]
|
||
|
else: # we need to search for it in the packaged binaries directory. It may have been shipped after export
|
||
|
for item in packaged_bin_file_list:
|
||
|
if param_list[1]:
|
||
|
if re.match("%s-%s.*rpm" % (param_list[0], param_list[1]), item): # package with version
|
||
|
if not os.path.exists(os.path.join(extracted_bin_path, param_list[0],param_list[1])):
|
||
|
os.makedirs(os.path.join(extracted_bin_path, param_list[0], param_list[1]))
|
||
|
extract_binary(os.path.join(packaged_bin_path, item), os.path.join(extracted_bin_path, param_list[0],param_list[1]))
|
||
|
bb.plain("Using {} for {}".format(os.path.join(packaged_bin_path, item), param_list[0]))
|
||
|
break
|
||
|
else:
|
||
|
if re.match("%s-.*rpm" % param_list[0], item):
|
||
|
found_version = re.match(".*-([0-9]+\.[0-9]+)-", item).group(1)
|
||
|
if not os.path.exists(os.path.join(extracted_bin_path, param_list[0], found_version)):
|
||
|
os.makedirs(os.path.join(extracted_bin_path, param_list[0], found_version))
|
||
|
bb.plain("Used ver. %s for %s" % (found_version, param_list[0]))
|
||
|
extract_binary(os.path.join(packaged_bin_path, item), os.path.join(extracted_bin_path, param_list[0], found_version))
|
||
|
break
|
||
|
else:
|
||
|
bb.warn("Couldn't find target package %s%s. Please ensure it is available "
|
||
|
"in either of these directories: extracted_binaries or packaged_binaries. "
|
||
|
"Related tests will probably fail." % (param_list[0], " with version " + param_list[1] if param_list[1] else ""))
|
||
|
return
|
||
|
return "Binary %s extracted successfully." % param_list[0]
|
||
|
|
||
|
|
||
|
def files_to_copy(base_dir):
|
||
|
"""
|
||
|
Produces a list of files relative to the base dir path sent as param
|
||
|
:return: the list of relative path files
|
||
|
"""
|
||
|
files_list = []
|
||
|
dir_list = [base_dir]
|
||
|
count = 1
|
||
|
dir_count = 1
|
||
|
while (dir_count == 1 or dir_count != count):
|
||
|
count = dir_count
|
||
|
for dir in dir_list:
|
||
|
for item in os.listdir(dir):
|
||
|
if os.path.isdir(os.path.join(dir, item)) and os.path.join(dir, item) not in dir_list:
|
||
|
dir_list.append(os.path.join(dir, item))
|
||
|
dir_count = len(dir_list)
|
||
|
elif os.path.join(dir, item) not in files_list and os.path.isfile(os.path.join(dir, item)):
|
||
|
files_list.append(os.path.join(dir, item))
|
||
|
return files_list
|
||
|
|
||
|
|
||
|
def send_bin_to_DUT(d,params):
|
||
|
from oeqa.oetest import oeRuntimeTest
|
||
|
param_list = params
|
||
|
cleanup_list = list()
|
||
|
bins_dir = os.path.join(d.getVar("TEST_EXPORT_DIR"), "binaries") if determine_if_poky_env() \
|
||
|
else os.getenv("bin_dir")
|
||
|
arch = get_dest_folder(d.getVar("TUNE_FEATURES"), os.listdir(bins_dir))
|
||
|
arch_rpms_dir = os.path.join(bins_dir, arch, "packaged_binaries")
|
||
|
extracted_bin_dir = os.path.join(bins_dir, arch, "extracted_binaries", param_list[0])
|
||
|
|
||
|
def send_extracted_binary():
|
||
|
bin_local_dir = os.path.join(extracted_bin_dir, param_list[1] if param_list[1] else os.listdir(extracted_bin_dir)[0])
|
||
|
for item in files_to_copy(bin_local_dir):
|
||
|
split_path = item.split(bin_local_dir)[1]
|
||
|
path_on_DUT = split_path if split_path[0] is "/" else "/" + split_path # create the path as on DUT; eg. /usr/bin/bin_file
|
||
|
(status, output) = oeRuntimeTest.tc.target.copy_to(item, path_on_DUT)
|
||
|
if status != 0:
|
||
|
bb.warn("Failed to copy %s binary file %s on the remote target: %s" %
|
||
|
(param_list[0], "ver. " + param_list[1] if param_list[1] else "", d.getVar("MACHINE")))
|
||
|
return
|
||
|
if param_list[4] == "rm":
|
||
|
cleanup_list.append(path_on_DUT)
|
||
|
return cleanup_list
|
||
|
|
||
|
def send_rpm(remote_path): # if it is not required to have an extracted binary, but to send an .rpm file
|
||
|
rpm_to_send = ""
|
||
|
for item in os.listdir(arch_rpms_dir):
|
||
|
if param_list[1] and re.match("%s-%s-.*rpm"%(param_list[0], param_list[1]), item):
|
||
|
rpm_to_send = item
|
||
|
break
|
||
|
elif re.match("%s-[0-9]+\.[0-9]+-.*rpm" % param_list[0], item):
|
||
|
rpm_to_send = item
|
||
|
break
|
||
|
else:
|
||
|
bb.warn("No rpm package found for %s %s in .rpm files dir %s. Skipping deployment." %
|
||
|
(param_list[0], "ver. " + param_list[1] if param_list[1] else "", rpms_file_dir) )
|
||
|
return
|
||
|
(status, output) = oeRuntimeTest.tc.target.copy_to(os.path.join(arch_rpms_dir, rpm_to_send), remote_path)
|
||
|
if status != 0:
|
||
|
bb.warn("Failed to copy %s on the remote target: %s" %(param_list[0], d.getVar("MACHINE")))
|
||
|
return
|
||
|
if param_list[4] == "rm":
|
||
|
cleanup_list.append(os.path.join(remote_path, rpm_to_send))
|
||
|
return cleanup_list
|
||
|
|
||
|
if param_list[2] == "rpm": # send an .rpm file
|
||
|
return send_rpm("/home/root") # rpms will be sent on home dir of remote machine
|
||
|
else:
|
||
|
return send_extracted_binary()
|
||
|
|
||
|
|
||
|
def rm_bin(removal_list): # need to know both if the binary is sent archived and the path where it is sent if archived
|
||
|
from oeqa.oetest import oeRuntimeTest
|
||
|
for item in removal_list:
|
||
|
(status,output) = oeRuntimeTest.tc.target.run("rm " + item)
|
||
|
if status != 0:
|
||
|
bb.warn("Failed to remove: %s. Please ensure connection with the target device is up and running and "
|
||
|
"you have the needed rights." % item)
|
||
|
|