Skip to content

Commit

Permalink
Merge pull request #16 from dbarrosop/FortiOSDriver
Browse files Browse the repository at this point in the history
Added fortigate support
  • Loading branch information
dbarrosop committed Apr 24, 2015
2 parents a8490db + 00990b0 commit a087b3b
Show file tree
Hide file tree
Showing 12 changed files with 10,994 additions and 3 deletions.
4 changes: 2 additions & 2 deletions napalm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
from eos import EOSDriver
from iosxr import IOSXRDriver
from junos import JunOSDriver

from fortios import FortiOSDriver

def get_network_driver(vendor):
driver_mapping = {
Expand All @@ -25,7 +25,7 @@ def get_network_driver(vendor):
'IOSXR': IOSXRDriver,
'JUNOS': JunOSDriver,
'JUNIPER': JunOSDriver,

'fortios': FortiOSDriver,
}
try:
return driver_mapping[vendor.upper()]
Expand Down
99 changes: 99 additions & 0 deletions napalm/fortios.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright 2015 Spotify AB. All rights reserved.
#
# The contents of this file are licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

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

from base import NetworkDriver
from exceptions import ReplaceConfigException, MergeConfigException


class FortiOSDriver(NetworkDriver):

def __init__(self, hostname, username, password):
self.hostname = hostname
self.username = username
self.password = password
self.device = FortiOS(hostname, username=username, password=password)
self.config_replace = False

def open(self):
self.device.open()

def close(self):
self.device.close()

def _load_config(self, filename, config):
if filename is None:
configuration = config
else:
with open(filename) as f:
configuration = f.read()

self.device.load_config(in_candidate=True, config_text=configuration)

def load_replace_candidate(self, filename=None, config=None):
self.config_replace = True

self.device.candidate_config = FortiConfig('candidate')
self.device.running_config = FortiConfig('running')

self._load_config(filename, config)

self.device.load_config(empty_candidate=True)

def load_merge_candidate(self, filename=None, config=None):
self.config_replace = False

self.device.candidate_config = FortiConfig('candidate')
self.device.running_config = FortiConfig('running')

self._load_config(filename, config)

for block in self.device.candidate_config.get_block_names():
try:
self.device.load_config(path=block, empty_candidate=True)
except CommandExecutionException as e:
raise MergeConfigException(e.message)

def compare_config(self):
return self.device.compare_config()

def commit_config(self):
try:
self.device.execute_command('execute backup config flash commit_with_napalm')
self.device.commit()
self.discard_config()
except FailedCommit as e:
if self.config_replace:
raise ReplaceConfigException(e.message)
else:
raise MergeConfigException(e.message)

def discard_config(self):
self.device.candidate_config = FortiConfig('candidate')
self.device.load_config(in_candidate=True)

def rollback(self):
output = self.device.execute_command('fnsysctl ls -l data2/config')
rollback_file = output[-2].split()[-1]
rollback_config = self.device.execute_command('fnsysctl cat data2/config/%s' % rollback_file)

self.device.load_config(empty_candidate=True)
self.load_replace_candidate(config=rollback_config)
self.device.candidate_config['vpn certificate local']['Fortinet_CA_SSLProxy'].del_param('private-key')
self.device.candidate_config['vpn certificate local']['Fortinet_CA_SSLProxy'].del_param('certificate')
self.device.candidate_config['vpn certificate local']['Fortinet_SSLProxy'].del_param('private-key')
self.device.candidate_config['vpn certificate local']['Fortinet_SSLProxy'].del_param('certificate')
self.device.commit()
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pyEOS
ncclient
junos-eznc
pyIOSXR==0.6
pyFG
31 changes: 31 additions & 0 deletions test/unit/TestFortiOSDriver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright 2015 Spotify AB. All rights reserved.
#
# The contents of this file are licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import unittest

from napalm.fortios import FortiOSDriver
from base import TestNetworkDriver


class TestFortiOSDriver(unittest.TestCase, TestNetworkDriver):

@classmethod
def setUpClass(cls):
hostname = '192.168.76.13'
username = 'dbarroso'
password = 'this_is_not_a_secure_password'
cls.vendor = 'fortios'

cls.device = FortiOSDriver(hostname, username, password)
cls.device.open()
6 changes: 5 additions & 1 deletion test/unit/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class TestNetworkDriver:

@classmethod
def tearDownClass(cls):
cls.device.load_replace_candidate(filename='%s/initial.conf' % cls.vendor)
cls.device.commit_config()
cls.device.close()

@staticmethod
Expand All @@ -44,7 +46,9 @@ def test_replacing_config_with_typo(self):
self.device.load_replace_candidate(filename='%s/new_typo.conf' % self.vendor)
self.device.commit_config()
except exceptions.ReplaceConfigException:
result = True
self.device.load_replace_candidate(filename='%s/initial.conf' % self.vendor)
diff = self.device.compare_config()
result = True and len(diff) == 0
self.assertTrue(result)

def test_replacing_config_and_diff_and_discard(self):
Expand Down

0 comments on commit a087b3b

Please sign in to comment.