Create keywords to check and verify PTP

Change-Id: Iae86fde1ba0d14521e66018814f0977d74f824e1
Signed-off-by: Guntaka Umashankar Reddy <umashankarguntaka.reddy@windriver.com>
This commit is contained in:
Guntaka Umashankar Reddy
2025-04-18 07:00:21 -04:00
parent f9515810f4
commit 750fea6f09
17 changed files with 893 additions and 56 deletions

View File

@@ -78,9 +78,11 @@ class LabConnectionKeywords(BaseKeyword):
"""
lab_config = ConfigurationManager.get_lab_config()
if 'worker' in lab_config.get_node(hostname).get_type() :
return self.get_compute_ssh(hostname)
host_ip = lab_config.get_node(hostname).get_ip()
jump_host_config = None
if lab_config.is_use_jump_server():
jump_host_config = lab_config.get_jump_host_configuration()
@@ -92,7 +94,6 @@ class LabConnectionKeywords(BaseKeyword):
ssh_port=lab_config.get_ssh_port(),
jump_host=jump_host_config,
)
return connection
def get_compute_ssh(self, compute_name: str) -> SSHConnection:

View File

@@ -190,6 +190,17 @@ class PTPSetupExecutorKeywords(BaseKeyword):
system_ptp_interface_show_output = system_ptp_interface_keywords.get_system_ptp_interface_show(interface_name)
validate_str_contains(system_ptp_interface_show_output.get_ptp_interface().get_interface_names(), f"{ctrl1_hostname}/{interface}", f"assign ptp interface for {ctrl1_hostname}")
compute_0_interfaces = ptp_host_if.get_compute_0_interfaces()
comp0_hostname = "compute-0"
for interface in compute_0_interfaces:
if not interface :
continue
system_host_if_ptp_keywords.system_host_if_ptp_assign(comp0_hostname, interface, interface_name)
system_ptp_interface_show_output = system_ptp_interface_keywords.get_system_ptp_interface_show(interface_name)
validate_str_contains(system_ptp_interface_show_output.get_ptp_interface().get_interface_names(), f"{comp0_hostname}/{interface}", f"assign ptp interface for {comp0_hostname}")
ptp_interface_parameters = ptp_host_if.get_ptp_interface_parameter()
if ptp_interface_parameters :
system_ptp_interface_parameter_add_output = system_ptp_interface_keywords.system_ptp_interface_parameter_add(interface_name, ptp_interface_parameters)

View File

@@ -0,0 +1,623 @@
import re
from typing import Any
from framework.logging.automation_logger import get_logger
from framework.validation.validation import validate_equals
from keywords.base_keyword import BaseKeyword
from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords
from keywords.linux.systemctl.systemctl_status_keywords import SystemCTLStatusKeywords
from keywords.ptp.cat.cat_ptp_cgu_keywords import CatPtpCguKeywords
from keywords.ptp.cat.cat_ptp_config_keywords import CatPtpConfigKeywords
from keywords.ptp.gnss_keywords import GnssKeywords
from keywords.ptp.pmc.pmc_keywords import PMCKeywords
from keywords.ptp.setup.object.ptp_host_interface_setup import PTPHostInterfaceSetup
from keywords.ptp.setup.ptp_setup_reader import PTPSetupKeywords
class PTPVerifyConfigKeywords(BaseKeyword):
"""
Verify all PTP configurations using given SSH connection.
Attributes:
ssh_connection: An instance of an SSH connection.
"""
def __init__(self, ssh_connection, ptp_setup_template_path):
"""
Initializes the PTPVerifyConfigKeywords with an SSH connection.
Args:
ssh_connection: An instance of an SSH connection.
ptp_setup_template_path : ptp setup template path
"""
self.ssh_connection = ssh_connection
ptp_setup_keywords = PTPSetupKeywords()
ptp_setup = ptp_setup_keywords.generate_ptp_setup_from_template(ptp_setup_template_path)
self.ptp4l_setup_list = ptp_setup.get_ptp4l_setup_list()
self.phc2sys_setup_list = ptp_setup.get_phc2sys_setup_list()
self.ts2phc_setup_list = ptp_setup.get_ts2phc_setup_list()
self.clock_setup_list = ptp_setup.get_clock_setup_list()
self.ctrl0_hostname = "controller-0"
self.ctrl1_hostname = "controller-1"
self.comp0_hostname = "compute-0"
def verify_all_ptp_configurations(self) -> None:
"""
verify all ptp configurations
Returns: None
"""
self.verify_gnss_status()
self.verify_sma_status()
self.verify_systemctl_status()
self.verify_ptp_pmc_values()
self.verify_ptp_config_file_content()
def verify_gnss_status(self) -> None:
"""
verify GNSS status
Returns: None
"""
gnss_keywords = GnssKeywords()
for ts2phc_instance_obj in self.ts2phc_setup_list:
ptp_host_ifs = ts2phc_instance_obj.get_ptp_interfaces()
instance_parameters = ts2phc_instance_obj.get_instance_parameters()
expected_gnss_port = gnss_keywords.extract_gnss_port(instance_parameters)
if not expected_gnss_port: # No need to verify GNSS status if ts2phc.nmea_serialport not configured
get_logger().log_info("Validation skipped as expected; GNSS port is None")
continue
for ptp_host_if in ptp_host_ifs:
controller_0_interfaces = ptp_host_if.get_controller_0_interfaces()
for interface in controller_0_interfaces:
if not interface:
continue
self.validate_gnss_status_on_hostname(self.ctrl0_hostname, interface, expected_gnss_port)
controller_1_interfaces = ptp_host_if.get_controller_1_interfaces()
for interface in controller_1_interfaces:
if not interface:
continue
self.validate_gnss_status_on_hostname(self.ctrl1_hostname, interface, expected_gnss_port)
compute_0_interfaces = ptp_host_if.get_compute_0_interfaces()
for interface in compute_0_interfaces:
if not interface:
continue
self.validate_gnss_status_on_hostname(self.comp0_hostname, interface, expected_gnss_port)
def verify_sma_status(self) -> None:
"""
verify SMA status
Returns: None
"""
for clock_instance_obj in self.clock_setup_list:
ptp_host_ifs = clock_instance_obj.get_ptp_interfaces()
for ptp_host_if in ptp_host_ifs:
ptp_interface_parameters = ptp_host_if.get_ptp_interface_parameter()
if "input" in ptp_interface_parameters:
controller_0_interfaces = ptp_host_if.get_controller_0_interfaces()
for interface in controller_0_interfaces:
if not interface:
continue
self.validate_sma_status_on_hostname(self.ctrl0_hostname, interface)
controller_1_interfaces = ptp_host_if.get_controller_1_interfaces()
for interface in controller_1_interfaces:
if not interface:
continue
self.validate_sma_status_on_hostname(self.ctrl1_hostname, interface)
compute_0_interfaces = ptp_host_if.get_compute_0_interfaces()
for interface in compute_0_interfaces:
if not interface:
continue
self.validate_sma_status_on_hostname(self.comp0_hostname, interface)
def verify_systemctl_status(self) -> None:
"""
verify ptp systemctl ptp services status
Returns: None
"""
systemctl_status_Keywords = SystemCTLStatusKeywords(self.ssh_connection)
for ptp4l_instance_obj in self.ptp4l_setup_list:
name = ptp4l_instance_obj.get_name()
service_name = f"ptp4l@{name}.service"
hostnames = ptp4l_instance_obj.get_instance_hostnames()
for hostname in hostnames:
systemctl_status_Keywords.verify_status_on_hostname(hostname, name, service_name)
for phc2sys_instance_obj in self.phc2sys_setup_list:
name = phc2sys_instance_obj.get_name()
service_name = f"phc2sys@{name}.service"
hostnames = phc2sys_instance_obj.get_instance_hostnames()
instance_parameters = phc2sys_instance_obj.get_instance_parameters()
for hostname in hostnames:
systemctl_status_Keywords.verify_ptp_status_and_instance_parameters_on_hostname(hostname, name, service_name, instance_parameters)
for ts2phc_instance_obj in self.ts2phc_setup_list:
name = ts2phc_instance_obj.get_name()
service_name = f"ts2phc@{name}.service"
hostnames = ts2phc_instance_obj.get_instance_hostnames()
for hostname in hostnames:
systemctl_status_Keywords.verify_status_on_hostname(hostname, name, service_name)
def verify_ptp_config_file_content(self) -> None:
"""
Verify ptp config file content
Returns: None
"""
for ptp4l_instance_obj in self.ptp4l_setup_list:
config_file = f"/etc/linuxptp/ptpinstance/ptp4l-{ptp4l_instance_obj.get_name()}.conf"
hostnames = ptp4l_instance_obj.get_instance_hostnames()
for hostname in hostnames:
self.validate_ptp_config_file_content(ptp4l_instance_obj, hostname, config_file)
for ts2phc_instance_obj in self.ts2phc_setup_list:
config_file = f"/etc/linuxptp/ptpinstance/ts2phc-{ts2phc_instance_obj.get_name()}.conf"
hostnames = ts2phc_instance_obj.get_instance_hostnames()
for hostname in hostnames:
self.validate_ptp_config_file_content(ts2phc_instance_obj, hostname, config_file)
def verify_ptp_pmc_values(self) -> None:
"""
verify ptp pmc values
Returns: 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}"
hostnames = ptp4l_instance_obj.get_instance_hostnames()
instance_parameters = ptp4l_instance_obj.get_instance_parameters()
ptp_role = ptp4l_instance_obj.get_ptp_role()
for hostname in hostnames:
self.validate_port_data_set(hostname, config_file, socket_file, expected_port_state="MASTER")
self.validate_get_domain(hostname, instance_parameters, config_file, socket_file)
self.validate_parent_data_set(hostname, instance_parameters, config_file, socket_file)
self.validate_time_properties_data_set(hostname, config_file, socket_file)
self.validate_grandmaster_settings_np(hostname, ptp_role, config_file, socket_file)
def validate_gnss_status_on_hostname(self, hostname: str, interface: str, expected_gnss_port: str) -> None:
"""
Validate GNSS status on the hostname
Args:
hostname (str): The name of the host.
interface (str): The name of the ptp interface (e.g., "enp138s0f0").
expected_gnss_port (str): Expected GNSS serial port value
Returns: None
"""
gnss_keywords = GnssKeywords()
input_name = "GNSS-1PPS"
expected_gnss_1pps_state = "valid"
expected_dpll_status = "locked_ho_acq"
observed_gnss_port = gnss_keywords.get_gnss_serial_port_from_gnss_directory(hostname, interface)
if expected_gnss_port == observed_gnss_port:
pci_address = gnss_keywords.get_pci_slot_name(hostname, interface)
cgu_location = f"/sys/kernel/debug/ice/{pci_address}/cgu"
self.validate_cgu_input_and_dpll_status(hostname, cgu_location, input_name, expected_gnss_1pps_state, expected_dpll_status)
else:
get_logger().log_info(f"Validation skipped; GNSS port does not match for hostname {hostname} and interface {interface}")
get_logger().log_info(f"Expected GNSS port: {expected_gnss_port}")
get_logger().log_info(f"Observed GNSS port: {observed_gnss_port}")
def validate_sma_status_on_hostname(self, hostname: str, interface: str) -> None:
"""
Validate SMA status on the hostname
Args:
hostname (str): The name of the host.
interface (str): The name of the ptp interface (e.g., "enp138s0f0").
Returns: None
"""
gnss_keywords = GnssKeywords()
input_name = "SMA1"
expected_sma1_state = "valid"
expected_dpll_status = "locked_ho_acq"
pci_address = gnss_keywords.get_pci_slot_name(hostname, interface)
cgu_location = f"/sys/kernel/debug/ice/{pci_address}/cgu"
self.validate_cgu_input_and_dpll_status(hostname, cgu_location, input_name, expected_sma1_state, expected_dpll_status)
def validate_cgu_input_and_dpll_status(
self,
hostname: str,
cgu_location: str,
input_name: str,
expected_input_state: str,
expected_status: str,
) -> None:
"""
Validates the cgu and dpll status.
Args:
hostname (str): The name of the host.
cgu_location (str): the cgu location.
input_name (str): the cgu input name.
expected_input_state (str): The expected cgu input state.
expected_status (str): expected of DPLL status.
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
cat_ptp_cgu_keywords = CatPtpCguKeywords(ssh_connection)
ptp_cgu_output = cat_ptp_cgu_keywords.cat_ptp_cgu(cgu_location)
ptp_cgu_component = ptp_cgu_output.get_cgu_component()
input_object = ptp_cgu_component.get_cgu_input(input_name)
state = input_object.get_state()
eec_dpll_object = ptp_cgu_component.get_eec_dpll()
eec_dpll_current_reference = eec_dpll_object.get_current_reference()
eec_dpll_status = eec_dpll_object.get_status()
pps_dpll_object = ptp_cgu_component.get_pps_dpll()
pps_dpll_current_reference = pps_dpll_object.get_current_reference()
pps_dpll_status = pps_dpll_object.get_status()
if state == expected_input_state and eec_dpll_current_reference == input_name and eec_dpll_status == expected_status and pps_dpll_current_reference == input_name and pps_dpll_status == expected_status:
get_logger().log_info(f"Validation Successful - {input_name} state and DPLL status")
else:
get_logger().log_info(f"Validation Failed - {input_name} state and DPLL status")
get_logger().log_info(f"Expected {input_name}: {expected_input_state}")
get_logger().log_info(f"Observed {input_name}: {state}")
get_logger().log_info(f"Expected EEC DPLL current refrence: {input_name}")
get_logger().log_info(f"Observed EEC DPLL current refrence: {eec_dpll_current_reference}")
get_logger().log_info(f"Expected EEC DPLL status: {expected_status}")
get_logger().log_info(f"Observed EEC DPLL status: {eec_dpll_status}")
get_logger().log_info(f"Expected PPS DPLL current refrence: {input_name}")
get_logger().log_info(f"Observed PPS DPLL current refrence: {pps_dpll_current_reference}")
get_logger().log_info(f"Expected PPS DPLL status: {expected_status}")
get_logger().log_info(f"Observed PPS DPLL status: {pps_dpll_status}")
raise Exception("Validation Failed")
def validate_ptp_config_file_content(
self,
ptp_instance_obj: Any,
hostname: str,
config_file: str,
) -> None:
"""
Validates the ptp config file content.
Args:
ptp_instance_obj (Any) : PTP instance setup object
hostname (str): The name of the host.
config_file (str): the config file.
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
cat_ptp_config_keywords = CatPtpConfigKeywords(ssh_connection)
cat_ptp_config_output = cat_ptp_config_keywords.cat_ptp_config(config_file)
get_pmc_get_default_data_set_object = cat_ptp_config_output.data_set_output.get_pmc_get_default_data_set_object()
instance_parameters = ptp_instance_obj.get_instance_parameters()
parameters = self.parse_instance_parameters_string(instance_parameters)
expected_boundary_clock_jbod = parameters.get("boundary_clock_jbod")
if expected_boundary_clock_jbod:
observed_boundary_clock_jbod = get_pmc_get_default_data_set_object.get_boundary_clock_jbod()
validate_equals(observed_boundary_clock_jbod, expected_boundary_clock_jbod, "boundary_clock_jbod value within PTP config file content")
expected_dataset_comparison = parameters.get("dataset_comparison")
if expected_dataset_comparison:
observed_dataset_comparison = get_pmc_get_default_data_set_object.get_dataset_comparison()
validate_equals(observed_dataset_comparison, expected_dataset_comparison, "dataset_comparison value within PTP config file content")
expected_domain_number = parameters.get("domainNumber")
if expected_domain_number:
observed_domain_number = get_pmc_get_default_data_set_object.get_domain_number()
validate_equals(observed_domain_number, expected_domain_number, "domainNumber value within PTP config file content")
expected_priority1 = parameters.get("priority1")
if expected_priority1:
observed_priority1 = get_pmc_get_default_data_set_object.get_priority1()
validate_equals(observed_priority1, expected_priority1, "priority1 value within PTP config file content")
expected_priority2 = parameters.get("priority2")
if expected_priority2:
observed_priority2 = get_pmc_get_default_data_set_object.get_priority2()
validate_equals(observed_priority2, expected_priority2, "priority2 value within PTP config file content")
expected_tx_timestamp_timeout = parameters.get("tx_timestamp_timeout")
if expected_tx_timestamp_timeout:
observed_tx_timestamp_timeout = get_pmc_get_default_data_set_object.get_tx_timestamp_timeout()
validate_equals(observed_tx_timestamp_timeout, expected_tx_timestamp_timeout, "tx_timestamp_timeout value within PTP config file content")
get_associated_interfaces = list(
map(
lambda ptp_host_if: ptp_host_if.get_controller_0_interfaces() if hostname == "controller-0" else ptp_host_if.get_controller_1_interfaces() if hostname == "controller-1" else ptp_host_if.get_compute_0_interfaces() if hostname == "compute-0" else [],
ptp_instance_obj.get_ptp_interfaces(),
)
)
expected_associated_interfaces = sum(get_associated_interfaces, [])
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")
def validate_port_data_set(
self,
hostname: str,
config_file: str,
socket_file: str,
expected_port_state: str,
) -> None:
"""
Validates the get port data set.
Args:
hostname (str): The name of the host.
config_file (str): the config file.
socket_file (str): the socket file.
expected_port_state (str): The current state of the port (e.g., MASTER, SLAVE, PASSIVE, LISTENING)
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
pmc_keywords = PMCKeywords(ssh_connection)
get_port_data_set_output = pmc_keywords.pmc_get_port_data_set(config_file, socket_file)
get_pmc_get_port_data_set_object = get_port_data_set_output.get_pmc_get_port_data_set_object()
observed_port_identity = get_pmc_get_port_data_set_object.get_port_identity()
observed_port_state = get_pmc_get_port_data_set_object.get_port_state()
validate_equals(observed_port_state, expected_port_state, "portState value within GET PORT_DATA_SET")
def validate_get_domain(
self,
hostname: str,
instance_parameters: str,
config_file: str,
socket_file: str,
) -> None:
"""
Validates the get domain number.
Args:
hostname (str): The name of the host.
instance_parameters (str): instance parameters
config_file (str): the config file.
socket_file (str): the socket file.
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
pmc_keywords = PMCKeywords(ssh_connection)
parameters = self.parse_instance_parameters_string(instance_parameters)
expected_domain_number = parameters.get("domainNumber")
get_domain_output = pmc_keywords.pmc_get_domain(config_file, socket_file)
observed_domain_number = get_domain_output.get_pmc_get_domain_object().get_domain_number()
validate_equals(observed_domain_number, expected_domain_number, "domainNumber value within GET DOMAIN")
def validate_parent_data_set(
self,
hostname: str,
instance_parameters: str,
config_file: str,
socket_file: str,
) -> None:
"""
Validates the get parent data set.
Args:
hostname (str): The name of the host.
instance_parameters (str): instance parameters
config_file (str): the config file.
socket_file (str): the socket file.
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
pmc_keywords = PMCKeywords(ssh_connection)
# gm.ClockClass value is always 6 if it is in a good status.
expected_gm_clock_class = 6
# gm.ClockAccuracy and gm.OffsetScaledLogVariance values can be overwritten using instance parameters,
# but for now, the default values are in use
expected_gm_clock_accuracy = "0x20"
expected_gm_offset_scaled_log_variance = "0x4e5d"
parameters = self.parse_instance_parameters_string(instance_parameters)
expected_grandmaster_priority2 = parameters.get("priority2")
get_parent_data_set_output = pmc_keywords.pmc_get_parent_data_set(config_file, socket_file)
get_parent_data_set_object = get_parent_data_set_output.get_pmc_get_parent_data_set_object()
observed_gm_clock_class = get_parent_data_set_object.get_gm_clock_class()
observed_gm_clock_accuracy = get_parent_data_set_object.get_gm_clock_accuracy()
observed_gm_offset_scaled_log_variance = get_parent_data_set_object.get_gm_offset_scaled_log_variance()
observed_grandmaster_priority2 = get_parent_data_set_object.get_grandmaster_priority2()
validate_equals(observed_gm_clock_class, expected_gm_clock_class, "gm.ClockClass value within GET PARENT_DATA_SET")
validate_equals(observed_gm_clock_accuracy, expected_gm_clock_accuracy, "gm.ClockAccuracy value within GET PARENT_DATA_SET")
validate_equals(observed_gm_offset_scaled_log_variance, expected_gm_offset_scaled_log_variance, "gm.OffsetScaledLogVariance value within GET PARENT_DATA_SET")
validate_equals(observed_grandmaster_priority2, expected_grandmaster_priority2, "grandmasterPriority2 value within GET PARENT_DATA_SET")
def validate_time_properties_data_set(
self,
hostname: str,
config_file: str,
socket_file: str,
) -> None:
"""
Validates the get time properties data set.
Args:
hostname (str): The name of the host.
config_file (str): the config file.
socket_file (str): the socket file.
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
pmc_keywords = PMCKeywords(ssh_connection)
# default values if it is in a good status.
expected_current_utc_offset = 37
expected_current_utc_offset_valid = 0
expected_time_traceable = 1
expected_frequency_traceable = 1
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()
observed_current_utc_off_set_valid = get_time_properties_data_set_object.get_current_utc_off_set_valid()
observed_time_traceable = get_time_properties_data_set_object.get_time_traceable()
observed_frequency_traceable = get_time_properties_data_set_object.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")
validate_equals(observed_frequency_traceable, expected_frequency_traceable, "frequencyTraceable value within GET TIME_PROPERTIES_DATA_SET")
def validate_grandmaster_settings_np(
self,
hostname: str,
ptp_role: str,
config_file: str,
socket_file: str,
) -> None:
"""
Validates the get grandmaster settings np.
Args:
hostname (str): The name of the host.
ptp_role (str): state of the port (e.g., MASTER and SLAVE)
config_file (str): the config file.
socket_file (str): the socket file.
Returns: None
Raises:
Exception: raised when validate fails
"""
if ptp_role == "MASTER":
expected_clock_class = 6
expected_clock_accuracy = "0x20"
expected_offset_scaled_log_variance = "0x4e5d"
expected_time_traceable = 1
expected_frequency_traceable = 1
expected_time_source = "0x20"
else:
expected_clock_class = 248
expected_clock_accuracy = "0xfe"
expected_offset_scaled_log_variance = "0xffff"
expected_time_traceable = 0
expected_frequency_traceable = 0
expected_time_source = "0xa0"
expected_current_utc_offset_valid = 0
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()
observed_clock_accuracy = get_grandmaster_settings_np_object.get_clock_accuracy()
observed_offset_scaled_log_variance = get_grandmaster_settings_np_object.get_offset_scaled_log_variance()
observed_current_utc_offset_valid = get_grandmaster_settings_np_object.get_current_utc_off_set_valid()
observed_time_traceable = get_grandmaster_settings_np_object.get_time_traceable()
observed_frequency_traceable = get_grandmaster_settings_np_object.get_frequency_traceable()
observed_time_source = get_grandmaster_settings_np_object.get_time_source()
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")
validate_equals(observed_current_utc_offset_valid, expected_current_utc_offset_valid, "currentUtcOffsetValid value within GET GRANDMASTER_SETTINGS_NP")
validate_equals(observed_time_traceable, expected_time_traceable, "timeTraceable value within GET GRANDMASTER_SETTINGS_NP")
validate_equals(observed_frequency_traceable, expected_frequency_traceable, "frequencyTraceable value within GET GRANDMASTER_SETTINGS_NP")
validate_equals(observed_time_source, expected_time_source, "timeSource value within GET GRANDMASTER_SETTINGS_NP")
def parse_instance_parameters_string(self, instance_parameters: str) -> dict:
"""
Parses a string containing instance parameters and returns a dictionary.
Args:
instance_parameters (str): A string containing instance parameters (e.g., "key1=value1 key2=value2").
Returns:
dict: A dictionary where keys are the instance parameter names and values are the
corresponding values. Returns an empty dictionary if the input string
is empty or doesn't contain any valid parameters.
Values are returned as integers if they consist only of digits,
otherwise as strings.
"""
parameters = {}
# Split the string by spaces to get individual key-value pairs
for item in instance_parameters.split():
# boundary_clock_jbod=1
match = re.search(r"([^=]+)=([^ ]+)", item)
if match:
key, value = match.groups()
# Try converting the value to an integer; if it fails, keep it as a string
try:
value = int(value)
except ValueError:
pass
parameters[key] = value
return parameters

