Skip to content

Commit

Permalink
Merge pull request #118 from spotify/base_new_methods
Browse files Browse the repository at this point in the history
Base new methods
  • Loading branch information
dbarrosop committed Dec 15, 2015
2 parents 4c69749 + c795474 commit 09c74ca
Show file tree
Hide file tree
Showing 52 changed files with 91,771 additions and 1,185 deletions.
1 change: 0 additions & 1 deletion napalm/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,6 @@ def get_bgp_neighbors(self):
* remote_id - peer router id
* is_up (True/False)
* is_enabled (True/False)
* remote_as (int)
* description (string)
* uptime (int in seconds)
* address_family (dictionary) - A dictionary of address families available for the neighbor. So far it can
Expand Down
144 changes: 93 additions & 51 deletions napalm/eos.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,14 @@

import pyeapi
import re

from base import NetworkDriver

from exceptions import MergeConfigException, ReplaceConfigException, SessionLockedException

from datetime import datetime
import time

from utils import string_parsers
from napalm.utils import string_parsers


class EOSDriver(NetworkDriver):

def __init__(self, hostname, username, password, timeout=60):
self.device = None
self.hostname = hostname
Expand Down Expand Up @@ -234,52 +229,97 @@ def get_interfaces_counters(self):
interface_counters[interface]['tx_errors'] = errors['outErrors']
interface_counters[interface]['rx_errors'] = errors['inErrors']


return interface_counters



# def get_bgp_neighbors(self):
# bgp_neighbors = dict()
#
# for vrf, vrf_data in self.device.show_ip_bgp_summary_vrf_all()['vrfs'].iteritems():
# bgp_neighbors[vrf] = dict()
# bgp_neighbors[vrf]['router_id'] = vrf_data['routerId']
# bgp_neighbors[vrf]['local_as'] = vrf_data['asn']
# bgp_neighbors[vrf]['peers'] = dict()
#
# for n, n_data in vrf_data['peers'].iteritems():
# bgp_neighbors[vrf]['peers'][n] = dict()
#
# if n_data['peerState'] == 'Established':
# bgp_neighbors[vrf]['peers'][n]['is_up'] = True
# bgp_neighbors[vrf]['peers'][n]['is_enabled'] = True
# else:
# bgp_neighbors[vrf]['peers'][n]['is_up'] = False
#
# reason = n_data.pop('peerStateIdleReason', None)
# if reason == 'Admin':
# bgp_neighbors[vrf]['peers'][n]['is_enabled'] = False
# else:
# bgp_neighbors[vrf]['peers'][n]['is_enabled'] = True
#
# bgp_neighbors[vrf]['peers'][n]['remote_as'] = n_data['asn']
# bgp_neighbors[vrf]['peers'][n]['uptime'] = n_data['upDownTime']
#
# raw_data = eval(
# 'self.device.show_ip_bgp_neighbors_vrf_{}(format="text", pipe="section {}")'.format(vrf, n)
# )['output']
#
# n_data_full = colon_separated_string_to_dict(raw_data)
# sent, rcvd = n_data_full['IPv4 Unicast'].split()
#
# bgp_neighbors[vrf]['peers'][n]['received_prefixes'] = int(rcvd)
# bgp_neighbors[vrf]['peers'][n]['sent_prefixes'] = int(sent)
# bgp_neighbors[vrf]['peers'][n]['accepted_prefixes'] = n_data['prefixAccepted']
#
# bgp_neighbors[vrf]['peers'][n]['description'] = n_data_full.pop('Description', '')
#
# return bgp_neighbors
def get_bgp_neighbors(self):

commands_json = list()
commands_txt = list()
commands_json.append('show ip bgp summary vrf all')
commands_json.append('show ipv6 bgp summary vrf all')
commands_txt.append('show ip bgp neighbors vrf all | include remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:')
commands_txt.append('show ipv6 bgp neighbors vrf all | include remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:')

output_summary = self.device.run_commands(commands_json, encoding='json')
output_neighbors = self.device.run_commands(commands_txt, encoding='text')

