Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
config.ini
venv/
**/__pycache__/
3 changes: 2 additions & 1 deletion config_example.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ api_url = https://snipe-it.example.com/api/v1
api_key = your_snipeit_api_key
unifi_manufacturer = 3
unifi_model_category_id = 16
unifi_model_fieldset_id = 3
mac_address_field_name = _snipeit_mac_address_5
ip_address_field_name = _snipeit_local_ip_address_2
default_status_id = 2
Expand All @@ -31,4 +32,4 @@ US24PRO = USW-Pro-24-PoE
US24PRO2 = USW-Pro-24
UHDIW = UAP-IW-HD
U7HD = UAP-AC-HD
UGW4 = USG-Pro-4
UGW4 = USG-Pro-4
7 changes: 4 additions & 3 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
config = configparser.ConfigParser()
config.read("config.ini")

unifi_model_mapping = {v.lower(): k for k, v in config["unifi_model_mapping"].items()}
unifi_model_mapping = {k.lower(): v for k, v in config["unifi_model_mapping"].items()}
mac_address_field_name = config.get('SnipeIT', 'mac_address_field_name')

# Set up Snipe-IT API
Expand Down Expand Up @@ -100,6 +100,7 @@ def create_model_if_not_exists(model, unifi_models, dry_run):
else:
#add model category to request
model['category_id'] = config.get("SnipeIT", "unifi_model_category_id")
model['fieldset_id'] = config.get("SnipeIT", "unifi_model_fieldset_id")
response = snipe.create_model(model)
new_model_json = response.json()
status = new_model_json.get("status")
Expand Down Expand Up @@ -128,12 +129,12 @@ def add_devices_to_snipeit(devices, unifi_devices_in_snipe, dry_run):
print("Checking device "+device['name']+" - ("+device['serial']+")")
# print(device)
existing_device = device_exists_in_snipeit(device["serial"], unifi_devices_in_snipe)
remapped_model_number = unifi_model_mapping.get(device["model"], device["model"])
remapped_model_number = unifi_model_mapping.get( device['model'].lower(), device['model'])
# print("remapped_model_number", remapped_model_number)
model = {
"name": remapped_model_number,
"manufacturer_id": config.get("SnipeIT", "unifi_manufacturer_id"),
"model_number": remapped_model_number
"model_number": device["model"]
}
model_in_snipeit = create_model_if_not_exists(model, unifi_models, dry_run)

Expand Down
10 changes: 7 additions & 3 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
certifi==2024.2.2
charset-normalizer==2.0.12
idna==3.7
pyrate-limiter==3.6.1
pyunifi==2.21
requests==2.26.0
ratelimiter==1.2.0
tabulate==0.8.9
pyunifi==2.21
termcolor==2.2.0
termcolor==2.2.0
urllib3==1.26.18
15 changes: 10 additions & 5 deletions snipe.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# snipe.py
import requests
from ratelimiter import RateLimiter
from pyrate_limiter import Duration, Rate, Limiter, BucketFullException
from time import sleep

class Snipe:
Expand All @@ -13,14 +13,15 @@ def __init__(self, api_url, api_key, rate_limit, timeout=30):
"Content-Type": "application/json",
"Authorization": f"Bearer {self.api_key}"
}
self.rate_limiter = RateLimiter(max_calls=rate_limit, period=60)
self.rate_limiter = Limiter(Rate(rate_limit, Duration.MINUTE))

def fetch_paginated_results(self, url, params=None):
results = []
page = 1

while True:
with self.rate_limiter:
try:
self.rate_limiter.try_acquire("snipe")
params = params or {}
params["offset"] = (page - 1) * 500
params["limit"] = 500
Expand All @@ -30,7 +31,6 @@ def fetch_paginated_results(self, url, params=None):

if data.get("status") == "error" and data.get("messages") == "Too Many Requests":
sleep(60)
self.rate_limiter.clear()
continue

response.raise_for_status()
Expand All @@ -41,6 +41,11 @@ def fetch_paginated_results(self, url, params=None):

page += 1

except BucketFullException as err:
print(err)
sleep(10)
continue

return results


Expand Down Expand Up @@ -68,4 +73,4 @@ def create_model(self, data):
url = f"{self.api_url}/models"
response = requests.post(url, headers=self.headers, json=data, timeout=self.timeout)
response.raise_for_status()
return response
return response