Skip to content

Commit 88d4aac

Browse files
committed
Add navrefresh command line program
This program can be used to send refresh events to ipdevpoll "by hand".
1 parent c4374fa commit 88d4aac

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ navdump = "nav.bin.navdump:main"
118118
naventity = "nav.bin.naventity:main"
119119
navoidverify = "nav.bin.navoidverify:main"
120120
navpgdump = "nav.pgdump:main"
121+
navrefresh = "nav.bin.navrefresh:main"
121122
navsnmp = "nav.bin.navsnmp:main"
122123
navstats = "nav.bin.navstats:main"
123124
navsyncdb = "nav.pgsync:main"

python/nav/bin/navrefresh.py

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright 2025 Sikt
4+
#
5+
# This file is part of Network Administration Visualized (NAV).
6+
#
7+
# NAV is free software: you can redistribute it and/or modify it under
8+
# the terms of the GNU General Public License version 3 as published by
9+
# the Free Software Foundation.
10+
#
11+
# This program is distributed in the hope that it will be useful, but WITHOUT
12+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14+
# more details. You should have received a copy of the GNU General Public
15+
# License along with NAV. If not, see <http://www.gnu.org/licenses/>.
16+
#
17+
"""A command line interface to send refresh commands to a running ipdevpoll daemon"""
18+
19+
20+
import argparse
21+
import sys
22+
23+
from nav.bootstrap import bootstrap_django
24+
25+
bootstrap_django(__file__)
26+
27+
from django.db import transaction
28+
from nav.models.manage import Netbox
29+
from nav.event2 import EventFactory
30+
31+
RefreshEvent = EventFactory("devBrowse", "ipdevpoll", event_type="notification")
32+
33+
34+
def main():
35+
"""Main program"""
36+
args = parse_args()
37+
if not args.netbox:
38+
sys.exit(f"Sysname pattern {args.netbox.pattern!r} matched nothing")
39+
40+
send_refresh_events(args.netbox, args.job)
41+
42+
43+
@transaction.atomic
44+
def send_refresh_events(netboxes: list[Netbox], job: str):
45+
for netbox in netboxes:
46+
print(f"Sending refresh event for {netbox.sysname} job {job}")
47+
event = RefreshEvent.notify(netbox=netbox, subid=job)
48+
event.save()
49+
50+
51+
def parse_args():
52+
"""Builds an ArgumentParser and returns parsed program arguments"""
53+
parser = argparse.ArgumentParser(
54+
description="Sends job refresh commands to a running ipdevpoll daemon",
55+
)
56+
parser.add_argument(
57+
"netbox",
58+
type=SysnamePattern,
59+
help="sysname (or sysname prefix) of devices that should be refreshed. Be aware that multiple devices can match.",
60+
)
61+
parser.add_argument("job", type=non_empty_string, help="ipdevpoll job to refresh.")
62+
return parser.parse_args()
63+
64+
65+
class SysnamePattern(list):
66+
def __init__(self, pattern: str):
67+
super().__init__()
68+
self.pattern = pattern.strip() if pattern else ""
69+
if not self.pattern:
70+
raise ValueError("sysname pattern cannot be empty")
71+
self.extend(Netbox.objects.filter(sysname__startswith=self.pattern))
72+
73+
74+
def non_empty_string(value: str):
75+
if not value.strip():
76+
raise argparse.ArgumentTypeError("cannot be empty")
77+
return value.strip()
78+
79+
80+
if __name__ == '__main__':
81+
main()

0 commit comments

Comments
 (0)