##########################################
# no JSON available for show ip bgp neigh
# Using 'show ipv[4-6] bgp neighbors vrf all | i remote AS|remote router ID|Description|^ *IPv[4-6] Unicast:'
# NOTE: if there is no description, EOS does not print the line.


# Regex the output from show ip bgp neigh
def get_bgp_neighbor(needed_peer, vrf, output_to_parse):
import re

bgp_neighbors = dict()
bgp_peer = dict()
neighbor_regexp = re.compile('BGP neighbor is (.*?),')
description_regexp = re.compile('Description: (.*?)$')
remote_id_regexp = re.compile('remote router ID (.*?),')
vrf_regexp = re.compile('VRF (.*?)$')
IPv4_sent_regexp = re.compile('IPv4 Unicast: ( *)(\d*) ')
IPv6_sent_regexp = re.compile('IPv6 Unicast: ( *)(\d*) ')

for line in output_to_parse.splitlines():
if re.search(neighbor_regexp, line):
peer = re.search(neighbor_regexp, line).group(1)
bgp_neighbors[peer] = dict()
bgp_neighbors[peer]['description'] = ''
continue
elif re.search(description_regexp, line):
bgp_neighbors[peer]['description'] = re.search(description_regexp, line).group(1)
continue
elif re.search(remote_id_regexp, line):
bgp_neighbors[peer]['remote_id'] = re.search(remote_id_regexp, line).group(1)
bgp_neighbors[peer]['vrf'] = re.search(vrf_regexp, line).group(1)
continue
elif re.search(IPv4_sent_regexp, line):
bgp_neighbors[peer]['ipv4'] = re.search(IPv4_sent_regexp, line).group(2)
continue
elif re.search(IPv6_sent_regexp, line):
bgp_neighbors[peer]['ipv6'] = re.search(IPv6_sent_regexp, line).group(2)
continue
try:
peer = next(peer for peer in bgp_neighbors if peer == needed_peer)
except StopIteration:
raise Exception("Peer %s not found in show bgp neighbors" % needed_peer)
if bgp_neighbors[peer]['vrf'] == vrf:
bgp_peer['remote_id'] = bgp_neighbors[peer]['remote_id']
bgp_peer['description'] = bgp_neighbors[peer]['description']
bgp_peer['ipv4'] = bgp_neighbors[peer]['ipv4']
bgp_peer['ipv6'] = bgp_neighbors[peer]['ipv6']
return bgp_peer

bgp_counters = dict()
for id in [0,1]:
for vrf in output_summary[id]['vrfs']:
bgp_counters[vrf] = dict()
bgp_counters[vrf]['router_id'] = unicode(output_summary[id]['vrfs'][vrf]['routerId'])
bgp_counters[vrf]['peers'] = dict()
for peer in output_summary[id]['vrfs'][vrf]['peers']:
bgp_counters[vrf]['peers'][peer] = dict()
bgp_counters[vrf]['peers'][peer]['local_as'] = int(output_summary[id]['vrfs'][vrf]['asn'])
bgp_counters[vrf]['peers'][peer]['remote_as'] = int(output_summary[id]['vrfs'][vrf]['peers'][peer]['asn'])
peerState = output_summary[id]['vrfs'][vrf]['peers'][peer]['peerState']
bgp_counters[vrf]['peers'][peer]['is_up'] = peerState == 'Established'
if 'peerStateIdleReason' in output_summary[id]['vrfs'][vrf]['peers'][peer]:
bgp_counters[vrf]['peers'][peer]['is_enabled'] = False
else:
bgp_counters[vrf]['peers'][peer]['is_enabled'] = peerState == 'Established' or peerState == 'Active'
bgp_counters[vrf]['peers'][peer]['uptime'] = int(output_summary[id]['vrfs'][vrf]['peers'][peer]['upDownTime'])
bgp_peer = get_bgp_neighbor(peer, vrf, output_neighbors[id]['output'])
bgp_counters[vrf]['peers'][peer]['remote_id'] = unicode(bgp_peer['remote_id'])
bgp_counters[vrf]['peers'][peer]['description'] = unicode(bgp_peer['description'])
bgp_counters[vrf]['peers'][peer]['address_family'] = dict()
for family in ['ipv4', 'ipv6']:
bgp_counters[vrf]['peers'][peer]['address_family'][family] = dict()
bgp_counters[vrf]['peers'][peer]['address_family'][family]['received_prefixes'] = int(output_summary[id]['vrfs'][vrf]['peers'][peer]['prefixReceived'])
bgp_counters[vrf]['peers'][peer]['address_family'][family]['accepted_prefixes'] = int(output_summary[id]['vrfs'][vrf]['peers'][peer]['prefixAccepted'])
bgp_counters[vrf]['peers'][peer]['address_family'][family]['sent_prefixes'] = int(bgp_peer[family])
bgp_counters['global'] = bgp_counters.pop('default')
return bgp_counters

