Skip to content

Commit fb13128

Browse files
committed
update version and changelog
1 parent d988c37 commit fb13128

7 files changed

Lines changed: 237 additions & 124 deletions

File tree

CHANGELOG.md

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,158 @@
11
# CHANGELOG
2+
## Version 0.61.0 (March 2026)
3+
4+
**Released**: March 13, 2026
5+
6+
**MAJOR RELEASE** with extensive new features, code quality improvements, security enhancements, and performance optimizations. This release adds real-time WebSocket streaming, comprehensive device diagnostic utilities, extensive test coverage, and significant API improvements.
7+
8+
---
9+
10+
### 1. NEW FEATURES
11+
12+
#### **1.1 WebSocket Streaming Module** (`mistapi.websockets`)
13+
Complete real-time event streaming support with flexible consumption patterns:
14+
15+
**Available Channels:**
16+
* Organization Channels
17+
18+
| Class | Description |
19+
|-------|-------------|
20+
| `mistapi.websockets.orgs.InsightsEvents` | Real-time insights events for an organization |
21+
| `mistapi.websockets.orgs.MxEdgesStatsEvents` | Real-time MX edges stats for an organization |
22+
| `mistapi.websockets.orgs.MxEdgesUpgradesEvents` | Real-time MX edges upgrades events for an organization |
23+
24+
* Site Channels
25+
26+
| Class | Description |
27+
|-------|-------------|
28+
| `mistapi.websockets.sites.ClientsStatsEvents` | Real-time clients stats for a site |
29+
| `mistapi.websockets.sites.DeviceCmdEvents` | Real-time device command events for a site |
30+
| `mistapi.websockets.sites.DeviceStatsEvents` | Real-time device stats for a site |
31+
| `mistapi.websockets.sites.DeviceUpgradesEvents` | Real-time device upgrades events for a site |
32+
| `mistapi.websockets.sites.MxEdgesStatsEvents` | Real-time MX edges stats for a site |
33+
| `mistapi.websockets.sites.PcapEvents` | Real-time PCAP events for a site |
34+
35+
* Location Channels
36+
37+
| Class | Description |
38+
|-------|-------------|
39+
| `mistapi.websockets.location.BleAssetsEvents` | Real-time BLE assets location events |
40+
| `mistapi.websockets.location.ConnectedClientsEvents` | Real-time connected clients location events |
41+
| `mistapi.websockets.location.SdkClientsEvents` | Real-time SDK clients location events |
42+
| `mistapi.websockets.location.UnconnectedClientsEvents` | Real-time unconnected clients location events |
43+
| `mistapi.websockets.location.DiscoveredBleAssetsEvents` | Real-time discovered BLE assets location events |
44+
45+
46+
**Features:**
47+
- Callback-based message handling
48+
- Generator-style iteration
49+
- Context manager support
50+
- Automatic reconnection with configurable ping intervals
51+
- Non-blocking background threads
52+
- Type-safe API with full parameter validation
53+
54+
**Example Usage:**
55+
```python
56+
ws = mistapi.websockets.sites.DeviceStatsEvents(apisession, site_ids=["<site_id>"])
57+
ws.connect(run_in_background=True)
58+
59+
for msg in ws.receive(): # blocks, yields each message as a dict
60+
print(msg)
61+
if some_condition:
62+
ws.disconnect() # stops the generator cleanly
63+
```
64+
65+
#### **1.2 Device Utilities Module** (`mistapi.device_utils`)
66+
`mistapi.device_utils` provides high-level utilities for running diagnostic commands on Mist-managed devices. Each function triggers a REST API call and streams the results back via WebSocket. The library handles the connection plumbing — you just call the function and get back a `UtilResponse` object.
67+
68+
**Device-Specific Modules** (Recommended):
69+
| Module | Device Type | Functions |
70+
|--------|-------------|-----------|
71+
| `device_utils.ap` | Mist Access Points | `ping`, `traceroute`, `retrieveArpTable` |
72+
| `device_utils.ex` | Juniper EX Switches | `ping`, `monitorTraffic`, `retrieveArpTable`, `retrieveBgpSummary`, `retrieveDhcpLeases`, `releaseDhcpLeases`, `retrieveMacTable`, `clearMacTable`, `clearLearnedMac`, `clearBpduError`, `clearDot1xSessions`, `clearHitCount`, `bouncePort`, `cableTest` |
73+
| `device_utils.srx` | Juniper SRX Firewalls | `ping`, `monitorTraffic`, `retrieveArpTable`, `retrieveBgpSummary`, `retrieveDhcpLeases`, `releaseDhcpLeases`, `showDatabase`, `showNeighbors`, `showInterfaces`, `bouncePort`, `retrieveRoutes` |
74+
| `device_utils.ssr` | Juniper SSR Routers | `ping`, `retrieveArpTable`, `retrieveBgpSummary`, `retrieveDhcpLeases`, `releaseDhcpLeases`, `showDatabase`, `showNeighbors`, `showInterfaces`, `bouncePort`, `retrieveRoutes`, `showServicePath` |
75+
76+
**Example Usage:**
77+
```python
78+
from mistapi.device_utils import ap, ex
79+
80+
# Ping from an AP
81+
result = ap.ping(apisession, site_id, device_id, host="8.8.8.8")
82+
print(result.ws_data)
83+
84+
# Retrieve ARP table from a switch
85+
result = ex.retrieveArpTable(apisession, site_id, device_id)
86+
print(result.ws_data)
87+
88+
# With real-time callback
89+
def handle(msg):
90+
print("got:", msg)
91+
92+
result = ex.cableTest(apisession, site_id, device_id, port="ge-0/0/0", on_message=handle)
93+
```
94+
95+
#### **1.3 New API Endpoints**
96+
97+
**MapStacks API** (`mistapi.api.v1.sites.mapstacks`):
98+
- `listSiteMapStacks()`: List map stacks with filtering
99+
- `createSiteMapStack()`: Create new map stack
100+
101+
**Enhanced Query Parameters**:
102+
- Additional filtering options across alarms, clients, and devices endpoints
103+
- Improved parameter handling in JSI, NAC clients, and WAN clients APIs
104+
105+
---
106+
107+
### 2. SECURITY IMPROVEMENTS
108+
109+
##### **HashiCorp Vault SSL Verification**
110+
- Now properly verifies SSL certificates when connecting to Vault
111+
- Made vault configuration attributes private (`_vault_url`, `_vault_path`, etc.)
112+
- Improved cleanup of vault credentials after loading
113+
114+
---
115+
116+
### 3. PERFORMANCE IMPROVEMENTS
117+
118+
##### **Lazy Module Loading**
119+
- Implemented lazy loading for `api` and `cli` subpackages
120+
- Reduces initial import time by deferring heavy module imports until accessed
121+
- Uses `__getattr__` for transparent lazy loading
122+
123+
---
124+
125+
### 4. CODE QUALITY IMPROVEMENTS
126+
127+
##### **HTTP Request Error Handling**
128+
- Consolidated duplicate error handling logic into `_request_with_retry()` method
129+
- Extracts HTTP operations into inner functions for cleaner code
130+
- Reduces code duplication by ~55 lines across GET/POST/PUT/DELETE/POST_FILE methods
131+
- Centralizes 429 rate limit handling and retry logic
132+
133+
##### **Session Management**
134+
- Added `_new_session()` helper method for consistent session initialization
135+
- Improves code reusability when creating new HTTP sessions
136+
137+
##### **API Token Management**
138+
- Added `validate` parameter to `set_api_token()` method
139+
- Allows skipping token validation when needed (default: `True`)
140+
- Useful for faster initialization when tokens are known to be valid
141+
142+
##### **Logging Improvements**
143+
- Fixed logging sanitization to use `getMessage()` instead of direct `msg` access
144+
- Clear `record.args` after sanitization to prevent re-formatting issues
145+
- Improved logging format consistency using %-style formatting
146+
147+
---
148+
149+
### 6. DEPENDENCIES
150+
151+
##### **New Dependencies**
152+
- Added `websocket-client>=1.8.0` for WebSocket streaming support
153+
154+
---
155+
2156
## Version 0.60.3 (February 2026)
3157

4158
**Released**: February 21, 2026

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "mistapi"
7-
version = "0.55.15"
7+
version = "0.61.0"
88
authors = [{ name = "Thomas Munzer", email = "tmunzer@juniper.net" }]
99
description = "Python package to simplify the Mist System APIs usage"
1010
keywords = ["Mist", "Juniper", "API"]

src/mistapi/__version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = "0.55.15"
1+
__version__ = "0.61.0"
22
__author__ = "Thomas Munzer <tmunzer@juniper.net>"

src/mistapi/api/v1/sites/sle.py

Lines changed: 4 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,16 @@
1010
--------------------------------------------------------------------------------
1111
"""
1212

13+
import deprecation
14+
1315
from mistapi import APISession as _APISession
1416
from mistapi.__api_response import APIResponse as _APIResponse
15-
import deprecation
1617

1718

1819
@deprecation.deprecated(
1920
deprecated_in="0.59.2",
2021
removed_in="0.65.0",
21-
current_version="0.55.15",
22+
current_version="0.61.0",
2223
details="function replaced with getSiteSleClassifierSummaryTrend",
2324
)
2425
def getSiteSleClassifierDetails(
@@ -72,57 +73,6 @@ def getSiteSleClassifierDetails(
7273
return resp
7374

7475

75-
def getSiteSleClassifierDetails(
76-
mist_session: _APISession,
77-
site_id: str,
78-
scope: str,
79-
scope_id: str,
80-
metric: str,
81-
classifier: str,
82-
start: str | None = None,
83-
end: str | None = None,
84-
duration: str | None = None,
85-
) -> _APIResponse:
86-
"""
87-
API doc: https://www.juniper.net/documentation/us/en/software/mist/api/http/api/sites/sles/get-site-sle-classifier-details
88-
89-
PARAMS
90-
-----------
91-
mistapi.APISession : mist_session
92-
mistapi session including authentication and Mist host information
93-
94-
PATH PARAMS
95-
-----------
96-
site_id : str
97-
scope : str{'ap', 'client', 'gateway', 'site', 'switch'}
98-
scope_id : str
99-
metric : str
100-
classifier : str
101-
102-
QUERY PARAMS
103-
------------
104-
start : str
105-
end : str
106-
duration : str, default: 1d
107-
108-
RETURN
109-
-----------
110-
mistapi.APIResponse
111-
response from the API call
112-
"""
113-
114-
uri = f"/api/v1/sites/{site_id}/sle/{scope}/{scope_id}/metric/{metric}/classifier/{classifier}/summary"
115-
query_params: dict[str, str] = {}
116-
if start:
117-
query_params["start"] = str(start)
118-
if end:
119-
query_params["end"] = str(end)
120-
if duration:
121-
query_params["duration"] = str(duration)
122-
resp = mist_session.mist_get(uri=uri, query=query_params)
123-
return resp
124-
125-
12676
def getSiteSleClassifierSummaryTrend(
12777
mist_session: _APISession,
12878
site_id: str,
@@ -741,7 +691,7 @@ def listSiteSleImpactedWirelessClients(
741691
@deprecation.deprecated(
742692
deprecated_in="0.59.2",
743693
removed_in="0.65.0",
744-
current_version="0.55.15",
694+
current_version="0.61.0",
745695
details="function replaced with getSiteSleSummaryTrend",
746696
)
747697
def getSiteSleSummary(
@@ -793,55 +743,6 @@ def getSiteSleSummary(
793743
return resp
794744

795745

796-
def getSiteSleSummary(
797-
mist_session: _APISession,
798-
site_id: str,
799-
scope: str,
800-
scope_id: str,
801-
metric: str,
802-
start: str | None = None,
803-
end: str | None = None,
804-
duration: str | None = None,
805-
) -> _APIResponse:
806-
"""
807-
API doc: https://www.juniper.net/documentation/us/en/software/mist/api/http/api/sites/sles/get-site-sle-summary
808-
809-
PARAMS
810-
-----------
811-
mistapi.APISession : mist_session
812-
mistapi session including authentication and Mist host information
813-
814-
PATH PARAMS
815-
-----------
816-
site_id : str
817-
scope : str{'ap', 'client', 'gateway', 'site', 'switch'}
818-
scope_id : str
819-
metric : str
820-
821-
QUERY PARAMS
822-
------------
823-
start : str
824-
end : str
825-
duration : str, default: 1d
826-
827-
RETURN
828-
-----------
829-
mistapi.APIResponse
830-
response from the API call
831-
"""
832-
833-
uri = f"/api/v1/sites/{site_id}/sle/{scope}/{scope_id}/metric/{metric}/summary"
834-
query_params: dict[str, str] = {}
835-
if start:
836-
query_params["start"] = str(start)
837-
if end:
838-
query_params["end"] = str(end)
839-
if duration:
840-
query_params["duration"] = str(duration)
841-
resp = mist_session.mist_get(uri=uri, query=query_params)
842-
return resp
843-
844-
845746
def getSiteSleSummaryTrend(
846747
mist_session: _APISession,
847748
site_id: str,

src/mistapi/websockets/orgs.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ def __init__(
129129
)
130130

131131

132-
class MxEdgesUpgradesEvents(_MistWebsocket):
133-
"""WebSocket stream for org MX edges upgrades events.
132+
class MxEdgesEvents(_MistWebsocket):
133+
"""WebSocket stream for org MX edges events.
134134
135135
Subscribes to the ``orgs/{org_id}/mxedges`` channel and delivers
136-
real-time MX edges upgrades events for the given org.
136+
real-time MX edges events for the given org.
137137
138138
PARAMS
139139
-----------
@@ -150,22 +150,22 @@ class MxEdgesUpgradesEvents(_MistWebsocket):
150150
-----------
151151
Callback style (background thread)::
152152
153-
ws = OrgMxEdgesUpgradesEvents(session, org_id="abc123")
153+
ws = MxEdgesEvents(session, org_id="abc123")
154154
ws.on_message(lambda data: print(data))
155155
ws.connect() # non-blocking, runs in background thread
156156
input("Press Enter to stop")
157157
ws.disconnect()
158158
159159
Generator style::
160160
161-
ws = OrgMxEdgesUpgradesEvents(session, org_id="abc123")
161+
ws = MxEdgesEvents(session, org_id="abc123")
162162
ws.connect(run_in_background=True)
163163
for msg in ws.receive():
164164
process(msg)
165165
166166
Context manager::
167167
168-
with OrgMxEdgesUpgradesEvents(session, org_id="abc123") as ws:
168+
with MxEdgesEvents(session, org_id="abc123") as ws:
169169
ws.on_message(my_handler)
170170
ws.connect() # non-blocking, runs in background thread
171171
time.sleep(60)

0 commit comments

Comments
 (0)