ktbyers / netmiko

Multi-vendor library to simplify Paramiko SSH connections to network devices
MIT License
3.55k stars 1.3k forks source link

Fortigate/Netmiko Does not capture the entire command output. #3063

Open iamakkss opened 1 year ago

iamakkss commented 1 year ago

Python 3.10.6 Netmiko 4.1.2 FortiGate-2000e v7.0.7 Firewall Vdom Enable

This is my example script:

def get_saved_config_firewall(host): forti_os = { 'device_type': 'fortinet', 'host': host, 'port': portnumber, 'username': uname, 'password': passwd, 'fast_cli': False, 'global_delay_factor': 2 }

    net_connect = ConnectHandler(**forti_os)
    net_connect.enable()

    net_connect.send_command("config global \n",expect_string=r"#",read_timeout=90)
    hostname = net_connect.send_command(" get system global | grep -f hostname \n",expect_string=r"#",read_timeout=90)
    net_connect.send_command("end \n ",expect_string=r"#",read_timeout=90)
    hostname = hostname.split()
    hostname = hostname[8]
    fileName = hostname + "_" + dt_string

    # Taking backup of root vdom
    net_connect.send_command("config vdom \n ",expect_string=r"#",read_timeout=90)
    net_connect.send_command("edit root \n ",expect_string=r"#",read_timeout=90)
    outputversionroot = net_connect.send_command("show full-configuration \n",expect_string=r"#",read_timeout=90)

    backupFileroot = open("backup-config-firewall/" + fileName + "-root.txt", "w+")
    backupFileroot.write("\n Backup of root vdom \n \n show full-configuration \n \n" + outputversionroot + "\n")
    print("Outputted to " + fileName + "-root.txt!")

    # coming out of root vdom.
    net_connect.send_command("end \n ",expect_string=r"#",read_timeout=90)

    # Taking backup of Global vdom
    outputversionglobal = net_connect.send_command("show full-configuration \n",expect_string=r"#",read_timeout=90,delay_factor=4)
    backupFileGlobal = open("backup-config-firewall/" + fileName + "-Global.txt", "w+")
    backupFileGlobal.write("show full-configuration \n \n" + outputversionglobal + "\n")
    print("Outputted to " + fileName + "-Gloabal.txt!")

While taking the backup of the global vdom. Netmiko does not capture the entire firewall backup configuration. It gets terminated in between, Has anyone faced the same issue please help me in resolving the issue.

kacem-expereo commented 1 year ago

Hi, Sorry I don't have a fortigate to try but this can be caused by different parameters. The first that comes to mind is that you match the expected string during the show full-configuration command. Do you have any "#" character in that config? Does it correspond to where your output is cut? I don't know about the default prompt for fortigate but if the previous statements are correct you will need to set the exact prompt instead.

ktbyers commented 1 year ago

@iamakkss There are some known issues with the Fortinet driver:

https://github.com/ktbyers/netmiko/issues/2146

And there is a PR in process to improve/fix some of these.

Hopefully, I can see if I can get this fixes incorporated in the first quarter of next year.

iamakkss commented 1 year ago

@ktbyers @kacem-expereo Thank you for response and clarity on the issue. I will be awaiting for the fix.

ktbyers commented 1 year ago

@iamakkss Updated fortinet driver here:

https://github.com/ktbyers/netmiko/pull/3091

If anyone is available to test it, that would be helpful.

Regards, Kirk

iamakkss commented 1 year ago

@ktbyers i will test it today post updating the netmiko package

ktbyers commented 1 year ago

@iamakkss Okay, great. Let me know what you see.

iamakkss commented 1 year ago

@ktbyers, post updating netmiko on 4.1.2, The issue still remains the same. Please let me know if you are open to connecting over a zoom call to work on the issue jointly.

ktbyers commented 1 year ago

You have to install this specific branch to test the new code:

https://github.com/ktbyers/netmiko/tree/fortinet_perf3

