Book Image

Python Network Programming Techniques

By : Marcel Neidinger
Book Image

Python Network Programming Techniques

By: Marcel Neidinger

Overview of this book

Network automation offers a powerful new way of changing your infrastructure network. Gone are the days of manually logging on to different devices to type the same configuration commands over and over again. With this book, you'll find out how you can automate your network infrastructure using Python. You'll get started on your network automation journey with a hands-on introduction to the network programming basics to complement your infrastructure knowledge. You'll learn how to tackle different aspects of network automation using Python programming and a variety of open source libraries. In the book, you'll learn everything from templating, testing, and deploying your configuration on a device-by-device basis to using high-level REST APIs to manage your cloud-based infrastructure. Finally, you'll see how to automate network security with Cisco’s Firepower APIs. By the end of this Python network programming book, you'll have not only gained a holistic overview of the different methods to automate the configuration and maintenance of network devices, but also learned how to automate simple to complex networking tasks and overcome common network programming challenges.
Table of Contents (14 chapters)

Executing a sequence of commands

In the previous recipes, we have always only dealt with a single command that we wanted to execute. Maybe you have tried adding another call to the exec_command() function to the client already and have run into an error telling you that the session is closed. It is indeed correct that, once your command is done executing, the connection will close.

But quite often we don't want to execute only one but a sequence of commands one after another. We could reconnect for each of the commands, but this is a workaround that would create a lot of unneeded disconnecting and reconnecting. What we can do instead is, if the target device's configuration allows it, open up a shell session. This shell session is a single command, and we can then use stdin, stderr, and stdout to send multiple commands in the same session.

In this recipe, you will see how to programmatically open an SSH connection to a device, open a shell, and then send a list of commands to the device before closing the connection.

Getting ready

Open your code editor and start by creating a file called exec_multiple_commands.py. Next, navigate your terminal to the same directory that you just created the exec_multiple_commands.py file in.

How to do it...

Let's start by creating our credentials file. We will then read that file from our Python script, create clients for each of these devices, and finally execute a command while also saving the output back to our file:

  1. Import the Paramiko library. We will also need the built-in time library:
    from paramiko.client import SSHClient
    import time
  2. Specify the host, username, and password. You can name these variables however you like. In the Python community, it has become a standard to uppercase these global variables:
    SSH_USER = "<Insert your ssh user here>"
    SSH_PASSWORD = "<Insert your ssh password here>"
    SSH_HOST = "<Insert the IP/host of your device/server here>"
    SSH_PORT = 22 # Change this if your SSH port is different
  3. Create an SSHClient object, which we just imported from Paramiko:
    client = SSHClient()
  4. While we have created our client object, we have not yet connected to the device. We will use the connect method of the client object to do so. Before actually connecting, we will need to make sure that our client knows the host keys:
    client.load_system_host_keys()
    client.connect(SSH_HOST, port=SSH_PORT,
                             username=SSH_USER,
                             password=SSH_PASSWORD)
  5. Open up an interactive shell session and a channel that we can use to retrieve the output:
    channel = client.get_transport().open_session()
    shell = channel.invoke_shell()
  6. Next, specify the list of commands we want to execute on the device:
    commands = [
         "configure terminal",
         "hostname test"
    ]
  7. Iterate over each of the commands, execute them, and then wait for 2 seconds:
    for cmd in commands:
         shell.send(cmd + "\n")
          out = shell.recv(1024)
          print(out)
         time.sleep(1)
  8. Finally, we need to close the connection:
    client.close()
  9. To run this script, go to your terminal and execute it with this:
    python3 exec_multiple_commands.py

How it works...

In this example, we use Paramiko's concept of an interactive shell to send multiple commands to the remote device one after another.

When invoking a shell with Paramiko, we will retrieve a channel. This channel was used by Paramiko in the background all along to execute our commands but has been hidden from us so far. The channel takes care of low-level aspects such as sending and receiving the data to and from the raw network connection to our device. The channel function we use in this example is the send() function, which sends a string to the remote device. Mind the carriage return we added to the command. The same way you, when connecting to a device via SSH, have to execute a command by typing enter, the interactive session has to indicate that via a linebreak, which is the same symbol sent by your interactive session when hitting the Enter key.

We are using the sleep function here to wait for the commands you have passed to have finished executing. For short-running commands, you can get away with not using this sleep function.