Updated PTP setup configuration
Change-Id: I852f670cc66d63b0504d742002e4a1cf3acd1aac Signed-off-by: Guntaka Umashankar Reddy <umashankarguntaka.reddy@windriver.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
from typing import Any
|
||||
from typing import Any, List, Tuple
|
||||
|
||||
from framework.logging.automation_logger import get_logger
|
||||
from framework.validation.validation import validate_equals, validate_equals_with_retry, validate_str_contains
|
||||
@@ -10,9 +10,10 @@ from keywords.cloud_platform.system.ptp.system_host_ptp_instance_keywords import
|
||||
from keywords.cloud_platform.system.ptp.system_ptp_instance_keywords import SystemPTPInstanceKeywords
|
||||
from keywords.cloud_platform.system.ptp.system_ptp_instance_parameter_keywords import SystemPTPInstanceParameterKeywords
|
||||
from keywords.cloud_platform.system.ptp.system_ptp_interface_keywords import SystemPTPInterfaceKeywords
|
||||
from keywords.linux.systemctl.systemctl_status_keywords import SystemCTLStatusKeywords
|
||||
from keywords.ptp.gnss_keywords import GnssKeywords
|
||||
from keywords.ptp.setup.object.ptp_setup import PTPSetup
|
||||
from keywords.ptp.setup.ptp_setup_reader import PTPSetupKeywords
|
||||
from starlingx.keywords.linux.systemctl.systemctl_status_keywords import SystemCTLStatusKeywords
|
||||
|
||||
|
||||
class PTPSetupExecutorKeywords(BaseKeyword):
|
||||
@@ -57,24 +58,7 @@ class PTPSetupExecutorKeywords(BaseKeyword):
|
||||
system_ptp_instance_apply_output = system_ptp_instance_keywords.system_ptp_instance_apply()
|
||||
validate_equals(system_ptp_instance_apply_output, "Applying the PTP Instance configuration", "apply PTP instance configuration")
|
||||
|
||||
# After applying the instance configuration, it needs to check whether the services are available or not.
|
||||
def check_ptp4l_status() -> bool:
|
||||
"""
|
||||
Checks if the PTP4L service is active and running.
|
||||
|
||||
Returns:
|
||||
bool: True if the service is active and running, False otherwise.
|
||||
"""
|
||||
ptp4l_status_output = SystemCTLStatusKeywords(self.ssh_connection).get_status("ptp4l@*")
|
||||
if not ptp4l_status_output:
|
||||
return False # Handle the case of an empty list
|
||||
|
||||
for line in ptp4l_status_output:
|
||||
if "Active: active (running)" in line:
|
||||
return True
|
||||
return False
|
||||
|
||||
validate_equals_with_retry(check_ptp4l_status, True, 600)
|
||||
self.wait_for_ptp_configuration_to_update_after_applying()
|
||||
|
||||
def add_all_ptp_configurations_for_ptp4l_service(self):
|
||||
"""
|
||||
@@ -219,3 +203,60 @@ class PTPSetupExecutorKeywords(BaseKeyword):
|
||||
Exception: raised when validate fails
|
||||
"""
|
||||
validate_equals(set(observed_value.split()), set(expected_value.split()), validation_description)
|
||||
|
||||
def wait_for_ptp_configuration_to_update_after_applying(self) -> None:
|
||||
"""
|
||||
Wait for the PTP configuration to update after applying
|
||||
|
||||
Returns: None
|
||||
|
||||
Raises:
|
||||
TimeoutError: raised when validate does not equal in the required time
|
||||
"""
|
||||
gnss_keywords = GnssKeywords()
|
||||
|
||||
# wait for systemctl status
|
||||
def check_ptp4l_status() -> bool:
|
||||
"""
|
||||
Checks if the PTP4L service is active and running.
|
||||
|
||||
Returns:
|
||||
bool: True if the service is active and running, False otherwise.
|
||||
"""
|
||||
ptp4l_status_output = SystemCTLStatusKeywords(self.ssh_connection).get_status("ptp4l@*")
|
||||
return any("Active: active (running)" in line for line in ptp4l_status_output or [])
|
||||
|
||||
validate_equals_with_retry(check_ptp4l_status, True, "systemctl status for ptp4l", 120, 30)
|
||||
|
||||
# wait for SMA status
|
||||
check_sma_status = False
|
||||
for clock_instance_obj in self.clock_setup_list:
|
||||
|
||||
ifaces_to_check = [(host, iface) for host in clock_instance_obj.get_instance_hostnames() for ptp_host_if in clock_instance_obj.get_ptp_interfaces() if "input" in ptp_host_if.get_ptp_interface_parameter() for iface in filter(None, ptp_host_if.get_interfaces_for_hostname(host))]
|
||||
|
||||
for host, interface in ifaces_to_check:
|
||||
pci_address = gnss_keywords.get_pci_slot_name(host, interface)
|
||||
cgu_location = f"/sys/kernel/debug/ice/{pci_address}/cgu"
|
||||
gnss_keywords.validate_gnss_1pps_state_and_pps_dpll_status(host, cgu_location, "SMA1", "valid", ["locked_ho_acq"], 120, 30)
|
||||
check_sma_status = True
|
||||
break
|
||||
|
||||
if check_sma_status:
|
||||
break
|
||||
|
||||
# wait for GNSS status
|
||||
check_gnss_status = False
|
||||
for ts2phc_instance_obj in self.ts2phc_setup_list:
|
||||
expected_gnss_port = gnss_keywords.extract_gnss_port(ts2phc_instance_obj.get_instance_parameters())
|
||||
if not expected_gnss_port:
|
||||
continue
|
||||
ifaces_to_check = [(host, iface) for host in ts2phc_instance_obj.get_instance_hostnames() for ptp_host_if in ts2phc_instance_obj.get_ptp_interfaces() for iface in filter(None, ptp_host_if.get_interfaces_for_hostname(host)) if gnss_keywords.get_gnss_serial_port_from_gnss_directory(host, iface) == expected_gnss_port]
|
||||
for host, interface in ifaces_to_check:
|
||||
pci_address = gnss_keywords.get_pci_slot_name(host, interface)
|
||||
cgu_location = f"/sys/kernel/debug/ice/{pci_address}/cgu"
|
||||
gnss_keywords.validate_gnss_1pps_state_and_pps_dpll_status(host, cgu_location, "GNSS-1PPS", "valid", ["locked_ho_acq"], 120, 30)
|
||||
check_gnss_status = True
|
||||
break
|
||||
|
||||
if check_gnss_status:
|
||||
break
|
||||
|
@@ -43,10 +43,6 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
self.clock_setup_list = ptp_setup.get_clock_setup_list()
|
||||
|
||||
self.ptp4l_expected_list_objects = ptp_setup.get_expected_ptp4l_list()
|
||||
self.expected_parent_data_set_object = ptp_setup.get_parent_data_set()
|
||||
self.expected_time_properties_data_set_object = ptp_setup.get_time_properties_data_set()
|
||||
self.expected_grandmaster_settings_tbc_object = ptp_setup.get_grandmaster_settings_tbc()
|
||||
self.expected_grandmaster_settings_tgm_object = ptp_setup.get_grandmaster_settings_tgm()
|
||||
|
||||
def verify_all_ptp_configurations(self) -> None:
|
||||
"""
|
||||
@@ -131,7 +127,7 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
instance_parameters = instance_obj.get_instance_parameters()
|
||||
|
||||
for hostname in hostnames:
|
||||
if service_type == "phc2sys":
|
||||
if service_type == "phc2sys" and "cmdline_opts" in instance_parameters: # Here the PHC service is using the clock from the NIC, not from the PTP instance.
|
||||
systemctl_status_Keywords.verify_ptp_status_and_instance_parameters_on_hostname(hostname, name, service_name, instance_parameters)
|
||||
else:
|
||||
systemctl_status_Keywords.verify_status_on_hostname(hostname, name, service_name)
|
||||
@@ -144,6 +140,7 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
"""
|
||||
for service_type, setup_list in [
|
||||
("ptp4l", self.ptp4l_setup_list),
|
||||
("phc2sys", self.phc2sys_setup_list),
|
||||
("ts2phc", self.ts2phc_setup_list),
|
||||
("clock", self.clock_setup_list),
|
||||
]:
|
||||
@@ -164,21 +161,12 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
"""
|
||||
port_data_set = self.get_port_data_set_using_interface_and_port_identity_mapping()
|
||||
|
||||
validate_parent = bool(self.expected_parent_data_set_object)
|
||||
validate_time_props = bool(self.expected_time_properties_data_set_object)
|
||||
|
||||
if not validate_parent:
|
||||
get_logger().log_info("Validation skipped as expected; expected_parent_data_set_object is None")
|
||||
if not validate_time_props:
|
||||
get_logger().log_info("Validation skipped as expected; expected_time_properties_data_set_object is None")
|
||||
|
||||
for ptp4l_instance_obj in self.ptp4l_setup_list:
|
||||
name = ptp4l_instance_obj.get_name()
|
||||
config_file = f"/etc/linuxptp/ptpinstance/ptp4l-{name}.conf"
|
||||
socket_file = f"/var/run/ptp4l-{name}"
|
||||
|
||||
instance_parameters = ptp4l_instance_obj.get_instance_parameters()
|
||||
ptp_role = self.ptp_setup.get_ptp4l_expected_by_name(name).get_ptp_role()
|
||||
|
||||
for hostname in ptp4l_instance_obj.get_instance_hostnames():
|
||||
|
||||
@@ -186,13 +174,11 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
|
||||
self.validate_get_domain(hostname, instance_parameters, config_file, socket_file)
|
||||
|
||||
if validate_parent:
|
||||
self.validate_parent_data_set(hostname, name, port_data_set, config_file, socket_file)
|
||||
self.validate_parent_data_set(hostname, name, port_data_set, config_file, socket_file)
|
||||
|
||||
if validate_time_props:
|
||||
self.validate_time_properties_data_set(hostname, config_file, socket_file)
|
||||
self.validate_time_properties_data_set(hostname, name, config_file, socket_file)
|
||||
|
||||
self.validate_grandmaster_settings_np(hostname, ptp_role, config_file, socket_file)
|
||||
self.validate_grandmaster_settings_np(hostname, name, config_file, socket_file)
|
||||
|
||||
def validate_gnss_status_on_hostname(self, hostname: str, interface: str, expected_gnss_port: str) -> None:
|
||||
"""
|
||||
@@ -368,7 +354,8 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
expected_associated_interfaces = [interface for ptp_host_if in ptp_instance_obj.get_ptp_interfaces() for interface in ptp_host_if.get_interfaces_for_hostname(hostname) if interface]
|
||||
|
||||
observed_associated_interfaces = cat_ptp_config_output.get_associated_interfaces()
|
||||
validate_equals(observed_associated_interfaces, expected_associated_interfaces, "Associated interfaces within PTP config file content")
|
||||
# In the PTP config file, the associated interfaces are unordered and do not follow the order of interface_names shown in the output of system ptp-interface-show <name>.
|
||||
validate_equals(sorted(observed_associated_interfaces), sorted(expected_associated_interfaces), "Associated interfaces within PTP config file content")
|
||||
|
||||
def validate_ptp_config_file_content_for_clock(
|
||||
self,
|
||||
@@ -436,9 +423,10 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
|
||||
pmc_keywords = PMCKeywords(ssh_connection)
|
||||
|
||||
observed_port_data_set_objects = pmc_keywords.pmc_get_port_data_set(config_file, socket_file).get_pmc_get_port_data_set_objects()
|
||||
|
||||
ptp4l_expected_obj = self.ptp_setup.get_ptp4l_expected_by_name(name)
|
||||
expected_port_data_set_objects = ptp4l_expected_obj.get_port_data_set_for_hostname(hostname)
|
||||
observed_port_data_set_objects = pmc_keywords.pmc_get_port_data_set(config_file, socket_file).get_pmc_get_port_data_set_objects()
|
||||
|
||||
if len(observed_port_data_set_objects) > len(expected_port_data_set_objects):
|
||||
raise Exception("Observed port data set objects contains more entries than expected port data set objects")
|
||||
@@ -509,17 +497,19 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
|
||||
parent_data_set_obj = pmc_keywords.pmc_get_parent_data_set(config_file, socket_file).get_pmc_get_parent_data_set_object()
|
||||
|
||||
validate_equals(parent_data_set_obj.get_gm_clock_class(), self.expected_parent_data_set_object.get_gm_clock_class(), "gm.ClockClass value within GET PARENT_DATA_SET")
|
||||
validate_equals(parent_data_set_obj.get_gm_clock_accuracy(), self.expected_parent_data_set_object.get_gm_clock_accuracy(), "gm.ClockAccuracy value within GET PARENT_DATA_SET")
|
||||
validate_equals(parent_data_set_obj.get_gm_offset_scaled_log_variance(), self.expected_parent_data_set_object.get_gm_offset_scaled_log_variance(), "gm.OffsetScaledLogVariance value within GET PARENT_DATA_SET")
|
||||
ptp4l_expected_obj = self.ptp_setup.get_ptp4l_expected_by_name(name)
|
||||
expected_parent_data_set_obj = ptp4l_expected_obj.get_parent_data_set_for_hostname(hostname)
|
||||
|
||||
validate_equals(parent_data_set_obj.get_gm_clock_class(), expected_parent_data_set_obj.get_gm_clock_class(), "gm.ClockClass value within GET PARENT_DATA_SET")
|
||||
validate_equals(parent_data_set_obj.get_gm_clock_accuracy(), expected_parent_data_set_obj.get_gm_clock_accuracy(), "gm.ClockAccuracy value within GET PARENT_DATA_SET")
|
||||
validate_equals(parent_data_set_obj.get_gm_offset_scaled_log_variance(), expected_parent_data_set_obj.get_gm_offset_scaled_log_variance(), "gm.OffsetScaledLogVariance value within GET PARENT_DATA_SET")
|
||||
|
||||
# Validates the parentPortIdentity of the SLAVE's PARENT_DATA_SET against the portIdentity of the MASTER's PORT_DATA_SET.
|
||||
if not port_data_set:
|
||||
return
|
||||
|
||||
ptp4l_expected_obj = self.ptp_setup.get_ptp4l_expected_by_name(name)
|
||||
expected_port_data_set_objects = ptp4l_expected_obj.get_port_data_set_for_hostname(hostname)
|
||||
observed_parent_port_identity = parent_data_set_obj.get_parent_port_identity()
|
||||
expected_port_data_set_objects = ptp4l_expected_obj.get_port_data_set_for_hostname(hostname)
|
||||
|
||||
for expected_port_data_set_obj in expected_port_data_set_objects:
|
||||
|
||||
@@ -542,6 +532,7 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
def validate_time_properties_data_set(
|
||||
self,
|
||||
hostname: str,
|
||||
name: str,
|
||||
config_file: str,
|
||||
socket_file: str,
|
||||
) -> None:
|
||||
@@ -550,6 +541,7 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
|
||||
Args:
|
||||
hostname (str): The name of the host.
|
||||
name (str): The ptp instance name
|
||||
config_file (str): the config file.
|
||||
socket_file (str): the socket file.
|
||||
|
||||
@@ -562,11 +554,6 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
|
||||
pmc_keywords = PMCKeywords(ssh_connection)
|
||||
|
||||
expected_current_utc_offset = self.expected_time_properties_data_set_object.get_current_utc_offset()
|
||||
expected_current_utc_offset_valid = self.expected_time_properties_data_set_object.get_current_utc_offset_valid()
|
||||
expected_time_traceable = self.expected_time_properties_data_set_object.get_time_traceable()
|
||||
expected_frequency_traceable = self.expected_time_properties_data_set_object.get_frequency_traceable()
|
||||
|
||||
get_time_properties_data_set_output = pmc_keywords.pmc_get_time_properties_data_set(config_file, socket_file)
|
||||
get_time_properties_data_set_object = get_time_properties_data_set_output.get_pmc_get_time_properties_data_set_object()
|
||||
observed_current_utc_offset = get_time_properties_data_set_object.get_current_utc_offset()
|
||||
@@ -574,6 +561,13 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
observed_time_traceable = get_time_properties_data_set_object.get_time_traceable()
|
||||
observed_frequency_traceable = get_time_properties_data_set_object.get_frequency_traceable()
|
||||
|
||||
ptp4l_expected_obj = self.ptp_setup.get_ptp4l_expected_by_name(name)
|
||||
expected_time_properties_data_set_obj = ptp4l_expected_obj.get_time_properties_data_set_for_hostname(hostname)
|
||||
expected_current_utc_offset = expected_time_properties_data_set_obj.get_current_utc_offset()
|
||||
expected_current_utc_offset_valid = expected_time_properties_data_set_obj.get_current_utc_offset_valid()
|
||||
expected_time_traceable = expected_time_properties_data_set_obj.get_time_traceable()
|
||||
expected_frequency_traceable = expected_time_properties_data_set_obj.get_frequency_traceable()
|
||||
|
||||
validate_equals(observed_current_utc_offset, expected_current_utc_offset, "currentUtcOffset value within GET TIME_PROPERTIES_DATA_SET")
|
||||
validate_equals(observed_current_utc_off_set_valid, expected_current_utc_offset_valid, "currentUtcOffsetValid value within GET TIME_PROPERTIES_DATA_SET")
|
||||
validate_equals(observed_time_traceable, expected_time_traceable, "timeTraceable value within GET TIME_PROPERTIES_DATA_SET")
|
||||
@@ -582,7 +576,7 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
def validate_grandmaster_settings_np(
|
||||
self,
|
||||
hostname: str,
|
||||
ptp_role: str,
|
||||
name: str,
|
||||
config_file: str,
|
||||
socket_file: str,
|
||||
) -> None:
|
||||
@@ -591,7 +585,7 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
|
||||
Args:
|
||||
hostname (str): The name of the host.
|
||||
ptp_role (str): state of the port (e.g., MASTER and SLAVE)
|
||||
name (str): The ptp instance name
|
||||
config_file (str): the config file.
|
||||
socket_file (str): the socket file.
|
||||
|
||||
@@ -600,25 +594,10 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
Raises:
|
||||
Exception: raised when validate fails
|
||||
"""
|
||||
expected_grandmaster_settings_object_map = {"tgm": self.expected_grandmaster_settings_tgm_object, "tbc": self.expected_grandmaster_settings_tbc_object}
|
||||
|
||||
expected_grandmaster_settings_object = expected_grandmaster_settings_object_map.get(ptp_role)
|
||||
|
||||
if not expected_grandmaster_settings_object:
|
||||
get_logger().log_info(f"Validation skipped as expected; expected_grandmaster_settings_{ptp_role}_object is None")
|
||||
return
|
||||
|
||||
expected_clock_class = expected_grandmaster_settings_object.get_clock_class()
|
||||
expected_clock_accuracy = expected_grandmaster_settings_object.get_clock_accuracy()
|
||||
expected_offset_scaled_log_variance = expected_grandmaster_settings_object.get_offset_scaled_log_variance()
|
||||
expected_time_traceable = expected_grandmaster_settings_object.get_time_traceable()
|
||||
expected_frequency_traceable = expected_grandmaster_settings_object.get_frequency_traceable()
|
||||
expected_time_source = expected_grandmaster_settings_object.get_time_source()
|
||||
expected_current_utc_offset_valid = expected_grandmaster_settings_object.get_current_utc_offset_valid()
|
||||
|
||||
lab_connect_keywords = LabConnectionKeywords()
|
||||
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
|
||||
pmc_keywords = PMCKeywords(ssh_connection)
|
||||
|
||||
get_grandmaster_settings_np_output = pmc_keywords.pmc_get_grandmaster_settings_np(config_file, socket_file)
|
||||
get_grandmaster_settings_np_object = get_grandmaster_settings_np_output.get_pmc_get_grandmaster_settings_np_object()
|
||||
observed_clock_class = get_grandmaster_settings_np_object.get_clock_class()
|
||||
@@ -629,6 +608,16 @@ class PTPVerifyConfigKeywords(BaseKeyword):
|
||||
observed_frequency_traceable = get_grandmaster_settings_np_object.get_frequency_traceable()
|
||||
observed_time_source = get_grandmaster_settings_np_object.get_time_source()
|
||||
|
||||
ptp4l_expected_obj = self.ptp_setup.get_ptp4l_expected_by_name(name)
|
||||
expected_grandmaster_settings_obj = ptp4l_expected_obj.get_grandmaster_settings_for_hostname(hostname)
|
||||
expected_clock_class = expected_grandmaster_settings_obj.get_clock_class()
|
||||
expected_clock_accuracy = expected_grandmaster_settings_obj.get_clock_accuracy()
|
||||
expected_offset_scaled_log_variance = expected_grandmaster_settings_obj.get_offset_scaled_log_variance()
|
||||
expected_time_traceable = expected_grandmaster_settings_obj.get_time_traceable()
|
||||
expected_frequency_traceable = expected_grandmaster_settings_obj.get_frequency_traceable()
|
||||
expected_time_source = expected_grandmaster_settings_obj.get_time_source()
|
||||
expected_current_utc_offset_valid = expected_grandmaster_settings_obj.get_current_utc_offset_valid()
|
||||
|
||||
validate_equals(observed_clock_class, expected_clock_class, "clockClass value within GET GRANDMASTER_SETTINGS_NP")
|
||||
validate_equals(observed_clock_accuracy, expected_clock_accuracy, "clockAccuracy value within GET GRANDMASTER_SETTINGS_NP")
|
||||
validate_equals(observed_offset_scaled_log_variance, expected_offset_scaled_log_variance, "offsetScaledLogVariance value within GET GRANDMASTER_SETTINGS_NP")
|
||||
|
@@ -35,8 +35,8 @@ class CatClockConfParser:
|
||||
output_values_dict = {}
|
||||
is_first_ifname = True
|
||||
for row in self.cat_clock_conf_output:
|
||||
if "~$" in row:
|
||||
continue # this is a prompt and should be ignored
|
||||
if "~$" in row or "Password:" in row:
|
||||
continue # these prompts and should be ignored
|
||||
values = row.strip("\n").split(None, 1) # split once
|
||||
if len(values) == 2:
|
||||
key, value = values
|
||||
|
@@ -115,7 +115,7 @@ class GnssKeywords(BaseKeyword):
|
||||
|
||||
expected_gnss_1pps_state = "valid"
|
||||
expected_pps_dpll_status = ["locked_ho_acq"]
|
||||
self.validate_gnss_1pps_state_and_pps_dpll_status(hostname, cgu_location, expected_gnss_1pps_state, expected_pps_dpll_status)
|
||||
self.validate_gnss_1pps_state_and_pps_dpll_status(hostname, cgu_location, "GNSS-1PPS", expected_gnss_1pps_state, expected_pps_dpll_status)
|
||||
|
||||
def gnss_power_off(self, hostname: str, nic: str) -> None:
|
||||
"""
|
||||
@@ -141,12 +141,13 @@ class GnssKeywords(BaseKeyword):
|
||||
|
||||
expected_gnss_1pps_state = "invalid"
|
||||
expected_pps_dpll_status = ["holdover", "freerun"]
|
||||
self.validate_gnss_1pps_state_and_pps_dpll_status(hostname, cgu_location, expected_gnss_1pps_state, expected_pps_dpll_status)
|
||||
self.validate_gnss_1pps_state_and_pps_dpll_status(hostname, cgu_location, "GNSS-1PPS", expected_gnss_1pps_state, expected_pps_dpll_status)
|
||||
|
||||
def validate_gnss_1pps_state_and_pps_dpll_status(
|
||||
self,
|
||||
hostname: str,
|
||||
cgu_location: str,
|
||||
cgu_input: str,
|
||||
expected_gnss_1pps_state: str,
|
||||
expected_pps_dpll_status: list,
|
||||
timeout: int = 800,
|
||||
@@ -158,6 +159,7 @@ class GnssKeywords(BaseKeyword):
|
||||
Args:
|
||||
hostname (str): The name of the host.
|
||||
cgu_location (str): the cgu location.
|
||||
cgu_input (str): the cgu input name.
|
||||
expected_gnss_1pps_state (str): The expected gnss 1pss state value.
|
||||
expected_pps_dpll_status (list): expected list of PPS DPLL status values.
|
||||
timeout (int): The maximum time (in seconds) to wait for the match.
|
||||
@@ -185,7 +187,7 @@ class GnssKeywords(BaseKeyword):
|
||||
pps_dpll_object = ptp_cgu_component.get_pps_dpll()
|
||||
status = pps_dpll_object.get_status()
|
||||
|
||||
input_object = ptp_cgu_component.get_cgu_input("GNSS-1PPS")
|
||||
input_object = ptp_cgu_component.get_cgu_input(cgu_input)
|
||||
state = input_object.get_state()
|
||||
|
||||
if status in expected_pps_dpll_status and state == expected_gnss_1pps_state:
|
||||
|
@@ -1,6 +1,9 @@
|
||||
from typing import Any, Dict, List
|
||||
|
||||
from keywords.ptp.setup.object.grandmaster_settings import GrandmasterSettings
|
||||
from keywords.ptp.setup.object.parent_data_set import ParentDataSet
|
||||
from keywords.ptp.setup.object.port_data_set import PortDataSet
|
||||
from keywords.ptp.setup.time_properties_data_set import TimePropertiesDataSet
|
||||
|
||||
|
||||
class PTP4LExpectedDict:
|
||||
@@ -16,26 +19,12 @@ class PTP4LExpectedDict:
|
||||
expected_dict (Dict[str, Any]): The dictionary read from the JSON setup template file associated with this ptp4l expected dict
|
||||
|
||||
"""
|
||||
self.expected_dict = expected_dict
|
||||
|
||||
if "name" not in expected_dict:
|
||||
raise Exception("Every PTP4L expected dict should have a name.")
|
||||
self.name = expected_dict["name"]
|
||||
|
||||
if "ptp_role" not in expected_dict:
|
||||
raise Exception("Every PTP4L expected dict should have a ptp_role.")
|
||||
self.ptp_role = expected_dict["ptp_role"]
|
||||
|
||||
self.controller_0_port_data_set = None
|
||||
if "controller_0_port_data_set" in expected_dict:
|
||||
self.controller_0_port_data_set = expected_dict["controller_0_port_data_set"]
|
||||
|
||||
self.controller_1_port_data_set = None
|
||||
if "controller_1_port_data_set" in expected_dict:
|
||||
self.controller_1_port_data_set = expected_dict["controller_1_port_data_set"]
|
||||
|
||||
self.compute_0_port_data_set = None
|
||||
if "compute_0_port_data_set" in expected_dict:
|
||||
self.compute_0_port_data_set = expected_dict["compute_0_port_data_set"]
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
String representation of this object.
|
||||
@@ -55,14 +44,68 @@ class PTP4LExpectedDict:
|
||||
"""
|
||||
return self.name
|
||||
|
||||
def get_ptp_role(self) -> str:
|
||||
def get_parent_data_set_for_hostname(self, hostname: str) -> ParentDataSet:
|
||||
"""
|
||||
Gets the ptp role.
|
||||
Gets the of parent data set for hostname.
|
||||
|
||||
Args:
|
||||
hostname (str): The name of the host.
|
||||
|
||||
Returns:
|
||||
str: The ptp role.
|
||||
ParentDataSet: The of parent data set for hostname.
|
||||
"""
|
||||
return self.ptp_role
|
||||
host_specific_data = self.expected_dict.get(hostname)
|
||||
|
||||
if not host_specific_data:
|
||||
raise Exception(f"Expected host specific data : {hostname} is not found for instance: {self.name}")
|
||||
|
||||
parent_data_set_raw = host_specific_data.get("parent_data_set")
|
||||
if not parent_data_set_raw:
|
||||
raise Exception(f"Expected parent data set not found for hostname: {hostname}")
|
||||
|
||||
return ParentDataSet(parent_data_set_raw)
|
||||
|
||||
def get_time_properties_data_set_for_hostname(self, hostname: str) -> TimePropertiesDataSet:
|
||||
"""
|
||||
Gets the of time properties data set for hostname.
|
||||
|
||||
Args:
|
||||
hostname (str): The name of the host.
|
||||
|
||||
Returns:
|
||||
TimePropertiesDataSet: The of time properties data set for hostname.
|
||||
"""
|
||||
host_specific_data = self.expected_dict.get(hostname)
|
||||
|
||||
if not host_specific_data:
|
||||
raise Exception(f"Expected host specific data : {hostname} is not found for instance: {self.name}")
|
||||
|
||||
time_properties_data_set_raw = host_specific_data.get("time_properties_data_set")
|
||||
if not time_properties_data_set_raw:
|
||||
raise Exception(f"Expected time properties data set not found for hostname: {hostname}")
|
||||
|
||||
return TimePropertiesDataSet(time_properties_data_set_raw)
|
||||
|
||||
def get_grandmaster_settings_for_hostname(self, hostname: str) -> GrandmasterSettings:
|
||||
"""
|
||||
Gets the of grandmaster settings for hostname.
|
||||
|
||||
Args:
|
||||
hostname (str): The name of the host.
|
||||
|
||||
Returns:
|
||||
GrandmasterSettings: The of grandmaster settings for hostname.
|
||||
"""
|
||||
host_specific_data = self.expected_dict.get(hostname)
|
||||
|
||||
if not host_specific_data:
|
||||
raise Exception(f"Expected host specific data : {hostname} is not found for instance: {self.name}")
|
||||
|
||||
grandmaster_settings_raw = host_specific_data.get("grandmaster_settings")
|
||||
if not grandmaster_settings_raw:
|
||||
raise Exception(f"Expected grandmaster settings not found for hostname: {hostname}")
|
||||
|
||||
return GrandmasterSettings(grandmaster_settings_raw)
|
||||
|
||||
def get_port_data_set_for_hostname(self, hostname: str) -> List[PortDataSet]:
|
||||
"""
|
||||
@@ -74,13 +117,13 @@ class PTP4LExpectedDict:
|
||||
Returns:
|
||||
List[PortDataSet]: The list of port data set for hostname.
|
||||
"""
|
||||
hostname_to_port_data_set = {
|
||||
"controller-0": self.controller_0_port_data_set,
|
||||
"controller-1": self.controller_1_port_data_set,
|
||||
"compute-0": self.compute_0_port_data_set,
|
||||
}.get(hostname)
|
||||
host_specific_data = self.expected_dict.get(hostname)
|
||||
|
||||
if not hostname_to_port_data_set:
|
||||
if not host_specific_data:
|
||||
raise Exception(f"Expected host specific data : {hostname} is not found for instance: {self.name}")
|
||||
|
||||
port_data_set_list_raw = host_specific_data.get("port_data_set")
|
||||
if not port_data_set_list_raw:
|
||||
raise Exception(f"Expected port data set not found for hostname: {hostname}")
|
||||
|
||||
return [PortDataSet(port_data_set) for port_data_set in hostname_to_port_data_set]
|
||||
return [PortDataSet(port_data_set) for port_data_set in port_data_set_list_raw]
|
||||
|
@@ -1,14 +1,11 @@
|
||||
from typing import Dict, List
|
||||
|
||||
from keywords.ptp.setup.object.clock_setup import ClockSetup
|
||||
from keywords.ptp.setup.object.grandmaster_settings import GrandmasterSettings
|
||||
from keywords.ptp.setup.object.parent_data_set import ParentDataSet
|
||||
from keywords.ptp.setup.object.phc2sys_setup import PHC2SysSetup
|
||||
from keywords.ptp.setup.object.ptp4l_expected_dict import PTP4LExpectedDict
|
||||
from keywords.ptp.setup.object.ptp4l_setup import PTP4LSetup
|
||||
from keywords.ptp.setup.object.ptp_host_interface_setup import PTPHostInterfaceSetup
|
||||
from keywords.ptp.setup.object.ts2phc_setup import TS2PHCSetup
|
||||
from keywords.ptp.setup.time_properties_data_set import TimePropertiesDataSet
|
||||
|
||||
|
||||
class PTPSetup:
|
||||
@@ -30,10 +27,6 @@ class PTPSetup:
|
||||
self.clock_setup_list: List[ClockSetup] = []
|
||||
self.host_ptp_if_dict: Dict[str, PTPHostInterfaceSetup] = {} # Name -> PTPHostInterfaceSetup
|
||||
self.ptp4l_expected_list: List[PTP4LExpectedDict] = []
|
||||
self.parent_data_set: Dict[str, ParentDataSet] = {}
|
||||
self.time_properties_data_set: Dict[str, TimePropertiesDataSet] = {}
|
||||
self.grandmaster_settings_tgm: Dict[str, GrandmasterSettings] = {}
|
||||
self.grandmaster_settings_tbc: Dict[str, GrandmasterSettings] = {}
|
||||
|
||||
if "ptp_instances" not in setup_dict:
|
||||
raise Exception("You must define a ptp_instances section in your ptp setup_dict")
|
||||
@@ -75,18 +68,6 @@ class PTPSetup:
|
||||
expected_dict = setup_dict.get("expected_dict", {})
|
||||
self.ptp4l_expected_list.extend(PTP4LExpectedDict(item) for item in expected_dict.get("ptp4l", []))
|
||||
|
||||
if "parent_data_set" in expected_dict:
|
||||
self.parent_data_set = ParentDataSet(expected_dict["parent_data_set"])
|
||||
|
||||
if "time_properties_data_set" in expected_dict:
|
||||
self.time_properties_data_set = TimePropertiesDataSet(expected_dict["time_properties_data_set"])
|
||||
|
||||
if "grandmaster_settings_tgm" in expected_dict:
|
||||
self.grandmaster_settings_tgm = GrandmasterSettings(expected_dict["grandmaster_settings_tgm"])
|
||||
|
||||
if "grandmaster_settings_tbc" in expected_dict:
|
||||
self.grandmaster_settings_tbc = GrandmasterSettings(expected_dict["grandmaster_settings_tbc"])
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
String representation of this object.
|
||||
@@ -216,39 +197,3 @@ class PTPSetup:
|
||||
if not ptp4l_expected_obj:
|
||||
raise ValueError(f"No expected PTP4L object found for name: {name}")
|
||||
return ptp4l_expected_obj
|
||||
|
||||
def get_parent_data_set(self) -> ParentDataSet:
|
||||
"""
|
||||
Getter for the parent data set.
|
||||
|
||||
Returns:
|
||||
ParentDataSet: The parent data set
|
||||
"""
|
||||
return self.parent_data_set
|
||||
|
||||
def get_time_properties_data_set(self) -> TimePropertiesDataSet:
|
||||
"""
|
||||
Getter for the time properties data set.
|
||||
|
||||
Returns:
|
||||
TimePropertiesDataSet: The time properties data set
|
||||
"""
|
||||
return self.time_properties_data_set
|
||||
|
||||
def get_grandmaster_settings_tgm(self) -> GrandmasterSettings:
|
||||
"""
|
||||
Getter for the grandmaster settings tgm.
|
||||
|
||||
Returns:
|
||||
GrandmasterSettings: The grandmaster settings tgm
|
||||
"""
|
||||
return self.grandmaster_settings_tgm
|
||||
|
||||
def get_grandmaster_settings_tbc(self) -> GrandmasterSettings:
|
||||
"""
|
||||
Getter for the grandmaster settings tbc.
|
||||
|
||||
Returns:
|
||||
GrandmasterSettings: The grandmaster settings tbc
|
||||
"""
|
||||
return self.grandmaster_settings_tbc
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
{
|
||||
name: "ptp1",
|
||||
instance_hostnames : ["compute-0", "controller-0", "controller-1"] ,
|
||||
instance_hostnames : ["compute-0", "controller-0", "controller-1"],
|
||||
instance_parameters: "priority2=100 tx_timestamp_timeout=700 boundary_clock_jbod=1 domainNumber=24 dataset_comparison=G.8275.x",
|
||||
ptp_interface_names: [
|
||||
"ptp1if1",
|
||||
@@ -48,7 +48,7 @@
|
||||
phc2sys : [
|
||||
{
|
||||
name: "phc1",
|
||||
instance_hostnames : ["controller-0", "compute-0", "controller-1"],
|
||||
instance_hostnames : ["controller-0", "compute-0"],
|
||||
instance_parameters: "cmdline_opts='-s {{controller_0.nic1.conn_to_proxmox}} -O -37 -m'",
|
||||
ptp_interface_names: [
|
||||
"phc1if1",
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
{
|
||||
name: "phc4",
|
||||
instance_hostnames : [],
|
||||
instance_hostnames : ['controller-1'],
|
||||
instance_parameters: "domainNumber=24 uds_address=/var/run/ptp4l-ptp4",
|
||||
ptp_interface_names: [
|
||||
"phc4if1",
|
||||
@@ -87,7 +87,7 @@
|
||||
ts2phc : [
|
||||
{
|
||||
name: "ts1",
|
||||
instance_hostnames : ["controller-1", "controller-0", "compute-0"],
|
||||
instance_hostnames : ["controller-0", "compute-0"],
|
||||
instance_parameters: "ts2phc.nmea_serialport=/dev/gnss0",
|
||||
ptp_interface_names: [
|
||||
"ts1if1",
|
||||
@@ -233,83 +233,116 @@
|
||||
"ptp4l": [
|
||||
{
|
||||
"name": "ptp1",
|
||||
"ptp_role": "tgm",
|
||||
"controller_0_port_data_set": [
|
||||
{
|
||||
"interface" : "{{ controller_0.nic1.nic_connection.interface }}",
|
||||
"port_state": "MASTER"
|
||||
},
|
||||
{
|
||||
"interface" : "{{ controller_0.nic1.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
],
|
||||
"controller_1_port_data_set": [
|
||||
{
|
||||
"interface" : "{{ controller_1.nic1.nic_connection.interface }}",
|
||||
"port_state": "PASSIVE"
|
||||
},
|
||||
{
|
||||
"interface" : "{{ controller_1.nic1.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
],
|
||||
"compute_0_port_data_set": [
|
||||
{
|
||||
"interface" : "{{ compute_0.nic1.nic_connection.interface }}",
|
||||
"port_state": "LISTENING"
|
||||
}
|
||||
]
|
||||
"controller-0": {
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {{ grandmaster_settings.grandmaster_settings_tgm_default }},
|
||||
"port_data_set": [
|
||||
{
|
||||
"interface" : "{{ controller_0.nic1.nic_connection.interface }}", // ctrl0 NIC1 is MASTER and ctr1 NIC1 is SLAVE
|
||||
"port_state": "MASTER"
|
||||
},
|
||||
{
|
||||
"interface" : "{{ controller_0.nic1.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"controller-1": {
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {
|
||||
"clock_class": 165,
|
||||
"clock_accuracy": "0xfe",
|
||||
"offset_scaled_log_variance": "0xffff",
|
||||
"time_traceable": 0,
|
||||
"frequency_traceable": 0,
|
||||
"time_source": "0xa0",
|
||||
"current_utc_offset_valid": 0
|
||||
},
|
||||
"port_data_set": [
|
||||
{
|
||||
"interface" : "{{ controller_1.nic1.nic_connection.interface }}",
|
||||
"port_state": "SLAVE",
|
||||
"parent_port_identity" : {
|
||||
"name": "ptp1",
|
||||
"hostname":"controller-0",
|
||||
"interface": "{{ controller_0.nic1.nic_connection.interface }}" // ctrl-0 NIC1 is Master and ctrl-1 NIC1 is slave
|
||||
},
|
||||
},
|
||||
{
|
||||
"interface" : "{{ controller_1.nic1.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
],
|
||||
},
|
||||
"compute-0": {
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {{ grandmaster_settings.grandmaster_settings_tgm_default }},
|
||||
"port_data_set": [
|
||||
{
|
||||
"interface" : "{{ compute_0.nic1.nic_connection.interface }}",
|
||||
"port_state": "LISTENING"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ptp2",
|
||||
"ptp_role": "tgm"
|
||||
},
|
||||
{
|
||||
"name": "ptp3",
|
||||
"ptp_role": "tgm",
|
||||
"controller_0_port_data_set": [
|
||||
{
|
||||
"interface": "{{ controller_0.nic2.nic_connection.interface }}", // ctrl0 NIC2 is MASTER and ctr1 NIC2 is SLAVE
|
||||
"port_state": "MASTER"
|
||||
},
|
||||
{
|
||||
"interface": "{{ controller_0.nic2.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
],
|
||||
"compute_0_port_data_set": [
|
||||
{
|
||||
"interface": "{{ compute_0.nic2.nic_connection.interface }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
]
|
||||
"controller-0" : {
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {{ grandmaster_settings.grandmaster_settings_tgm_default }},
|
||||
"port_data_set": [
|
||||
{
|
||||
"interface": "{{ controller_0.nic2.nic_connection.interface }}", // ctrl0 NIC2 is MASTER and ctr1 NIC2 is SLAVE
|
||||
"port_state": "MASTER"
|
||||
},
|
||||
{
|
||||
"interface": "{{ controller_0.nic2.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
]
|
||||
},
|
||||
"compute-0" : {
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {{ grandmaster_settings.grandmaster_settings_tgm_default }},
|
||||
"port_data_set": [
|
||||
{
|
||||
"interface": "{{ compute_0.nic2.nic_connection.interface }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "ptp4",
|
||||
"ptp_role": "tbc",
|
||||
"controller_1_port_data_set": [
|
||||
{
|
||||
"interface": "{{ controller_1.nic2.nic_connection.interface }}",
|
||||
"port_state": "SLAVE",
|
||||
"parent_port_identity" : {
|
||||
"name": "ptp3",
|
||||
"hostname":"controller-0",
|
||||
"interface": "{{ controller_0.nic2.nic_connection.interface }}" // ctrl-0 NIC2 is Master and ctrl-1 NIC2 is slave
|
||||
},
|
||||
},
|
||||
{
|
||||
"interface": "{{ controller_1.nic2.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
]
|
||||
"controller-1" : {
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {{ grandmaster_settings.grandmaster_settings_tbc_default }},
|
||||
"port_data_set": [
|
||||
{
|
||||
"interface": "{{ controller_1.nic2.nic_connection.interface }}",
|
||||
"port_state": "SLAVE",
|
||||
"parent_port_identity" : {
|
||||
"name": "ptp3",
|
||||
"hostname":"controller-0",
|
||||
"interface": "{{ controller_0.nic2.nic_connection.interface }}" // ctrl-0 NIC2 is Master and ctrl-1 NIC2 is slave
|
||||
},
|
||||
},
|
||||
{
|
||||
"interface": "{{ controller_1.nic2.conn_to_proxmox }}",
|
||||
"port_state": "MASTER"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"parent_data_set" : {{ parent_data_set_tgm_default }},
|
||||
"time_properties_data_set": {{ time_properties_data_set_tgm_default }},
|
||||
"grandmaster_settings": {
|
||||
"tgm" : {{ grandmaster_settings.grandmaster_settings_tgm_default }},
|
||||
"tbm" : {{ grandmaster_settings.grandmaster_settings_tbc_default }}
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
@@ -45,8 +45,8 @@ def test_delete_and_add_all_ptp_configuration_for_compute():
|
||||
|
||||
get_logger().log_info("Add all PTP configuration")
|
||||
ptp_setup_template_path = get_stx_resource_path("resources/ptp/setup/ptp_configuration_expectation_compute.json5")
|
||||
ptp_setup_keywords = PTPSetupExecutorKeywords(ssh_connection, ptp_setup_template_path)
|
||||
ptp_setup_keywords.add_all_ptp_configurations()
|
||||
ptp_setup_executor_keywords = PTPSetupExecutorKeywords(ssh_connection, ptp_setup_template_path)
|
||||
ptp_setup_executor_keywords.add_all_ptp_configurations()
|
||||
|
||||
get_logger().log_info("Verify all PTP configuration")
|
||||
ptp_verify_config_keywords = PTPVerifyConfigKeywords(ssh_connection, ptp_setup_template_path)
|
||||
|
Reference in New Issue
Block a user