View File

@@ -1,5 +1,10 @@
from multiprocessing import get_logger
from framework.ssh.ssh_connection import SSHConnection
from keywords.base_keyword import BaseKeyword
from keywords.ptp.ptp4l.objects.ptp4l_status_output import PTP4LStatusOutput
from keywords.cloud_platform.ssh.lab_connection_keywords import LabConnectionKeywords
from starlingx.framework.validation.validation import validate_equals
class SystemCTLStatusKeywords(BaseKeyword):
@@ -14,7 +19,7 @@ class SystemCTLStatusKeywords(BaseKeyword):
"""
Gets the status of the given service name
Args:
service_name (): the service name
service_name (str): the service name
Returns: the output as a list of strings - this should be consumed by a parser for the given output type
@@ -23,3 +28,75 @@ class SystemCTLStatusKeywords(BaseKeyword):
self.validate_success_return_code(self.ssh_connection)
return output
def verify_status_on_hostname(self, hostname :str, name : str, service_name : str) -> None:
"""
verify systemctl ptp service status on hostname
Args:
hostname (str): The name of the host
name (str): name of instance (e.g., "phc1")
service_name (str): service name (e.g., "phc2sys@phc1.service")
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
output = SystemCTLStatusKeywords(ssh_connection).get_status(service_name)
ptp_service_status_output = PTP4LStatusOutput(output)
expected_service_status = "active (running)"
observed_service_status = ptp_service_status_output.get_ptp4l_object(name).get_active()
if expected_service_status in observed_service_status :
get_logger().log_info(f"Validation Successful - systemctl status {service_name}")
else:
get_logger().log_info(f"Validation Failed - systemctl status {service_name}")
get_logger().log_info(f"Expected service status: {expected_service_status}")
get_logger().log_info(f"Observed service status: {observed_service_status}")
raise Exception("Validation Failed")
def verify_ptp_status_and_instance_parameters_on_hostname(self, hostname :str, name : str, service_name : str, instance_parameters : str) -> None:
"""
verify systemctl ptp service status and instance parameters on hostname
Args:
hostname (str): The name of the host
name (str) : name of instance (e.g., "phc1")
service_name (str): service name (e.g., "phc2sys@phc1.service")
instance_parameters (str) : instance parameters
Returns: None
Raises:
Exception: raised when validate fails
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
output = SystemCTLStatusKeywords(ssh_connection).get_status(service_name)
ptp_service_status_output = PTP4LStatusOutput(output)
expected_service_status = "active (running)"
observed_service_status = ptp_service_status_output.get_ptp4l_object(name).get_active()
get_command = ptp_service_status_output.get_ptp4l_object(name).get_command()
# From the input string "cmdline_opts='-s enpXXs0f2 -O -37 -m'"
# The extracted output string is '-s enpXXs0f2 -O -37 -m'
instance_parameter = eval(instance_parameters.split("=")[1])
if expected_service_status in observed_service_status and instance_parameter in get_command :
get_logger().log_info(f"Validation Successful - systemctl status {service_name}")
else:
get_logger().log_info(f"Validation Failed - systemctl status {service_name}")
get_logger().log_info(f"Expected service status: {expected_service_status}")
get_logger().log_info(f"Observed service status: {observed_service_status}")
get_logger().log_info(f"Expected instance parameter: {instance_parameter}")
get_logger().log_info(f"Observed instance parameter: {get_command}")
raise Exception("Validation Failed")

View File

@@ -65,7 +65,7 @@ class CatPtpCguParser:
"""
cgu: PtpCguComponentObject = None
match = re.match(r"Found (\S+) CGU", self.cat_ptp_cgu_output[0])
match = re.match(r"(Found (\S+) CGU|Password: Found (\S+) CGU)", self.cat_ptp_cgu_output[0]) # Ask about this
if match:
chip_model = match.group(1)
config_version_match = re.search(

View File

@@ -65,7 +65,7 @@ class DefaultDataSetOutput:
self.pmc_get_default_data_set_object.set_clock_identity(output_values["clockIdentity"])
if "domainNumber" in output_values:
self.pmc_get_default_data_set_object.set_domain_number(output_values["domainNumber"])
self.pmc_get_default_data_set_object.set_domain_number(int(output_values["domainNumber"]))
if "free_running" in output_values:
self.pmc_get_default_data_set_object.set_free_running(int(output_values["free_running"]))
@@ -109,6 +109,9 @@ class DefaultDataSetOutput:
if "time_stamping" in output_values:
self.get_pmc_get_default_data_set_object().set_time_stamping(output_values["time_stamping"])
if "tx_timestamp_timeout" in output_values:
self.get_pmc_get_default_data_set_object().set_tx_timestamp_timeout(int(output_values["tx_timestamp_timeout"]))
if "uds_address" in output_values:
self.get_pmc_get_default_data_set_object().set_uds_address(output_values["uds_address"])

View File

@@ -1,3 +1,4 @@
import re
import time
from multiprocessing import get_logger
from time import sleep
@@ -19,6 +20,77 @@ class GnssKeywords(BaseKeyword):
Initializes the GnssKeywords.
"""
def get_pci_slot_name(self, hostname: str, interface: str) -> str:
"""
Retrieves the PCI_SLOT_NAME from the uevent file for a given PTP interface.
Args:
hostname (str) : The name of the host
interface (str): The name of the ptp interface (e.g., "enp138s0f0").
Returns:
str: The PCI slot name if found, otherwise None.
Raises:
Exception: raised when PCI_SLOT_NAME not found
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
# The GNSS signal will always be on port 0 of the NIC, even if ts2phc uses ports 1, 2, 3, and so on.
interface_name = f"{interface[:-1]}0"
uevent_path = f"/sys/class/net/{interface_name}/device/uevent"
uevent_content = ssh_connection.send(f"grep PCI_SLOT_NAME {uevent_path}")
# Use regex to find the PCI_SLOT_NAME
match = re.search(r"PCI_SLOT_NAME=(.*)", " ".join(uevent_content))
if match:
return match.group(1).strip() # Return the captured value, removing leading/trailing spaces
else:
raise Exception(f"PCI_SLOT_NAME not found in {uevent_path}")
def get_gnss_serial_port_from_gnss_directory(self, hostname: str, interface: str) -> str:
"""
Get GNSS serial port from the specified gnss directory.
Args:
hostname (str) : The name of the host
interface (str): The name of the PTP interface (e.g., "enp138s0f0").
Returns:
str: The GNSS serial port value (e.g., "gnss0") if found, otherwise None.
"""
lab_connect_keywords = LabConnectionKeywords()
ssh_connection = lab_connect_keywords.get_ssh_for_hostname(hostname)
pci_address = self.get_pci_slot_name(hostname, interface)
gnss_dir = f"/sys/bus/pci/devices/{pci_address}/gnss"
contents = ssh_connection.send(f"ls {gnss_dir}")
if not contents:
get_logger().log_info(f"The directory {gnss_dir} is empty.")
return None
return " ".join(contents).strip() # Return the captured value in str, removing leading/trailing spaces
def extract_gnss_port(self, instance_parameters: str) -> str:
"""
Extracts the GNSS serial port value from a ts2phc.nmea_serialport configuration string using regex.
Args:
instance_parameters (str): The string containing the ts2phc.nmea_serialport setting.
Returns:
str: The GNSS serial port value (e.g., "gnss0") if found, otherwise None.
"""
match = re.search(r"ts2phc\.nmea_serialport\s*=\s*/dev/([^ ]*)", instance_parameters)
if match:
return match.group(1)
else:
return None
def gnss_power_on(self, hostname: str, nic: str) -> None:
"""
Power on gnss
@@ -88,6 +160,8 @@ class GnssKeywords(BaseKeyword):
expected_pps_dpll_status (list): expected list of PPS DPLL status values.
timeout (int): The maximum time (in seconds) to wait for the match.
polling_sleep_time (int): The time period to wait to receive the expected output.
Returns: None
Raises:
TimeoutError: raised when validate does not equal in the required time

View File

@@ -232,7 +232,7 @@ class PMCGetDefaultDataSetObject:
"""
self.clock_identity = clock_identity
def get_domain_number(self) -> str:
def get_domain_number(self) -> int:
"""
Getter for domain_number
@@ -242,7 +242,7 @@ class PMCGetDefaultDataSetObject:
"""
return self.domain_number
def set_domain_number(self, domain_number: str):
def set_domain_number(self, domain_number: int):
"""
Setter for domain_number

View File

@@ -73,7 +73,7 @@ class PMCGetDefaultDataSetOutput:
self.pmc_get_default_data_set_object.set_clock_identity(output_values["clockIdentity"])
if "domainNumber" in output_values:
self.pmc_get_default_data_set_object.set_domain_number(output_values["domainNumber"])
self.pmc_get_default_data_set_object.set_domain_number(int(output_values["domainNumber"]))
if "free_running" in output_values:
self.pmc_get_default_data_set_object.set_free_running(int(output_values["free_running"]))

View File

@@ -8,6 +8,7 @@ from keywords.ptp.pmc.objects.pmc_get_parent_data_set_output import PMCGetParent
from keywords.ptp.pmc.objects.pmc_get_port_data_set_output import PMCGetPortDataSetOutput
from keywords.ptp.pmc.objects.pmc_get_time_properties_data_set_output import PMCGetTimePropertiesDataSetOutput
from keywords.ptp.pmc.objects.pmc_get_time_status_np_output import PMCGetTimeStatusNpOutput
from keywords.ptp.pmc.objects.pmc_get_port_data_set_output import PMCGetPortDataSetOutput
class PMCKeywords(BaseKeyword):
@@ -153,16 +154,12 @@ class PMCKeywords(BaseKeyword):
def pmc_get_default_data_set(self, config_file: str, socket_file: str, unicast: bool = True, boundry_clock: int = 0) -> PMCGetDefaultDataSetOutput:
"""
Gets the default data set
Args:
config_file (str): the config file
socket_file (str): the socket file
unicast (bool): true to use unicast
boundry_clock (int): the boundry clock
Returns:
PMCGetDefaultDataSetOutput: the default dataset output
Example: PMCKeywords(ssh_connection).pmc_get_default_data_set('/etc/linuxptp/ptpinstance/ptp4l-ptp5.conf', ' /var/run/ptp4l-ptp5')
"""
@@ -172,6 +169,24 @@ class PMCKeywords(BaseKeyword):
pmc_get_default_data_set_output = PMCGetDefaultDataSetOutput(output)
return pmc_get_default_data_set_output
def pmc_get_port_data_set(self, config_file: str, socket_file: str, unicast: bool = True, boundry_clock: int = 0) -> PMCGetPortDataSetOutput:
"""
Gets the port data set
Args:
config_file (str): the config file
socket_file (str): the socket file
unicast (bool): true to use unicast
boundry_clock (int): the boundry clock
Example: PMCKeywords(ssh_connection).pmc_get_port_data_set('/etc/linuxptp/ptpinstance/ptp4l-ptp5.conf', ' /var/run/ptp4l-ptp5')
"""
cmd = f"pmc {'-u' if unicast else ''} -b {boundry_clock} -f {config_file} -s {socket_file} 'GET PORT_DATA_SET'"
output = self.ssh_connection.send_as_sudo(cmd)
pmc_get_port_data_set_output = PMCGetPortDataSetOutput(output)
return pmc_get_port_data_set_output
def pmc_get_domain(self, config_file: str, socket_file: str, unicast: bool = True, boundry_clock: int = 0) -> PMCGetDomainOutput:
"""
Gets the domain

View File

@@ -80,7 +80,7 @@ class PTP4LStatusOutput:
"""
Getter for ptp4l object with the given service name
Args:
service_name (): the name of the service
service_name (str): the name of the service (e.g., "phc1")
Returns: PTP4LStatusObject

View File

@@ -46,7 +46,7 @@ class PTP4LStatusParser:
for line in self.ptp4l_status_output:
line = line.strip()
if line.startswith(''): # we have a new service to get values for
service_name = line.split('@')[1].split(' ')[0] # format ptp4l@ptp1.service - Precision Time Protocol (PTP) service
service_name = line.split('@')[1].split(' ')[0].replace('.service','') # format ptp4l@ptp1.service - Precision Time Protocol (PTP) service
services[service_name] = {}
current_service = services[service_name]
elif line.startswith('└─') and current_service is not None:

View File

@@ -39,6 +39,12 @@ class PTP4LSetup:
ptp_interfaces.append(ptp_host_ifs_dict[ptp_interface_name])
self.ptp_interfaces = ptp_interfaces
self.ptp_role = "MASTER" # default value is MASTER
if "ptp_role" in setup_dict:
self.ptp_role = setup_dict["ptp_role"]
self.port_state = setup_dict.get("port_state")
def __str__(self) -> str:
"""
String representation of this object.
@@ -99,3 +105,22 @@ class PTP4LSetup:
if ptp_interface.get_name() == interface_name:
return ptp_interface
raise Exception(f"There is no ptp interface named {interface_name} in the ptp4l setup.")
def get_ptp_role(self) -> str:
"""
Gets the ptp role
Returns:
str: ptp role
"""
return self.ptp_role
def get_port_state(self) -> str:
"""
Gets the port state
Returns:
str: port state
"""
return self.port_state

View File

@@ -30,6 +30,10 @@ class PTPHostInterfaceSetup:
raise Exception(f"The ptp host interface entry {self.name} must have controller_1_interfaces defined.")
self.controller_1_interfaces = setup_dict["controller_1_interfaces"]
self.compute_0_interfaces = None
if "compute_0_interfaces" in setup_dict:
self.compute_0_interfaces = setup_dict.get("compute_0_interfaces")
def __str__(self):
"""
String representation of this object.
@@ -75,3 +79,12 @@ class PTPHostInterfaceSetup:
List[str]: The controller_1_interfaces of this ptp host interface setup.
"""
return self.controller_1_interfaces
def get_compute_0_interfaces(self) -> List[str]:
"""
Gets the compute_0_interfaces of this ptp host interface setup.
Returns:
List[str]: The compute_0_interfaces of this ptp host interface setup.
"""
return self.compute_0_interfaces

View File

@@ -211,14 +211,14 @@
name: "clock1if1",
controller_0_interfaces: ["{{ controller_0.nic1.conn_to_spirent }}"],
controller_1_interfaces: [],
ptp_interface_parameter : "sma1={{ controller_0.nic1.sma1.name }}",
ptp_interface_parameter : "sma1={{ controller_0.nic1.sma1.is_input_or_output }}",
},
{
name: "clock1if2",
controller_0_interfaces: ["{{ controller_0.nic2.base_port }}"],
controller_1_interfaces: [],
ptp_interface_parameter : "sma1={{ controller_0.nic2.sma1.name }}",
ptp_interface_parameter : "sma1={{ controller_0.nic2.sma1.is_input_or_output }}",
},
],

