Skip to content

Commit abf1511

Browse files
shinmogbtorresgil
authored andcommitted
Fixes #71 - add reorganizer and allow subinterfaces to have vsys/fw objects as parents (#79)
1 parent c3b6ee6 commit abf1511

File tree

3 files changed

+142
-2
lines changed

3 files changed

+142
-2
lines changed

pandevice/firewall.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"""Palo Alto Networks Firewall object"""
1919

2020
# import modules
21+
import itertools
2122
import re
2223
import logging
2324
import xml.etree.ElementTree as ET
@@ -360,6 +361,63 @@ def commit_policy_and_objects(self, sync=False, exception=False):
360361
return self._commit(sync=sync, exclude="policy-and-objects",
361362
exception=exception)
362363

364+
def organize_into_vsys(self, create_vsys_objects=True, refresh_vsys=True):
365+
"""Organizes all imported objects under the appropriate Vsys object.
366+
367+
Args:
368+
create_vsys_objects (bool): Create the vsys objects (True) or use the ones already connected to this firewall (False).
369+
refresh_vsys (bool): Refresh all vsys objects' parameters before doing the reorganization or not. This is assumed True if create_vsys_objects is True.
370+
371+
"""
372+
from pandevice import network
373+
374+
# Mapping of device.Vsys params to pandevice classes.
375+
mapping = {
376+
'interface': network.Interface,
377+
'vlans': network.Vlan,
378+
'virtual_wires': network.VirtualWire,
379+
'virtual_routers': network.VirtualRouter,
380+
}
381+
382+
# Optional: create the vsys objects.
383+
if create_vsys_objects:
384+
device.Vsys.refreshall(self, name_only=True)
385+
386+
# Vsys to put objects into.
387+
available_vsys = [x for x in self.children
388+
if isinstance(x, device.Vsys)]
389+
390+
# Optional: refresh the vsys params.
391+
if create_vsys_objects or refresh_vsys:
392+
for x in available_vsys:
393+
x.refresh(refresh_children=False)
394+
395+
# List of objects we need to iterate over.
396+
parents = self.children[:]
397+
398+
# Reorganize into vsys.
399+
for x in itertools.chain(parents):
400+
# Skip device.Vsys children.
401+
if isinstance(x, device.Vsys):
402+
continue
403+
404+
# Add children for later processing.
405+
parents.extend(x.children)
406+
407+
# Check this class against the importable classes.
408+
for param, importable_class in mapping.items():
409+
if isinstance(x, importable_class):
410+
# Importable class found, check if it should be moved.
411+
for vsys in available_vsys:
412+
if (getattr(vsys, param) is not None and
413+
x.uid in getattr(vsys, param)):
414+
# If its vsys isn't right, move it.
415+
if x.vsys != vsys.uid:
416+
x.parent.remove(x)
417+
vsys.add(x)
418+
break
419+
break
420+
363421

364422
class FirewallState(object):
365423

pandevice/network.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -549,11 +549,24 @@ class Subinterface(Interface):
549549
Do not instantiate this object. Use a subclass.
550550
551551
"""
552+
_BASE_INTERFACE_NAME = 'entry BASE_INTERFACE_NAME'
553+
552554
def set_name(self):
553555
"""Create a name appropriate for a subinterface if it isn't already"""
554556
if '.' not in self.name:
555557
self.name = '{0}.{1}'.format(self.name, self.tag)
556558

559+
@property
560+
def XPATH(self):
561+
path = super(Subinterface, self).XPATH
562+
563+
if self._BASE_INTERFACE_NAME in path:
564+
base = self.uid.split('.')[0]
565+
path = path.replace(self._BASE_INTERFACE_NAME,
566+
"entry[@name='{0}']".format(base))
567+
568+
return path
569+
557570

558571
class AbstractSubinterface(object):
559572
"""When a subinterface is needed, but the layer is unknown
@@ -689,8 +702,13 @@ class Layer3Subinterface(Subinterface):
689702
)
690703

691704
def _setup(self):
692-
# xpaths
705+
# xpaths for parents: EthernetInterface, AggregateInterface)
693706
self._xpaths.add_profile(value='/layer3/units')
707+
# xpaths for parents: firewall.Firewall, device.Vsys
708+
self._xpaths.add_profile(
709+
parents=('Firewall', 'Vsys'),
710+
value=('/network/interface/ethernet/{0}/layer3/units'.format(
711+
self._BASE_INTERFACE_NAME)))
694712

695713
# xpath imports
696714
self._xpath_imports.add_profile(value='/network/interface')
@@ -759,8 +777,13 @@ class Layer2Subinterface(Subinterface):
759777
ALLOW_SET_VLAN = True
760778

761779
def _setup(self):
762-
# xpaths
780+
# xpaths for parents: EthernetInterface, AggregateInterface
763781
self._xpaths.add_profile(value='/layer2/units')
782+
# xpaths for parents: firewall.Firewall, device.Vsys
783+
self._xpaths.add_profile(
784+
parents=('Firewall', 'Vsys'),
785+
value=('/network/interface/ethernet/{0}/layer2/units'.format(
786+
self._BASE_INTERFACE_NAME)))
764787

765788
# xpath imports
766789
self._xpath_imports.add_profile(value='/network/interface')

tests/test_integration.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,5 +658,64 @@ def test_set_xpath_from_addressobject_with_dg_panorama_parents(self):
658658

659659
self.assertEqual(expected, ret_val)
660660

661+
662+
class TestVariousSubinterfaceXpaths(unittest.TestCase):
663+
def test_l2_subinterface_with_firewall_parent(self):
664+
fw = pandevice.firewall.Firewall('192.168.1.1', 'admin', 'admin', vsys='vsys2')
665+
iface = pandevice.network.EthernetInterface('ethernet1/3', 'layer2')
666+
eth = pandevice.network.Layer2Subinterface('ethernet1/3.3', 3)
667+
iface.add(eth)
668+
fw.add(iface)
669+
670+
expected = eth.xpath()
671+
672+
fw.add(eth)
673+
674+
self.assertEqual(expected, eth.xpath())
675+
676+
def test_l2_subinterface_with_vsys_parent(self):
677+
fw = pandevice.firewall.Firewall('192.168.1.1', 'admin', 'admin')
678+
vsys = pandevice.device.Vsys('vsys2')
679+
iface = pandevice.network.EthernetInterface('ethernet1/3', 'layer2')
680+
eth = pandevice.network.Layer2Subinterface('ethernet1/3.3', 3)
681+
iface.add(eth)
682+
vsys.add(iface)
683+
fw.add(vsys)
684+
685+
expected = eth.xpath()
686+
687+
vsys.add(eth)
688+
689+
self.assertEqual(expected, eth.xpath())
690+
691+
def test_l3_subinterface_with_firewall_parent(self):
692+
fw = pandevice.firewall.Firewall('192.168.1.1', 'admin', 'admin', vsys='vsys3')
693+
iface = pandevice.network.EthernetInterface('ethernet1/4', 'layer3')
694+
eth = pandevice.network.Layer3Subinterface('ethernet1/4.4', 4)
695+
iface.add(eth)
696+
fw.add(iface)
697+
698+
expected = eth.xpath()
699+
700+
fw.add(eth)
701+
702+
self.assertEqual(expected, eth.xpath())
703+
704+
def test_l3_subinterface_with_vsys_parent(self):
705+
fw = pandevice.firewall.Firewall('192.168.1.1', 'admin', 'admin')
706+
vsys = pandevice.device.Vsys('vsys3')
707+
iface = pandevice.network.EthernetInterface('ethernet1/4', 'layer3')
708+
eth = pandevice.network.Layer2Subinterface('ethernet1/4.4', 4)
709+
iface.add(eth)
710+
vsys.add(iface)
711+
fw.add(vsys)
712+
713+
expected = eth.xpath()
714+
715+
vsys.add(eth)
716+
717+
self.assertEqual(expected, eth.xpath())
718+
719+
661720
if __name__=='__main__':
662721
unittest.main()

0 commit comments

Comments
 (0)