Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
44 changes: 44 additions & 0 deletions tests/read_mac/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""
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",
required=True,
)

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

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

parser.addoption(
'--minigraph1',
action='store',
type=str,
help='path to the minigraph1',
)
parser.addoption(
'--minigraph2',
action='store',
type=str,
help='path to the minigraph2',
)
131 changes: 131 additions & 0 deletions tests/read_mac/test_read_mac_metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
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
from tests.common.reboot import reboot

logger = logging.getLogger(__name__)

BINARY_FILE_ON_LOCALHOST_1 = "/tmp/sonic_image_on_localhost_1.bin"
BINARY_FILE_ON_LOCALHOST_2 = "/tmp/sonic_image_on_localhost_2.bin"
BINARY_FILE_ON_DUTHOST = "/tmp/sonic_image_on_duthost.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_1))
localhost.shell("rm -rf {}".format(BINARY_FILE_ON_LOCALHOST_2))

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):
image1 = request.config.getoption("--image1")
image2 = request.config.getoption("--image2")
self.iteration = request.config.getoption("--iteration")
self.minigraph1 = request.config.getoption("--minigraph1")
self.minigraph2 = request.config.getoption("--minigraph2")

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

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

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")

logger.info("Download SONiC image1: {}".format(image1))
localhost.get_url(url=image1, dest=BINARY_FILE_ON_LOCALHOST_1)

logger.info("Download SONiC image2: {}".format(image2))
localhost.get_url(url=image2, dest=BINARY_FILE_ON_LOCALHOST_2)

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 = self.minigraph1 if counter % 2 == 1 else self.minigraph2

logger.info("Iteration #{}".format(counter))
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, counter)
reboot(duthost, localhost, wait=120)
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")


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, counter):
logger.info("Upload SONiC image to device")
if counter % 2 == 1:
duthost.copy(src=BINARY_FILE_ON_LOCALHOST_1, dest=BINARY_FILE_ON_DUTHOST)
else:
duthost.copy(src=BINARY_FILE_ON_LOCALHOST_2, dest=BINARY_FILE_ON_DUTHOST)

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

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()