Skip to content

Commit

Permalink
Merge pull request napalm-automation-community#38 from napalm-automat…
Browse files Browse the repository at this point in the history
…ion/develop

Release 0.4.0
  • Loading branch information
mirceaulinic authored Feb 3, 2017
2 parents eb98f2c + bc55c7f commit 6971016
Show file tree
Hide file tree
Showing 13 changed files with 304 additions and 13 deletions.
6 changes: 2 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ python:
- 3.5

install:
- pip install -r requirements-dev.txt
- pip install .
- pip install tox-travis
- pip install coveralls

deploy:
Expand All @@ -20,8 +19,7 @@ deploy:
branch: master

script:
- py.test --cov-report= --cov=napalm_panos test/
- pylama .
- tox

after_success:
- coveralls
Expand Down
113 changes: 111 additions & 2 deletions napalm_panos/panos.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ def commit_config(self):
time.sleep(3)
self.loaded = False
self.changed = True
except:
except: # noqa
if self.merge_config:
raise MergeConfigException('Error while commiting config')
else:
Expand Down Expand Up @@ -338,7 +338,7 @@ def rollback(self):
self.loaded = False
self.changed = False
self.merge_config = False
except:
except: # noqa
ReplaceConfigException("Error while loading backup config")

def get_facts(self):
Expand Down Expand Up @@ -378,6 +378,115 @@ def get_facts(self):
facts['interface_list'].sort()
return facts

def get_lldp_neighbors(self):
"""Return LLDP neighbors details."""

neighbors = {}

cmd = '<show><lldp><neighbors>all</neighbors></lldp></show>'
try:
self.device.op(cmd=cmd)
lldp_table_xml = xmltodict.parse(self.device.xml_root())
lldp_table_json = json.dumps(lldp_table_xml['response']['result']['entry'])
lldp_table = json.loads(lldp_table_json)
except AttributeError:
lldp_table = []

for lldp_item in lldp_table:

local_int = lldp_item['@name']

if local_int not in neighbors.keys():
neighbors[local_int] = []

lldp_neighs = lldp_item['neighbors']['entry']
if isinstance(lldp_neighs, dict):
lldp_neighs = [lldp_neighs]

for neighbor in lldp_neighs:
n = {}
n['hostname'] = neighbor['system-name']
n['port'] = neighbor['port-id']
neighbors[local_int].append(n)
return neighbors

def get_route_to(self, destination='', protocol=''):
"""Return route details to a specific destination, learned from a certain protocol."""

# Note, it should be possible to query the FIB:
# "<show><routing><fib></fib></routing></show>"
# To add informations to this getter
routes = {}

if destination:
destination = "<destination>{0}</destination>".format(destination)
if protocol:
protocol = "<type>{0}</type>".format(protocol)

cmd = "<show><routing><route>{0}{1}</route></routing></show>".format(protocol, destination)
try:
self.device.op(cmd=cmd)
routes_table_xml = xmltodict.parse(self.device.xml_root())
routes_table_json = json.dumps(routes_table_xml['response']['result']['entry'])
routes_table = json.loads(routes_table_json)
except AttributeError:
routes_table = []

if isinstance(routes_table, dict):
routes_table = [routes_table]

for route in routes_table:
d = {
'current_active': False,
'last_active': False,
'age': -1,
'next_hop': u'',
'protocol': u'',
'outgoing_interface': u'',
'preference': -1,
'inactive_reason': u'',
'routing_table': u'default',
'selected_next_hop': False,
'protocol_attributes': {}
}
destination = route['destination']
flags = route['flags']

if 'A' in flags:
d['current_active'] = True
else:
d['current_active'] = False
if 'C' in flags:
d['protocol'] = "connect"
if 'S' in flags:
d['protocol'] = "static"
if 'R' in flags:
d['protocol'] = "rip"
if 'R' in flags:
d['protocol'] = "rip"
if 'O' in flags:
d['protocol'] = "ospf"
if 'B' in flags:
d['protocol'] = "bgp"
if 'H' in flags:
d['protocol'] = "host"
if route['age'] is not None:
d['age'] = int(route['age'])
if route['nexthop'] is not None:
d['next_hop'] = route['nexthop']
if route['interface'] is not None:
d['outgoing_interface'] = route['interface']
if route['metric'] is not None:
d['preference'] = int(route['metric'])
if route['virtual-router'] is not None:
d['routing_table'] = route['virtual-router']

if destination not in routes.keys():
routes[destination] = []
routes[destination].append(d)

return routes

def get_interfaces(self):
interface_dict = {}
interface_list = self.get_facts()['interface_list']
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ pytest-json
pytest-pythonpath
pylama
flake8-import-order
tox
-r requirements.txt
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
napalm-base>=0.18.0
pan-python
netmiko>=0.5.0
netmiko>=1.0.0
requests-toolbelt
xmltodict
future
9 changes: 4 additions & 5 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
[pylama]
linters = mccabe,pep8,pyflakes
ignore = D203,C901
skip = build/*,.tox/*

[pylama:pep8]
max_line_length = 100

[tool:pytest]
addopts = --cov=./ -vs
[pytest]
addopts = --cov=napalm_panos --cov-report term-missing -vs --pylama
json_report = report.json
jsonapi = true

[coverage:run]
include =
napalm_panos/*

source = napalm_panos
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

setup(
name="napalm-panos",
version="0.3.0",
version="0.4.0",
packages=find_packages(),
author="Gabriele Gerbino",
author_email="[email protected]",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<response status="success">
<result>
<entry name="ethernet1/15">
<local>
<index>30</index>
<port-id>15</port-id>
</local>
<neighbors>
<entry name="006cbc0000004769312f302f32">
<chassis-type>MAC address</chassis-type>
<chassis-id>00:6c:bc:00:00:00</chassis-id>
<port-type>Interface name</port-type>
<port-id>Gi1/0/2</port-id>
<port-description>GigabitEthernet1/0/2</port-description>
<ttl>116</ttl>
<system-name>peer00.lab.demo</system-name>
<system-description>mock system description</system-description>
<system-capabilities>B, R,
</system-capabilities>
<enabled-capabilities>B, R,
</enabled-capabilities>
<management-address>
<entry name="10.0.0.1">
<address-type>ipv4</address-type>
<interface-number>0</interface-number>
<interface-type>System Port Number</interface-type>
</entry>
</management-address>
</entry>
</neighbors>
</entry>
<entry name="ethernet1/16">
<local>
<index>31</index>
<port-id>16</port-id>
</local>
<neighbors>
<entry name="006cbc0000014769322f302f32">
<chassis-type>MAC address</chassis-type>
<chassis-id>00:6c:bc:00:00:00</chassis-id>
<port-type>Interface name</port-type>
<port-id>Gi2/0/2</port-id>
<port-description>GigabitEthernet2/0/2</port-description>
<ttl>107</ttl>
<system-name>peer01.lab.demo</system-name>
<system-description>mock system description</system-description>
<system-capabilities>B, R,
</system-capabilities>
<enabled-capabilities>B, R,
</enabled-capabilities>
<management-address>
<entry name="10.0.0.1">
<address-type>ipv4</address-type>
<interface-number>0</interface-number>
<interface-type>System Port Number</interface-type>
</entry>
</management-address>
</entry>
</neighbors>
</entry>
<entry name="ethernet1/13">
<local>
<index>28</index>
<port-id>13</port-id>
</local>
<neighbors>
<entry name="44f477000000353138">
<chassis-type>MAC address</chassis-type>
<chassis-id>44:f4:77:00:00:00</chassis-id>
<port-type>Locally assigned</port-type>
<port-id>518</port-id>
<port-description>mockdescription</port-description>
<ttl>92</ttl>
<system-name>peer01.lab.demo</system-name>
<system-description>mock system description
</system-description>
<system-capabilities>B, R,
</system-capabilities>
<enabled-capabilities>B, R,
</enabled-capabilities>
<management-address>
<entry name="10.0.0.2">
<address-type>ipv4</address-type>
<interface-number>1</interface-number>
<interface-type>Ifindex</interface-type>
<oid>0.1.3.6.1.2.1.31.1.1.1.1.1.</oid>
</entry>
</management-address>
</entry>
</neighbors>
</entry>
<entry name="ethernet1/14">
<local>
<index>29</index>
<port-id>14</port-id>
</local>
<neighbors>
<entry name="44f477000001353138">
<chassis-type>MAC address</chassis-type>
<chassis-id>44:f4:77:00:00:01</chassis-id>
<port-type>Locally assigned</port-type>
<port-id>518</port-id>
<port-description>mockdescription</port-description>
<ttl>110</ttl>
<system-name>peer02.lab.demo</system-name>
<system-description>mock system description
</system-description>
<system-capabilities>B, R,
</system-capabilities>
<enabled-capabilities>B, R,
</enabled-capabilities>
<management-address>
<entry name="10.0.0.3">
<address-type>ipv4</address-type>
<interface-number>1</interface-number>
<interface-type>Ifindex</interface-type>
<oid>0.1.3.6.1.2.1.31.1.1.1.1.1.</oid>
</entry>
</management-address>
</entry>
</neighbors>
</entry>
</result>
</response>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"ethernet1/13": [{"hostname": "peer01.lab.demo", "port": "518"}], "ethernet1/16": [{"hostname": "peer01.lab.demo", "port": "Gi2/0/2"}], "ethernet1/14": [{"hostname": "peer02.lab.demo", "port": "518"}], "ethernet1/15": [{"hostname": "peer00.lab.demo", "port": "Gi1/0/2"}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<response status="success">
<result>
<flags>flags: A:active, ?:loose, C:connect, H:host, S:static, ~:internal, R:rip, O:ospf, B:bgp, Oi:ospf intra-area, Oo:ospf inter-area, O1:ospf ext-type-1, O2:ospf ext-type-2, E:ecmp</flags>
<entry>
<virtual-router>default</virtual-router>
<destination>10.22.0.0/16</destination>
<nexthop>10.0.0.1</nexthop>
<metric/>
<flags>A?B
</flags>
<age>2832970</age>
<interface/></entry>
</result>
</response>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"10.22.0.0/16": [{"protocol": "bgp", "last_active": false, "next_hop": "10.0.0.1", "outgoing_interface": "", "preference": -1, "inactive_reason": "", "current_active": true, "age": 2832970, "routing_table": "default", "selected_next_hop": false, "protocol_attributes": {}}]}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<response status="success">
<result>
<flags>flags: A:active, ?:loose, C:connect, H:host, S:static, ~:internal, R:rip, O:ospf, B:bgp, Oi:ospf intra-area, Oo:ospf inter-area, O1:ospf ext-type-1, O2:ospf ext-type-2, E:ecmp</flags>
<entry>
<virtual-router>default</virtual-router>
<destination>10.0.0.128/30</destination>
<nexthop>10.0.0.1</nexthop>
<metric>0</metric>
<flags>A C
</flags>
<age/>
<interface>tunnel.34</interface>
</entry>
<entry>
<virtual-router>default</virtual-router>
<destination>10.0.0.132/30</destination>
<nexthop>10.0.0.2</nexthop>
<metric>0</metric>
<flags>A C
</flags>
<age/>
<interface>tunnel.35</interface>
</entry>
<entry>
<virtual-router>default</virtual-router>
<destination>192.168.1.1/32</destination>
<nexthop>0.0.0.0</nexthop>
<metric>0</metric>
<flags>A H
</flags>
<age/>
<interface/></entry>
</result>
</response>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"10.0.0.128/30": [{"protocol": "connect","current_active": true,"age": -1,"routing_table": "default","next_hop": "10.0.0.1","outgoing_interface": "tunnel.34","preference": 0, "protocol_attributes": {}, "inactive_reason": "", "last_active": false, "selected_next_hop": false }], "192.168.1.1/32": [{"protocol": "host", "current_active": true,"age": -1,"routing_table": "default","next_hop": "0.0.0.0","outgoing_interface": "","preference": 0, "protocol_attributes": {}, "inactive_reason": "", "last_active": false, "selected_next_hop": false }], "10.0.0.132/30": [{"protocol": "connect","current_active": true,"age": -1,"routing_table": "default","next_hop": "10.0.0.2","outgoing_interface": "tunnel.35","preference": 0, "protocol_attributes": {}, "inactive_reason": "", "last_active": false, "selected_next_hop": false }]}
9 changes: 9 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[tox]
envlist = py27,py34,py35

[testenv]
deps =
-rrequirements-dev.txt

commands=
py.test

0 comments on commit 6971016

Please sign in to comment.