Skip to content

Conversation

@chiconws
Copy link
Contributor

Add SSH Terminal Access Support

This PR adds SSH terminal access functionality to the NanoKVM Python client, providing an independent SSH client alongside the existing HTTP API client.

New Features

NanoKVMSSH Class

A new generic SSH client that allows executing commands on the NanoKVM device:

from nanokvm.ssh_client import NanoKVMSSH

# Create SSH client
ssh = NanoKVMSSH("kvm-host")
await ssh.authenticate("password")

# Execute commands and get raw output
uptime = await ssh.run_command("cat /proc/uptime")
disk = await ssh.run_command("df -k")

await ssh.disconnect()

Key Features:

  • Independent Authentication - SSH and HTTP auth are completely separate
  • Generic Command Execution - Returns raw command output
  • Async/Await Support - Full asyncio compatibility with timeout handling

Architecture:

  • Separation of Concerns - HTTP client handles API calls, SSH client handles terminal access
  • Generic Design - SSH client returns raw output, letting users parse as needed
  • Backwards Compatible - No changes to existing HTTP API functionality

Usage Examples

# HTTP API (existing functionality - unchanged)
from nanokvm.client import NanoKVMClient

# SSH access (new functionality)
from nanokvm.ssh_client import NanoKVMSSH

# They work independently
http_client = NanoKVMClient("http://kvm/api", session)
ssh_client = NanoKVMSSH("kvm-host")

Dependencies

  • Added paramiko for SSH functionality

This provides users with both structured API access (HTTP) and direct terminal access (SSH) to their NanoKVM devices, making the library more versatile for different use cases.

- Add NanoKVMSSH class and paramiko dependency
- Add SSH usage examples to README.md
- Fix line length violations (Ruff E501)
- Add proper exception chaining (Ruff B904)
- Fix MyPy union attribute errors with type assertions
- Improve code formatting and readability
- Break long exception message line to comply with Ruff E501
- Add trailing comma for consistency
@puddly
Copy link
Owner

puddly commented Sep 21, 2025

This SSH client submodule is fully independent of the main client, sharing zero code. Is there a reason you can't use paramiko directly?

- Reformat run_in_executor call to single line
@chiconws
Copy link
Contributor Author

Yeah, I went out of my way to keep everything separated so as not to mess with existing functionality. I thought about this SSH wrapper while I was thinking about the Home Assistant integration, since I wanted to pull some information from the NanoKVM that the API didn't provide. This wrapper provides specific error handling and simplifies things. For users who just want to run commands without dealing with paramiko's async complexities, this wrapper makes it much simpler. At one point I implemented specific commands and parsing, like memory info and uptime info, but I felt that this should be implemented by the user, what do you think? Anyway, it's your call.

@puddly
Copy link
Owner

puddly commented Sep 21, 2025

Ahh. That makes sense.

  1. Let's subclass the SSH exceptions from the base API exception class, to allow catching all of them at once.
  2. Do you think it's possible to pull the SSH credentials via the API, to automate authentication?
  3. Are there any SSH-only sensors or actions you can think of? I think those would depend on 2, as otherwise it'd be unwieldy to authenticate.

@chiconws
Copy link
Contributor Author

  1. Ok, I'll implement that.

  2. Early on, I tried integrating SSH directly into NanoKVMClient. I modified it to save the password during client creation and reuse it for SSH auth. But I decided to keep them separate since you can SSH without logging into the web interface first. The passwords seem identical, though SSH uses plain text. I doubt the API exposes passwords anyway - that'd be a huge security risk.

  3. There are tons of useful Linux commands available. For example, cat /sys/class/thermal/thermal_zone0/temp gives CPU temperature. Uptime is crucial for me since my NanoKVM is in a remote area with frequent power outages - the API doesn't provide this. You also get disk usage, memory stats, and basically full Linux shell access.
    I removed all that specific functionality because adding just some commands to the library felt arbitrary. But it's your call - I can implement them back, though it relies on helper functions to parse the raw terminal responses.

- SSH exceptions now inherit from NanoKVMError for unified error handling
- Users can catch all NanoKVM errors (API + SSH) with single base class
@puddly puddly merged commit 6bebcf4 into puddly:dev Oct 29, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants