diff options
Diffstat (limited to 'docs')
34 files changed, 980 insertions, 328 deletions
diff --git a/docs/Makefile b/docs/Makefile deleted file mode 100644 index d0c3cbf..0000000 --- a/docs/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/api-reference.md b/docs/api-reference.md new file mode 100644 index 0000000..3cd24bb --- /dev/null +++ b/docs/api-reference.md @@ -0,0 +1,88 @@ +# API Reference + +Complete reference for all PyVyOS classes and methods. + +## VyDevice Class + +Main class for interacting with VyOS devices. + +### Constructor + +```python +VyDevice(hostname: str, apikey: str, protocol: "http"|"https" = "https", + port: int = 443, verify: bool = True, timeout: int = 10) +``` + +**Parameters:** `hostname`, `apikey`, `protocol`, `port` (1-65535), `verify`, `timeout` + +### Configuration Methods + +- `configure_set(path)`: Set configuration values +- `configure_delete(path)`: Delete configuration values +- `configure_multiple_op(op_path)`: Execute multiple operations atomically + +```python +device.configure_set(path=["interfaces", "ethernet", "eth0", "address", "192.168.1.1/24"]) +device.configure_delete(path=["interfaces", "dummy", "dum1"]) +device.configure_multiple_op(op_path=[ + {"op": "set", "path": [...]}, + {"op": "delete", "path": [...]} +]) +``` + +### Retrieval Methods + +- `retrieve_show_config(path)`: Get configuration in show format +- `retrieve_return_values(path)`: Get specific configuration values + +```python +device.retrieve_show_config(path=["system"]) +device.retrieve_return_values(path=["interfaces", "dummy", "dum1", "address"]) +``` + +### Operational Methods + +- `show(path)`: Execute show commands +- `generate(path)`: Generate configuration elements +- `reset(path)`: Reset configuration elements + +```python +device.show(path=["system", "image"]) +device.generate(path=["ssh", "client-key", "/tmp/key"]) +device.reset(path=["conntrack-sync", "internal-cache"]) +``` + +### File Operations + +- `config_file_save(file)`: Save configuration to file +- `config_file_load(file)`: Load configuration from file + +```python +device.config_file_save(file="/config/backup.config") +device.config_file_load(file="/config/backup.config") +``` + +**Note:** The `path` parameter is automatically included as `[]` for config-file operations, as required by the VyOS API. + +### System Operations + +- `reboot(path=["now"])`: Reboot the device +- `poweroff(path=["now"])`: Power off the device + +### Image Management + +- `image_add(url, file, path)`: Add VyOS system image +- `image_delete(name, url, file, path)`: Delete a system image + +## ApiResponse Class + +Response object: `status` (int), `request` (dict, API key removed), `result` (dict), `error` (str|bool) + +```python +response = device.show(path=["system"]) +if response.error: + print(f"Error {response.status}: {response.error}") +else: + print(response.result) +``` + diff --git a/docs/concepts.md b/docs/concepts.md new file mode 100644 index 0000000..058d20c --- /dev/null +++ b/docs/concepts.md @@ -0,0 +1,88 @@ +# Concepts + +Key concepts and architecture of PyVyOS. + +## Architecture Overview + +PyVyOS is built on a REST client architecture: +- `RestClient`: Base class handling HTTP communication +- `VyDevice`: High-level interface for VyOS operations +- `ApiResponse`: Standardized response structure + +## API Command Structure + +VyOS API uses a hierarchical command structure: +- Commands: `configure`, `retrieve`, `show`, `generate`, `reset` +- Operations: `set`, `delete`, `showConfig`, `returnValues` +- Paths: Array representing configuration hierarchy + +## Path Format + +Paths are always arrays representing the configuration tree: + +```python +# Single path +["interfaces", "ethernet", "eth0", "address", "192.168.1.1/24"] + +# Multiple paths (for configure_set) +[ + ["interfaces", "ethernet", "eth0", "address", "192.168.1.1/24"], + ["interfaces", "ethernet", "eth0", "description", "Management"] +] +``` + +## Response Handling + +All methods return `ApiResponse`: +- Consistent error checking +- Sanitized request payloads (API keys removed) +- Structured result data + +## Operation Types + +### Configuration Operations +- `set`: Add or modify configuration +- `delete`: Remove configuration +- `showConfig`: Get full configuration +- `returnValues`: Get specific values + +### Operational Commands +- `show`: Execute show commands +- `generate`: Generate configurations/keys +- `reset`: Reset state/cache + +## Multi-Operation Requests + +`configure_multiple_op` allows atomic operations: +- Multiple set/delete operations in one API call +- Transaction-like behavior +- Better performance than individual calls + +## Error Handling Strategy + +PyVyOS uses defensive error handling: +- Network errors captured as exceptions +- API errors returned in response.error +- HTTP status codes in response.status + +## Security Considerations + +- API keys never appear in response.request +- SSL verification configurable per connection +- Timeout protection prevents hanging connections + +## Connection Lifecycle + +1. Initialize VyDevice with connection parameters +2. Parameters validated on initialization +3. Each method creates new HTTP request +4. Responses parsed and returned as ApiResponse + +## Best Practices + +- Use environment variables for credentials +- Enable SSL verification in production +- Handle errors explicitly +- Use configure_multiple_op for bulk changes +- Set appropriate timeouts for operations + diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..b6634d2 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,84 @@ +# Configuration + +Guide to configuring PyVyOS for connecting to VyOS devices. + +## Environment Variables + +The recommended way to configure PyVyOS is using environment variables with a `.env` file. + +### Required Variables + +- `VYDEVICE_HOSTNAME`: IP address or hostname of your VyOS device +- `VYDEVICE_APIKEY`: API key for authentication + +### Optional Variables + +- `VYDEVICE_PORT`: API port (default: 443) +- `VYDEVICE_PROTOCOL`: Protocol "http" or "https" (default: https) +- `VYDEVICE_VERIFY_SSL`: "True" or "False" (default: True) + +## .env File Setup + +Create a `.env` file in your project root: + +```bash +VYDEVICE_HOSTNAME=192.168.1.1 +VYDEVICE_APIKEY=your-secret-api-key +VYDEVICE_PORT=443 +VYDEVICE_PROTOCOL=https +VYDEVICE_VERIFY_SSL=False +``` + +## Loading Configuration + +```python +from dotenv import load_dotenv +import os +from pyvyos import VyDevice + +load_dotenv() +device = VyDevice( + hostname=os.getenv('VYDEVICE_HOSTNAME'), + apikey=os.getenv('VYDEVICE_APIKEY'), + port=int(os.getenv('VYDEVICE_PORT', 443)), + protocol=os.getenv('VYDEVICE_PROTOCOL', 'https'), + verify=os.getenv('VYDEVICE_VERIFY_SSL', 'True').lower() == 'true' +) +``` + +## Direct Configuration + +Pass parameters directly: + +```python +device = VyDevice(hostname="192.168.1.1", apikey="your-api-key", + port=443, protocol="https", verify=False, timeout=30) +``` + +## SSL & Timeout + +SSL verification enabled by default. To disable (dev only): + +```python +import urllib3 +urllib3.disable_warnings() +device = VyDevice(..., verify=False, timeout=60) +``` + +## Generating API Key on VyOS + +1. SSH into your VyOS device +2. Run: `configure` +3. Run: `set system api http interface <interface>` +4. Run: `set system api http port <port>` +5. Run: `set system api http api-key <key-name> key <key-value>` +6. Run: `commit` and `save` + +## Security Best Practices + +- Never commit `.env` files to version control +- Use strong API keys +- Enable SSL verification in production +- Restrict API access to specific interfaces/IPs on VyOS +- Rotate API keys regularly + diff --git a/docs/development/architecture.md b/docs/development/architecture.md new file mode 100644 index 0000000..aceda08 --- /dev/null +++ b/docs/development/architecture.md @@ -0,0 +1,77 @@ +# Development Architecture (Proposed) + +## Goals +- Strong separation of concerns (transport, domain, specs, utils) +- Backward compatibility for 0.3.0 via shims +- Clear public API surface and internal boundaries +- Minimal maintenance burden for a public, official SDK + +## Source Layout (file tree) +``` +pyvyos/ + __init__.py # public API exports (VyDevice, ApiResponse) + core/ # internal, stable layers + __init__.py + rest_client.py # RestClient, ApiResponse (transport layer) + device.py # VyDevice (domain layer) + specs/ # optional Pydantic models (validation) + __init__.py + models.py # base models (ApiRequest/Response) + commands/ # split by responsibility + __init__.py + configure.py # set, delete, multiple_op + retrieve.py # show_config, return_values + config_file.py # save, load (path: []) + show.py # show + generate.py # generate + reset.py # reset + system.py # reboot, poweroff + image.py # add, delete + utils/ # reusable helpers (no side effects) + __init__.py + json.py # safe_json, redact_key + http.py # timeouts, retries (future) + paths.py # path builder helpers + ids.py # request_id helpers + exceptions.py # typed exceptions (SDKError, HttpError, ApiError) + types.py # public typing aliases if needed + device.py # shim re-export (compat) + rest.py # shim re-export (compat) + vyos_api/ # JSON specs (docs/reference, optional at runtime) +``` + +## Layers & Responsibilities +- Transport (core.rest_client): HTTP, payload assembly, response validation +- Domain (core.device): high-level methods (configure, show, reset, etc.) +- Specs (specs.*): optional Pydantic models to validate requests/answers +- Utils: pure helpers (formatting, ids, path building) +- Shims (device.py, rest.py): ensure 0.3.0 compatibility + +## Public API Surface +- `from pyvyos import VyDevice, ApiResponse` +- Stable imports; internal moves hidden by shims + +## Compatibility Strategy +- Keep shims until 1.0.0 +- Deprecation policy: warn after N minors, remove at next major +- Document migration path (import from `pyvyos.core` for new code) + +## Data Validation Flow (optional) +- App builds `path` with utils.paths +- If validation enabled, use `specs.commands.*` models +- RestClient serializes payload and executes request +- Response validated (structure: success/data/error) + +## Testing Strategy +- Unit: core.rest_client and core.device isolated via monkeypatch +- Contract: JSON fixtures mirror VyOS responses +- E2E (future): optional with test VyOS VM + +## Packaging +- Include `vyos_api/` only if needed at runtime +- Otherwise treat it as docs/reference, not required by the package + +## Naming & Conventions +- Use underscores `_` in file and module names +- One responsibility per module (keep files small) +- Typed public APIs, specific exceptions, no prints (only logging) diff --git a/docs/development/quality-and-utils.md b/docs/development/quality-and-utils.md new file mode 100644 index 0000000..ff78ec2 --- /dev/null +++ b/docs/development/quality-and-utils.md @@ -0,0 +1,72 @@ +# Quality, Utils, and Pitfalls + +## Goals +- Reduce regressions and supportability burden +- Consistent error handling and logging +- Clear utilities to avoid duplication + +## Exceptions (typed) +- `SDKError` (base) +- `HttpError(status, message)` +- `ApiError(message, details=None)` # when success=False +- `ValidationError(message)` # client-side validation + +## Logging +- Use `logging.getLogger("pyvyos")` +- Include: op, command, status, elapsed_ms, request_id +- Redact secrets (api key) – via `utils.json.redact_key(data, keys=["key"])` +- Default INFO; DEBUG guarded by env `PYVYOS_DEBUG=1` + +## Timeouts & Retries +- Default timeout: 10s (configurable) +- No implicit retries by default +- Future: retry idempotent ops only (exponential backoff) + +## Security +- `verify=True` by default +- Document `urllib3.disable_warnings()` only for dev +- Never log secrets or full payloads by default + +## Utilities (proposal) +- `utils.paths.build(*segments) -> list[str]` +- `utils.ids.request_id() -> str` +- `utils.json.safe_dumps(obj) -> str` (with redaction) +- `utils.http.timeout(seconds) -> int` (normalize) + +## Validation (optional) +- `specs.commands.*` Pydantic models validate request structures +- Enforce path rules (e.g., config-file requires `path=[]`) +- Gate behind feature flag or optional dependency group + +## Testing +- Unit: small, isolated, no real I/O +- Contract: success/error fixtures per command +- Naming: `test_should_<do>_when_<condition>` +- Use monkeypatch on `_execute_request` + +## Documentation +- Keep developer docs scoped and short (≤100 lines) +- Update api-reference and path rules on changes + +## Style & Types +- Type hints on public APIs, avoid `Any` +- Early returns, no deep nesting, no bare `except` +- Constants for command/operation strings + +## Release Hygiene +- Conventional commits; CHANGELOG generated +- Tag every release; ensure `git push --tags` +- Patch bumps for fixes, minor for features + +## Potential Pitfalls & Fixes +- Path handling inconsistencies → centralize in RestClient +- Logging secrets → redact before logging +- Tight coupling device↔transport → maintain clean core boundaries +- Hidden breaking changes → keep shims until 1.0.0 +- Non-deterministic tests → remove sleeps, use fixed seeds + +## Next Steps (ordered) +1. Introduce `exceptions.py` and wire into RestClient +2. Add `utils/` with `json.py`, `paths.py`, `ids.py` +3. Add optional `specs/` models for high-value commands +4. CI: lint+type-check, codecov, test matrix diff --git a/docs/development/refactor-roadmap.md b/docs/development/refactor-roadmap.md new file mode 100644 index 0000000..eeee879 --- /dev/null +++ b/docs/development/refactor-roadmap.md @@ -0,0 +1,56 @@ +# Refactor Roadmap (Prioritized) + +## Priorities +- P0 (now): safety, compatibility, correctness +- P1 (next): validation, observability, developer UX +- P2 (later): performance, async, resiliency + +## P0 — Immediate +- Stabilize transport: keep `_get_payload(include_empty_path)`; special-case `config-file` +- Keep shims: `pyvyos/device.py` and `pyvyos/rest.py` re-export from `pyvyos/core/*` +- Typed exceptions: introduce `SDKError`, `HttpError`, `ApiError`, `ValidationError` +- Timeouts: ensure sane defaults, expose in `VyDevice` +- Logging: centralize in transport, structured key fields (op, command, status) +- Tests: payload assertions for `config-file` (path: []), regression for others +- Docs: architecture and path rules (done) + +## P1 — Short Term +- Specs (optional): Pydantic models in `pyvyos/specs/commands/*` +- `utils/`: path builders, request_id, safe_json redaction +- Deprecation policy: note in README; warn on internal imports (future only) +- CI: test matrix (Python 3.13), codecov, lint (ruff/flake8), type-check (pyright/mypy) +- Release: conventional commits + CHANGELOG; ensure tags push +- Docs: contributor guide, release playbook (short) + +## P2 — Medium Term +- Async client: `AsyncRestClient` (aiohttp/httpx), opt-in +- Retries & backoff: idempotent ops only; circuit-breaker (future) +- Rate limiting: client-side token bucket (opt-in) +- Caching: read-only `show/retrieve` (TTL) optional +- Batch ops: smarter `configure_multiple_op` planning + +## Migration & Compatibility +- Public API: `from pyvyos import VyDevice, ApiResponse` (stable) +- Internal: prefer `pyvyos.core.*` for new code +- Shims stay until 1.0.0; removal at next major only + +## Testing Plan +- Unit: transport (errors, timeouts), domain (paths) +- Contract: sample JSON fixtures per command +- E2E: optional job against a test VyOS (gated, non-blocking) + +## Release Flow (lean) +- Branch: feature → PR → squash merge +- Pre-release (optional): `-rcX` tags +- Tag + publish: GitHub Action (uv build + PyPI publish) + +## Risks & Mitigations +- Hidden breakages → keep shims, add regression tests +- API drift (VyOS) → specs folder eases updates +- Logging noise → default INFO; debug gated via env +- Security → default `verify=True`, redact secrets in logs + +## Success Criteria +- 0.3.x users unaffected +- New structure adopted by contributors +- Lower maintenance overhead (fewer regressions) diff --git a/docs/development/vyos_api/config-file-load.json b/docs/development/vyos_api/config-file-load.json new file mode 100644 index 0000000..3e1fcef --- /dev/null +++ b/docs/development/vyos_api/config-file-load.json @@ -0,0 +1,2 @@ +{"command":"config-file","operation":"load","description":"Load configuration from a file.","endpoint":"/config-file","method":"POST","request":{"payload":{"data":{"op":"load","path":[],"file":"/config/backup.config"},"key":"your-api-key"},"example":{"op":"load","path":[],"file":"/config/backup.config"}},"response":{"success":{"success":true,"data":null,"error":null},"error":{"success":false,"data":null,"error":"Failed to load configuration file"}},"parameters":{"file":{"type":"string","required":true,"description":"Path to the configuration file to load","example":"/config/backup.config"},"path":{"type":"array","required":false,"description":"Path parameter (required by API, typically empty array)","default":[],"example":[]}},"python_usage":"device.config_file_load(file=\"/config/backup.config\")","notes":"The path parameter is required by the VyOS API even though it's typically empty for load operations."} + diff --git a/docs/development/vyos_api/config-file-save.json b/docs/development/vyos_api/config-file-save.json new file mode 100644 index 0000000..563e0ad --- /dev/null +++ b/docs/development/vyos_api/config-file-save.json @@ -0,0 +1,58 @@ +{ + "command": "config-file", + "operation": "save", + "description": "Save the current configuration to a file.", + "endpoint": "/config-file", + "method": "POST", + "request": { + "payload": { + "data": { + "op": "save", + "path": [], + "file": "/config/backup.config" + }, + "key": "your-api-key" + }, + "example": { + "with_file": { + "op": "save", + "path": [], + "file": "/config/backup.config" + }, + "default_location": { + "op": "save", + "path": [] + } + } + }, + "response": { + "success": { + "success": true, + "data": "", + "error": null + }, + "error": { + "success": false, + "data": null, + "error": "Failed to save configuration" + } + }, + "parameters": { + "file": { + "type": "string", + "required": false, + "description": "Path to the file where configuration will be saved. If not provided, uses default location.", + "example": "/config/backup.config" + }, + "path": { + "type": "array", + "required": false, + "description": "Path parameter (required by API, typically empty array)", + "default": [], + "example": [] + } + }, + "python_usage": "device.config_file_save(file=\"/config/backup.config\")", + "notes": "The path parameter is required by the VyOS API even though it's typically empty for save operations." +} + diff --git a/docs/development/vyos_api/configure-delete.json b/docs/development/vyos_api/configure-delete.json new file mode 100644 index 0000000..f68c5c8 --- /dev/null +++ b/docs/development/vyos_api/configure-delete.json @@ -0,0 +1,2 @@ +{"command":"configure","operation":"delete","description":"Delete configuration values based on a path.","endpoint":"/configure","method":"POST","request":{"payload":{"data":{"op":"delete","path":["interfaces","dummy","dum1"]},"key":"your-api-key"},"example":{"op":"delete","path":["interfaces","dummy","dum1"]}},"response":{"success":{"success":true,"data":{},"error":null},"error":{"success":false,"data":null,"error":"Path does not exist"}},"parameters":{"path":{"type":"array","required":true,"description":"Configuration path to delete as array of strings","example":["interfaces","dummy","dum1"]}},"python_usage":"device.configure_delete(path=[\"interfaces\", \"dummy\", \"dum1\"])"} + diff --git a/docs/development/vyos_api/configure-multiple-op.json b/docs/development/vyos_api/configure-multiple-op.json new file mode 100644 index 0000000..a0d0ab4 --- /dev/null +++ b/docs/development/vyos_api/configure-multiple-op.json @@ -0,0 +1,2 @@ +{"command":"configure","operation":"multiple","description":"Execute multiple configuration operations atomically in a single request.","endpoint":"/configure","method":"POST","request":{"payload":{"data":[{"op":"set","path":["interfaces","dummy","dum1","address","192.168.1.1/24"]},{"op":"delete","path":["interfaces","dummy","old1"]}],"key":"your-api-key"},"example":[{"op":"set","path":["interfaces","dummy","dum1","address","192.168.1.1/24"]},{"op":"set","path":["interfaces","dummy","dum1","description","Test interface"]},{"op":"delete","path":["interfaces","dummy","old1"]}]},"response":{"success":{"success":true,"data":null,"error":null},"error":{"success":false,"data":null,"error":"One or more operations failed"}},"parameters":{"op_path":{"type":"array","required":true,"description":"Array of operation objects, each with 'op' and 'path'","items":{"type":"object","required":["op","path"],"properties":{"op":{"type":"string","enum":["set","delete"]},"path":{"type":"array","items":{"type":"string"}}}},"example":[{"op":"set","path":["interfaces","dummy","dum1","address","192.168.1.1/24"]},{"op":"delete","path":["interfaces","dummy","old1"]}]}},"python_usage":"device.configure_multiple_op(op_path=[{\"op\": \"set\", \"path\": [...]}, {\"op\": \"delete\", \"path\": [...]}])"} + diff --git a/docs/development/vyos_api/configure-set.json b/docs/development/vyos_api/configure-set.json new file mode 100644 index 0000000..e99da8c --- /dev/null +++ b/docs/development/vyos_api/configure-set.json @@ -0,0 +1,2 @@ +{"command":"configure","operation":"set","description":"Set configuration values based on a path. Can accept single or multiple configuration paths.","endpoint":"/configure","method":"POST","request":{"payload":{"data":{"op":"set","path":["interfaces","ethernet","eth0","address","192.168.1.1/24"]},"key":"your-api-key"},"example":{"single_path":{"op":"set","path":["interfaces","ethernet","eth0","address","192.168.1.1/24"]},"multiple_paths":{"op":"set","path":[["interfaces","ethernet","eth0","address","192.168.1.1/24"],["interfaces","ethernet","eth0","description","Management"]]}}},"response":{"success":{"success":true,"data":{},"error":null},"error":{"success":false,"data":null,"error":"Configuration validation failed"}},"parameters":{"path":{"type":"array","required":true,"description":"Configuration path(s) as array of strings or array of path arrays for multiple configurations","examples":[["interfaces","ethernet","eth0","address","192.168.1.1/24"],[["interfaces","ethernet","eth0","address","192.168.1.1/24"],["interfaces","ethernet","eth0","description","Management"]]]}},"python_usage":"device.configure_set(path=[\"interfaces\", \"ethernet\", \"eth0\", \"address\", \"192.168.1.1/24\"])"} + diff --git a/docs/development/vyos_api/generate.json b/docs/development/vyos_api/generate.json new file mode 100644 index 0000000..bae9e16 --- /dev/null +++ b/docs/development/vyos_api/generate.json @@ -0,0 +1,2 @@ +{"command":"generate","operation":"generate","description":"Generate configuration elements such as SSH keys, certificates, etc.","endpoint":"/generate","method":"POST","request":{"payload":{"data":{"op":"generate","path":["ssh","client-key","/tmp/key_random"]},"key":"your-api-key"},"example":{"op":"generate","path":["ssh","client-key","/tmp/key_random"]}},"response":{"success":{"success":true,"data":"Generating public/private rsa key pair.\nYour identification has been saved in /tmp/key_random\nYour public key has been saved in /tmp/key_random.pub","error":null},"error":{"success":false,"data":null,"error":"Generation failed"}},"parameters":{"path":{"type":"array","required":true,"description":"Path specifying what to generate","example":["ssh","client-key","/tmp/key_random"]}},"python_usage":"device.generate(path=[\"ssh\", \"client-key\", \"/tmp/key_random\"])"} + diff --git a/docs/development/vyos_api/image-add.json b/docs/development/vyos_api/image-add.json new file mode 100644 index 0000000..068adbe --- /dev/null +++ b/docs/development/vyos_api/image-add.json @@ -0,0 +1,2 @@ +{"command":"image","operation":"add","description":"Add a VyOS system image from a URL or file.","endpoint":"/image","method":"POST","request":{"payload":{"data":{"op":"add","url":"https://example.com/vyos-image.iso"},"key":"your-api-key"},"example":{"from_url":{"op":"add","url":"https://example.com/vyos-image.iso"},"from_file":{"op":"add","file":"/path/to/local/image.iso"}}},"response":{"success":{"success":true,"data":{"status":"added","image":"vyos-image.iso"},"error":null},"error":{"success":false,"data":null,"error":"Failed to add image"}},"parameters":{"url":{"type":"string","required":false,"description":"URL of the image to download and add","format":"uri","example":"https://example.com/vyos-image.iso"},"file":{"type":"string","required":false,"description":"Local file path to the image","example":"/path/to/local/image.iso"},"path":{"type":"array","required":false,"description":"Additional path parameters","default":[],"example":[]}},"python_usage":"device.image_add(url=\"https://example.com/vyos-image.iso\")","notes":"Either url or file parameter must be provided."} + diff --git a/docs/development/vyos_api/image-delete.json b/docs/development/vyos_api/image-delete.json new file mode 100644 index 0000000..56ab796 --- /dev/null +++ b/docs/development/vyos_api/image-delete.json @@ -0,0 +1,2 @@ +{"command":"image","operation":"delete","description":"Delete a VyOS system image.","endpoint":"/image","method":"POST","request":{"payload":{"data":{"op":"delete","name":"image-name"},"key":"your-api-key"},"example":{"op":"delete","name":"image-name"}},"response":{"success":{"success":true,"data":{"status":"deleted","image":"image-name"},"error":null},"error":{"success":false,"data":null,"error":"Image not found or deletion failed"}},"parameters":{"name":{"type":"string","required":true,"description":"Name of the image to delete","example":"image-name"},"url":{"type":"string","required":false,"description":"Optional URL associated with the image","format":"uri"},"file":{"type":"string","required":false,"description":"Optional file path associated with the image"},"path":{"type":"array","required":false,"description":"Additional path parameters","default":[],"example":[]}},"python_usage":"device.image_delete(name=\"image-name\")"} + diff --git a/docs/development/vyos_api/index.json b/docs/development/vyos_api/index.json new file mode 100644 index 0000000..54a64c7 --- /dev/null +++ b/docs/development/vyos_api/index.json @@ -0,0 +1,2 @@ +{"title":"VyOS API Command Index","description":"Complete index of all VyOS REST API commands documented in this directory","version":"1.0.0","schema":"schema.json","commands":[{"file":"configure-set.json","command":"configure","operation":"set","python_method":"configure_set","description":"Set configuration values"},{"file":"configure-delete.json","command":"configure","operation":"delete","python_method":"configure_delete","description":"Delete configuration values"},{"file":"configure-multiple-op.json","command":"configure","operation":"multiple","python_method":"configure_multiple_op","description":"Execute multiple configuration operations atomically"},{"file":"retrieve-show-config.json","command":"retrieve","operation":"showConfig","python_method":"retrieve_show_config","description":"Retrieve configuration in show format"},{"file":"retrieve-return-values.json","command":"retrieve","operation":"returnValues","python_method":"retrieve_return_values","description":"Retrieve specific configuration values"},{"file":"show.json","command":"show","operation":"show","python_method":"show","description":"Execute show commands"},{"file":"generate.json","command":"generate","operation":"generate","python_method":"generate","description":"Generate configuration elements"},{"file":"reset.json","command":"reset","operation":"reset","python_method":"reset","description":"Reset configuration elements"},{"file":"config-file-save.json","command":"config-file","operation":"save","python_method":"config_file_save","description":"Save configuration to file"},{"file":"config-file-load.json","command":"config-file","operation":"load","python_method":"config_file_load","description":"Load configuration from file"},{"file":"reboot.json","command":"reboot","operation":"reboot","python_method":"reboot","description":"Reboot the device"},{"file":"poweroff.json","command":"poweroff","operation":"poweroff","python_method":"poweroff","description":"Power off the device"},{"file":"image-add.json","command":"image","operation":"add","python_method":"image_add","description":"Add VyOS system image"},{"file":"image-delete.json","command":"image","operation":"delete","python_method":"image_delete","description":"Delete VyOS system image"}],"statistics":{"total_commands":14,"command_types":{"configure":3,"retrieve":2,"show":1,"generate":1,"reset":1,"config-file":2,"reboot":1,"poweroff":1,"image":2}}} + diff --git a/docs/development/vyos_api/poweroff.json b/docs/development/vyos_api/poweroff.json new file mode 100644 index 0000000..1950691 --- /dev/null +++ b/docs/development/vyos_api/poweroff.json @@ -0,0 +1,2 @@ +{"command":"poweroff","operation":"poweroff","description":"Power off the VyOS device.","endpoint":"/poweroff","method":"POST","request":{"payload":{"data":{"op":"poweroff","path":["now"]},"key":"your-api-key"},"example":{"op":"poweroff","path":["now"]}},"response":{"success":{"success":true,"data":{"status":"powering off"},"error":null},"error":{"success":false,"data":null,"error":"Power off operation failed"}},"parameters":{"path":{"type":"array","required":false,"description":"Power off parameters, typically ['now']","default":["now"],"example":["now"]}},"python_usage":"device.poweroff(path=[\"now\"])","warning":"This operation will immediately power off the device."} + diff --git a/docs/development/vyos_api/reboot.json b/docs/development/vyos_api/reboot.json new file mode 100644 index 0000000..3ca92da --- /dev/null +++ b/docs/development/vyos_api/reboot.json @@ -0,0 +1,2 @@ +{"command":"reboot","operation":"reboot","description":"Reboot the VyOS device.","endpoint":"/reboot","method":"POST","request":{"payload":{"data":{"op":"reboot","path":["now"]},"key":"your-api-key"},"example":{"op":"reboot","path":["now"]}},"response":{"success":{"success":true,"data":{"status":"rebooting"},"error":null},"error":{"success":false,"data":null,"error":"Reboot operation failed"}},"parameters":{"path":{"type":"array","required":false,"description":"Reboot parameters, typically ['now']","default":["now"],"example":["now"]}},"python_usage":"device.reboot(path=[\"now\"])","warning":"This operation will immediately reboot the device."} + diff --git a/docs/development/vyos_api/reset.json b/docs/development/vyos_api/reset.json new file mode 100644 index 0000000..8418456 --- /dev/null +++ b/docs/development/vyos_api/reset.json @@ -0,0 +1,2 @@ +{"command":"reset","operation":"reset","description":"Reset configuration elements or system state.","endpoint":"/reset","method":"POST","request":{"payload":{"data":{"op":"reset","path":["conntrack-sync","internal-cache"]},"key":"your-api-key"},"example":{"op":"reset","path":["conntrack-sync","internal-cache"]}},"response":{"success":{"success":true,"data":"conntrack-sync is not configured!","error":null},"error":{"success":false,"data":null,"error":"Reset operation failed"}},"parameters":{"path":{"type":"array","required":false,"description":"Path specifying what to reset","default":[],"example":["conntrack-sync","internal-cache"]}},"python_usage":"device.reset(path=[\"conntrack-sync\", \"internal-cache\"])"} + diff --git a/docs/development/vyos_api/retrieve-return-values.json b/docs/development/vyos_api/retrieve-return-values.json new file mode 100644 index 0000000..c827b5d --- /dev/null +++ b/docs/development/vyos_api/retrieve-return-values.json @@ -0,0 +1,2 @@ +{"command":"retrieve","operation":"returnValues","description":"Retrieve and return specific configuration values for a given path.","endpoint":"/retrieve","method":"POST","request":{"payload":{"data":{"op":"returnValues","path":["interfaces","dummy","dum1","address"]},"key":"your-api-key"},"example":{"op":"returnValues","path":["interfaces","dummy","dum1","address"]}},"response":{"success":{"success":true,"data":["192.168.56.100/24"],"error":null},"error":{"success":false,"data":null,"error":"Path not found"}},"parameters":{"path":{"type":"array","required":true,"description":"Configuration path to retrieve values from","example":["interfaces","dummy","dum1","address"]}},"python_usage":"device.retrieve_return_values(path=[\"interfaces\", \"dummy\", \"dum1\", \"address\"])"} + diff --git a/docs/development/vyos_api/retrieve-show-config.json b/docs/development/vyos_api/retrieve-show-config.json new file mode 100644 index 0000000..bf5231f --- /dev/null +++ b/docs/development/vyos_api/retrieve-show-config.json @@ -0,0 +1,2 @@ +{"command":"retrieve","operation":"showConfig","description":"Retrieve and show the device configuration in show format.","endpoint":"/retrieve","method":"POST","request":{"payload":{"data":{"op":"showConfig","path":["system"]},"key":"your-api-key"},"example":{"op":"showConfig","path":["system"]}},"response":{"success":{"success":true,"data":{"config-management":{"commit-revisions":"100"},"host-name":"vyos-device","name-server":"eth0"},"error":null},"error":{"success":false,"data":null,"error":"Invalid path"}},"parameters":{"path":{"type":"array","required":false,"description":"Configuration path to retrieve, empty array for full config","default":[],"example":["system"]}},"python_usage":"device.retrieve_show_config(path=[\"system\"])"} + diff --git a/docs/development/vyos_api/schema.json b/docs/development/vyos_api/schema.json new file mode 100644 index 0000000..fb125b1 --- /dev/null +++ b/docs/development/vyos_api/schema.json @@ -0,0 +1,2 @@ +{"$schema":"http://json-schema.org/draft-07/schema#","$id":"https://github.com/vyos-contrib/pyvyos/docs/vyos-api/schema.json","title":"VyOS API Command Schema","description":"Schema definition for VyOS REST API commands","type":"object","definitions":{"apiRequest":{"type":"object","required":["command","op"],"properties":{"command":{"type":"string","description":"API endpoint command","enum":["configure","retrieve","show","generate","reset","config-file","reboot","poweroff","image"]},"op":{"type":"string","description":"Operation type","enum":["set","delete","showConfig","returnValues","show","generate","reset","save","load","reboot","poweroff","add","delete",""]},"path":{"oneOf":[{"type":"array","description":"Single configuration path","items":{"type":"string"}},{"type":"array","description":"Multiple configuration paths","items":{"type":"array","items":{"type":"string"}}},{"type":"array","description":"Multiple operations with paths","items":{"type":"object","required":["op","path"],"properties":{"op":{"type":"string","enum":["set","delete"]},"path":{"type":"array","items":{"type":"string"}}}]}]},"file":{"type":"string","description":"File path for file operations"},"url":{"type":"string","description":"URL for external resources","format":"uri"},"name":{"type":"string","description":"Resource name identifier"},"method":{"type":"string","description":"HTTP method","enum":["GET","POST","PUT","DELETE"],"default":"POST"}}},"apiResponse":{"type":"object","required":["success","data","error"],"properties":{"success":{"type":"boolean","description":"Whether the operation succeeded"},"data":{"description":"Response data (type varies by operation)","oneOf":[{"type":"object"},{"type":"array"},{"type":"string"},{"type":"null"}]},"error":{"oneOf":[{"type":"null"},{"type":"string"}],"description":"Error message if operation failed"}}}},"properties":{"request":{"$ref":"#/definitions/apiRequest"},"response":{"$ref":"#/definitions/apiResponse"}}} + diff --git a/docs/development/vyos_api/show.json b/docs/development/vyos_api/show.json new file mode 100644 index 0000000..3576e43 --- /dev/null +++ b/docs/development/vyos_api/show.json @@ -0,0 +1,2 @@ +{"command":"show","operation":"show","description":"Execute show commands to display system information.","endpoint":"/show","method":"POST","request":{"payload":{"data":{"op":"show","path":["system","image"]},"key":"your-api-key"},"example":{"op":"show","path":["system","image"]}},"response":{"success":{"success":true,"data":"Name Default boot Running\n------------------------ -------------- ---------\n1.5-rolling-202407300021 Yes Yes","error":null},"error":{"success":false,"data":null,"error":"Command not found"}},"parameters":{"path":{"type":"array","required":false,"description":"Command path for show operation","default":[],"example":["system","image"]}},"python_usage":"device.show(path=[\"system\", \"image\"])"} + diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 0000000..6f4cf29 --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,91 @@ +# Examples + +Common usage patterns and examples for PyVyOS. + +## Basic Connection + +```python +from pyvyos import VyDevice +device = VyDevice(hostname="192.168.1.1", apikey="your-api-key", verify=False) +``` + +## Viewing System Information + +```python +response = device.show(path=["system", "image"]) +if not response.error: + print(response.result) +``` + +## Interface Configuration + +Add, view, get, or remove interface configuration: + +```python +# Add address +device.configure_set(path=["interfaces", "ethernet", "eth0", "address", "192.168.1.1/24"]) + +# View configuration +device.retrieve_show_config(path=["interfaces", "ethernet", "eth0"]) + +# Get address value +device.retrieve_return_values(path=["interfaces", "ethernet", "eth0", "address"]) + +# Remove interface +device.configure_delete(path=["interfaces", "dummy", "dum1"]) +``` + +## Multiple Operations + +Execute multiple configuration changes atomically: + +```python +device.configure_multiple_op(op_path=[ + {"op": "set", "path": ["interfaces", "dummy", "dum1", "address", "192.168.1.1/24"]}, + {"op": "set", "path": ["interfaces", "dummy", "dum1", "description", "Test"]}, + {"op": "delete", "path": ["interfaces", "dummy", "old1"]} +]) +``` + +## Configuration Backup + +```python +device.config_file_save(file="/config/backup-2024.config") +device.config_file_load(file="/config/backup-2024.config") +``` + +## SSH Key Generation + +```python +import random, string +randstring = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(20)) +device.generate(path=["ssh", "client-key", f'/tmp/key_{randstring}']) +``` + +## System Operations + +```python +device.reboot(path=["now"]) +device.poweroff(path=["now"]) +``` + +## Error Handling + +```python +response = device.configure_set(path=["invalid", "path"]) +if response.error: + print(f"Error {response.status}: {response.error}") +else: + print("Success:", response.result) +``` + +## Working with Responses + +```python +response = device.show(path=["system"]) +print(f"Status: {response.status}") +if not response.error: + data = response.result # Process data... +print(f"Request: {response.request}") # API key sanitized +``` + diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000..183c109 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,77 @@ +# Getting Started + +This guide will help you set up PyVyOS and make your first API call to a VyOS device. + +## Prerequisites + +- VyOS device with REST API enabled +- API key generated on your VyOS device +- Network access to your VyOS device + +## Step 1: Install PyVyOS + +See [Installation](installation.md) for detailed instructions. + +## Step 2: Configure Environment Variables + +Create a `.env` file in your project directory: + +```bash +VYDEVICE_HOSTNAME=192.168.1.1 +VYDEVICE_APIKEY=your-api-key-here +VYDEVICE_PORT=443 +VYDEVICE_PROTOCOL=https +VYDEVICE_VERIFY_SSL=False +``` + +## Step 3: Create Your First Script + +```python +import os +from dotenv import load_dotenv +from pyvyos import VyDevice + +load_dotenv() + +device = VyDevice( + hostname=os.getenv('VYDEVICE_HOSTNAME'), + apikey=os.getenv('VYDEVICE_APIKEY'), + port=os.getenv('VYDEVICE_PORT'), + protocol=os.getenv('VYDEVICE_PROTOCOL'), + verify=os.getenv('VYDEVICE_VERIFY_SSL', 'True').lower() == 'true' +) + +response = device.show(path=["system", "image"]) +if not response.error: + print(response.result) +else: + print(f"Error: {response.error}") +``` + +## Step 4: Disable SSL Warnings (Optional) + +If using `verify=False`, disable urllib3 warnings: + +```python +import urllib3 +urllib3.disable_warnings() +``` + +## Understanding API Responses + +All methods return an `ApiResponse` object with: +- `status`: HTTP status code +- `request`: Request payload (API key sanitized) +- `result`: Response data dictionary +- `error`: Error message (False if successful) + +## Common Operations + +See [Examples](examples.md) for more detailed usage patterns. + +## Next Steps + +- Read [API Reference](api-reference.md) for complete method documentation +- Explore [Configuration](configuration.md) for advanced setup +- Check [Concepts](concepts.md) to understand PyVyOS architecture + diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..1bc9cb7 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,56 @@ +# PyVyOS Documentation + +PyVyOS is a Python SDK for interacting with VyOS devices via their REST API. This library provides a simple and intuitive interface to manage VyOS network devices programmatically. + +## Overview + +PyVyOS enables developers to: +- Configure VyOS devices remotely +- Retrieve configuration and operational data +- Manage system operations (reboot, poweroff) +- Generate SSH keys and manage images +- Save and load configuration files + +## Documentation Structure + +- [Installation](installation.md) - How to install PyVyOS +- [Getting Started](getting-started.md) - Quick start guide +- [API Reference](api-reference.md) - Complete API documentation +- [Configuration](configuration.md) - Device setup and authentication +- [Examples](examples.md) - Common usage patterns +- [Concepts](concepts.md) - Key concepts and architecture +- [Troubleshooting](troubleshooting.md) - Common issues and solutions + +## Requirements + +- Python 3.13 or higher +- VyOS device with REST API enabled +- API key for authentication + +## Quick Example + +```python +from pyvyos import VyDevice + +device = VyDevice( + hostname="192.168.1.1", + apikey="your-api-key", + port=443, + protocol="https", + verify=False +) + +response = device.show(path=["system", "image"]) +print(response.result) +``` + +## Resources + +- [GitHub Repository](https://github.com/vyos-contrib/pyvyos) +- [PyPI Package](https://pypi.org/project/pyvyos/) +- [Read the Docs](https://pyvyos.readthedocs.io/) + +## License + +MIT License - See LICENSE file for details + diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..e83974e --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,65 @@ +# Installation + +## Prerequisites + +PyVyOS requires Python 3.13 or higher. Make sure you have a compatible Python version installed. + +## Using pip + +The recommended way to install PyVyOS is using pip: + +```bash +pip install pyvyos +``` + +## Using uv + +If you use `uv` for package management: + +```bash +uv add pyvyos +``` + +## From Source + +To install from source: + +```bash +git clone https://github.com/vyos-contrib/pyvyos.git +cd pyvyos +pip install . +``` + +## Verify Installation + +After installation, verify it works: + +```python +from pyvyos import VyDevice +print("PyVyOS installed successfully") +``` + +## Dependencies + +PyVyOS automatically installs: +- `requests>=2.32.0` - HTTP library for API calls +- `python-dotenv>=1.0.1` - Environment variable management +- `urllib3>=2.5.0` - HTTP client utilities + +## Development Installation + +For development with testing support: + +```bash +pip install pyvyos[dev] +``` + +This includes: +- `pytest>=6.2.5` - Testing framework +- `pytest-cov>=4.1` - Coverage reporting +- `pytest-env>=0.6.2` - Environment variable testing + +## Next Steps + +After installation, proceed to [Getting Started](getting-started.md) to configure your first device connection. + diff --git a/docs/make.bat b/docs/make.bat deleted file mode 100644 index 747ffb7..0000000 --- a/docs/make.bat +++ /dev/null @@ -1,35 +0,0 @@ -@ECHO OFF
-
-pushd %~dp0
-
-REM Command file for Sphinx documentation
-
-if "%SPHINXBUILD%" == "" (
- set SPHINXBUILD=sphinx-build
-)
-set SOURCEDIR=source
-set BUILDDIR=build
-
-%SPHINXBUILD% >NUL 2>NUL
-if errorlevel 9009 (
- echo.
- echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
- echo.installed, then set the SPHINXBUILD environment variable to point
- echo.to the full path of the 'sphinx-build' executable. Alternatively you
- echo.may add the Sphinx directory to PATH.
- echo.
- echo.If you don't have Sphinx installed, grab it from
- echo.https://www.sphinx-doc.org/
- exit /b 1
-)
-
-if "%1" == "" goto help
-
-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
-goto end
-
-:help
-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
-
-:end
-popd
diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index f1ce7d3..0000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -Sphinx>=7.2.6 -sphinx-rtd-theme>=2.0.0 diff --git a/docs/source/conf.py b/docs/source/conf.py deleted file mode 100644 index bfa4675..0000000 --- a/docs/source/conf.py +++ /dev/null @@ -1,36 +0,0 @@ -# Configuration file for the Sphinx documentation builder. -# -# For the full list of built-in configuration values, see the documentation: -# https://www.sphinx-doc.org/en/master/usage/configuration.html - -# -- Project information ----------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information - -project = "pyvyos" -copyright = "2024, Roberto Berto" -author = "Roberto Berto" -release = "0.3.0" - -# -- General configuration --------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration - -templates_path = ["_templates"] -exclude_patterns = [] - - -# -- Options for HTML output ------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output - -html_theme = "sphinx_rtd_theme" -html_static_path = ["_static"] - - -import os -import sys - -sys.path.insert(0, os.path.abspath("../../pyvyos")) - -extensions = [ - "sphinx.ext.autodoc", - "sphinx_rtd_theme", -] diff --git a/docs/source/index.rst b/docs/source/index.rst deleted file mode 100644 index 05c2aa0..0000000 --- a/docs/source/index.rst +++ /dev/null @@ -1,214 +0,0 @@ -.. PyVyOS documentation master file, created by - sphinx-quickstart on Wed Dec 13 13:02:59 2023. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -PyVyOS - documentation -================================== - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - -pyvyos -====== - -.. toctree:: - :maxdepth: 4 - - pyvyos - -PyVyOS Usage -================== - -.. _pyvyos-documentation: - -PyVyOS Documentation -==================== - -PyVyOS is a Python library for interacting with VyOS devices via their API. This documentation provides a guide on how to use PyVyOS to manage your VyOS devices programmatically. - -Installation ------------- - -You can install PyVyOS using pip: - -.. code-block:: bash - - pip install pyvyos - -Getting Started ---------------- - -Importing and Disabling Warnings for verify=False --------------------------------------------------- - -Before using PyVyOS, it's a good practice to disable urllib3 warnings and import the required modules, IF you use verify=False: - -.. code-block:: python - - import urllib3 - urllib3.disable_warnings() - -Using API Response Class ------------------------- - -PyVyOS uses a custom `ApiResponse` data class to handle API responses: - -.. code-block:: python - - @dataclass - class ApiResponse: - status: int - request: dict - result: dict - error: str - -Initializing a VyDevice Object ------------------------------- - -To interact with your VyOS device, you'll need to create an instance of the `VyDevice` class. You can set up your device using the following code, assuming you've stored your credentials as environment variables: - -.. code-block:: python - - from dotenv import load_dotenv - - # Load environment variables from a .env file - load_dotenv() - - # Retrieve VyOS device connection details from environment variables - hostname = os.getenv('VYDEVICE_HOSTNAME') - apikey = os.getenv('VYDEVICE_APIKEY') - port = os.getenv('VYDEVICE_PORT') - protocol = os.getenv('VYDEVICE_PROTOCOL') - verify_ssl = os.getenv('VYDEVICE_VERIFY_SSL') - - # Convert the verify_ssl value to a boolean - verify = verify_ssl.lower() == "true" if verify_ssl else True - - # Create an instance of the VyOS device - device = VyDevice(hostname=hostname, apikey=apikey, port=port, protocol=protocol, verify=verify) - -Using PyVyOS ------------- - -Once you have created a VyDevice object, you can use it to interact with your VyOS device using various methods provided by the library. - -Reset ------ - -The reset method allows you to run a reset command: - -.. code-block:: python - - # Execute the reset command - response = device.reset(path=["conntrack-sync", "internal-cache"]) - - # Check for errors and print the result - if not response.error: - print(response.result) - -Retrieve Show Configuration ---------------------------- - -The retrieve_show_config method retrieves the VyOS configuration: - -.. code-block:: python - - # Retrieve the VyOS configuration - response = device.retrieve_show_config(path=[]) - - # Check for errors and print the result - if not response.error: - print(response.result) - -Retrieve Return Values ------------------------- - -.. code-block:: python - - # Retrieve VyOS return values for a specific interface - response = device.retrieve_return_values(path=["interfaces", "dummy", "dum1", "address"]) - print(response.result) - -Configure Delete ----------------- - -.. code-block:: python - - # Delete a VyOS interface configuration - response = device.configure_delete(path=["interfaces", "dummy", "dum1"]) - -Generate ----------- - -.. code-block:: python - - # Generate an SSH key with a random string in the name - randstring = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(20)) - keyrand = f'/tmp/key_{randstring}' - response = device.generate(path=["ssh", "client-key", keyrand]) - -Show ------- - -.. code-block:: python - - # Show VyOS system image information - response = device.show(path=["system", "image"]) - print(response.result) - -Reset ------- - -.. code-block:: python - - # Reset VyOS with specific parameters - response = device.reset(path=["conntrack-sync", "internal-cache"]) - -Configure Set -------------- - -The configure_set method sets a VyOS configuration: - -.. code-block:: python - - # Set a VyOS configuration - response = device.configure_set(path=["interfaces ethernet eth0 address '192.168.1.1/24'"]) - - # Check for errors and print the result - if not response.error: - print(response.result) - -Config File Save ----------------- - -.. code-block:: python - - # Save VyOS configuration without specifying a file (default location) - response = device.config_file_save() - -Config File Save with custom filename -------------------------------------- - -.. code-block:: python - - # Save VyOS configuration to a specific file - response = device.config_file_save(file="/config/test300.config") - -Config File Load ----------------- - -.. code-block:: python - - # Load VyOS configuration from a specific file - response = device.config_file_load(file="/config/test300.config") - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search`
\ No newline at end of file diff --git a/docs/source/pyvyos.rst b/docs/source/pyvyos.rst deleted file mode 100644 index fc02f1a..0000000 --- a/docs/source/pyvyos.rst +++ /dev/null @@ -1,21 +0,0 @@ -pyvyos package -============== - -Submodules ----------- - -pyvyos.device module --------------------- - -.. automodule:: pyvyos.device - :members: - :undoc-members: - :show-inheritance: - -Module contents ---------------- - -.. automodule:: pyvyos - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..3e7f286 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,60 @@ +# Troubleshooting + +Common issues and solutions when using PyVyOS. + +## Connection Issues + +**Cannot Connect:** Verify hostname/IP, network connectivity, API enabled, firewall rules, port number. + +**SSL Errors:** Use `verify=False` for dev (self-signed certs), install CA certs for production. + +## Authentication Problems + +**Invalid API Key:** Verify key is correct, check expiration, ensure permissions, regenerate if needed. + +## Configuration Errors + +**Invalid Path:** Verify path syntax matches VyOS tree, check path exists, use `retrieve_show_config` to inspect. + +**Not Applied:** Call `config_file_save()` after changes, check commit requirements, verify permissions. + +## Response Issues + +**Empty Results:** Check if path has data, verify syntax, try broader path. + +**Error Format:** Always check `response.error` first, inspect `response.status`, log full response. + +## Performance Issues + +**Timeouts:** Increase timeout parameter, check latency, verify device load, break into smaller operations. + +**Slow Operations:** Use `configure_multiple_op` for bulk, avoid short polling, consider async for multiple devices. + +## Environment Setup + +**Variables Not Loading:** Verify `.env` exists, check `load_dotenv()` call, match variable names, use defaults. + +## Debugging Tips + +```python +# Enable verbose logging +import logging +logging.basicConfig(level=logging.DEBUG) + +# Inspect full response +response = device.show(path=["system"]) +print(f"Status: {response.status}, Error: {response.error}") +print(f"Result: {response.result}, Request: {response.request}") + +# Test connection +response = device.show(path=["system", "host-name"]) +if response.error: + print(f"Connection issue: {response.error}") +``` + +## Getting Help + +- Check [API Reference](api-reference.md) for method details +- Review [Examples](examples.md) for usage patterns +- Open issue on [GitHub](https://github.com/vyos-contrib/pyvyos/issues) + diff --git a/docs/vyos-api.md b/docs/vyos-api.md new file mode 100644 index 0000000..33a443f --- /dev/null +++ b/docs/vyos-api.md @@ -0,0 +1,78 @@ +# VyOS API Command Reference + +The JSON definitions for each VyOS REST API command supported by PyVyOS are located in `docs/development/vyos_api/`. + +## Location + +All JSON specification files are stored in: **`docs/development/vyos_api/`** + +These JSONs are reference documentation and are: +- Used for API documentation generation +- Available for validation and testing +- Not packaged with the library (reference only) + +## Files + +- `schema.json` - JSON Schema definition for all API commands +- Individual command files: + - `configure-set.json` - Set configuration values + - `configure-delete.json` - Delete configuration values + - `configure-multiple-op.json` - Execute multiple operations atomically + - `retrieve-show-config.json` - Retrieve configuration in show format + - `retrieve-return-values.json` - Retrieve specific configuration values + - `show.json` - Execute show commands + - `generate.json` - Generate configuration elements (SSH keys, etc.) + - `reset.json` - Reset configuration elements + - `config-file-save.json` - Save configuration to file + - `config-file-load.json` - Load configuration from file + - `reboot.json` - Reboot the device + - `poweroff.json` - Power off the device + - `image-add.json` - Add VyOS system image + - `image-delete.json` - Delete VyOS system image + +## Structure + +Each JSON file follows this structure: + +```json +{ + "command": "command-name", + "operation": "operation-name", + "description": "Description of what the command does", + "endpoint": "/endpoint-path", + "method": "HTTP_METHOD", + "request": { + "payload": { ... }, + "example": { ... } + }, + "response": { + "success": { ... }, + "error": { ... } + }, + "parameters": { ... }, + "python_usage": "device.method_name(...)" +} +``` + +## Usage + +These JSON files can be used for: +- API documentation generation +- Request validation +- Response schema validation +- Client library code generation +- Testing and mocking + +## JSON Schema + +The `schema.json` file defines the complete structure for all API commands and can be used with JSON Schema validators. + +## Path Parameter Handling + +**Important:** The `path` parameter handling varies by command: + +- **config-file commands** (`save`, `load`): The VyOS API requires `path` to be present in the payload, even if empty (`[]`). PyVyOS handles this automatically. +- **Other commands**: When `path` is empty or not provided, it may be omitted from the payload for cleaner requests. + +See individual JSON files in `docs/development/vyos_api/` for specific parameter requirements. + |