View File

@@ -5,51 +5,54 @@
{
name: "ptp1",
instance_hostnames : ["controller-0", "controller-1","compute-0"] ,
instance_parameters: "tx_timestamp_timeout=700 domainNumber=24 dataset_comparison=G.8275.x priority2=100 boundary_clock_jbod=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",
"ptp1if2",
]
],
ptp_role: "MASTER"
},
{
name: "ptp2",
instance_hostnames : [],
instance_parameters: "dataset_comparison=G.8275.x domainNumber=24 tx_timestamp_timeout=700 boundary_clock_jbod=1 priority2=110",
instance_parameters: "priority2=110 dataset_comparison=G.8275.x tx_timestamp_timeout=700 boundary_clock_jbod=1 domainNumber=24",
ptp_interface_names: [
"ptp2if1",
"ptp2if2"
],
ptp_role: "MASTER"
},
{
name: "ptp3",
instance_hostnames : ["controller-0"],
instance_parameters: "dataset_comparison=G.8275.x domainNumber=24 tx_timestamp_timeout=700 boundary_clock_jbod=1 priority2=100",
instance_hostnames : ["controller-0", "compute-0"],
instance_parameters: "priority2=100 dataset_comparison=G.8275.x tx_timestamp_timeout=700 boundary_clock_jbod=1 domainNumber=24",
ptp_interface_names: [
"ptp3if1",
"ptp3if2"
],
ptp_role: "MASTER"
},
{
name: "ptp4",
instance_hostnames : ["controller-1"],
instance_parameters: "priority2=110 dataset_comparison=G.8275.x domainNumber=24 tx_timestamp_timeout=700 boundary_clock_jbod=1",
instance_parameters: "boundary_clock_jbod=1 tx_timestamp_timeout=700 priority2=110 dataset_comparison=G.8275.x domainNumber=24",
ptp_interface_names: [
"ptp4if1",
"ptp4if2"
],
ptp_role: "SLAVE"
}
],
phc2sys : [
{
name: "phc1",
instance_hostnames : ["controller-0", "controller-1","compute-0"],
instance_hostnames : ["controller-0", "compute-0", "controller-1"],
instance_parameters: "cmdline_opts='-s {{controller_0.nic1.conn_to_proxmox}} -O -37 -m'",
ptp_interface_names: [
"phc1if1",
@@ -68,7 +71,7 @@
{
name: "phc3",
instance_hostnames : [],
instance_parameters: "uds_address=/var/run/ptp4l-ptp3 domainNumber=24",
instance_parameters: "domainNumber=24 uds_address=/var/run/ptp4l-ptp3",
ptp_interface_names: [
"phc3if1",
],
@@ -77,7 +80,7 @@
{
name: "phc4",
instance_hostnames : [],
instance_parameters: "uds_address=/var/run/ptp4l-ptp4 domainNumber=24",
instance_parameters: "domainNumber=24 uds_address=/var/run/ptp4l-ptp4",
ptp_interface_names: [
"phc4if1",
],
@@ -86,41 +89,35 @@
],
ts2phc : [
{
name: "ts1",
instance_hostnames : ["controller-0"],
instance_hostnames : ["controller-1", "controller-0", "compute-0"],
instance_parameters: "ts2phc.nmea_serialport=/dev/gnss0",
ptp_interface_names: [
"ts1if1",
],
}
},
],
clock : [
{
name: "clock1",
instance_hostnames : ["controller-0"],
instance_hostnames : ["controller-0","compute-0"],
instance_parameters: "",
ptp_interface_names: [
"clock1if1",
"clock1if2",
],
}
},
],
},
ptp_host_ifs: [
{
name: "ptp1if1",
controller_0_interfaces: ["{{ controller_0.nic1.nic_connection.interface }}"], // Connection to controller1-nic1
controller_1_interfaces: ["{{ controller_1.nic1.nic_connection.interface }}"], // Connection to controller0-nic1
compute_0_interfaces: [],
controller_0_interfaces: ["{{ controller_0.nic1.nic_connection.interface }}"],
controller_1_interfaces: ["{{ controller_1.nic1.nic_connection.interface }}"],
compute_0_interfaces: ["{{ compute_0.nic1.nic_connection.interface }}"],
ptp_interface_parameter : "",
},
@@ -150,9 +147,9 @@
{
name: "ptp3if1",
controller_0_interfaces: ["{{ controller_0.nic2.nic_connection.interface }}"], // Connection to Controller1 Nic 2
controller_0_interfaces: ["{{ controller_0.nic2.nic_connection.interface }}"],
controller_1_interfaces: [],
compute_0_interfaces: [],
compute_0_interfaces: ["{{ compute_0.nic2.nic_connection.interface }}"],
ptp_interface_parameter : "",
},
@@ -167,7 +164,7 @@
{
name: "ptp4if1",
controller_0_interfaces: [],
controller_1_interfaces: ["{{ controller_0.nic2.nic_connection.interface }}"], // Connection to Controller1 Nic 2
controller_1_interfaces: ["{{ controller_1.nic2.nic_connection.interface }}"],
compute_0_interfaces: [],
ptp_interface_parameter : "",
},
@@ -207,16 +204,16 @@
{
name: "phc4if1",
controller_0_interfaces: [],
controller_1_interfaces: ["{{ controller_1.nic1.base_port }}", "{{ controller_1.nic2.base_port }}"],
controller_1_interfaces: ["{{ controller_1.nic2.base_port }}"],
compute_0_interfaces: [],
ptp_interface_parameter :"",
},
{
name: "ts1if1",
controller_0_interfaces: ["{{ controller_0.nic1.conn_to_proxmox }}", "{{ controller_0.nic2.base_port }}"],
controller_1_interfaces: [],
compute_0_interfaces: [],
controller_0_interfaces: ["{{ controller_0.nic2.base_port }}", "{{ controller_0.nic1.conn_to_proxmox }}"],
controller_1_interfaces: ["{{ controller_1.nic1.conn_to_proxmox }}"],
compute_0_interfaces: ["{{ compute_0.nic1.nic_connection.interface }}", "{{ compute_0.nic2.nic_connection.interface }}"],
ptp_interface_parameter : "",
},
@@ -224,17 +221,15 @@
name: "clock1if1",
controller_0_interfaces: ["{{ controller_0.nic1.conn_to_proxmox }}"],
controller_1_interfaces: [],
compute_0_interfaces: [],
ptp_interface_parameter : "sma1={{ controller_0.nic1.sma1.name }}",
compute_0_interfaces: ["{{ compute_0.nic1.nic_connection.interface }}"],
ptp_interface_parameter : "sma1={{ controller_0.nic1.sma1.is_input_or_output }}",
},
{
name: "clock1if2",
controller_0_interfaces: ["{{ controller_0.nic2.base_port }}"],
controller_1_interfaces: [],
compute_0_interfaces: [],
ptp_interface_parameter : "sma1={{ controller_0.nic2.sma1.name }}",
compute_0_interfaces: ["{{ compute_0.nic2.nic_connection.interface }}"],
ptp_interface_parameter : "sma1={{ controller_0.nic2.sma1.is_input_or_output }}",
},
],
}

