Commit e9211827 authored by Morten Brekkevold's avatar Morten Brekkevold

Merge branch 'diffupdate'

parents 7f034b36 90abceac
......@@ -55,9 +55,9 @@ def main():
find_reverse_dns_mismatches(devices)
if not args.kind_only:
check_nav(devices,
api_url=args.api_url, api_token=args.api_token,
dry_run=args.dry_run)
update_nav(devices,
api_url=args.api_url, api_token=args.api_token,
dry_run=args.dry_run)
def parse_args():
......@@ -227,7 +227,7 @@ class NAVBox(dict):
return hash(self.id)
def check_nav(kind_devices, api_url, api_token, dry_run=False):
def update_nav(kind_devices, api_url, api_token, dry_run=False):
kind_by_ip = {ip: dev
for dev in kind_devices.values() for ip in dev.ipaddrs}
nav_api = NAVAPI(url=api_url, auth_token=api_token)
......@@ -251,7 +251,7 @@ def check_nav(kind_devices, api_url, api_token, dry_run=False):
if matched_netboxes:
LOG.debug("Utstyr som allerede ligger i NAV:\n %s",
"\n ".join(sorted(n['sysname'] for n in matched_netboxes)))
"\n ".join(sorted(n['sysname'] for n in matched_netboxes)))
if unmatched_kind_devices:
LOG.info("Utstyr som skal inn i NAV:\n %s",
"\n ".join(sorted(str(d) for d in unmatched_kind_devices)))
......@@ -262,7 +262,9 @@ def check_nav(kind_devices, api_url, api_token, dry_run=False):
if not dry_run:
remove_from_nav(nav_api, unmatched_netboxes)
insert_into_nav(nav_api, unmatched_kind_devices)
# TODO Update existing devices that have changed!
update_existing_in_nav(nav_api,
[device for device in kind_devices.values()
if device.netbox])
def insert_into_nav(nav_api, kind_devices):
......@@ -302,6 +304,50 @@ def insert_one_into_nav(nav_api, kind_device):
nav_api.post_netbox(netbox)
def update_existing_in_nav(nav_api, kind_devices):
LOG.debug("Sammenligner eksisterende utstyr i NAV med utstyr fra Kind")
for device in kind_devices:
update_device_in_nav_if_changed(nav_api, device)
def update_device_in_nav_if_changed(nav_api, kind_device):
"""Updates kind_device in NAV if its details have changed.
Specifically, if the room or category has changed in Kind, NAV is updated.
:type nav_api: kindnavsync.navapi.NAVAPI
:type kind_device: KindDevice
"""
if not is_device_changed(kind_device):
return
patch = dict(
roomid=kind_device.room,
categoryid=CATEGORY_MAP.get(kind_device.type, DEFAULT_CATEGORY),
)
try:
nav_api.get_room(kind_device.room)
except ObjectNotFound:
room = dict(id=kind_device.room, location=DEFAULT_LOCATION)
nav_api.post_room(room)
nav_api.patch_netbox(netbox_id=kind_device.netbox.id, patch=patch)
def is_device_changed(kind_device):
assert kind_device.netbox
expected_category = CATEGORY_MAP.get(kind_device.type, DEFAULT_CATEGORY)
diff = (kind_device.room != kind_device.netbox['room']['id'] or
kind_device.netbox['category']['id'] != expected_category)
if diff:
LOG.info("%s er forandret i Kind: room %r -> %r / category %r -> %r",
kind_device.name,
kind_device.netbox['room']['id'], kind_device.room,
kind_device.netbox['category']['id'], expected_category)
return diff
def remove_from_nav(nav_api, deleteable_boxes):
if not deleteable_boxes:
return
......
......@@ -33,6 +33,16 @@ class NAVAPI(object):
response.raise_for_status()
return response.json()
def _simple_patch(self, endpoint, data, **kwargs):
response = requests.patch(
self._endpoint(endpoint),
headers=self._base_headers(),
data=data,
**kwargs
)
response.raise_for_status()
return response.json()
def _simple_delete(self, endpoint, **kwargs):
response = requests.delete(
self._endpoint(endpoint),
......@@ -48,7 +58,7 @@ class NAVAPI(object):
def get_netbox(self, netbox_id):
try:
response = self._simple_get('/netbox/{}'.format(netbox_id))
response = self._simple_get('/netbox/{}/'.format(netbox_id))
except HTTPError as error:
if error.response.status_code == 404:
raise ObjectNotFound(error.response.content.decode())
......@@ -60,13 +70,24 @@ class NAVAPI(object):
response = self._simple_post('/netbox/', data=netbox)
return response
def patch_netbox(self, netbox_id, patch):
try:
response = self._simple_patch('/netbox/{}/'.format(netbox_id),
data=patch)
except HTTPError as error:
if error.response.status_code == 404:
raise ObjectNotFound(error.response.content.decode())
else:
raise
return response
def delete_netbox(self, netbox_id):
response = self._simple_delete("/netbox/{}".format(netbox_id))
response = self._simple_delete("/netbox/{}/".format(netbox_id))
return response
def get_room(self, room_id):
try:
response = self._simple_get('/room/{}'.format(room_id))
response = self._simple_get('/room/{}/'.format(room_id))
except HTTPError as error:
if error.response.status_code == 404:
raise ObjectNotFound(error.response.content.decode())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment