Skip to content

Commit 8c40d73

Browse files
Merge pull request #74 from aruba/v2.0a14-2
v2.0a14-2
2 parents cc7b4b9 + 222620b commit 8c40d73

4 files changed

Lines changed: 60 additions & 22 deletions

File tree

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Today, there are two versions of PyCentral, each designed for different versions
2626
| Version | Supports | Notes |
2727
| :------------------------------------------------------------- | :--------------------------------------------------------------------------------------------- | :--------------------------- |
2828
| [v1](https://pypi.org/project/pycentral/) | HPE Aruba Networking Central (Classic Central) | Legacy Version |
29-
| [v2(pre-release)](https://pypi.org/project/pycentral/2.0a13/) | HPE Aruba Networking Central(new Central), GLP, HPE Aruba Networking Central (Classic Central) | Backwards compatible with v1 |
29+
| [v2(pre-release)](https://pypi.org/project/pycentral/2.0a14/) | HPE Aruba Networking Central(new Central), GLP, HPE Aruba Networking Central (Classic Central) | Backwards compatible with v1 |
3030

3131
## Quick Example
3232

pycentral/new_monitoring/clients.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from ..utils.monitoring_utils import (
22
execute_get,
33
build_timestamp_filter,
4+
_validate_mac_address,
45
)
56
from ..exceptions import ParameterError
67

@@ -382,6 +383,27 @@ def get_top_n_site_clients(
382383

383384
return execute_get(central_conn, endpoint=path, params=params)
384385

386+
@staticmethod
387+
def get_client_details(
388+
central_conn,
389+
client_mac,
390+
):
391+
"""
392+
Fetch details for a specific client by MAC address.
393+
This method makes an API call to the following endpoint - `GET network-monitoring/v1alpha1/clients/{client_mac}`
394+
395+
Args:
396+
central_conn (NewCentralBase): Central connection object.
397+
client_mac (str): MAC address of the client to query.
398+
399+
Returns:
400+
(dict): Client details as returned by the API.
401+
"""
402+
_validate_mac_address(client_mac)
403+
404+
path = f"clients/{client_mac}"
405+
return execute_get(central_conn, endpoint=path)
406+
385407
def _time_filter(params, start_time, end_time, duration):
386408
"""
387409
Apply a time filter to params using unix timestamps.

pycentral/utils/monitoring_utils.py

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pycentral.utils.url_utils import generate_url
44

55
from ..exceptions import ParameterError
6+
import re
67

78

89
def build_timestamp_filter(
@@ -37,17 +38,11 @@ def build_timestamp_filter(
3738

3839
# --- Validation ---
3940
if (start_time or end_time) and duration:
40-
raise ValueError(
41-
"Cannot specify start/end timestamps together with duration."
42-
)
41+
raise ValueError("Cannot specify start/end timestamps together with duration.")
4342
if (start_time and not end_time) or (end_time and not start_time):
44-
raise ValueError(
45-
"Both start_time and end_time must be provided together."
46-
)
43+
raise ValueError("Both start_time and end_time must be provided together.")
4744
if not duration and not (start_time and end_time):
48-
raise ValueError(
49-
"Provide either both start_time and end_time or a duration."
50-
)
45+
raise ValueError("Provide either both start_time and end_time or a duration.")
5146

5247
# --- Case 1: Start + End (pass-through) ---
5348
if start_time and end_time:
@@ -161,9 +156,7 @@ def simplified_site_resp(site):
161156
),
162157
}
163158
site["alerts"] = {
164-
"critical": site.get("alerts", {})
165-
.get("groups", [{}])[0]
166-
.get("count", 0)
159+
"critical": site.get("alerts", {}).get("groups", [{}])[0].get("count", 0)
167160
if site.get("alerts", {}).get("groups")
168161
else 0,
169162
"total": site.get("alerts", {}).get("totalCount", 0),
@@ -185,11 +178,7 @@ def _groups_to_dict(groups_list):
185178
result = {"Poor": 0, "Fair": 0, "Good": 0}
186179
if isinstance(groups_list, list):
187180
for group in groups_list:
188-
if (
189-
isinstance(group, dict)
190-
and "name" in group
191-
and "value" in group
192-
):
181+
if isinstance(group, dict) and "name" in group and "value" in group:
193182
result[group["name"]] = group["value"]
194183
return result
195184

@@ -246,3 +235,30 @@ def merged_dict_to_sorted_list(merged):
246235
except Exception:
247236
keys = sorted(merged.keys())
248237
return [{"timestamp": ts, **merged[ts]} for ts in keys]
238+
239+
240+
def _validate_mac_address(mac):
241+
"""
242+
Validate a MAC address string and return True if valid.
243+
Accepts the format AA:BB:CC:DD:EE:FF
244+
245+
Args:
246+
mac (str): MAC address string to validate.
247+
248+
Returns:
249+
(bool): True if the MAC address is valid.
250+
251+
Raises:
252+
ParameterError: If mac is missing or does not match the expected format.
253+
254+
Note:
255+
Internal SDK function
256+
"""
257+
_MAC_PATTERN = re.compile(r"^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$")
258+
if not mac:
259+
raise ParameterError("MAC address is required")
260+
if not isinstance(mac, str) or not _MAC_PATTERN.match(mac):
261+
raise ParameterError(
262+
f"Invalid MAC address format: '{mac}'. Expected format: AA:BB:CC:DD:EE:FF"
263+
)
264+
return True

setup.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
with open(path.join(this_directory, "README.md"), encoding="utf-8") as fh:
66
long_description = fh.read()
77

8-
VERSION = "2.0a13"
8+
VERSION = "2.0a14"
99

1010
setuptools.setup(
1111
name="pycentral",
@@ -31,12 +31,12 @@
3131
],
3232
python_requires=">=3.8",
3333
install_requires=[
34-
"requests==2.32.4",
35-
"PyYAML==6.0.2",
34+
"requests==2.32.5",
35+
"PyYAML==6.0.3",
3636
"oauthlib==3.2.2",
3737
"requests_oauthlib==2.0.0",
3838
"pytz==2025.2",
39-
"protobuf==6.33.2",
39+
"protobuf==6.33.5",
4040
"websocket-client==1.9.0",
4141
],
4242
extras_require={"colorLog": ["colorlog"]},

0 commit comments

Comments
 (0)