mirror of
https://github.com/ansible/awx.git
synced 2026-01-13 11:00:03 -03:30
Adds facts processing for ansible_net_neighbors
* Adds logic for consuming ansible_net_neighbors facts This consumes facts emitted from Ansible over a websocket to Tower. This allows consumers in network to process the facts and emit messges to the network UI. This requires a special callback plugin to run in Tower to emit the messages into the websocket using the python websocket-client library.
This commit is contained in:
parent
6f1000cd94
commit
3f84ef69eb
@ -8,7 +8,9 @@ from awx.network_ui.models import DataSheet, DataBinding, DataType
|
||||
from awx.network_ui.models import Process, Stream
|
||||
from awx.network_ui.models import Toolbox, ToolboxItem
|
||||
from awx.network_ui.serializers import yaml_serialize_topology
|
||||
from awx.network_ui.messages import MultipleMessage, InterfaceCreate, LinkCreate, to_dict
|
||||
import urlparse
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.db.models import Q
|
||||
from collections import defaultdict
|
||||
from django.conf import settings
|
||||
@ -259,7 +261,8 @@ class _Persistence(object):
|
||||
print "no sender"
|
||||
return
|
||||
if isinstance(data[1], dict) and client_id != data[1].get('sender'):
|
||||
print "client_id mismatch expected:", client_id, "actual:", data[1].get('sender')
|
||||
logger.error("client_id mismatch expected:", client_id, "actual:", data[1].get('sender'))
|
||||
logger.error(pformat(data))
|
||||
return
|
||||
message_type = data[0]
|
||||
message_value = data[1]
|
||||
@ -633,75 +636,73 @@ class _Discovery(object):
|
||||
def onFacts(self, message, topology_id):
|
||||
send_updates = False
|
||||
logger.info("onFacts message key %s", message['key'])
|
||||
logger.info("onFacts message %s", pformat(message))
|
||||
return
|
||||
name = message['key']
|
||||
device, created = Device.objects.get_or_create(topology_id=topology_id,
|
||||
name=name,
|
||||
defaults=dict(x=0,
|
||||
y=0,
|
||||
type="switch",
|
||||
id=0))
|
||||
|
||||
if created:
|
||||
device.id = device.pk
|
||||
device.save()
|
||||
send_updates = True
|
||||
logger.info("onFacts Created device %s", device)
|
||||
#logger.info("onFacts message %s", pformat(message))
|
||||
device_name = message['key']
|
||||
updates = MultipleMessage('MultipleMessage', [])
|
||||
try:
|
||||
device = Device.objects.get(topology_id=topology_id, name=device_name)
|
||||
except ObjectDoesNotExist:
|
||||
logger.info("onFacts Could not find %s in topology %s", device_name, topology_id)
|
||||
return
|
||||
|
||||
try:
|
||||
interfaces = dpath.util.get(message, '/value/ansible_local/lldp/lldp')
|
||||
interfaces = dpath.util.get(message, '/value/ansible_net_neighbors')
|
||||
logger.info(pformat(interfaces))
|
||||
except KeyError:
|
||||
interfaces = []
|
||||
for interface in interfaces:
|
||||
logger.info("onFacts %s: ", pformat(interface))
|
||||
for inner_interface in interface.get('interface', []):
|
||||
name = inner_interface.get('name')
|
||||
if not name:
|
||||
continue
|
||||
interface, created = Interface.objects.get_or_create(device_id=device.pk,
|
||||
name=name,
|
||||
defaults=dict(id=0))
|
||||
if created:
|
||||
interface.id = interface.pk
|
||||
interface.save()
|
||||
send_updates = True
|
||||
print "Created interface ", interface
|
||||
interfaces = {}
|
||||
logger.info("onFacts %s: ", pformat(interfaces))
|
||||
"""
|
||||
ansible_net_neighbors example:
|
||||
{u'eth1': [{u'host': u'Spine1', u'port': u'eth3'}],
|
||||
u'eth2': [{u'host': u'Spine2', u'port': u'eth3'}],
|
||||
u'eth3': [{u'host': u'Host2', u'port': u'eth1'}]}
|
||||
"""
|
||||
for interface_name, neighbors in interfaces.iteritems():
|
||||
logger.info("interface_name %s neighbors %s", interface_name, neighbors)
|
||||
interface, created = Interface.objects.get_or_create(device_id=device.pk,
|
||||
name=interface_name,
|
||||
defaults=dict(id=0))
|
||||
if created:
|
||||
interface.id = interface.pk
|
||||
interface.save()
|
||||
updates.messages.append(InterfaceCreate('InterfaceCreate',
|
||||
0,
|
||||
interface.device.id,
|
||||
interface.id,
|
||||
interface.name))
|
||||
send_updates = True
|
||||
logger.info("Created interface %s", interface)
|
||||
|
||||
|
||||
for neighbor in neighbors:
|
||||
logger.info("neighbor %s", neighbor)
|
||||
connected_interface = None
|
||||
connected_device = None
|
||||
neighbor_name = neighbor.get('host')
|
||||
if not neighbor_name:
|
||||
continue
|
||||
try:
|
||||
connected_device = Device.objects.get(topology_id=topology_id, name=neighbor_name)
|
||||
except ObjectDoesNotExist:
|
||||
continue
|
||||
|
||||
for chassis in inner_interface.get('chassis', []):
|
||||
name = chassis.get('name', [{}])[0].get('value')
|
||||
if not name:
|
||||
continue
|
||||
connected_device, created = Device.objects.get_or_create(topology_id=topology_id,
|
||||
name=name,
|
||||
defaults=dict(x=0,
|
||||
y=0,
|
||||
type="switch",
|
||||
id=0))
|
||||
if created:
|
||||
connected_device.id = connected_device.pk
|
||||
connected_device.save()
|
||||
send_updates = True
|
||||
print "Created device ", connected_device
|
||||
break
|
||||
logger.info("neighbor %s %s", neighbor_name, connected_device.pk)
|
||||
|
||||
if connected_device:
|
||||
for port in inner_interface.get('port', []):
|
||||
for port_id in port.get('id', []):
|
||||
if port_id['type'] == 'ifname':
|
||||
name = port_id['value']
|
||||
break
|
||||
connected_interface, created = Interface.objects.get_or_create(device_id=connected_device.pk,
|
||||
name=name,
|
||||
defaults=dict(id=0))
|
||||
if created:
|
||||
connected_interface.id = connected_interface.pk
|
||||
connected_interface.save()
|
||||
print "Created interface ", connected_interface
|
||||
send_updates = True
|
||||
remote_interface_name = neighbor.get('port')
|
||||
|
||||
connected_interface, created = Interface.objects.get_or_create(device_id=connected_device.pk,
|
||||
name=remote_interface_name,
|
||||
defaults=dict(id=0))
|
||||
if created:
|
||||
connected_interface.id = connected_interface.pk
|
||||
connected_interface.save()
|
||||
updates.messages.append(InterfaceCreate('InterfaceCreate',
|
||||
0,
|
||||
connected_interface.device.id,
|
||||
connected_interface.id,
|
||||
connected_interface.name))
|
||||
logger.info("Created interface %s", connected_interface)
|
||||
send_updates = True
|
||||
|
||||
if connected_device and connected_interface:
|
||||
exists = Link.objects.filter(Q(from_device_id=device.pk,
|
||||
@ -718,14 +719,25 @@ class _Discovery(object):
|
||||
from_interface_id=interface.pk,
|
||||
to_interface_id=connected_interface.pk,
|
||||
id=0)
|
||||
|
||||
link.save()
|
||||
link.id = link.pk
|
||||
link.save()
|
||||
print "Created link ", link
|
||||
updates.messages.append(LinkCreate('LinkCreate',
|
||||
0,
|
||||
link.id,
|
||||
link.name,
|
||||
link.from_device.id,
|
||||
link.to_device.id,
|
||||
link.from_interface.id,
|
||||
link.to_interface.id))
|
||||
logger.info("Created link %s", link)
|
||||
send_updates = True
|
||||
|
||||
if send_updates:
|
||||
send_snapshot(Group("topology-%s" % topology_id), topology_id)
|
||||
logger.info("onFacts send_updates")
|
||||
channel = Group("topology-%s" % topology_id)
|
||||
channel.send({"text": json.dumps([updates.msg_type, to_dict(updates)])})
|
||||
|
||||
|
||||
discovery = _Discovery()
|
||||
|
||||
32
awx/network_ui/messages.py
Normal file
32
awx/network_ui/messages.py
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
MultipleMessage = namedtuple('MultipleMessage', ['msg_type',
|
||||
'messages'])
|
||||
InterfaceCreate = namedtuple('InterfaceCreate', ['msg_type',
|
||||
'sender',
|
||||
'device_id',
|
||||
'id',
|
||||
'name'])
|
||||
LinkCreate = namedtuple('LinkCreate', ['msg_type',
|
||||
'sender',
|
||||
'id',
|
||||
'name',
|
||||
'from_device_id',
|
||||
'to_device_id',
|
||||
'from_interface_id',
|
||||
'to_interface_id'])
|
||||
|
||||
|
||||
def to_dict(message):
|
||||
if isinstance(message, MultipleMessage):
|
||||
d = dict(message._asdict())
|
||||
inner_messages = []
|
||||
for m in d['messages']:
|
||||
inner_messages.append(to_dict(m))
|
||||
d['messages'] = inner_messages
|
||||
return d
|
||||
else:
|
||||
return dict(message._asdict())
|
||||
Loading…
x
Reference in New Issue
Block a user