Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 0 additions & 22 deletions ansible/roles/test/tasks/read_mac/check_interfaces_and_mtu.yml

This file was deleted.

20 changes: 0 additions & 20 deletions ansible/roles/test/tasks/read_mac/loganalyzer_analyze_mac.yml

This file was deleted.

This file was deleted.

84 changes: 0 additions & 84 deletions ansible/roles/test/tasks/read_mac/read_mac_metadata_loop.yml

This file was deleted.

59 changes: 9 additions & 50 deletions ansible/roles/test/tasks/read_mac_metadata.yml
Original file line number Diff line number Diff line change
@@ -1,52 +1,11 @@
# Input Parameters:
# -e image1=http://IP_ADDR/SERVER_URL/IMAGE_NAME.bin
# -e image2=http://IP_ADDR/SERVER_URL/IMAGE_NAME.bin
# -e iterations=INT_NUMBER
# Optional:
# -e minigraph1=/path/to/the/minigraph.xml
# -e minigraph2=/path/to/the/minigraph.xml
# Note
# This test has at least 2 parameters that cannot be defined as default (image1 and image2)
# Because of this backward compatibility currently does not work (I mean ability to run test using ansible-playbook)

- block:
- fail: msg="Please specify URL to the image1"
when: image1 is not defined
# ansible-playbook test_sonic.yml -i inventory --limit {DUT_NAME} -e testbed_name={TESTBED_NAME} -e testbed_type={TESTBED_TYPE} -e testcase_name=read_mac -e iterations={ITERATIONS} -e image1={IMAGE1} -e image2={IMAGE2}
# Current implementation of ansible to pytest wrapper does not allow to pass python input params. And this may be motivation to improve it fuctionality in future

- fail: msg="Please specify URL to the image2"
when: image2 is not defined

- fail: msg="Please specify 'iterations' variable"
when: iterations is not defined

# Prepare variables for loganalyzer
- set_fact:
testname: read_mac
- set_fact:
testname_unique: "{{ testname }}.{{ lookup('pipe','date +%Y-%m-%d-%H:%M:%S') }}"
- set_fact:
# Set custom match instead of default match
test_match_file: read_mac_meta_match_messages.txt
summary_file: summary.loganalysis.{{ testname_unique }}.log
result_file: result.loganalysis.{{ testname_unique }}.log
errors_expected: false
skip_common_match: true
out_dir: /tmp
run_dir: /tmp
tests_location: roles/test/tasks
current_image: ""
temp_minigraph: ""

- name: Check minigraph exists
stat:
path: /etc/sonic/minigraph.xml
register: output

- set_fact: store_original_minigraph=true
when: output.stat.exists

# Store current minigraph for debug purpose
- shell: cp /etc/sonic/minigraph.xml /home/
become: true
when: (minigraph1 is defined) or (minigraph2 is defined) and (store_original_minigraph is defined)

