Skip to content
Snippets Groups Projects
Commit 96ca8834 authored by Erik Reid's avatar Erik Reid
Browse files

refactored to share some code between both routes

parent 4e51b8ff
No related branches found
No related tags found
No related merge requests found
......@@ -176,36 +176,78 @@ def _load_interfaces(hostname):
}
def _load_poller_interfaces(hostname=None):
def _add_bundle_parents(interfaces, hostname=None):
"""
generator that adds bundle-parents info to each interface.
snmp_indexes = _load_snmp_indexes(hostname)
:param interfaces: result of _load_interfaces
:param hostname: hostname or None for all
:return: generator with bundle-parents populated in each element
"""
bundles = _load_interface_bundles(hostname)
services = _load_services(hostname)
for ifc in _load_interfaces(hostname):
router_snmp = snmp_indexes.get(ifc['router'], None)
if not router_snmp or ifc['name'] not in router_snmp:
# there's no way to poll this interface
continue
ifc['snmp-index'] = router_snmp[ifc['name']]['index']
# TODO: uncomment this when it won't break poller-admin-service
# not urgent ... it looks empirically like all logical-system
# interfaces are repeated for both communities
# ifc['snmp-community'] = router_snmp[ifc['name']]['community']
for ifc in interfaces:
router_bundle = bundles.get(ifc['router'], None)
if router_bundle:
base_ifc = ifc['name'].split('.')[0]
ifc['bundle-parents'] = router_bundle.get(base_ifc, [])
yield ifc
def _add_circuits(interfaces, hostname=None):
"""
generator that adds service info to each interface.
:param interfaces: result of _load_interfaces
:param hostname: hostname or None for all
:return: generator with 'circuits' populated in each element, if present
"""
services = _load_services(hostname)
for ifc in interfaces:
router_services = services.get(ifc['router'], None)
if router_services:
ifc['circuits'] = router_services.get(ifc['name'], [])
yield ifc
def _add_snmp_indexes(interfaces, hostname=None):
"""
generator that adds snmp info to each interface, if available
:param interfaces: result of _load_interfaces
:param hostname: hostname or None for all
:return: generator with 'snmp-index' optionally added to each element
"""
snmp_indexes = _load_snmp_indexes(hostname)
for ifc in interfaces:
router_snmp = snmp_indexes.get(ifc['router'], None)
if router_snmp and ifc['name'] in router_snmp:
ifc['snmp-index'] = router_snmp[ifc['name']]['index']
# TODO: uncomment this when it won't break poller-admin-service
# not urgent ... it looks empirically like all logical-system
# interfaces are repeated for both communities
# ifc['snmp-community'] = router_snmp[ifc['name']]['community']
yield ifc
def _load_interfaces_to_poll(hostname=None):
"""
prepares the result of a call to /interfaces
:param hostname: hostname or None for all
:return: generator yielding interface elements
"""
basic_interfaces = _load_interfaces(hostname)
with_bundles = _add_bundle_parents(basic_interfaces, hostname)
with_circuits = _add_circuits(with_bundles, hostname)
with_snmp = _add_snmp_indexes(with_circuits, hostname)
def _has_snmp_index(ifc):
return 'snmp-index' in ifc
# only return interfaces that can be polled
return filter(_has_snmp_index, with_snmp)
@routes.route("/interfaces", methods=['GET', 'POST'])
@routes.route('/interfaces/<hostname>', methods=['GET', 'POST'])
@common.require_accepts_json
......@@ -236,7 +278,7 @@ def interfaces(hostname=None):
if result:
result = result.decode('utf-8')
else:
result = list(_load_poller_interfaces(hostname))
result = list(_load_interfaces_to_poll(hostname))
if not result:
return Response(
response='no interfaces found',
......@@ -250,6 +292,60 @@ def interfaces(hostname=None):
return Response(result, mimetype="application/json")
def interface_speed(ifc):
"""
Return the maximum bits per second expected for the given interface.
cf. https://www.juniper.net/documentation/us/en/software/
vmx/vmx-getting-started/topics/task/
vmx-chassis-interface-type-configuring.html
:param ifc:
:return: an integer bits per second
"""
GB = 1000000000
# GB = 1 << 30
def _name_to_speed(ifc_name):
if ifc_name.startswith('ge'):
return GB
if ifc_name.startswith('xe'):
return 10 * GB
if ifc_name.startswith('et'):
return 100 * GB
logger.warning(f'unrecognized interface name: {ifc_name}')
return -1
if ifc['bundle-parents']:
if not ifc['name'].startswith('ae'):
logger.warning(
f'ifc has bundle-parents, but name is {ifc["name"]}')
return sum(_name_to_speed(name) for name in ifc['bundle-parents'])
return _name_to_speed(ifc['name'])
def _load_interfaces_and_speeds(hostname=None):
"""
prepares the result of a call to /speeds
:param hostname: hostname or None for all
:return: generator yielding interface elements
"""
basic_interfaces = _load_interfaces(hostname)
with_bundles = _add_bundle_parents(basic_interfaces, hostname)
with_bundles = list(with_bundles)
def _result_ifc(ifc):
return {
'router': ifc['router'],
'name': ifc['name'],
'speed': interface_speed(ifc)
}
return map(_result_ifc, with_bundles)
@routes.route("/speeds", methods=['GET', 'POST'])
@routes.route('/speeds/<hostname>', methods=['GET', 'POST'])
@common.require_accepts_json
......@@ -260,8 +356,9 @@ def interface_speeds(hostname=None):
which returns information for either all interfaces
or those on the requested hostname.
The response is a list of speed information for all
known interfaces.
The response is a list of maximum speed information (in bits
per second) for all known interfaces.
[speed <= 0 means the max interface speed can't be determined]
.. asjson::
inventory_provider.routes.poller.INTERFACE_SPEED_LIST_SCHEMA
......@@ -279,20 +376,7 @@ def interface_speeds(hostname=None):
if result:
result = result.decode('utf-8')
else:
def _speed(ifc):
# TODO
return -1
def _result_ifc(ifc):
return {
'router': ifc['router'],
'name': ifc['name'],
'speed': _speed(ifc)
}
result = list(map(_result_ifc, _load_interfaces(hostname)))
result = list(_load_interfaces_and_speeds(hostname))
if not result:
return Response(
response='no interfaces found',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment