|
18 | 18 |
|
19 | 19 | from datetime import datetime |
20 | 20 | from ipaddress import ip_interface, IPv4Interface |
| 21 | +from tests.common.connections.base_console_conn import ( |
| 22 | + CONSOLE_SSH_CISCO_CONFIG, |
| 23 | + CONSOLE_SSH_DIGI_CONFIG, |
| 24 | + CONSOLE_SSH_SONIC_CONFIG |
| 25 | +) |
21 | 26 | from tests.common.fixtures.conn_graph_facts import conn_graph_facts # noqa F401 |
22 | 27 | from tests.common.devices.local import Localhost |
23 | 28 | from tests.common.devices.ptf import PTFHost |
@@ -1883,24 +1888,112 @@ def duthost_console(duthosts, enum_supervisor_dut_hostname, localhost, conn_grap |
1883 | 1888 | console_host = console_host.split("/")[0] |
1884 | 1889 | console_port = conn_graph_facts['device_console_link'][dut_hostname]['ConsolePort']['peerport'] |
1885 | 1890 | console_type = conn_graph_facts['device_console_link'][dut_hostname]['ConsolePort']['type'] |
| 1891 | + console_menu_type = conn_graph_facts['device_console_link'][dut_hostname]['ConsolePort']['menu_type'] |
1886 | 1892 | console_username = conn_graph_facts['device_console_link'][dut_hostname]['ConsolePort']['proxy'] |
1887 | 1893 |
|
1888 | | - console_type = "console_" + console_type |
| 1894 | + console_type = f"console_{console_type}" |
| 1895 | + console_menu_type = f"{console_type}_{console_menu_type}" |
1889 | 1896 |
|
1890 | 1897 | # console password and sonic_password are lists, which may contain more than one password |
1891 | 1898 | sonicadmin_alt_password = localhost.host.options['variable_manager']._hostvars[dut_hostname].get( |
1892 | 1899 | "ansible_altpassword") |
1893 | | - host = ConsoleHost(console_type=console_type, |
1894 | | - console_host=console_host, |
1895 | | - console_port=console_port, |
1896 | | - sonic_username=creds['sonicadmin_user'], |
1897 | | - sonic_password=[creds['sonicadmin_password'], sonicadmin_alt_password], |
1898 | | - console_username=console_username, |
1899 | | - console_password=creds['console_password'][console_type]) |
| 1900 | + sonic_password = [creds['sonicadmin_password'], sonicadmin_alt_password] |
| 1901 | + |
| 1902 | + # Attempt to clear the console port |
| 1903 | + try: |
| 1904 | + duthost_clear_console_port( |
| 1905 | + menu_type=console_menu_type, |
| 1906 | + console_host=console_host, |
| 1907 | + console_port=console_port, |
| 1908 | + console_username=console_username, |
| 1909 | + console_password=creds['console_password'][console_type] |
| 1910 | + ) |
| 1911 | + except Exception as e: |
| 1912 | + logger.warning(f"Issue trying to clear console port: {e}") |
| 1913 | + |
| 1914 | + # Set up console host |
| 1915 | + host = None |
| 1916 | + for attempt in range(1, 4): |
| 1917 | + try: |
| 1918 | + host = ConsoleHost(console_type=console_type, |
| 1919 | + console_host=console_host, |
| 1920 | + console_port=console_port, |
| 1921 | + sonic_username=creds['sonicadmin_user'], |
| 1922 | + sonic_password=sonic_password, |
| 1923 | + console_username=console_username, |
| 1924 | + console_password=creds['console_password'][console_type]) |
| 1925 | + break |
| 1926 | + except Exception as e: |
| 1927 | + logger.warning(f"Attempt {attempt}/3 failed: {e}") |
| 1928 | + continue |
| 1929 | + else: |
| 1930 | + raise Exception("Failed to set up connection to console port. See warning logs for details.") |
| 1931 | + |
1900 | 1932 | yield host |
1901 | 1933 | host.disconnect() |
1902 | 1934 |
|
1903 | 1935 |
|
| 1936 | +def duthost_clear_console_port( |
| 1937 | + menu_type: str, |
| 1938 | + console_host: str, |
| 1939 | + console_port: str, |
| 1940 | + console_username: str, |
| 1941 | + console_password: str |
| 1942 | +): |
| 1943 | + """ |
| 1944 | + Helper function to clear the console port for a given DUT. |
| 1945 | + Useful when a device has an occupied console port, preventing dut_console tests from running. |
| 1946 | +
|
| 1947 | + Parameters: |
| 1948 | + menu_type: Connection type for the console's config menu (as expected by the ConsoleTypeMapper) |
| 1949 | + console_host: DUT host's console IP address |
| 1950 | + console_port: DUT host's console port, to be cleared |
| 1951 | + console_username: Username for the console account (overridden for Digi console) |
| 1952 | + console_password: Password for the console account |
| 1953 | + """ |
| 1954 | + if menu_type == "console_ssh_": |
| 1955 | + raise Exception("Device does not have a defined Console_menu_type.") |
| 1956 | + |
| 1957 | + # Override console user if the configuration menu is Digi, as this requires admin login |
| 1958 | + console_user = 'admin' if menu_type == CONSOLE_SSH_DIGI_CONFIG else console_username |
| 1959 | + |
| 1960 | + duthost_config_menu = ConsoleHost( |
| 1961 | + console_type=menu_type, |
| 1962 | + console_host=console_host, |
| 1963 | + console_port=console_port, |
| 1964 | + console_username=console_user, |
| 1965 | + console_password=console_password, |
| 1966 | + sonic_username=None, |
| 1967 | + sonic_password=None |
| 1968 | + ) |
| 1969 | + |
| 1970 | + # Command lists for each config menu type |
| 1971 | + # List of tuples, containing a command to execute, and an optional pattern to wait for |
| 1972 | + command_list = { |
| 1973 | + CONSOLE_SSH_DIGI_CONFIG: [ |
| 1974 | + ('2', None), # Enter serial port config |
| 1975 | + (console_port, None), # Choose DUT console port |
| 1976 | + ('a', None), # Enter port management |
| 1977 | + ('1', f'Port #{console_port} has been reset successfully.') # Reset chosen port |
| 1978 | + ], |
| 1979 | + CONSOLE_SSH_SONIC_CONFIG: [ |
| 1980 | + (f'sudo sonic-clear line {console_port}', None) # Clear DUT console port (requires sudo) |
| 1981 | + ], |
| 1982 | + CONSOLE_SSH_CISCO_CONFIG: [ |
| 1983 | + (f'clear line tty {console_port}', '[confirm]'), # Clear DUT console port |
| 1984 | + ('', '[OK]') # Confirm selection |
| 1985 | + ], |
| 1986 | + } |
| 1987 | + |
| 1988 | + for command, wait_for_pattern in command_list[menu_type]: |
| 1989 | + duthost_config_menu.write_channel(command + duthost_config_menu.RETURN) |
| 1990 | + duthost_config_menu.read_until_prompt_or_pattern(wait_for_pattern) |
| 1991 | + |
| 1992 | + duthost_config_menu.disconnect() |
| 1993 | + logger.info(f"Successfully cleared console port {console_port}, sleeping for 5 seconds") |
| 1994 | + time.sleep(5) |
| 1995 | + |
| 1996 | + |
1904 | 1997 | @pytest.fixture(scope='session') |
1905 | 1998 | def cleanup_cache_for_session(request): |
1906 | 1999 | """ |
|
0 commit comments