Source code for lvmopstools.devices.switch
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# @Author: José Sánchez-Gallego (gallegoj@uw.edu)
# @Date: 2025-03-20
# @Filename: switch.py
# @License: BSD 3-clause (http://www.opensource.org/licenses/BSD-3-Clause)
from __future__ import annotations
import os
import warnings
from lvmopstools import config
try:
import netmiko
except ImportError:
netmiko = None
__all__ = ["power_cycle_interface", "get_ag_poe_port_info"]
def _get_connection(enable: bool = True):
"""Gets a connection to the switch."""
if not netmiko:
raise ImportError("netmiko is required to power cycle the switch port.")
HOST: str = os.getenv("LVM_SWITCH_HOST", config["devices.switch.host"])
USERNAME: str = os.getenv("LVM_SWITCH_USERNAME", config["devices.switch.username"])
PASSWORD: str | None = os.getenv("LVM_SWITCH_PASSWORD")
SECRET: str | None = os.getenv("LVM_SWITCH_SECRET")
if not PASSWORD:
raise ValueError("$LVM_SWITCH_PASSWORD has not been set.")
if not SECRET:
raise ValueError("$LVM_SWITCH_SECRET has not been set.")
lvm_switch = {
"device_type": "netgear_prosafe",
"host": HOST,
"username": USERNAME,
"password": PASSWORD,
"secret": SECRET, # Enable password
}
connection = netmiko.ConnectHandler(**lvm_switch)
if enable:
connection.enable() # Enable method
return connection
[docs]
def power_cycle_interface(interface: str, verbose: bool = False):
"""Power cycles the PoE for a switch interface.
The environment variales ``LVM_SWITCH_HOST``, ``LVM_SWITCH_USERNAME``,
``LVM_SWITCH_PASSWORD``, and ``LVM_SWITCH_SECRET`` must be set when
calling this function.
Parameters
----------
interface
The switch interface to power cycle, e.g., ``"2/0/6"``.
verbose
If ``True``, prints the commands that are being run.
"""
connection = _get_connection()
output = connection.send_config_set([f"interface {interface}", "poe reset"])
if verbose:
print(output)
print("Closing connection ...")
connection.disconnect()
[docs]
def get_ag_poe_port_info(camera: str | None = None) -> dict[str, str]:
"""Returns the PoE port information for a given camera.
Parameters
----------
camera
The name of the camera. If not provided, returns the information
for all cameras.
Returns
-------
dict
A dictionary with the PoE port information for the camera.
"""
connection = _get_connection()
agcams_config = config["devices.agcams.power"]
results: dict[str, str] = {}
for cam_config_name, cam_config in agcams_config.items():
if camera is None or camera.lower() == cam_config_name.lower():
interface = cam_config["interface"]
if interface is None:
warnings.warn(f"Interface for camera {cam_config_name} is not set.")
continue
data = connection.send_command(f"show poe port info {interface}")
assert isinstance(data, str)
results[cam_config_name] = data
if camera is not None and len(results) == 0:
raise ValueError(f"No PoE port information found for camera {camera}.")
connection.disconnect()
return results