feature: Support read service function maps.
This commit is contained in:
@@ -12,6 +12,8 @@ RUN sed -i s@/dl-cdn.alpinelinux.org/@/mirrors.ustc.edu.cn/@g /etc/apk/repositor
|
||||
&& pip3 install CIUnitTest \
|
||||
&& pip3 install pytelegraf \
|
||||
&& pip3 install dnspython \
|
||||
&& pip3 install prettytable \
|
||||
&& pip3 install pyyaml \
|
||||
&& mv /opt/dign_client/etc/client.conf /opt/dign_client/etc/client.conf.sample
|
||||
|
||||
WORKDIR /opt/dign_client
|
||||
|
||||
@@ -19,6 +19,7 @@ import sys
|
||||
import logging
|
||||
import copy
|
||||
from prettytable import PrettyTable,NONE,HEADER
|
||||
import yaml
|
||||
|
||||
class ConfigLoader:
|
||||
DEFAULT_CONFIGS = {
|
||||
@@ -162,9 +163,6 @@ class ConfigLoader:
|
||||
},
|
||||
'test_shaping_ratelimit_1000gbps_https': {
|
||||
'conn_timeout': 4,'max_recv_speed_large': 6553600
|
||||
},
|
||||
'start_time_random_delay_range': {
|
||||
'left_edge': 1,'right_edge': 30
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,6 +190,45 @@ class ConfigLoader:
|
||||
else:
|
||||
raise KeyError("%s not in configs or %s.%s not in configs." % (section, section, key))
|
||||
|
||||
class ServiceFunctionConfigLoader:
|
||||
TABLE_NAME = "service_function_maps"
|
||||
SF_NAME_KEY = "service_function_name"
|
||||
DEVICE_ID_KEY = "device_id"
|
||||
|
||||
def __init__(self, config_path, name_pattern):
|
||||
self._config_path = config_path
|
||||
self._name_pattern = name_pattern
|
||||
self._configs = None
|
||||
self._load_configs()
|
||||
self._pairs = self._read_name_id_pairs_by_name_pattern(self._name_pattern)
|
||||
|
||||
def _load_configs(self):
|
||||
try:
|
||||
with open(self._config_path, 'r') as f:
|
||||
load_configs = yaml.safe_load(f)
|
||||
if load_configs is not None:
|
||||
self._configs = load_configs
|
||||
else:
|
||||
print(f"Error: No config loaded from path: {self._config_path}")
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File not found: {self._config_path}")
|
||||
except yaml.YAMLError as e:
|
||||
print(f"Error parsing YAML file: {e}")
|
||||
|
||||
def _read_name_id_pairs_by_name_pattern(self, name_pattern):
|
||||
if (self._configs is None) or (self.TABLE_NAME not in self._configs):
|
||||
return []
|
||||
|
||||
return [
|
||||
{"name": item[self.SF_NAME_KEY], "id": int(item[self.DEVICE_ID_KEY])}
|
||||
for item in self._configs[self.TABLE_NAME]
|
||||
if re.match(name_pattern, item[self.SF_NAME_KEY])
|
||||
]
|
||||
|
||||
@property
|
||||
def name_id_pairs(self):
|
||||
return self._pairs
|
||||
|
||||
class CommandParser:
|
||||
COUNT_MIN = 1
|
||||
COUNT_MAX = 65535
|
||||
@@ -209,12 +246,20 @@ class CommandParser:
|
||||
help='Specifies the number of TSG diagnoses. Default: 1. Range: [1,65535].')
|
||||
parser.add_argument('-l','--loop', action='store_true', default = False,
|
||||
help='Enable TSG diagnose loop, exit when recv a signal.')
|
||||
parser.add_argument('--service_function_indexs', type = str, default = "0",
|
||||
help = "Specifies the service function indexs. Example: 0,2,4-6,7. Range: [0,63]")
|
||||
parser.add_argument('--service_function_names_regexp', type = str, default = '.+',
|
||||
help = "Regexp of the case names to run. Example: .+")
|
||||
parser.add_argument('--service_function_config_path', type = str, default = '/opt/dign_client/share/service_function_maps.yaml',
|
||||
help = "Specifies the service function config file, default /opt/dign_client/share/service_function_maps.yaml")
|
||||
parser.add_argument('--config_path', type = str, default = '/opt/dign_client/etc/client.conf',
|
||||
help='Specifies the config file, default /opt/dign_client/etc/client.conf')
|
||||
parser.add_argument('--case_names_regexp', type = str, default = '.+',
|
||||
help='Regexp of the case names to run. Example: .+')
|
||||
parser.add_argument('--enable_delay', action='store_true', default = False,
|
||||
help='Enable a random delay between 1 and 30 seconds before running a case.')
|
||||
parser.add_argument('--delay_left_edge', type = int, default = 1,
|
||||
help='The seconds of the delay left edge. Default: 1.')
|
||||
parser.add_argument('--delay_right_edge', type = int, default = 30,
|
||||
help='The seconds of the delay right edge. Default: 30.')
|
||||
|
||||
# parser.add_argument('-o','--compatible_mode', action='store_true', default = False, help='Tsg diagnose compatible mode to running')
|
||||
args = parser.parse_args()
|
||||
@@ -226,23 +271,21 @@ class CommandParser:
|
||||
self.__interval_s = args.interval
|
||||
self.__count = args.count
|
||||
self.__loop = args.loop
|
||||
self.__service_function_indexs = args.service_function_indexs
|
||||
self.__config_path = args.config_path
|
||||
self.__case_names_regexp = args.case_names_regexp
|
||||
self.__service_function_names_regexp = args.service_function_names_regexp
|
||||
self.__service_function_config_path = args.service_function_config_path
|
||||
self._enable_delay = args.enable_delay
|
||||
self._delay_left_edge = args.delay_left_edge
|
||||
self._delay_right_edge = args.delay_right_edge
|
||||
|
||||
def __is_legal_args(self, args) -> bool:
|
||||
if args.count < self.COUNT_MIN or args.count > self.COUNT_MAX:
|
||||
print("Error: the number of TSG diagnoses must in [1,65535]")
|
||||
return False
|
||||
|
||||
str_indexs = args.service_function_indexs.split(",")
|
||||
for item in str_indexs:
|
||||
if not re.match(self.INDEX_PATTERN, item):
|
||||
sub_indexs = item.split("-")
|
||||
if len(sub_indexs) != 2 or (not re.match(self.INDEX_PATTERN, sub_indexs[0])) or \
|
||||
(not re.match(self.INDEX_PATTERN, sub_indexs[1])) or (int(sub_indexs[1]) < int(sub_indexs[0])):
|
||||
print("Error: The service function indexs must in [0,63]")
|
||||
return False
|
||||
if args.delay_left_edge > args.delay_right_edge:
|
||||
print("Error: The delay in seconds on the left edge is greater than on the right edge.")
|
||||
|
||||
return True
|
||||
|
||||
@@ -257,22 +300,6 @@ class CommandParser:
|
||||
@property
|
||||
def loop(self):
|
||||
return self.__loop
|
||||
|
||||
@property
|
||||
def service_function_indexs(self):
|
||||
return self.__parse_service_function_indexs_str(self.__service_function_indexs)
|
||||
|
||||
def __parse_service_function_indexs_str(self, indexs_str: str) -> list:
|
||||
indexs = []
|
||||
str_indexs = indexs_str.split(",")
|
||||
for item in str_indexs:
|
||||
if re.match(self.INDEX_PATTERN, item):
|
||||
indexs.append(int(item))
|
||||
else:
|
||||
sub_str_indexs = item.split("-")
|
||||
indexs.extend([i for i in range(int(sub_str_indexs[0]), int(sub_str_indexs[1]) + 1)])
|
||||
indexs = list(set(indexs))
|
||||
return indexs
|
||||
|
||||
@property
|
||||
def config_path(self):
|
||||
@@ -282,6 +309,21 @@ class CommandParser:
|
||||
def case_names_regexp(self):
|
||||
return r"{}".format(self.__case_names_regexp)
|
||||
|
||||
@property
|
||||
def service_function_names_regexp(self):
|
||||
return r"{}".format(self.__service_function_names_regexp)
|
||||
|
||||
@property
|
||||
def service_function_config_path(self):
|
||||
return self.__service_function_config_path
|
||||
|
||||
@property
|
||||
def delay_seconds(self):
|
||||
if self._enable_delay:
|
||||
return random.randint(self._delay_left_edge, self._delay_right_edge)
|
||||
else:
|
||||
return None
|
||||
|
||||
class ServerAddressBuilder:
|
||||
IPv4_4TH_OCTET_LEFT_EDGE = 101
|
||||
DOMAIN_TO_PORT_LIST = [
|
||||
@@ -355,9 +397,10 @@ class URLTransferBuilder:
|
||||
try:
|
||||
self._setup_connection()
|
||||
self._perform_connection()
|
||||
self._close_connection()
|
||||
except pycurl.error as error_info:
|
||||
self._error_info = error_info
|
||||
finally:
|
||||
self._close_connection()
|
||||
|
||||
@property
|
||||
def response_code(self):
|
||||
@@ -519,7 +562,7 @@ class DNSResponseAnalyzer:
|
||||
|
||||
def is_error_type_equal(self, present_error_info, desired_type):
|
||||
if present_error_info is None:
|
||||
return False, f"Error: The error info is None. Maybe the relevant actions didn’t take effect."
|
||||
return False, f"Error: The error info is None. Maybe the relevant actions didn't take effect."
|
||||
|
||||
if type(present_error_info) == desired_type:
|
||||
return True, None
|
||||
@@ -764,6 +807,9 @@ class ShapingCaseRunner:
|
||||
is_error_none = self._analyzer.is_pycurl_error_none(conn.error_info)
|
||||
if not is_error_none[0]:
|
||||
return False, is_error_none[1]
|
||||
is_code_equal = self._analyzer.is_response_code_equal(conn.response_code, 200)
|
||||
if not is_code_equal[0]:
|
||||
return False, is_code_equal[1]
|
||||
return True, None
|
||||
|
||||
def rate_limit_1000gbps_protocol_https(self, url, resolves, conn_timeout, max_recv_speed_large):
|
||||
@@ -772,6 +818,9 @@ class ShapingCaseRunner:
|
||||
is_error_none = self._analyzer.is_pycurl_error_none(conn.error_info)
|
||||
if not is_error_none[0]:
|
||||
return False, is_error_none[1]
|
||||
is_code_equal = self._analyzer.is_response_code_equal(conn.response_code, 200)
|
||||
if not is_code_equal[0]:
|
||||
return False, is_code_equal[1]
|
||||
is_cert_matched = self._analyzer.is_cert_issuer_matched(conn.cert_issuer, r'\bCN[\s]*=[\s]*BadSSL\b')
|
||||
if not is_cert_matched[0]:
|
||||
return False, is_cert_matched[1]
|
||||
@@ -1063,9 +1112,12 @@ class DiagnoseCasesRunner:
|
||||
self._loop = cmd_parser.loop
|
||||
self._count = cmd_parser.count
|
||||
self._interval_s = cmd_parser.interval_s
|
||||
self._service_function_indexs = cmd_parser.service_function_indexs
|
||||
self._case_names_regexp = cmd_parser.case_names_regexp
|
||||
self._config_path = cmd_parser.config_path
|
||||
self._service_function_names_regexp = cmd_parser.service_function_names_regexp
|
||||
self._service_function_config_path = cmd_parser.service_function_config_path
|
||||
self._random_delay_seconds = cmd_parser.delay_seconds
|
||||
|
||||
self._config_loader = ConfigLoader(self._config_path)
|
||||
|
||||
self._proxy_case = ProxyCasesRunner()
|
||||
@@ -1339,6 +1391,9 @@ class DiagnoseCasesRunner:
|
||||
]
|
||||
|
||||
def run_cases(self):
|
||||
if self._random_delay_seconds is not None:
|
||||
time.sleep(self._random_delay_seconds)
|
||||
|
||||
run_count = 1
|
||||
while True:
|
||||
print("\nRUN %d" % run_count)
|
||||
@@ -1349,14 +1404,15 @@ class DiagnoseCasesRunner:
|
||||
run_count = run_count + 1
|
||||
|
||||
def __run_cases_by_service_function_ids(self):
|
||||
for sf_id in self._service_function_indexs:
|
||||
sf_loader = ServiceFunctionConfigLoader(self._service_function_config_path, self._service_function_names_regexp)
|
||||
for sf_pair in sf_loader.name_id_pairs:
|
||||
start_timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
print(format(("Service function id:" + str(sf_id) + ",Test start time: " + start_timestamp),'#^70s'))
|
||||
print(format(("Service function name: " + str(sf_pair["name"]) + ",Test start time: " + start_timestamp),'#^100s'))
|
||||
|
||||
self._run_cases_in_one_service_function_id(sf_id)
|
||||
self._run_cases_in_one_service_function_id(sf_pair["id"])
|
||||
|
||||
end_timestamp = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
|
||||
print(format(("Service function id:" + str(sf_id) + ",Test end time: " + end_timestamp),'=^70s'))
|
||||
print(format(("Service function name: " + str(sf_pair["name"]) + ",Test end time: " + end_timestamp),'=^100s'))
|
||||
|
||||
def _run_cases_in_one_service_function_id(self, service_function_id):
|
||||
resolve_Builder = ServerAddressBuilder(service_function_id)
|
||||
|
||||
@@ -236,10 +236,3 @@ max_recv_speed_large = 6553600
|
||||
enabled = 1
|
||||
conn_timeout = 4
|
||||
max_recv_speed_large = 6553600
|
||||
|
||||
[start_time_random_delay_range]
|
||||
enabled = 0
|
||||
#Left_edge is the left edge of the randomly generated time in seconds
|
||||
left_edge = 0
|
||||
#Left_edge is the right edge of the randomly generated time in seconds
|
||||
right_edge = 30
|
||||
|
||||
Reference in New Issue
Block a user