def get_environment(self):
"""
Expand Down Expand Up @@ -347,7 +387,9 @@ def get_environment(self):

''' Get CPU counters '''
m = re.search('(\d+.\d+)\%', cpu_output.splitlines()[2])
environment_counters['cpu'][0] = float(m.group(1))
environment_counters['cpu'][0] = {
'%usage': float(m.group(1))
}
m = re.search('(\d+)k\W+total\W+(\d+)k\W+used\W+(\d+)k\W+free', cpu_output.splitlines()[3])

environment_counters['memory'] = {
Expand Down
125 changes: 103 additions & 22 deletions napalm/fortios.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@
# License for the specific language governing permissions and limitations under
# the License.
import re

from pyFG.fortios import FortiOS, FortiConfig, logger
from pyFG.exceptions import FailedCommit, CommandExecutionException

from base import NetworkDriver
from exceptions import ReplaceConfigException, MergeConfigException

from utils.string_parsers import colon_separated_string_to_dict, convert_uptime_string_seconds
from napalm.utils.string_parsers import colon_separated_string_to_dict, convert_uptime_string_seconds


def execute_get(device, cmd, separator=':', auto=False):
Expand Down Expand Up @@ -174,12 +171,13 @@ def get_interfaces(self):

return interface_statistics

def get_bgp_neighbors(self):
@staticmethod
def _search_line_in_lines(search, lines):
for l in lines:
if search in l:
return l

def search_line_in_lines(search, lines):
for l in lines:
if search in l:
return l
def get_bgp_neighbors(self):

families = ['ipv4', 'ipv6']
terms = dict({'accepted_prefixes': 'accepted', 'sent_prefixes': 'announced'})
Expand Down Expand Up @@ -224,7 +222,7 @@ def search_line_in_lines(search, lines):
block = detail_output[x:]

for term, fortiname in terms.iteritems():
text = search_line_in_lines('%s prefixes' % fortiname, block)
text = self._search_line_in_lines('%s prefixes' % fortiname, block)
t = [int(s) for s in text.split() if s.isdigit()][0]
neighbor_dict['address_family'][family][term] = t

Expand Down Expand Up @@ -258,27 +256,110 @@ def get_interfaces_counters(self):
elif (data[1].startswith('RX packets') or data[1].startswith('TX packets')) and if_name:
if_data = data[1].split(' ')
direction = if_data[0].lower()
interface_counters[if_name][direction + '_unicast_packets'] = if_data[1].split(':')[1]
interface_counters[if_name][direction + '_errors'] = if_data[2].split(':')[1]
interface_counters[if_name][direction + '_discards'] = if_data[2].split(':')[1]
interface_counters[if_name][direction + '_unicast_packets'] = int(if_data[1].split(':')[1])
interface_counters[if_name][direction + '_errors'] = int(if_data[2].split(':')[1])
interface_counters[if_name][direction + '_discards'] = int(if_data[2].split(':')[1])
interface_counters[if_name][direction + '_multicast_packets'] = -1
interface_counters[if_name][direction + '_broadcast_packets'] = -1
elif data[1].startswith('RX bytes'):
if_data = data[1].split(' ')
interface_counters[if_name]['rx_octets'] = if_data[1].split(':')[1]
interface_counters[if_name]['rx_octets'] = int(if_data[1].split(':')[1])
try:
interface_counters[if_name]['tx_octets'] = if_data[6].split(':')[1]
interface_counters[if_name]['tx_octets'] = int(if_data[6].split(':')[1])
except IndexError:
interface_counters[if_name]['tx_octets'] = if_data[7].split(':')[1]
interface_counters[if_name]['tx_octets'] = int(if_data[7].split(':')[1])
return interface_counters

def get_lldp_neighbors(self):
return {}

def get_environment(self):

def parse_string(line):
return re.sub(' +', ' ', line.lower())

def search_disabled(line):
m = re.search("(.+?) (.+?) alarm=(.+?) \(scanning disabled\)", line)
return m.group(2)

def search_normal(line):
m = re.search("(.+?) (.+?) alarm=(.+?) value=(.+?) threshold_status=(.+?)", line)
return m

def get_fans(fan_lines):
output = dict()
for fan_line in fan_lines:
if 'disabled' in fan_line:
name = search_disabled(fan_line)
output[name] = dict(status=False)
continue

m = search_normal(fan_line)
output[m.group(2)] = dict(status=True)
return output

def get_cpu(cpu_lines):
output = dict()
for l in cpu_lines:
m = re.search('(.+?) states: (.+?)% user (.+?)% system (.+?)% nice (.+?)% idle', l)
cpuname = m.group(1)
idle = m.group(5)
output[cpuname] = {
'%usage': 100.0 - int(idle)
}
return output

def get_memory(memory_line):
total, used = int(memory_line[1]) >> 20, int(memory_line[2]) >> 20 # convert from byte to MB
return dict(available_ram=total, used_ram=used)

def get_temperature(temperature_lines, detail_block):
output = dict()
for temp_line in temperature_lines:
if 'disabled' in temp_line:
sensor_name = search_disabled(temp_line)
output[sensor_name] = {'is_alert': False, 'is_critical': False, 'temperature': 0.0}
continue

m = search_normal(temp_line)
sensor_name, temp_value, status = m.group(2), m.group(4), int(m.group(5))
is_alert = True if status == 1 else False

# find block
fullline = self._search_line_in_lines(sensor_name, detail_block)
index_line = detail_block.index(fullline)
sensor_block = detail_block[index_line:]

v = int(self._search_line_in_lines('upper_non_recoverable', sensor_block).split('=')[1])

output[sensor_name] = dict(temperature=float(temp_value), is_alert=is_alert,
is_critical=True if v > temp_value else False)

return output

out = dict()

sensors_block = [parse_string(x) for x in self.device.execute_command('execute sensor detail') if x]

# temp
temp_lines = [x for x in sensors_block if any([True for y in ['dts', 'temp', 'adt7490'] if y in x])]
out['temperature'] = get_temperature(temp_lines, sensors_block)

# fans
out['fans'] = get_fans([x for x in sensors_block if 'fan' in x and 'temp' not in x])

# cpu
out['cpu'] = get_cpu(
[x for x in self.device.execute_command('get system performance status | grep CPU')[1:] if x])

# memory
memory_command = 'diag hard sys mem | grep Mem:'
t = [x for x in re.split('\s+', self.device.execute_command(memory_command)[0]) if x]
out['memory'] = get_memory(t)

# power, not implemented
sensors = [x.split()[1] for x in sensors_block if x.split()[0].isdigit()]
psus = {x for x in sensors if x.startswith('ps')}
out['power'] = {t: {'status': True, 'capacity': -1.0, 'output': -1.0} for t in psus}

# def get_environment(self):
# sensors_output = self.device.execute_command('execute sensor list')
# from pprint import pprint
# pprint(sensors_output)
#
# return {}
return out

0 comments on commit 09c74ca

Please sign in to comment.