diff --git a/napalm_procurve/procurve.py b/napalm_procurve/procurve.py index 43cd376..a44ee69 100644 --- a/napalm_procurve/procurve.py +++ b/napalm_procurve/procurve.py @@ -592,52 +592,37 @@ class ProcurveDriver(ConfigLifecycleMixin, SwitchDriver): return {"running": running, "startup": startup, "candidate": candidate} def _get_config_via_ssh(self) -> str: - """Retrieve running-config via OpenSSH subprocess (sshpass + ssh). + """Open a one-shot SSH session on port 22 to retrieve running-config. - paramiko is incompatible with Mocana SSH 6.3 on HP 2530 / YA firmware. - OpenSSH has better legacy algorithm support and connects where paramiko - fails. Requires openssh-client + sshpass installed in the environment. + Used when the REST API does not expose the running-config endpoint + (e.g. HP 2530 / YA firmware). Uses port 22 explicitly because + self.port is the REST API port (443) in API transport mode. """ - import shutil - import subprocess + import paramiko - _TIMEOUT = 12 + _TIMEOUT = 15 - if not shutil.which("sshpass") or not shutil.which("ssh"): - logger.warning("sshpass/ssh not available — skipping SSH config fallback for %s", self.hostname) - return "" - - cmd = [ - "sshpass", "-p", self.password or "", - "ssh", - "-o", "StrictHostKeyChecking=no", - "-o", "UserKnownHostsFile=/dev/null", - "-o", f"ConnectTimeout={_TIMEOUT}", - "-o", "BatchMode=no", - "-o", "KexAlgorithms=+diffie-hellman-group1-sha1,diffie-hellman-group14-sha1", - "-o", "HostKeyAlgorithms=+ssh-rsa", - "-p", "22", # always SSH port — self.port is the REST API port (443) - f"{self.username}@{self.hostname}", - "show running-config", - ] try: - result = subprocess.run( - cmd, - capture_output=True, - text=True, - timeout=_TIMEOUT + 3, + client = paramiko.SSHClient() + client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) + client.connect( + hostname=self.hostname, + port=22, # always SSH — self.port is the REST API port + username=self.username, + password=self.password, + timeout=_TIMEOUT, + banner_timeout=_TIMEOUT, + auth_timeout=_TIMEOUT, + look_for_keys=False, + allow_agent=False, ) - if result.returncode == 0 and result.stdout.strip(): - return result.stdout - logger.warning( - "SSH config fallback (openssh) failed for %s: rc=%s err=%s", - self.hostname, result.returncode, result.stderr[:200], - ) - except subprocess.TimeoutExpired: - logger.warning("SSH config fallback timed out for %s", self.hostname) + _, stdout, _ = client.exec_command("show running-config", timeout=_TIMEOUT) + config = stdout.read().decode("utf-8", errors="replace") + client.close() + return config except Exception as exc: logger.warning("SSH config fallback failed for %s: %s", self.hostname, exc) - return "" + return "" # ------------------------------------------------------------------ # NAPALM: get_environment