View File

@@ -33,7 +33,7 @@ def test_ptp4l_service_status_output_parser():
ptp4l_service_status_output = PTP4LStatusOutput(ptp4l_status_output)
# validate first service 'ptp1.service'
ptp4l_status_object = ptp4l_service_status_output.get_ptp4l_object('ptp1.service')
ptp4l_status_object = ptp4l_service_status_output.get_ptp4l_object('ptp1')
assert ptp4l_status_object.get_active() == 'active (running) since Mon 2025-02-10 18:36:34 UTC; 3 days ago'
assert ptp4l_status_object.get_c_group() == '/system.slice/system-ptp4l.slice/ptp4l@ptp1.service'
@@ -46,7 +46,7 @@ def test_ptp4l_service_status_output_parser():
assert ptp4l_status_object.get_tasks() == '1 (limit: 150897)'
# validate second service 'ptp3.service
ptp4l_status_object = ptp4l_service_status_output.get_ptp4l_object('ptp3.service')
ptp4l_status_object = ptp4l_service_status_output.get_ptp4l_object('ptp3')
assert ptp4l_status_object.get_active() == 'active (running) since Wed 2025-02-12 16:22:23 UTC; 2 days ago'
assert ptp4l_status_object.get_c_group() == '/system.slice/system-ptp4l.slice/ptp4l@ptp3.service'