From: "Juraj Linkeš" <juraj.linkes@pantheon.tech>
To: thomas@monjalon.net, david.marchand@redhat.com,
Honnappa.Nagarahalli@arm.com, ohilyard@iol.unh.edu,
lijuan.tu@intel.com
Cc: dev@dpdk.org, "Juraj Linkeš" <juraj.linkes@pantheon.tech>
Subject: [RFC PATCH v1 13/15] dts: merge DTS framework/utils.py to DPDK
Date: Wed, 6 Apr 2022 14:56:04 +0000 [thread overview]
Message-ID: <20220406145606.2913834-14-juraj.linkes@pantheon.tech> (raw)
In-Reply-To: <20220406145606.2913834-1-juraj.linkes@pantheon.tech>
---
dts/framework/utils.py | 353 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 353 insertions(+)
create mode 100644 dts/framework/utils.py
diff --git a/dts/framework/utils.py b/dts/framework/utils.py
new file mode 100644
index 0000000000..8b22d24b0c
--- /dev/null
+++ b/dts/framework/utils.py
@@ -0,0 +1,353 @@
+# BSD LICENSE
+#
+# Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import inspect
+import json # json format
+import os
+import re
+import socket
+import struct
+import sys
+import threading
+import types
+from functools import wraps
+
+DTS_ENV_PAT = r"DTS_*"
+
+
+def create_parallel_locks(num_duts):
+ """
+ Create thread lock dictionary based on DUTs number
+ """
+ global locks_info
+ locks_info = []
+ for _ in range(num_duts):
+ lock_info = dict()
+ lock_info["update_lock"] = threading.RLock()
+ locks_info.append(lock_info)
+
+
+def parallel_lock(num=1):
+ """
+ Wrapper function for protect parallel threads, allow multiple threads
+ share one lock. Locks are created based on function name. Thread locks are
+ separated between duts according to argument 'dut_id'.
+ Parameter:
+ num: Number of parallel threads for the lock
+ """
+ global locks_info
+
+ def decorate(func):
+ @wraps(func)
+ def wrapper(*args, **kwargs):
+ if "dut_id" in kwargs:
+ dut_id = kwargs["dut_id"]
+ else:
+ dut_id = 0
+
+ # in case function arguments is not correct
+ if dut_id >= len(locks_info):
+ dut_id = 0
+
+ lock_info = locks_info[dut_id]
+ uplock = lock_info["update_lock"]
+
+ name = func.__name__
+ uplock.acquire()
+
+ if name not in lock_info:
+ lock_info[name] = dict()
+ lock_info[name]["lock"] = threading.RLock()
+ lock_info[name]["current_thread"] = 1
+ else:
+ lock_info[name]["current_thread"] += 1
+
+ lock = lock_info[name]["lock"]
+
+ # make sure when owned global lock, should also own update lock
+ if lock_info[name]["current_thread"] >= num:
+ if lock._is_owned():
+ print(
+ RED(
+ "DUT%d %s waiting for func lock %s"
+ % (dut_id, threading.current_thread().name, func.__name__)
+ )
+ )
+ lock.acquire()
+ else:
+ uplock.release()
+
+ try:
+ ret = func(*args, **kwargs)
+ except Exception as e:
+ if not uplock._is_owned():
+ uplock.acquire()
+
+ if lock._is_owned():
+ lock.release()
+ lock_info[name]["current_thread"] = 0
+ uplock.release()
+ raise e
+
+ if not uplock._is_owned():
+ uplock.acquire()
+
+ if lock._is_owned():
+ lock.release()
+ lock_info[name]["current_thread"] = 0
+
+ uplock.release()
+
+ return ret
+
+ return wrapper
+
+ return decorate
+
+
+def RED(text):
+ return "\x1B[" + "31;1m" + str(text) + "\x1B[" + "0m"
+
+
+def BLUE(text):
+ return "\x1B[" + "36;1m" + str(text) + "\x1B[" + "0m"
+
+
+def GREEN(text):
+ return "\x1B[" + "32;1m" + str(text) + "\x1B[" + "0m"
+
+
+def pprint(some_dict, serialzer=None):
+ """
+ Print JSON format dictionary object.
+ """
+ return json.dumps(some_dict, sort_keys=True, indent=4, default=serialzer)
+
+
+def regexp(s, to_match, allString=False):
+ """
+ Ensure that the re `to_match' only has one group in it.
+ """
+
+ scanner = re.compile(to_match, re.DOTALL)
+ if allString:
+ return scanner.findall(s)
+ m = scanner.search(s)
+ if m is None:
+ print(RED("Failed to match " + to_match + " in the string " + s))
+ return None
+ return m.group(1)
+
+
+def get_obj_funcs(obj, func_name_regex):
+ """
+ Return function list which name matched regex.
+ """
+ for func_name in dir(obj):
+ func = getattr(obj, func_name)
+ if callable(func) and re.match(func_name_regex, func.__name__):
+ yield func
+
+
+@parallel_lock()
+def remove_old_rsa_key(crb, ip):
+ """
+ Remove the old RSA key of specified IP on crb.
+ """
+ rsa_key_path = "~/.ssh/known_hosts"
+ remove_rsa_key_cmd = "sed -i '/%s/d' %s" % (ip, rsa_key_path)
+ crb.send_expect(remove_rsa_key_cmd, "# ")
+
+
+def human_read_number(num):
+ if num > 1000000:
+ num /= 1000000
+ return str(num) + "M"
+ elif num > 1000:
+ num /= 1000
+ return str(num) + "K"
+ else:
+ return str(num)
+
+
+def get_subclasses(module, clazz):
+ """
+ Get module attribute name and attribute.
+ """
+ for subclazz_name, subclazz in inspect.getmembers(module):
+ if (
+ hasattr(subclazz, "__bases__")
+ and subclazz.__bases__
+ and clazz in subclazz.__bases__
+ ):
+ yield (subclazz_name, subclazz)
+
+
+def copy_instance_attr(from_inst, to_inst):
+ for key in list(from_inst.__dict__.keys()):
+ to_inst.__dict__[key] = from_inst.__dict__[key]
+
+
+def create_mask(indexes):
+ """
+ Convert index to hex mask.
+ """
+ val = 0
+ for index in indexes:
+ val |= 1 << int(index)
+
+ return hex(val).rstrip("L")
+
+
+def convert_int2ip(value, ip_type=4):
+ """
+ @change:
+ 2019.0403 set default value
+ """
+ if ip_type == 4:
+ ip_str = socket.inet_ntop(socket.AF_INET, struct.pack("!I", value))
+ else:
+ h = value >> 64
+ l = value & ((1 << 64) - 1)
+ ip_str = socket.inet_ntop(socket.AF_INET6, struct.pack("!QQ", h, l))
+
+ return ip_str
+
+
+def convert_ip2int(ip_str, ip_type=4):
+ """
+ @change:
+ 2019.0403 set default value
+ """
+ if ip_type == 4:
+ ip_val = struct.unpack("!I", socket.inet_aton(ip_str))[0]
+ else:
+ _hex = socket.inet_pton(socket.AF_INET6, ip_str)
+ h, l = struct.unpack("!QQ", _hex)
+ ip_val = (h << 64) | l
+
+ return ip_val
+
+
+def convert_mac2long(mac_str):
+ """
+ convert the MAC type from the string into the int.
+ """
+ mac_hex = "0x"
+ for mac_part in mac_str.lower().split(":"):
+ mac_hex += mac_part
+ ret = int(mac_hex, 16)
+ return ret
+
+
+def convert_mac2str(mac_long):
+ """
+ convert the MAC type from the int into the string.
+ """
+ mac = hex(mac_long)[2:].zfill(12)
+ b = []
+ [b.append(mac[n : n + 2]) for n in range(len(mac)) if n % 2 == 0]
+ new_mac = ":".join(b)
+ return new_mac
+
+
+def get_backtrace_object(file_name, obj_name):
+ import inspect
+
+ frame = inspect.currentframe()
+ obj = None
+ found = False
+ while frame:
+ file_path = inspect.getsourcefile(frame)
+ call_file = file_path.split(os.sep)[-1]
+ if file_name == call_file:
+ found = True
+ break
+
+ frame = frame.f_back
+
+ if found:
+ obj = getattr(frame.f_locals["self"], obj_name, None)
+
+ return obj
+
+
+def check_crb_python_version(crb):
+ cmd = "python3 -V"
+ out = crb.send_expect(cmd, "#", 5)
+ pat = "Python (\d+).(\d+).(\d+)"
+ result = re.findall(pat, out)
+ if (
+ not result
+ or int(result[0][0]) < 3
+ or (int(result[0][0]) == 3 and int(result[0][1]) < 6)
+ or (int(result[0][0]) == 3 and int(result[0][1]) == 6 and int(result[0][2]) < 9)
+ ):
+ crb.logger.warning(
+ (
+ "WARNING: Tester node python version is lower than python 3.6, "
+ "it is deprecated for use in DTS, "
+ "and will not work in future releases."
+ )
+ )
+ crb.logger.warning("Please use Python >= 3.6.9 instead")
+
+
+def check_dts_python_version():
+ if (
+ sys.version_info.major < 3
+ or (sys.version_info.major == 3 and sys.version_info.minor < 6)
+ or (
+ sys.version_info.major == 3
+ and sys.version_info.minor == 6
+ and sys.version_info.micro < 9
+ )
+ ):
+ print(
+ RED(
+ (
+ "WARNING: Dts running node python version is lower than python 3.6, "
+ "it is deprecated for use in DTS, "
+ "and will not work in future releases."
+ )
+ ),
+ file=sys.stderr,
+ )
+ print(RED("Please use Python >= 3.6.9 instead"), file=sys.stderr)
+
+
+def get_module_path(module_name):
+ from importlib import import_module
+
+ _module = import_module(module_name)
+ _module_file_path = _module.__file__
+ del _module
+ return os.path.dirname(_module_file_path)
--
2.20.1
next prev parent reply other threads:[~2022-04-06 14:58 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-04-06 14:55 [RFC PATCH v1 00/15] merge DTS core files " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 01/15] dts: merge DTS dep/tclclient.tgz " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 02/15] dts: merge DTS dep/tgen.tgz " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 03/15] dts: merge DTS dts " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 04/15] dts: merge DTS framework/__init__.py " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 05/15] dts: merge DTS framework/asan_test.py " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 06/15] dts: merge DTS framework/checkCase.py " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 07/15] dts: merge DTS framework/dts.py " Juraj Linkeš
2022-04-06 14:55 ` [RFC PATCH v1 08/15] dts: merge DTS framework/exception.py " Juraj Linkeš
2022-04-06 14:56 ` [RFC PATCH v1 09/15] dts: merge DTS framework/logger.py " Juraj Linkeš
2022-04-06 14:56 ` [RFC PATCH v1 10/15] dts: merge DTS framework/packet.py " Juraj Linkeš
2022-04-06 14:56 ` [RFC PATCH v1 11/15] dts: merge DTS framework/project_dpdk.py " Juraj Linkeš
2022-04-06 14:56 ` [RFC PATCH v1 12/15] dts: merge DTS framework/serializer.py " Juraj Linkeš
2022-04-06 14:56 ` Juraj Linkeš [this message]
2022-04-06 14:56 ` [RFC PATCH v1 14/15] dts: merge DTS main.py " Juraj Linkeš
2022-04-06 14:56 ` [RFC PATCH v1 15/15] dts: merge DTS version.py " Juraj Linkeš
2022-04-07 5:04 ` [RFC PATCH v1 00/15] merge DTS core files " Jerin Jacob
2022-04-07 7:33 ` Thomas Monjalon
2022-04-11 7:41 ` Juraj Linkeš
2022-04-11 17:55 ` Honnappa Nagarahalli
2022-04-11 18:20 ` Owen Hilyard
2022-04-11 19:06 ` Honnappa Nagarahalli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220406145606.2913834-14-juraj.linkes@pantheon.tech \
--to=juraj.linkes@pantheon.tech \
--cc=Honnappa.Nagarahalli@arm.com \
--cc=david.marchand@redhat.com \
--cc=dev@dpdk.org \
--cc=lijuan.tu@intel.com \
--cc=ohilyard@iol.unh.edu \
--cc=thomas@monjalon.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).