- name: Verify MAC in image reinstall loop
include_tasks: roles/test/tasks/read_mac/read_mac_metadata_loop.yml
with_sequence: count={{ iterations }}
- name: run test
include_tasks: roles/test/tasks/pytest_runner.yml
vars:
test_node: read_mac/test_read_mac_metadata.py
41 changes: 41 additions & 0 deletions tests/read_mac/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
Pytest configuration used by the read MAC tests.
"""

def pytest_addoption(parser):
"""
Adding arguments required for read MAC metadata testcase
"""
parser.addoption(
"--iteration",
action="store",
type=int,
help="Number of image installing iterations",
)

parser.addoption(
'--image1',
action='store',
type=str,
help='1st image to download and install',
)

parser.addoption(
'--image2',
action='store',
type=str,
help='2nd image to download and install',
)

parser.addoption(
'--minigraph1',
action='store',
type=str,
help='path to the minigraph1',
)
parser.addoption(
'--minigraph2',
action='store',
type=str,
help='path to the minigraph2',
)
146 changes: 146 additions & 0 deletions tests/read_mac/test_read_mac_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import pytest
import logging

from tests.common.utilities import wait
from tests.common.utilities import wait_until
from tests.common.plugins.sanity_check import checks
from tests.common.plugins.loganalyzer.loganalyzer import LogAnalyzer
from tests.common.helpers.assertions import pytest_assert
from datetime import datetime


logger = logging.getLogger(__name__)

BINARY_FILE_ON_LOCALHOST = "/tmp/update_image.bin"
BINARY_FILE_ON_DUTHOST = "/tmp/mellanox.bin"

pytestmark = [
pytest.mark.topology('any')
]

@pytest.fixture(scope='function')
def cleanup_read_mac(duthost, localhost):
yield
logger.info('Remove temporary images')
duthost.shell("rm -rf {}".format(BINARY_FILE_ON_DUTHOST))
localhost.shell("rm -rf {}".format(BINARY_FILE_ON_LOCALHOST))

backup_minigraph_exist = duthost.stat(path = "/etc/sonic/minigraph.xml.backup")["stat"]["exists"]
if backup_minigraph_exist:
logger.info("Apply minigraph from backup")
duthost.shell("mv /etc/sonic/minigraph.xml.backup /etc/sonic/minigraph.xml")
duthost.shell("config load_minigraph -y")
duthost.shell("config save -y")

class ReadMACMetadata():
def __init__(self, request):
self.iteration = request.config.getoption("--iteration")
self.image1 = request.config.getoption("--image1")
self.image2 = request.config.getoption("--image2")
self.minigraph1 = request.config.getoption("--minigraph1")
self.minigraph2 = request.config.getoption("--minigraph2")

if not self.image1:
pytest.fail("Please specify --image1")
if not self.image2:
pytest.fail("Please specify --image2")
if not self.iteration or self.iteration < 1:
pytest.fail("Please specify --iteration in correct range")

self.request = request
duthost = request.getfixturevalue('duthost')

minigraph_exist = duthost.stat(path = "/etc/sonic/minigraph.xml")["stat"]["exists"]
if (self.minigraph1 is not None or self.minigraph2 is not None) and minigraph_exist:
logger.info("Store current minigraph for debug purpose")
duthost.shell("cp /etc/sonic/minigraph.xml /etc/sonic/minigraph.xml.backup")

def run_test_in_reinstall_loop(self):
logger.info("Verify MAC in image reinstall loop")
duthost = self.request.getfixturevalue('duthost')
localhost = self.request.getfixturevalue('localhost')

for counter in range(1, self.iteration + 1):
current_minigraph = None

if counter % 2 == 1:
current_image = self.image1
current_minigraph = self.minigraph1
else:
current_image = self.image2
current_minigraph = self.minigraph2

logger.info("Iteration #{}".format(counter))
logger.info("Current image: {}, temporary minigraph: {}".format(current_image, current_minigraph))
if current_minigraph:
logger.info("Copy specified minigraph {} to the /etc/sonic folder".format(current_minigraph))
duthost.copy(src=current_minigraph, dest="/etc/sonic/minigraph.xml")

loganalyzer = LogAnalyzer(ansible_host=duthost, marker_prefix="read_mac_metadata")
loganalyzer.match_regex = [ ".*can't parse mac address 'None'*" ]

with loganalyzer:
self.deploy_image_to_duthost(duthost, localhost , current_image)
self.reboot_dut(localhost, duthost)

if current_minigraph:
logger.info("Execute cli 'config load_minigraph -y' to apply new minigraph")
duthost.shell("config load_minigraph -y")
duthost.shell("config save -y")

logger.info("Remove old (not current) sonic image")
duthost.reduce_and_add_sonic_images(disk_used_pcent = 1)

self.check_mtu_and_interfaces(duthost)

def deploy_image_to_duthost(self, duthost, localhost, current_image):
logger.info("Download SONiC image {}".format(current_image))
localhost.get_url(url=current_image, dest=BINARY_FILE_ON_LOCALHOST)

logger.info("Upload SONiC image to device")
duthost.copy(src=BINARY_FILE_ON_LOCALHOST, dest=BINARY_FILE_ON_DUTHOST)

logger.info("Installing new SONiC image")
duthost.shell("sonic_installer install -y {}".format(BINARY_FILE_ON_DUTHOST))

def reboot_dut(self, localhost, duthost):
hostname = duthost.hostname
logger.info("Execute task: reboot {}".format(hostname))
duthost.command("sudo reboot", module_ignore_errors=True, module_async=True)
logger.info("Wait for {} to go down".format(hostname))
result = localhost.wait_for(host=hostname, port=22, state='stopped', timeout=180, module_ignore_errors=True)
if 'msg' in result.keys() and 'Timeout' in result['msg']:
pytest.fail(result['msg'])

logger.info("Wait for {} to come back".format(hostname))
localhost.wait_for(host=hostname, port=22, state='started', delay=10, timeout=300)
logger.info("Wait until system is stable")
pytest_assert(wait_until(300, 20, duthost.critical_services_fully_started), "Not all critical services are fully started")

def check_mtu_and_interfaces(self, duthost):
logger.info("Verify that MAC address fits template XX:XX:XX:XX:XX:XX")
mac = duthost.shell("redis-cli -n 4 hget 'DEVICE_METADATA|localhost' mac| grep -io '[0-9a-fA-F:]\{17\}'", module_ignore_errors=True)['stdout']
logger.info("DUT MAC is {}".format(mac))

if not mac:
pytest.fail("MAC entry does not exist")

logger.info("Verify interfaces are UP and MTU == 9100")
checks.check_interfaces(duthost)

cfg_facts = duthost.config_facts(host=duthost.hostname, source="persistent")['ansible_facts']
non_default_ports = [k for k,v in cfg_facts["PORT"].items() if "mtu" in v and v["mtu"] != "9100" and "admin_status" in v and v["admin_status"] == "up" ]
non_default_portchannel = [k for k,v in cfg_facts["PORTCHANNEL"].items() if "mtu" in v and v["mtu"] != "9100" and "admin_status" in v and v["admin_status"] == "up" ]

if len(non_default_ports) != 0 or len(non_default_portchannel) != 0:
pytest.fail("There are ports/portchannel with non default MTU:\nPorts: {}\nPortchannel: {}".format(non_default_ports,non_default_portchannel))


@pytest.mark.disable_loganalyzer
def test_read_mac_metadata(request,cleanup_read_mac):
"""
Verify that after installing new image on duthost MAC remains valid on interfaces
"""
read_mac_metadata = ReadMACMetadata(request)
read_mac_metadata.run_test_in_reinstall_loop()