Skip to content

Commit

Permalink
[swap_syncd] Fix failures in swap syncd (#1632)
Browse files Browse the repository at this point in the history
Signed-off-by: Danny Allen <[email protected]>
  • Loading branch information
daall authored May 1, 2020
1 parent c8aea29 commit 980623d
Showing 1 changed file with 82 additions and 33 deletions.
115 changes: 82 additions & 33 deletions tests/common/system_utils/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,55 +28,69 @@ class DockerRegistryInfo(_DockerRegistryInfo):
"""
pass

def parse_registry_file(registry_file):
def load_docker_registry_info(dut):
"""
parse_registry_file parses the provided file to produce a DockerRegistryInfo.
Attempts to load Docker registry information.
See `SONIC_DOCKER_REGISTRY` for the expected format of this file.
This method will first search for the registry in the `secret_vars` section
of the Ansible inventory. If it's not found, then it will load the registry from
the `SONIC_DOCKER_REGISTRY` file.
Args:
registry_file (str): The name of the file holding the registry information.
dut (SonicHost): The target device.
Raises:
IOError: If the file cannot be opened for any reason.
ValueError: If the provided file is missing any required fields.
IOError: If the registry file cannot be read.
ValueError: If the registry information is missing from both the
Ansible inventory and the registry file.
Returns:
DockerRegistryInfo: The registry info from the registry file.
DockerRegistryInfo: The registry information that was loaded.
"""

try:
with open(registry_file) as contents:
registry_vars = yaml.safe_load(contents)
except IOError as err:
_LOGGER.error("Failed to parse registry file \"%s\" (%s)", registry_file, err)
raise
# FIXME: In Ansible we're able to load the facts regardless of where they're
# stored. We should figure out how to do this in pytest so the registry
# location isn't hard-coded.
registry_vars = dut.host.options['variable_manager'] \
._hostvars.get(dut.hostname, {}) \
.get("secret_vars", {}) \
.get("docker_registry")

if not registry_vars:
_LOGGER.warning("Registry info not found in inventory, falling back to registry file")

try:
with open(SONIC_DOCKER_REGISTRY) as contents:
registry_vars = yaml.safe_load(contents)
except IOError as err:
_LOGGER.error("Failed to parse registry file (%s)", err)
raise

host = registry_vars.get("docker_registry_host")
username = registry_vars.get("docker_registry_username")
password = registry_vars.get("docker_registry_password")

if not host or not username or not password:
error_message = "Registry file \"{}\" is missing login or hostname".format(registry_file)
error_message = "Missing registry hostname or login"
_LOGGER.error(error_message)
raise ValueError(error_message)

return DockerRegistryInfo(host, username, password)

def delete_container(dut, container_name):
"""
delete_container attempts to delete the specified container from the DUT.
Attempts to delete the specified container from the DUT.
Args:
dut (SonicHost): The target device.
container_name (str): The name of the container to delete.
"""

dut.docker_container(name=container_name, state="absent")
dut.command("docker rm {}".format(container_name))

def download_image(dut, registry, image_name, image_version="latest"):
"""
download_image attempts to download the specified image from the registry.
Attempts to download the specified image from the registry.
Args:
dut (SonicHost): The target device.
Expand All @@ -85,15 +99,12 @@ def download_image(dut, registry, image_name, image_version="latest"):
image_version (str): The version of the image to download.
"""

dut.docker_login(registry_url=registry.host,
username=registry.username,
password=registry.password)
dut.docker_image(source="pull",
name="{}/{}:{}".format(registry.host, image_name, image_version))
dut.command("docker login {} -u {} -p {}".format(registry.host, registry.username, registry.password))
dut.command("docker pull {}/{}:{}".format(registry.host, image_name, image_version))

def tag_image(dut, tag, image_name, image_version="latest"):
"""
tag_image applies the specified tag to a Docker image on the DUT.
Applies the specified tag to a Docker image on the DUT.
Args:
dut (SonicHost): The target device.
Expand All @@ -102,19 +113,16 @@ def tag_image(dut, tag, image_name, image_version="latest"):
image_version (str): The version of the image to tag.
"""

dut.docker_image(source="local",
name="{}:{}".format(image_name, image_version),
tag=tag)
dut.command("docker tag {}:{} {}".format(image_name, image_version, tag))

def swap_syncd(dut, registry_file=SONIC_DOCKER_REGISTRY):
def swap_syncd(dut):
"""
swap_syncd replaces the default syncd container on the DUT with an RPC version of it.
Replaces the running syncd container with the RPC version of it.
This command will download a new Docker image to the DUT and restart the swss service.
This will download a new Docker image to the DUT and restart the swss service.
Args:
dut (SonicHost): The target device.
registry_file (str): The registry file describing where to download the RPC image.
"""

if is_broadcom_device(dut):
Expand All @@ -139,14 +147,55 @@ def swap_syncd(dut, registry_file=SONIC_DOCKER_REGISTRY):
output = dut.command("sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version")
sonic_version = output["stdout_lines"][0].strip()

registry = parse_registry_file(registry_file)
registry = load_docker_registry_info(dut)
download_image(dut, registry, docker_rpc_image, sonic_version)

tag_image(dut,
"{}/{}".format(registry.host, docker_syncd_name),
docker_rpc_image,
"{}:latest".format(docker_syncd_name),
"{}/{}".format(registry.host, docker_rpc_image),
sonic_version)

dut.command("systemctl reset-failed swss")
dut.command("systemctl start swss")

_LOGGER.info("swss has been restarted, waiting 60 seconds to initialize...")
time.sleep(60)

def restore_default_syncd(dut):
"""
Replaces the running syncd with the default syncd that comes with the image.
This will restart the swss service.
Args:
dut (SonicHost): The target device.
"""

if is_broadcom_device(dut):
vendor_id = "brcm"
elif is_mellanox_device(dut):
vendor_id = "mlnx"
else:
error_message = "\"{}\" is not currently supported".format(dut.get_asic_type())
_LOGGER.error(error_message)
raise ValueError(error_message)

docker_syncd_name = "docker-syncd-{}".format(vendor_id)

dut.command("systemctl stop swss")
delete_container(dut, "syncd")

# TODO: Getting the base image version should be a common utility
output = dut.command("sonic-cfggen -y /etc/sonic/sonic_version.yml -v build_version")
sonic_version = output["stdout_lines"][0].strip()

tag_image(dut,
"{}:latest".format(docker_syncd_name),
docker_syncd_name,
sonic_version)

dut.command("systemctl reset-failed swss")
dut.command("systemctl start swss")

_LOGGER.info("swss has been restarted, waiting 60 seconds to initialize...")
time.sleep(60)

0 comments on commit 980623d

Please sign in to comment.