General process is here (assuming you have git cloned my Netmiko repository and are in the base of the repository directory.

git fetch origin       # where 'origin' is https://github.com/ktbyers/netmiko
git checkout -b fortinet_perf3 origin/fortinet_perf3
pip install -e .       # Install the current Netmiko branch in PIP editable mode

@iamakkss

iamakkss commented 1 year ago

Hi @ktbyers, Post updating the changes that you have suggested. I am getting below error while running program.

ValueError: Unable to determine the output mode on the Fortinet device.

ktbyers commented 1 year ago

@iamakkss Which Version of FortIOS are you using?

get system status | grep Version
iamakkss commented 1 year ago

@ktbyers the version of fortios is 7.0.7

ktbyers commented 1 year ago

@iamakkss Can you show the full exception stack trace (from your above error)?

iamakkss commented 1 year ago

@ktbyers Please find the snapshot of the exception traceback attached in the snapshot, Also please find the below program i wrote to capture the exception trace.

try: firewall program logic

except Exception: print(sys.exc_info()[2])

Please let me know if this is correct or you want a different output python error

ktbyers commented 1 year ago

If you look at git log for your Netmiko code, what is the last commit you have?

Also can you show me the output for get system console for the device that is failing?

iamakkss commented 1 year ago

@ktbyers I have below commit version

C:\Users\netmiko>git log commit bd334e2702bcbafe4f14be1001f8be6a290c859c (HEAD -> fortinet_perf3, origin/fortinet_perf3) Author: Kirk Byers ktbyers@twb-tech.com Date: Tue Jan 24 16:54:24 2023 -0800

Need separate output mode patterns for V6 and V7

attached get system console output

consoleoutput

ktbyers commented 1 year ago

Okay, that is the right commit.

Okay, given the output above, the code looks like it should work properly (and I just tested it against a similar output).

    def _get_output_mode_v7(self) -> str:
        """
        FortiOS V7 and later.
        Retrieve the current output mode.
        """
        output = self._send_command_str(
            "get system console", expect_string=self.prompt_pattern
        )

        pattern = r"output\s+:\s+(?P<mode>\S+)\s*$"
        result_mode_re = re.search(pattern, output, flags=re.M)
        if result_mode_re:
            result_mode = result_mode_re.group("mode").strip()
            if result_mode in ["more", "standard"]:
                return result_mode

        raise ValueError("Unable to determine the output mode on the Fortinet device.")

It would be interesting if you added print statements here:

https://github.com/ktbyers/netmiko/blob/develop/netmiko/fortinet/fortinet_ssh.py#L179

Make line 179 say:

print(repr(output))

And then right before this line:

https://github.com/ktbyers/netmiko/blob/develop/netmiko/fortinet/fortinet_ssh.py#L182

print(result_mode_re)

And then re-run your code and see what the value of those two things is.

iamakkss commented 1 year ago

@ktbyers made the said changes attached is the error. output1python

ktbyers commented 1 year ago

@iamakkss Okay, let me look at that...that is where the error/issue is.

ktbyers commented 1 year ago

@iamakkss Can you capture the session_log so we can see what is going on in the failing device:

forti_os = {
  'device_type': 'fortinet',
  'host': host,
  'port': portnumber,
  'username': uname,
  'password': passwd,
  'fast_cli': False,
  'global_delay_factor': 2
  'session_log: 'output.txt'       # Add this argument
}

Then re-run your script. You should get a file created named output.txt.

You can scrub anything that is confidential. Can you post the output of that here?

iamakkss commented 1 year ago

@ktbyers Please find the attached output of the session log.

output.txt

ktbyers commented 1 year ago

@iamakkss Does get system console not work with the permissions that you use to login?

You showed it above--did you have to elevate permissions to get that output?

get system console

command parse error before 'console'
Command fail. Return code -61
iamakkss commented 1 year ago

@ktbyers I run this application using the default admin users of the firewall. So permission is not the problem.

ktbyers commented 1 year ago

Your firewall is responding with the below to the get system console command?

command parse error before 'console'
Command fail. Return code -61

This is the output from your device to that command (which would indicate it is not understanding that command in its current context).

MilesTails commented 1 year ago

Hi Kirk,

When a fortigate firewall is in Multi-VDOM mode you need to perform a config global prior to this command. In Single-VDOM mode it would be done from the standard initial login prompt.

fortigate # get system console

command parse error before 'console'
Command fail. Return code -61

fortigate # config global

fortigate (global) # get system console
mode                : line
baudrate            : 9600
output              : standard
login               : enable
fortiexplorer       : enable
MilesTails commented 1 year ago

Not sure if this is the fix but I've just added the following to def _get_output_mode_v7 and it seems to work for me now.

    def _get_output_mode_v7(self) -> str:
        """
        FortiOS V7 and later.
        Retrieve the current output mode.
        """
        if self._vdoms:
            self._config_global()

        output = self._send_command_str(
            "get system console", expect_string=self.prompt_pattern
        )
ktbyers commented 1 year ago

Okay, let me fix that.

iamakkss commented 1 year ago

@ktbyers hey i was away from systems for few days. Please let me know once you are done with fix, I will check code and let you the result.

ktbyers commented 1 year ago

@iamakkss Sounds good. I haven't fixed this yet...

ktbyers commented 1 year ago

@iamakkss Okay, this fix is in the develop branch now if you want to test it.

https://github.com/ktbyers/netmiko/pull/3115

iamakkss commented 1 year ago

@ktbyers I have cloned the new repo. Tested the new code, Still, the same issue is there not capturing the entire global vdom output.

ktbyers commented 1 year ago

@iamakkss Okay, do you want to look at the session log and see what is going on?

Mainly see what is happening during this call:

    output = self._send_command_str(
        "get system console", expect_string=self.prompt_pattern
    )

It should be in config global mode now (per the recent PR).

You should also probably double check that you have this commit:

https://github.com/ktbyers/netmiko/pull/3115

You can view this in git log

iamakkss commented 1 year ago

@ktbyers Sorry for the delay in response. I have captured the session log, Still, the issue is same, Attaching the session log for your reference. output.txt

ktbyers commented 1 year ago

@iamakkss

How many lines are in your output?

The file you attached is incredibly large (over 50,000 lines). You might think of different solutions for capturing it than screen scraping (for example, save to a file to the device and transfer the file would be a common pattern--at least on other platforms).

I don't know if you will be able to achieve that with Netmiko (trying to capture that large and slow of output is really challenging with screen scraping).

iamakkss commented 1 year ago

@ktbyers sorry for the delay in response, I have left the company where i wsas facing the issue in the code, As i do not have access to the code now i can provide you required information on this

ktbyers commented 1 year ago

@iamakkss No worries at all. Thanks for responding.